in endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/gpx/Reader.java [145:247]
public Version initialize(final boolean readMetadata) throws DataStoreException,
XMLStreamException, JAXBException, URISyntaxException, EOFException
{
/*
* Skip comments, characters, entity declarations, etc. until we find the root element.
* If that root is anything other than <gpx>, we consider that this is not a GPX file.
*/
moveToRootElement(Reader::isGPX, Tags.GPX);
/*
* If a version attribute is found on the <gpx> element, use that value for detecting the GPX version.
* If a version is specified, we require major.minor version 1.0 or 1.1 but accept any bug-fix versions
* (e.g. 1.1.x). If no version attribute was found, try to infer the version from the namespace URL.
*/
namespace = reader.getNamespaceURI();
String ver = reader.getAttributeValue(null, Attributes.VERSION);
Version version = null;
if (ver != null) {
version = new Version(ver);
if (version.compareTo(StoreProvider.V1_0, 2) < 0 ||
version.compareTo(StoreProvider.V1_1, 2) > 0)
{
throw new DataStoreContentException(errors().getString(
Errors.Keys.UnsupportedFormatVersion_2, owner.getFormatName(), version));
}
} else if (namespace != null) {
switch (namespace) {
case Tags.NAMESPACE_V10: version = StoreProvider.V1_0; break;
case Tags.NAMESPACE_V11: version = StoreProvider.V1_1; break;
}
}
/*
* Read metadata immediately, from current position until the beginning of way points, tracks or routes.
* The metadata can appear in two forms:
*
* - In GPX 1.0, they are declared directly in the <gpx> body.
* Those elements are parsed in the switch statement below.
*
* - In GPX 1.1, they are declared in a <metadata> sub-element and their structure is a little bit
* more elaborated than what it was in the previous version. We will use JAXB for parsing them.
*/
parse: while (reader.hasNext()) {
switch (next()) {
case START_ELEMENT: {
/*
* GPX 1.0 and 1.1 metadata should not be mixed. However, the following code will work even
* if GPX 1.0 metadata like <name> or <author> appear after the GPX 1.1 <metadata> element.
* If both kind of metadata are specified, the latest value overwrites the values before it.
*/
if (isGPX()) {
final String name = reader.getLocalName();
if (readMetadata) {
switch (name) {
// GPX 1.1 metadata
case Tags.METADATA: metadata = unmarshal(Metadata.class); break;
// GPX 1.0 metadata
case Tags.NAME: metadata().name = getElementText(); break;
case Tags.DESCRIPTION: metadata().description = getElementText(); break;
case Tags.AUTHOR: author() .name = getElementText(); break;
case Tags.EMAIL: author() .email = getElementText(); break;
case Tags.URL: link() .uri = getElementAsURI(); break;
case Tags.URL_NAME: link() .text = getElementText(); break;
case Tags.TIME: metadata().time = getElementAsDate(); break;
case Tags.KEYWORDS: metadata().keywords = getElementAsList(); break;
case Tags.BOUNDS: metadata().bounds = unmarshal(Bounds.class); break;
case Tags.WAY_POINT: // stop metadata parsing.
case Tags.TRACKS:
case Tags.ROUTES: break parse;
case Tags.GPX: throw new DataStoreContentException(nestedElement(Tags.GPX));
}
} else {
/*
* If the caller asked to skip metadata, just look for the end of metadata elements.
*/
switch (name) {
case Tags.METADATA: skipUntilEnd(reader.getName()); break;
case Tags.WAY_POINT:
case Tags.TRACKS:
case Tags.ROUTES: break parse;
case Tags.GPX: throw new DataStoreContentException(nestedElement(Tags.GPX));
}
}
}
break;
}
case END_ELEMENT: {
/*
* Reminder: calling next() after getElementText(), getElementAsFoo() and unmarshal(…) methods
* moves the reader after the END_ELEMENT event. Consequently, there is only the enclosing <gpx>
* tag to check here.
*/
if (isEndGPX()) {
break parse;
}
break;
}
}
}
if (readMetadata) {
metadata().store = (Store) owner;
}
return version;
}