]> gitweb.fperrin.net Git - GpsPrune.git/blobdiff - tim/prune/save/GpxExporter.java
Version 11.1, August 2010
[GpsPrune.git] / tim / prune / save / GpxExporter.java
index 019cc438bdbf96003595e7c7ebe7d84654839d11..a662e2175c9e95097f28a610bdf135383df67535 100644 (file)
@@ -38,6 +38,8 @@ import tim.prune.data.Field;
 import tim.prune.data.Timestamp;
 import tim.prune.data.TrackInfo;
 import tim.prune.load.GenericFileFilter;
+import tim.prune.save.xml.GpxCacherList;
+
 
 /**
  * Class to export track information
@@ -288,8 +290,9 @@ public class GpxExporter extends GenericFunction implements Runnable
                // Instantiate source file cachers in case we want to copy output
                GpxCacherList gpxCachers = null;
                if (inUseCopy) gpxCachers = new GpxCacherList(inInfo.getFileInfo());
-               // Write or copy header
-               inWriter.write(getHeaderString(gpxCachers));
+               // Write or copy headers
+               inWriter.write(getXmlHeaderString(inWriter));
+               inWriter.write(getGpxHeaderString(gpxCachers));
                // Name field
                String trackName = "PruneTrack";
                if (inName != null && !inName.equals(""))
@@ -301,12 +304,7 @@ public class GpxExporter extends GenericFunction implements Runnable
                }
                // Description field
                inWriter.write("\t<desc>");
-               if (inDesc != null && !inDesc.equals("")) {
-                       inWriter.write(inDesc);
-               }
-               else {
-                       inWriter.write("Export from Prune");
-               }
+               inWriter.write((inDesc != null && !inDesc.equals(""))?inDesc:"Export from Prune");
                inWriter.write("</desc>\n");
 
                int i = 0;
@@ -334,7 +332,7 @@ public class GpxExporter extends GenericFunction implements Runnable
                                if (point.isWaypoint()) {
                                        if (exportWaypoints)
                                        {
-                                               String pointSource = (inUseCopy?gpxCachers.getSourceString(point):null);
+                                               String pointSource = (inUseCopy?getPointSource(gpxCachers, point):null);
                                                if (pointSource != null) {
                                                        inWriter.write(pointSource);
                                                        inWriter.write('\n');
@@ -404,7 +402,7 @@ public class GpxExporter extends GenericFunction implements Runnable
                                if ((point.getPhoto()==null && inExportTrackpoints) || (point.getPhoto()!=null && inExportPhotos))
                                {
                                        // get the source from the point (if any)
-                                       String pointSource = (inCachers!=null?inCachers.getSourceString(point):null);
+                                       String pointSource = getPointSource(inCachers, point);
                                        boolean writePoint = (pointSource != null && pointSource.toLowerCase().startsWith(inPointTag))
                                                || (pointSource == null && !inOnlyCopies);
                                        if (writePoint)
@@ -430,12 +428,83 @@ public class GpxExporter extends GenericFunction implements Runnable
                return numSaved;
        }
 
+
+       /**
+        * Get the point source for the specified point
+        * @param inCachers list of GPX cachers to ask for source
+        * @param inPoint point object
+        * @return xml source if available, or null otherwise
+        */
+       private static String getPointSource(GpxCacherList inCachers, DataPoint inPoint)
+       {
+               if (inCachers == null || inPoint == null) {return null;}
+               String source = inCachers.getSourceString(inPoint);
+               if (source == null || !inPoint.isModified()) {return source;}
+               // Point has been modified - maybe it's possible to modify the source
+               source = replaceGpxTags(source, "lat=\"", "\"", inPoint.getLatitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
+               source = replaceGpxTags(source, "lon=\"", "\"", inPoint.getLongitude().output(Coordinate.FORMAT_DECIMAL_FORCE_POINT));
+               source = replaceGpxTags(source, "<ele>", "</ele>", inPoint.getAltitude().getStringValue(Altitude.Format.METRES));
+               source = replaceGpxTags(source, "<time>", "</time>", inPoint.getTimestamp().getText(Timestamp.FORMAT_ISO_8601));
+               if (inPoint.isWaypoint()) {source = replaceGpxTags(source, "<name>", "</name>", inPoint.getWaypointName());}  // only for waypoints
+               return source;
+       }
+
+       /**
+        * Replace the given value into the given XML string
+        * @param inSource source XML for point
+        * @param inStartTag start tag for field
+        * @param inEndTag end tag for field
+        * @param inValue value to replace between start tag and end tag
+        * @return modified String, or null if not possible
+        */
+       private static String replaceGpxTags(String inSource, String inStartTag, String inEndTag, String inValue)
+       {
+               if (inSource == null) {return null;}
+               // Look for start and end tags within source
+               final int startPos = inSource.indexOf(inStartTag);
+               final int endPos = inSource.indexOf(inEndTag, startPos+inStartTag.length());
+               if (startPos > 0 && endPos > 0)
+               {
+                       String origValue = inSource.substring(startPos + inStartTag.length(), endPos);
+                       if (inValue != null && origValue.equals(inValue)) {
+                               // Value unchanged
+                               return inSource;
+                       }
+                       else if (inValue == null || inValue.equals("")) {
+                               // Need to delete value
+                               return inSource.substring(0, startPos) + inSource.substring(endPos + inEndTag.length());
+                       }
+                       else {
+                               // Need to replace value
+                               return inSource.substring(0, startPos+inStartTag.length()) + inValue + inSource.substring(endPos);
+                       }
+               }
+               // Value not found for this field in original source
+               if (inValue == null || inValue.equals("")) {return inSource;}
+               return null;
+       }
+
+       /**
+        * Get the header string for the xml document including encoding
+        * @param inWriter writer object
+        * @return header string defining encoding
+        */
+       private static String getXmlHeaderString(OutputStreamWriter inWriter)
+       {
+               String encoding = inWriter.getEncoding();
+               final String encodingUpper = encoding.toUpperCase();
+               if (encodingUpper.equals("UTF8") || encodingUpper.equals("UTF-8")) {
+                       encoding = "UTF-8";
+               }
+               return "<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n";
+       }
+
        /**
-        * Get the header string for the gpx
+        * Get the header string for the gpx tag
         * @param inCachers cacher list to ask for headers, if available
         * @return header string from cachers or as default
         */
-       private static String getHeaderString(GpxCacherList inCachers)
+       private static String getGpxHeaderString(GpxCacherList inCachers)
        {
                String gpxHeader = null;
                if (inCachers != null) {gpxHeader = inCachers.getFirstHeader();}
@@ -447,7 +516,7 @@ public class GpxExporter extends GenericFunction implements Runnable
                                + " xmlns=\"http://www.topografix.com/GPX/1/0\""
                                + " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n";
                }
-               return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + gpxHeader + "\n";
+               return gpxHeader + "\n";
        }
 
        /**