// This software is released into the Public Domain. See copying.txt for details.
package org.openstreetmap.osmosis.xml.v0_6.impl;
import java.util.logging.Logger;
import org.openstreetmap.osmosis.core.OsmosisRuntimeException;
import org.openstreetmap.osmosis.core.task.v0_6.Sink;
import org.openstreetmap.osmosis.xml.common.ElementProcessor;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
/**
* This class is a SAX default handler for processing OSM XML files. It utilises
* a tree of element processors to extract the data from the xml structure.
*
* @author Brett Henderson
*/
public class OsmHandler extends DefaultHandler {
private static final Logger LOG = Logger.getLogger(OsmHandler.class.getName());
private static final String ELEMENT_NAME_OSM = "osm";
/**
* The root element processor used to process the osm element.
*/
private ElementProcessor osmElementProcessor;
/**
* The currently active element processor. This is updated whenever new xml
* elements are entered or exited.
*/
private ElementProcessor elementProcessor;
/**
* Provides location information about the current position in the file
* which is useful for reporting errors.
*/
private Locator documentLocator;
/**
* Creates a new instance.
*
* @param osmSink
* The new osmSink to write data to.
* @param enableDateParsing
* If true, dates will be parsed from xml data, else the current
* date will be used thus saving parsing time.
*/
public OsmHandler(Sink osmSink, boolean enableDateParsing) {
osmElementProcessor = new OsmElementProcessor(null, osmSink, enableDateParsing, true);
}
/**
* Begins processing of a new element.
*
* @param uri
* The uri.
* @param localName
* The localName.
* @param qName
* The qName.
* @param attributes
* The attributes.
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
// Get the appropriate element processor for the element.
if (elementProcessor != null) {
// We already have an active element processor, therefore use the
// active element processor to retrieve the appropriate child
// element processor.
elementProcessor = elementProcessor.getChild(uri, localName, qName);
} else if (ELEMENT_NAME_OSM.equals(qName)) {
// There is no active element processor which means we have
// encountered the root osm element.
elementProcessor = osmElementProcessor;
} else {
// There is no active element processor which means that this is a
// root element. The root element in this case does not match the
// expected name.
throw new OsmosisRuntimeException("This does not appear to be an OSM XML file.");
}
// Initialise the element processor with the attributes of the new element.
elementProcessor.begin(attributes);
}
/**
* Ends processing of the current element.
*
* @param uri
* The uri.
* @param localName
* The localName.
* @param qName
* The qName.
*/
@Override
public void endElement(String uri, String localName, String qName) {
// Tell the currently active element processor to complete its processing.
elementProcessor.end();
// Set the active element processor to the parent of the existing processor.
elementProcessor = elementProcessor.getParent();
}
/**
* Sets the document locator which is used to report the position in the
* file when errors occur.
*
* @param documentLocator
* The document locator.
*/
@Override
public void setDocumentLocator(Locator documentLocator) {
this.documentLocator = documentLocator;
}
/**
* Called by the SAX parser when an error occurs. Used by this class to
* report the current position in the file.
*
* @param e
* The exception that occurred.
* @throws SAXException
* if the error reporting throws an exception.
*/
@Override
public void error(SAXParseException e) throws SAXException {
LOG.severe(
"Unable to parse xml file. publicId=(" + documentLocator.getPublicId()
+ "), systemId=(" + documentLocator.getSystemId()
+ "), lineNumber=" + documentLocator.getLineNumber()
+ ", columnNumber=" + documentLocator.getColumnNumber() + ".");
super.error(e);
}
}