/*
This file is part of RouteConverter.
RouteConverter is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
RouteConverter is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RouteConverter; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2007 Christian Pesch. All Rights Reserved.
*/
package slash.navigation.gpx;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import slash.navigation.base.ParserContext;
import slash.navigation.gpx.binding11.ExtensionsType;
import slash.navigation.gpx.binding11.GpxType;
import slash.navigation.gpx.binding11.MetadataType;
import slash.navigation.gpx.binding11.ObjectFactory;
import slash.navigation.gpx.binding11.RteType;
import slash.navigation.gpx.binding11.TrkType;
import slash.navigation.gpx.binding11.TrksegType;
import slash.navigation.gpx.binding11.WptType;
import slash.navigation.gpx.garmin3.AutoroutePointT;
import slash.navigation.gpx.garmin3.RoutePointExtensionT;
import slash.navigation.gpx.trackpoint2.TrackPointExtensionT;
import slash.navigation.gpx.trip1.ViaPointExtensionT;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static slash.common.io.Transfer.formatDouble;
import static slash.common.io.Transfer.formatInt;
import static slash.common.io.Transfer.formatXMLTime;
import static slash.common.io.Transfer.isEmpty;
import static slash.common.io.Transfer.parseDouble;
import static slash.common.io.Transfer.parseXMLTime;
import static slash.navigation.base.RouteCharacteristics.Route;
import static slash.navigation.base.RouteCharacteristics.Track;
import static slash.navigation.base.RouteCharacteristics.Waypoints;
import static slash.navigation.common.NavigationConversion.formatBigDecimal;
import static slash.navigation.common.NavigationConversion.formatElevation;
import static slash.navigation.common.NavigationConversion.formatHeading;
import static slash.navigation.common.NavigationConversion.formatHeadingAsString;
import static slash.navigation.common.NavigationConversion.formatPosition;
import static slash.navigation.common.NavigationConversion.formatSpeedAsString;
import static slash.navigation.common.NavigationConversion.formatTemperatureAsString;
import static slash.navigation.gpx.GpxUtil.marshal11;
import static slash.navigation.gpx.GpxUtil.unmarshal11;
/**
* Reads and writes GPS Exchange Format 1.1 (.gpx) files.
*
* @author Christian Pesch
*/
public class Gpx11Format extends GpxFormat {
static final String VERSION = "1.1";
public String getName() {
return "GPS Exchange Format " + VERSION + " (*" + getExtension() + ")";
}
void process(GpxType gpxType, ParserContext<GpxRoute> context) {
if (gpxType == null || !VERSION.equals(gpxType.getVersion()))
return;
GpxRoute wayPointsAsRoute = extractWayPoints(gpxType);
if (wayPointsAsRoute != null)
context.appendRoute(wayPointsAsRoute);
context.appendRoutes(extractRoutes(gpxType));
context.appendRoutes(extractTracks(gpxType));
}
public void read(InputStream source, ParserContext<GpxRoute> context) throws Exception {
GpxType gpxType = unmarshal11(source);
process(gpxType, context);
}
private List<GpxRoute> extractRoutes(GpxType gpxType) {
List<GpxRoute> result = new ArrayList<>();
for (RteType rteType : gpxType.getRte()) {
String name = rteType.getName();
String desc = rteType.getDesc();
List<String> descriptions = asDescription(desc);
List<GpxPosition> positions = extractRoute(rteType);
result.add(new GpxRoute(this, Route, name, descriptions, positions, gpxType, rteType));
// Garmin Extensions v3
if (rteType.getExtensions() != null && rteType.getExtensions().getAny().size() > 0) {
List<GpxPosition> extendedPositions = extractRouteWithGarminExtensions(rteType);
result.add(new GpxRoute(this, Track, name, descriptions, extendedPositions, gpxType, rteType));
}
}
return result;
}
private GpxRoute extractWayPoints(GpxType gpxType) {
String name = gpxType.getMetadata() != null ? gpxType.getMetadata().getName() : null;
String desc = gpxType.getMetadata() != null ? gpxType.getMetadata().getDesc() : null;
List<String> descriptions = asDescription(desc);
List<GpxPosition> positions = extractWayPoints(gpxType.getWpt());
return positions.size() == 0 ? null : new GpxRoute(this, Waypoints, name, descriptions, positions, gpxType);
}
private List<GpxRoute> extractTracks(GpxType gpxType) {
List<GpxRoute> result = new ArrayList<>();
for (TrkType trkType : gpxType.getTrk()) {
String name = trkType.getName();
String desc = trkType.getDesc();
List<String> descriptions = asDescription(desc);
List<GpxPosition> positions = extractTrack(trkType);
result.add(new GpxRoute(this, Track, name, descriptions, positions, gpxType, trkType));
}
return result;
}
private List<GpxPosition> extractRoute(RteType rteType) {
List<GpxPosition> positions = new ArrayList<>();
if (rteType != null) {
for (WptType wptType : rteType.getRtept()) {
positions.add(new GpxPosition(wptType.getLon(), wptType.getLat(), wptType.getEle(), getSpeed(wptType), getHeading(wptType), getTemperature(wptType), parseXMLTime(wptType.getTime()), asDescription(wptType.getName(), wptType.getDesc()), wptType.getHdop(), wptType.getPdop(), wptType.getVdop(), wptType.getSat(), wptType));
}
}
return positions;
}
private List<GpxPosition> extractRouteWithGarminExtensions(RteType rteType) {
List<GpxPosition> positions = new ArrayList<>();
if (rteType != null) {
for (WptType wptType : rteType.getRtept()) {
positions.add(new GpxPosition(wptType.getLon(), wptType.getLat(), wptType.getEle(), getSpeed(wptType), getHeading(wptType), getTemperature(wptType), parseXMLTime(wptType.getTime()), asDescription(wptType.getName(), wptType.getDesc()), wptType.getHdop(), wptType.getPdop(), wptType.getVdop(), wptType.getSat(), wptType));
ExtensionsType extensions = wptType.getExtensions();
if (extensions != null) {
for (Object any : extensions.getAny()) {
if (any instanceof JAXBElement) {
Object anyValue = ((JAXBElement) any).getValue();
if (anyValue instanceof RoutePointExtensionT) {
RoutePointExtensionT routePoint = (RoutePointExtensionT) anyValue;
for (AutoroutePointT autoroutePoint : routePoint.getRpt()) {
positions.add(new GpxPosition(autoroutePoint.getLon(), autoroutePoint.getLat(), null, null, null, null, null, null, null, null, null, null, null));
}
}
}
}
}
}
}
return positions;
}
private List<GpxPosition> extractWayPoints(List<WptType> wptTypes) {
List<GpxPosition> positions = new ArrayList<>();
for (WptType wptType : wptTypes) {
positions.add(new GpxPosition(wptType.getLon(), wptType.getLat(), wptType.getEle(), getSpeed(wptType), getHeading(wptType), getTemperature(wptType), parseXMLTime(wptType.getTime()), asDescription(wptType.getName(), wptType.getDesc()), wptType.getHdop(), wptType.getPdop(), wptType.getVdop(), wptType.getSat(), wptType));
}
return positions;
}
private List<GpxPosition> extractTrack(TrkType trkType) {
List<GpxPosition> positions = new ArrayList<>();
if (trkType != null) {
for (TrksegType trkSegType : trkType.getTrkseg()) {
for (WptType wptType : trkSegType.getTrkpt()) {
positions.add(new GpxPosition(wptType.getLon(), wptType.getLat(), wptType.getEle(), getSpeed(wptType), getHeading(wptType), getTemperature(wptType), parseXMLTime(wptType.getTime()), asDescription(wptType.getName(), wptType.getDesc()), wptType.getHdop(), wptType.getPdop(), wptType.getVdop(), wptType.getSat(), wptType));
}
}
}
return positions;
}
private Double getSpeed(WptType wptType) {
Double result = null;
ExtensionsType extensions = wptType.getExtensions();
if (extensions != null) {
for (Object any : extensions.getAny()) {
if (any instanceof JAXBElement) {
Object anyValue = ((JAXBElement) any).getValue();
if (anyValue instanceof TrackPointExtensionT) {
TrackPointExtensionT trackPoint = (TrackPointExtensionT) anyValue;
result = asKmh(trackPoint.getSpeed());
}
} else if (any instanceof Element) {
Element element = (Element) any;
// TrackPointExtension v1
if ("TrackPointExtension".equals(element.getLocalName())) {
Node firstChild = element.getFirstChild();
if (firstChild != null && "speed".equals(firstChild.getLocalName()))
result = asKmh(parseDouble(firstChild.getTextContent()));
// generic reading of speed elements
} else if ("speed".equals(element.getLocalName()))
result = asKmh(parseDouble(element.getTextContent()));
}
}
}
if (result == null)
result = parseSpeed(wptType.getCmt());
if (result == null)
result = parseSpeed(wptType.getName());
if (result == null)
result = parseSpeed(wptType.getDesc());
return result;
}
@SuppressWarnings("unchecked")
private JAXBElement<String> asJABElement(Object any) {
return (JAXBElement<String>) any;
}
private boolean isRemoveEmptyTrackPointExtension(TrackPointExtensionT trackPoint) {
return isEmpty(trackPoint.getAtemp()) && isEmpty(trackPoint.getCourse()) && isEmpty(trackPoint.getSpeed());
}
private void setSpeed(WptType wptType, Double speed) {
if (wptType.getExtensions() == null)
wptType.setExtensions(new ObjectFactory().createExtensionsType());
@SuppressWarnings("ConstantConditions")
List<Object> anys = wptType.getExtensions().getAny();
boolean foundSpeed = false;
Iterator<Object> iterator = anys.iterator();
while (iterator.hasNext()) {
Object any = iterator.next();
// this is parsed
if (any instanceof Element) {
Element element = (Element) any;
if ("speed".equals(element.getLocalName())) {
if (foundSpeed || speed == null)
iterator.remove();
else {
element.setTextContent(formatSpeedAsString(asMs(speed)));
foundSpeed = true;
}
}
}
// this is if I create the extensions with JAXB
if (any instanceof JAXBElement) {
Object anyValue = ((JAXBElement) any).getValue();
if (anyValue instanceof TrackPointExtensionT) {
TrackPointExtensionT trackPoint = (TrackPointExtensionT) anyValue;
trackPoint.setSpeed(asMs(speed));
if (foundSpeed || isRemoveEmptyTrackPointExtension(trackPoint))
iterator.remove();
foundSpeed = true;
}
}
}
if (!foundSpeed && speed != null) {
slash.navigation.gpx.trackpoint2.ObjectFactory trackpoint2Factory = new slash.navigation.gpx.trackpoint2.ObjectFactory();
TrackPointExtensionT trackPointExtensionT = trackpoint2Factory.createTrackPointExtensionT();
trackPointExtensionT.setSpeed(asMs(speed));
anys.add(trackpoint2Factory.createTrackPointExtension(trackPointExtensionT));
}
}
private Double getHeading(WptType wptType) {
Double result = null;
ExtensionsType extensions = wptType.getExtensions();
if (extensions != null) {
for (Object any : extensions.getAny()) {
if (any instanceof JAXBElement) {
Object anyValue = ((JAXBElement) any).getValue();
if (anyValue instanceof TrackPointExtensionT) {
TrackPointExtensionT trackPoint = (TrackPointExtensionT) anyValue;
result = formatDouble(trackPoint.getCourse());
}
} else if (any instanceof Element) {
Element element = (Element) any;
if ("course".equals(element.getLocalName()))
result = parseDouble(element.getTextContent());
}
}
}
if (result == null)
result = parseHeading(wptType.getCmt());
return result;
}
private void setHeading(WptType wptType, Double heading) {
if (wptType.getExtensions() == null)
wptType.setExtensions(new ObjectFactory().createExtensionsType());
@SuppressWarnings("ConstantConditions")
List<Object> anys = wptType.getExtensions().getAny();
boolean foundHeading = false;
Iterator<Object> iterator = anys.iterator();
while (iterator.hasNext()) {
Object any = iterator.next();
// this is parsed
if (any instanceof Element) {
Element element = (Element) any;
if ("course".equals(element.getLocalName())) {
if (foundHeading || heading == null)
iterator.remove();
else {
element.setTextContent(formatHeadingAsString(heading));
foundHeading = true;
}
}
}
// this is if I create the extensions with JAXB
if (any instanceof JAXBElement) {
Object anyValue = ((JAXBElement) any).getValue();
if (anyValue instanceof TrackPointExtensionT) {
TrackPointExtensionT trackPoint = (TrackPointExtensionT) anyValue;
trackPoint.setCourse(formatHeading(heading));
if (foundHeading || isRemoveEmptyTrackPointExtension(trackPoint))
iterator.remove();
foundHeading = true;
}
}
}
if (!foundHeading && heading != null) {
slash.navigation.gpx.trackpoint2.ObjectFactory trackpoint2Factory = new slash.navigation.gpx.trackpoint2.ObjectFactory();
TrackPointExtensionT trackPointExtensionT = trackpoint2Factory.createTrackPointExtensionT();
trackPointExtensionT.setCourse(formatHeading(heading));
anys.add(trackpoint2Factory.createTrackPointExtension(trackPointExtensionT));
}
}
private Double getTemperature(WptType wptType) {
Double result = null;
ExtensionsType extensions = wptType.getExtensions();
if (extensions != null) {
for (Object any : extensions.getAny()) {
if (any instanceof JAXBElement) {
Object anyValue = ((JAXBElement) any).getValue();
if (anyValue instanceof TrackPointExtensionT) {
TrackPointExtensionT trackPoint = (TrackPointExtensionT) anyValue;
result = trackPoint.getAtemp();
}
} else if (any instanceof Element) {
Element element = (Element) any;
// TrackPointExtension v1
if ("TrackPointExtension".equals(element.getLocalName())) {
Node firstChild = element.getFirstChild();
if (firstChild != null && "atemp".equals(firstChild.getLocalName())) {
result = parseDouble(firstChild.getTextContent());
}
}
}
}
}
return result;
}
private void setTemperature(WptType wptType, Double temperature) {
if (wptType.getExtensions() == null)
wptType.setExtensions(new ObjectFactory().createExtensionsType());
@SuppressWarnings("ConstantConditions")
List<Object> anys = wptType.getExtensions().getAny();
boolean foundTemperature = false;
Iterator<Object> iterator = anys.iterator();
while (iterator.hasNext()) {
Object any = iterator.next();
// this is parsed
if (any instanceof Element) {
Element element = (Element) any;
if ("atemp".equals(element.getLocalName())) {
if (foundTemperature || temperature == null)
iterator.remove();
else {
element.setTextContent(formatTemperatureAsString(temperature));
foundTemperature = true;
}
}
}
// this is if I create the extensions with JAXB
if (any instanceof JAXBElement) {
Object anyValue = ((JAXBElement) any).getValue();
if (anyValue instanceof TrackPointExtensionT) {
TrackPointExtensionT trackPoint = (TrackPointExtensionT) anyValue;
trackPoint.setAtemp(temperature);
if (foundTemperature || isRemoveEmptyTrackPointExtension(trackPoint))
iterator.remove();
foundTemperature = true;
}
}
}
if (!foundTemperature && temperature != null) {
slash.navigation.gpx.trackpoint2.ObjectFactory trackpoint2Factory = new slash.navigation.gpx.trackpoint2.ObjectFactory();
TrackPointExtensionT trackPointExtensionT = trackpoint2Factory.createTrackPointExtensionT();
trackPointExtensionT.setAtemp(temperature);
anys.add(trackpoint2Factory.createTrackPointExtension(trackPointExtensionT));
}
}
private void setExtension(WptType wptType, String extensionNameToRemove, String extensionNameToAdd, Object extensionToAdd) {
if (wptType.getExtensions() == null)
wptType.setExtensions(new ObjectFactory().createExtensionsType());
@SuppressWarnings("ConstantConditions")
List<Object> anys = wptType.getExtensions().getAny();
boolean foundElement = false;
Iterator<Object> iterator = anys.iterator();
while (iterator.hasNext()) {
Object any = iterator.next();
if (any instanceof JAXBElement) {
JAXBElement<String> element = asJABElement(any);
if (extensionNameToRemove.equals(element.getName().getLocalPart())) {
iterator.remove();
} else if (extensionNameToAdd.equals(element.getName().getLocalPart())) {
foundElement = true;
}
}
}
if (!foundElement)
anys.add(extensionToAdd);
}
private void setViaPoint(WptType wptType) {
slash.navigation.gpx.trip1.ObjectFactory tripFactory = new slash.navigation.gpx.trip1.ObjectFactory();
ViaPointExtensionT viaPointExtensionT = tripFactory.createViaPointExtensionT();
viaPointExtensionT.setCalculationMode("ShorterDistance");
viaPointExtensionT.setElevationMode("Standard");
setExtension(wptType, "ShapingPoint", "ViaPoint", tripFactory.createViaPoint(viaPointExtensionT));
}
private void setShapingPoint(WptType wptType) {
slash.navigation.gpx.trip1.ObjectFactory tripFactory = new slash.navigation.gpx.trip1.ObjectFactory();
ViaPointExtensionT viaPointExtensionT = tripFactory.createViaPointExtensionT();
viaPointExtensionT.setCalculationMode("ShorterDistance");
viaPointExtensionT.setElevationMode("Standard");
setExtension(wptType, "ViaPoint", "ShapingPoint", tripFactory.createShapingPoint(tripFactory.createShapingPointExtensionT()));
}
private void clearDistance(TrkType trkType) {
if (trkType.getExtensions() == null)
return;
@SuppressWarnings("ConstantConditions")
List<Object> anys = trkType.getExtensions().getAny();
if (anys == null)
return;
Iterator<Object> iterator = anys.iterator();
while (iterator.hasNext()) {
Object any = iterator.next();
if (any instanceof Element) {
Element element = (Element) any;
// TrackStatsExtension contains Distance element which BaseCamp uses if it's present
// but which might be inaccurate due to changes to the positions that affect the distance
if ("TrackStatsExtension".equals(element.getLocalName())) {
iterator.remove();
}
}
}
}
private WptType createWptType(GpxPosition position) {
BigDecimal latitude = formatPosition(position.getLatitude());
BigDecimal longitude = formatPosition(position.getLongitude());
if (latitude == null || longitude == null)
return null;
WptType wptType = position.getOrigin(WptType.class);
if (wptType == null)
wptType = new ObjectFactory().createWptType();
wptType.setLat(latitude);
wptType.setLon(longitude);
wptType.setEle(isWriteElevation() ? formatElevation(position.getElevation()) : null);
setSpeed(wptType, isWriteSpeed() ? position.getSpeed() : null);
setHeading(wptType, isWriteHeading() ? position.getHeading() : null);
setTemperature(wptType, isWriteTemperature() ? position.getTemperature() : null);
wptType.setTime(isWriteTime() ? formatXMLTime(position.getTime()) : null);
wptType.setName(isWriteName() ? asName(position.getDescription()) : null);
wptType.setDesc(isWriteName() ? asDesc(position.getDescription(), wptType.getDesc()) : null);
wptType.setHdop(isWriteAccuracy() && position.getHdop() != null ? formatBigDecimal(position.getHdop(), 6) : null);
wptType.setPdop(isWriteAccuracy() && position.getPdop() != null ? formatBigDecimal(position.getPdop(), 6) : null);
wptType.setVdop(isWriteAccuracy() && position.getVdop() != null ? formatBigDecimal(position.getVdop(), 6) : null);
wptType.setSat(isWriteAccuracy() && position.getSatellites() != null ? formatInt(position.getSatellites()) : null);
if (wptType.getExtensions() != null && wptType.getExtensions().getAny().size() == 0)
wptType.setExtensions(null);
return wptType;
}
private List<WptType> createWayPoints(GpxRoute route, int startIndex, int endIndex) {
List<WptType> wptTypes = new ArrayList<>();
List<GpxPosition> positions = route.getPositions();
for (int i = startIndex; i < endIndex; i++) {
GpxPosition position = positions.get(i);
WptType wptType = createWptType(position);
if (wptType != null)
wptTypes.add(wptType);
}
return wptTypes;
}
private List<RteType> createRoute(GpxRoute route, int startIndex, int endIndex) {
ObjectFactory objectFactory = new ObjectFactory();
List<RteType> rteTypes = new ArrayList<>();
RteType rteType = route.getOrigin(RteType.class);
if (rteType != null)
rteType.getRtept().clear();
else
rteType = objectFactory.createRteType();
if (isWriteMetaData()) {
rteType.setName(asRouteName(route.getName()));
rteType.setDesc(asDescription(route.getDescription()));
}
rteTypes.add(rteType);
List<GpxPosition> positions = route.getPositions();
for (int i = startIndex; i < endIndex; i++) {
GpxPosition position = positions.get(i);
WptType wptType = createWptType(position);
if (wptType != null) {
rteType.getRtept().add(wptType);
if (isWriteTrip()) {
if (i == startIndex || i == endIndex - 1)
setViaPoint(wptType);
else
setShapingPoint(wptType);
}
}
}
return rteTypes;
}
private List<TrkType> createTrack(GpxRoute route, int startIndex, int endIndex) {
ObjectFactory objectFactory = new ObjectFactory();
List<TrkType> trkTypes = new ArrayList<>();
TrkType trkType = route.getOrigin(TrkType.class);
if (trkType != null)
trkType.getTrkseg().clear();
else
trkType = objectFactory.createTrkType();
if (isWriteMetaData()) {
trkType.setName(asRouteName(route.getName()));
trkType.setDesc(asDescription(route.getDescription()));
clearDistance(trkType);
}
trkTypes.add(trkType);
TrksegType trksegType = objectFactory.createTrksegType();
List<GpxPosition> positions = route.getPositions();
for (int i = startIndex; i < endIndex; i++) {
GpxPosition position = positions.get(i);
WptType wptType = createWptType(position);
if (wptType != null)
trksegType.getTrkpt().add(wptType);
}
trkType.getTrkseg().add(trksegType);
return trkTypes;
}
private GpxType recycleGpxType(GpxRoute route) {
GpxType gpxType = route.getOrigin(GpxType.class);
if (gpxType != null) {
gpxType.getRte().clear();
gpxType.getTrk().clear();
gpxType.getWpt().clear();
}
return gpxType;
}
private MetadataType createMetaData(GpxRoute route, GpxType gpxType) {
ObjectFactory objectFactory = new ObjectFactory();
MetadataType metadataType = gpxType.getMetadata();
if (metadataType == null)
metadataType = objectFactory.createMetadataType();
if (isWriteMetaData()) {
metadataType.setName(asRouteName(route.getName()));
metadataType.setDesc(asDescription(route.getDescription()));
}
return metadataType;
}
private GpxType createGpxType(GpxRoute route, int startIndex, int endIndex) {
ObjectFactory objectFactory = new ObjectFactory();
GpxType gpxType = recycleGpxType(route);
if (gpxType == null)
gpxType = objectFactory.createGpxType();
gpxType.setCreator(GENERATED_BY);
gpxType.setVersion(VERSION);
if (route.getCharacteristics().equals(Waypoints))
gpxType.setMetadata(createMetaData(route, gpxType));
gpxType.getWpt().addAll(createWayPoints(route, startIndex, endIndex));
gpxType.getRte().addAll(createRoute(route, startIndex, endIndex));
gpxType.getTrk().addAll(createTrack(route, startIndex, endIndex));
return gpxType;
}
private GpxType createGpxType(List<GpxRoute> routes) {
ObjectFactory objectFactory = new ObjectFactory();
GpxType gpxType = null;
for (GpxRoute route : routes) {
gpxType = recycleGpxType(route);
if (gpxType != null)
break;
}
if (gpxType == null)
gpxType = objectFactory.createGpxType();
gpxType.setCreator(GENERATED_BY);
gpxType.setVersion(VERSION);
for (GpxRoute route : routes) {
switch (route.getCharacteristics()) {
case Waypoints:
gpxType.setMetadata(createMetaData(route, gpxType));
gpxType.getWpt().addAll(createWayPoints(route, 0, route.getPositionCount()));
break;
case Route:
gpxType.getRte().addAll(createRoute(route, 0, route.getPositionCount()));
break;
case Track:
gpxType.getTrk().addAll(createTrack(route, 0, route.getPositionCount()));
break;
default:
throw new IllegalArgumentException("Unknown RouteCharacteristics " + route.getCharacteristics());
}
}
return gpxType;
}
public void write(GpxRoute route, OutputStream target, int startIndex, int endIndex) {
try {
marshal11(createGpxType(route, startIndex, endIndex), target);
} catch (JAXBException e) {
throw new IllegalArgumentException(e);
}
}
public void write(List<GpxRoute> routes, OutputStream target) {
try {
marshal11(createGpxType(routes), target);
} catch (JAXBException e) {
throw new IllegalArgumentException(e);
}
}
}