// PlatformLatLongDataProvider.java
package org.eclipse.stem.definitions.adapters.spatial.geo;

/*******************************************************************************
 * Copyright (c) 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Preferences;
import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
import org.eclipse.core.runtime.Preferences.PropertyChangeEvent;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.URIConverterImpl;
import org.eclipse.stem.definitions.Activator;
import org.eclipse.stem.definitions.adapters.spatial.geo.LatLong.SegmentBuilder;
import org.eclipse.stem.definitions.adapters.spatial.geo.preferences.PreferenceConstants;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * This class interprets a URI that specifies a file of (i.e., "platform")
 * lat/long data in some format (currently <a
 * href="http://www.opengis.net/gml/">GML</a>).
 * 
 * @see InlineLatLongDataProvider
 * @see LatLongProviderAdapter
 */
@SuppressWarnings("deprecation")
public class PlatformLatLongDataProvider implements LatLongDataProvider {
	/**
	 * The class name of the first SAX XML parser to attempt to create if the
	 * default cannot be found. Value:
	 * <code>org.apache.xerces.parsers.SAXParser</code>
	 */
	public static final String SAX_PARSER1 = "org.apache.xerces.parsers.SAXParser";

	/**
	 * The class name of the second SAX XML parser to attempt to create if the
	 * default cannot be found. Value:
	 * <code>org.apache.crimson.parser.XMLReaderImpl</code>
	 */
	public static final String SAX_PARSER2 = "org.apache.crimson.parser.XMLReaderImpl";

	/**
	 * This set of nested Maps implements a cache for latitude/longitude data
	 * read in. The key of the first map is the URI of the file containing the
	 * data. The key of the second map is the identifier that is the fragment of
	 * the original query URI. If the first map does not contain an entry for a
	 * specified file, then one is created and populated with the contents of
	 * the file.
	 */
	static Map<URI, Map<String, LatLong>> cache = new ConcurrentHashMap<URI, Map<String, LatLong>>();

	/**
	 * This is the scheme for a "platform" data URI that specifies a file that
	 * contains lat/long data.
	 */
	public static final String PLATFORM_SCHEME = "platform";

	/**
	 * This is the name of the folder that contains the normal resolution GML
	 * files.
	 */
	private static final CharSequence NORMAL_RES_FOLDER = "country";

	/**
	 * This is the name of the folder that contains the lower resolution GML
	 * files
	 */
	private static final CharSequence LOW_RES_FOLDER = "country_reduced";

	/**
	 * If <code>true</code> then the latitude/longitude points will be sampled
	 * and some will be discarded to reduce their number.
	 */
	public boolean isSampling = false;

	/**
	 * This is the frequency at which the latitude/longitude data points will be
	 * sampled. A value of "1" means every point will be included, a value of
	 * "2" means that every 2nd point will be included. The first and last data
	 * points are always included.
	 */
	public int sampleFrequency = 1;

	/**
	 * If <code>true</code> then I/O Exceptions are logged, otherwise they are
	 * ignored.
	 */
	public boolean reportIOExceptions = true;

	/**
	 * If <code>true</code> then the path to the GML file will be modified to
	 * point to a smaller GML file that has a lower resolution.
	 */
	public boolean useLowerResolutionLatLongData = false;

	/**
	 * Constructor
	 */
	public PlatformLatLongDataProvider() {
		super();
		setPreferences();

		Activator.getDefault().getPluginPreferences()
				.addPropertyChangeListener(new IPropertyChangeListener() {
					public void propertyChange(final PropertyChangeEvent event) {
						setPreferences();
						// Flush everything in the cache to force it to be read
						// again from the gml file and re-sampled
						cache = new ConcurrentHashMap<URI, Map<String, LatLong>>();
					} // propertyChange
				} // IPropertyChangeListener
				);

	} // PlatformLatLongDataProvider

	
	public void flush()
	{
		cache = new ConcurrentHashMap<URI, Map<String, LatLong>>();
	}

	
	
	/**
	 * @param latlongFileURI
	 * @return the lat/long values
	 */
	public LatLong getLatLong(final URI latlongFileURI) {
		LatLong retValue = null;

		// The URI should have an ID as the fragment that specifies the
		// latitude/longitude data in the GML file.

		// Is there an entry for our key?
		retValue = getLatLongMap(latlongFileURI.trimFragment()).get(
				latlongFileURI.fragment());

		//retValue = retValue != null ? retValue : new LatLong();
		return retValue;
	} // getLatLong

	/**
	 * This method is just like {@link #getLatLong(URI)} except that it will
	 * immediately return an "empty" LatLong instance if the data for the URI
	 * has not been retrieved. It will also start a separate job to retrieve
	 * that data and will return it when that job completes successfully.
	 * 
	 * @param latlongFileURI
	 * @return the lat/long values
	 */
	public LatLong getLatLongNoWait(final URI latlongFileURI) {
		LatLong retValue = null;

		// The URI should have an ID as the fragment that specifies the
		// latitude/longitude data in the GML file.

		// Is there an entry for our key?
		retValue = getLatLongMapNoWait(latlongFileURI.trimFragment()).get(
				latlongFileURI.fragment());

		retValue = retValue != null ? retValue : new LatLong();
		return retValue;
	} // getLatLong

	/**
	 * @param fileURI
	 *            the uri of a file of latitude/longitude data
	 * @return the identifiers of the latitude/longitude data in the file
	 */
	public Set<String> getIds(final URI fileURI) {
		return getLatLongMap(fileURI).keySet();
	} // getIds

	/**
	 * This method is just like {@link #getIds(URI)} except that it will return
	 * an empty set if the data referenced by the URI has not been read yet. It
	 * will then cause a separate job to start that will read that data. A
	 * subsequent call, after that job completes successfully, would return a
	 * set of ids.
	 * 
	 * @param fileURI
	 *            the uri of a file of latitude/longitude data
	 * @return the identifiers of the latitude/longitude data in the file
	 */
	public Set<String> getIdsNoWait(final URI fileURI) {
		return getLatLongMapNoWait(fileURI).keySet();
	} // getIds

	/**
	 * @param fileURI
	 *            the uri of a file of latitude/longitude data
	 * @return the map between id's and data values for that file.
	 */
	private Map<String, LatLong> getLatLongMap(final URI fileURI) {
		// Have we processed this file before?
		Map<String, LatLong> latLongMap = cache.get(fileURI);
		if (latLongMap == null) {
			// No
			// We need to read the contents of the file and populate the entry
			latLongMap = createLatLongMap(fileURI);
			cache.put(fileURI, latLongMap);
		}
		return latLongMap;
	} // getLatLongMap

	/**
	 * This method is the same as {@link #getLatLongMap(URI)}, except that it
	 * immediately returns an instance of the lat/long map. This map will be
	 * empty if this is the first time a request has been made for it. In that
	 * case a separate Job (i.e., thread) is scheduled to read and populate the
	 * map from a GML file. When that is finished, the empty map is replaced by
	 * the populated one so that the next call will return the populated map.
	 * 
	 * @param fileURI
	 *            the uri of a file of latitude/longitude data
	 * @return the map between id's and data values for that file.
	 */
	synchronized private Map<String, LatLong> getLatLongMapNoWait(
			final URI fileURI) {
		// Have we processed this file before?
		Map<String, LatLong> latLongMap = cache.get(fileURI);
		if (latLongMap == null) {
			// No
			// We need to put an empty map into the cache so that the next call
			// doesn't try to start up another job to read in the file.
			latLongMap = new ConcurrentHashMap<String, LatLong>();
			cache.put(fileURI, latLongMap);

			// Now down to business, we create a separate job to read in the
			// lat/long data from the GML file and populate the map.
			final Job readGMLJob = new Job(fileURI.toString()) {
				/**
				 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
				 */
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					monitor.beginTask(fileURI.toString(), 100);
					// We need to read the contents of the file and populate the
					// entry
					final Map<String, LatLong> latLongMap = createLatLongMap(fileURI);
					// Replace the empty map with this one.
					cache.put(fileURI, latLongMap);
					monitor.done();
					return new Status(IStatus.OK, Activator.PLUGIN_ID,
							IStatus.OK, "Done", null);
				} // run
			}; // readGMLJob
			readGMLJob.schedule();
		} // if no lat/long map

		return latLongMap;
	} // getLatLongMap

	Map<String, LatLong> createLatLongMap(final URI fileURI) {
		final Map<String, LatLong> latLongMap = new ConcurrentHashMap<String, LatLong>();
		final URIConverter converter = new URIConverterImpl();
		final GMLDecoder gMLDecoder = new GMLDecoder(latLongMap);
		try {
			final InputStream is = converter
					.createInputStream(adjustFilePath(fileURI));
			final BufferedReader in = new BufferedReader(new InputStreamReader(
					is));
			parseInputStream(in, gMLDecoder);
		} // try
		catch (final IOException e) {
			// It could be that we tried to get a low resolution version of the
			// file and it wasn't found. So let's try getting the regular
			// resolution
			// Are we getting low resolution files?
			if (useLowerResolutionLatLongData) {
				// Yes
				try {
					// Try again without adjusting the file path
					final InputStream is = converter.createInputStream(fileURI);
					final BufferedReader in = new BufferedReader(
							new InputStreamReader(is));
					parseInputStream(in, gMLDecoder);
				} catch (final FileNotFoundException fnfe) {
					// Should we report the missing file?
					if (reportIOExceptions) {
						// Yes
						Activator.logInformation(fnfe.getMessage(), fnfe);
					}
				} // catch FileNotFoundException
				catch (final IOException e2) {
					// Should we report the error?
					if (reportIOExceptions) {
						// Yes
						Activator.logError(e2.getMessage(), e2);
					}
				} // catch IOException
			} // if using low resolution
			// Should we report the error?
			else if (reportIOExceptions) {
				// Yes
				Activator.logError(e.getMessage(), e);
			}
		} // catch

		return latLongMap;
	} // createLatLongMap

	/**
	 * This method determines if it should modify the path to the GML file so
	 * that a different file is selected. Typically, this is to switch to a
	 * lower resolution GML file.
	 * 
	 * @param fileURI
	 *            the original URI
	 * @return the adjusted URI
	 */
	private URI adjustFilePath(final URI fileURI) {
		URI retValue = fileURI;

		// Should we use a lower resolution version of the file?
		if (useLowerResolutionLatLongData) {
			// Yes
			final String adjustedPath = fileURI.toString().replace(
					NORMAL_RES_FOLDER, LOW_RES_FOLDER);
			retValue = URI.createURI(adjustedPath);
		}

		return retValue;
	} // adjustFilePath

	/**
	 * Set the preferences.
	 * 
	 * @see #isSampling
	 * @see #sampleFrequency
	 */
	private void setPreferences() {
		final Preferences preferences = Activator.getDefault()
				.getPluginPreferences();
		if(preferences !=null) {
			isSampling = preferences.getBoolean(PreferenceConstants.DOWN_SAMPLE_LAT_LONG_DATA_BOOLEAN_PREFERENCE);
			sampleFrequency = preferences.getInt(PreferenceConstants.LAT_LONG_SAMPLE_FREQUENCY_INTEGER_PREFERENCE);
			reportIOExceptions = preferences.getBoolean(PreferenceConstants.REPORT_IO_EXCEPTIONS_BOOLEAN_PREFERENCE);
			useLowerResolutionLatLongData = preferences.getBoolean(PreferenceConstants.USE_LOWER_RESOLUTION_LAT_LONG_DATA_BOOLEAN_PREFERENCE);
		}
		
	} // setPerferences

	/**
	 * Try to create a SAX Parser. The method first attempts to create the
	 * default parser. The class name of this parser is assigned to the property
	 * "org.xml.sax.driver". This value is defined on the command line that
	 * starts the Java interpreter
	 * <code>java -Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser</code>
	 * If it is not successful in finding this parser, it will attempt to create
	 * an instance of <code>org.apache.xerces.parsers.SAXParser</code>, if
	 * that fails, it will try the parser
	 * <code>"org.apache.crimson.parser.XMLReaderImpl</code>. If that fails,
	 * it will throw a <code>SimulationException</code> reporting the
	 * inability to create a SAX XML Parser.
	 * 
	 * @return a SAXParser
	 */
	public static XMLReader getSAXParser() {

		XMLReader retValue = null;
		try {
			// Try to make the default SAX Parser
			retValue = XMLReaderFactory.createXMLReader();

		} // try
		catch (final SAXException saxe) {
			// Try specific parsers
			try { // SAX_PARSER1
				retValue = XMLReaderFactory.createXMLReader(SAX_PARSER1);
			} // try SAX_PARSER1
			catch (final SAXException saxe1) {
				try { // try SAX_PARSER2
					retValue = XMLReaderFactory.createXMLReader(SAX_PARSER2);
				} // try SAX_PARSER2
				catch (final SAXException saxe2) {
					Activator.logError(saxe2.getMessage(), saxe2);
				} // catch SAX_PARSER2
			} // catch SAX_PARSER1
		} // catch default

		return retValue;
	} // getSAXParser()

	/**
	 * Parse the specified input character stream using the
	 * 
	 * specified Handler. Where the output is stored depends on the handler
	 * 
	 * @param in
	 *            BufferedReader to read the XML from.
	 * @param handler
	 *            The class that will handle the parsing
	 */
	public static void parseInputStream(final BufferedReader in,
			final DefaultHandler handler) {
		try {
			final XMLReader saxParser = getSAXParser();
			saxParser.setContentHandler(handler);
			saxParser.parse(new InputSource(in));
			in.close();
		} catch (final IOException e) {
			Activator.logError(e.getMessage(), e);
		} catch (final SAXException e) {
			Activator.logError(e.getMessage(), e);
		}
	} // parseInputStream

	/**
	 * This class is a SAX Handler used to process the contents of a GML file
	 * specifying latitude/longitude data.
	 */
	public class GMLDecoder extends DefaultHandler {

		// XML element name
		private static final String XML_MAP_ELEMENT_NAME = "Map";

		private static final String XML_TITLE_ELEMENT_NAME = "title";

		private static final String XML_SUBTITLE_ELEMENT_NAME = "subTitle";

		private static final String XML_UPDATED_ELEMENT_NAME = "updated";

		private static final String XML_ENTRY_ELEMENT_NAME = "entry";

		private static final String XML_WHERE_ELEMENT_NAME = "where";

		private static final String XML_OUTER_BOUNDARY_ELEMENT_NAME = "outerBoundaryIs";

		private static final String XML_LINEAR_RING_ELEMENT_NAME = "LinearRing";

		private static final String XML_POLYGON_ELEMENT_NAME = "Polygon";

		private static final String XML_POSLIST_ELEMENT_NAME = "posList";

		private static final String XML_ID_ATTR = "gml:id";

		/**
		 * This is the title parsed from the file
		 */
		private String title = "";

		/**
		 * This is the sub-title parsed from the file;
		 */
		// We're ignoring subtitles right now
		// private String subTitle = "";
		/**
		 * This is the date the file was updated as parsed from the file;
		 */
		// We're ignoring updated right now
		// private String updated = "";
		/**
		 * This is the identifier of the current polygon being parsed
		 */
		private String currentPolygonId = null;

		// Parse position in the document being parsed
		private Locator locator = null;

		/**
		 * The map that is constructed during the processing of the GML file.
		 */
		Map<String, LatLong> latLongMap = null;

		/**
		 * This is the collection of
		 * {@link org.eclipse.stem.definitions.adapters.spatial.geo.LatLong.Segment}'s
		 * collected for a polygon.
		 */
		private LatLong polygonLatLong = null;

		/**
		 * This segment builder is used to collect together related
		 * latitude/longitude data pairs to create a
		 * {@link org.eclipse.stem.definitions.adapters.spatial.geo.LatLong.Segment}
		 */
		private LatLong.SegmentBuilder segmentBuilder = null;

		/**
		 * These are the characters that have been collected but are not yet
		 * complete.
		 */
		private StringBuilder characterStringBuilder = new StringBuilder();

		/**
		 * Constructor
		 */
		protected GMLDecoder(final Map<String, LatLong> latLongMap) {
			super();
			this.latLongMap = latLongMap;
		} // GMLDecoder

		/**
		 * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
		 *      java.lang.String, java.lang.String, org.xml.sax.Attributes)
		 */
		@Override
		public void startElement(final String namespace, final String sName, final String qName,
				final Attributes attributes) throws SAXException {
			// The name of the element
			final String elementName = sName.equals("") ? qName : sName;

			// The "Map" root element?
			if (elementName.equalsIgnoreCase(XML_MAP_ELEMENT_NAME)) {
				// Yes
				assert latLongMap != null;
			} // else if Map

			// A title element?
			else if (elementName.equalsIgnoreCase(XML_TITLE_ELEMENT_NAME)) {
				// Yes
				characterStringBuilder = new StringBuilder();
			} // title

			// subTitle element?
			else if (elementName.equalsIgnoreCase(XML_SUBTITLE_ELEMENT_NAME)) {
				// Yes
				characterStringBuilder = new StringBuilder();
			} // subTitle

			// updated element?
			else if (elementName.equalsIgnoreCase(XML_UPDATED_ELEMENT_NAME)) {
				// Yes
				characterStringBuilder = new StringBuilder();
			} // updated

			// entry element?
			else if (elementName.equalsIgnoreCase(XML_ENTRY_ELEMENT_NAME)) {
				// Yes
			} // updated

			// where element?
			else if (elementName.equalsIgnoreCase(XML_WHERE_ELEMENT_NAME)) {
				// Yes
			} // where

			// outerBoundaryIs element?
			else if (elementName
					.equalsIgnoreCase(XML_OUTER_BOUNDARY_ELEMENT_NAME)) {
				// Yes
			} // outerBoundaryIs

			// linearRing element?
			else if (elementName.equalsIgnoreCase(XML_LINEAR_RING_ELEMENT_NAME)) {
				// Yes
			} // linearRing

			// polygon element?
			else if (elementName.equalsIgnoreCase(XML_POLYGON_ELEMENT_NAME)) {
				// Yes
				assert currentPolygonId == null;
				assert polygonLatLong == null;
				currentPolygonId = attributes.getValue(XML_ID_ATTR);
				polygonLatLong = new LatLong();
			} // polygon

			// posList element?
			else if (elementName.equalsIgnoreCase(XML_POSLIST_ELEMENT_NAME)) {
				// Yes
				assert segmentBuilder == null;
				segmentBuilder = new SegmentBuilder();
				characterStringBuilder = new StringBuilder();
			} // posList

			else {
				// No
				// We have no idea what this element is
				throw new SAXParseException("Invalid element name \""
						+ elementName + "\"", locator);
			} // else unrecognized element name
		} // startElement

		/**
		 * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
		 *      java.lang.String, java.lang.String)
		 */
		@Override
		public void endElement(final String namespace, final String sName, final String qName)
				throws SAXException {
			// The name of the element
			final String elementName = sName.equals("") ? qName : sName;

			// The "Map" root element?
			if (elementName.equalsIgnoreCase(XML_MAP_ELEMENT_NAME)) {
				// Yes
				assert latLongMap != null;
			} // else if Map

			// A title element?
			else if (elementName.equalsIgnoreCase(XML_TITLE_ELEMENT_NAME)) {
				// Yes
				title = characterStringBuilder.toString();
				characterStringBuilder = new StringBuilder();
			} // title

			// subTitle element?
			else if (elementName.equalsIgnoreCase(XML_SUBTITLE_ELEMENT_NAME)) {
				// Yes
				// We're ignoring subtitles right now
				// subTitle = characterStringBuilder.toString();
				characterStringBuilder = new StringBuilder();
			} // subTitle

			// updated element?
			else if (elementName.equalsIgnoreCase(XML_UPDATED_ELEMENT_NAME)) {
				// Yes
				// updated = characterStringBuilder.toString();
				characterStringBuilder = new StringBuilder();
			} // updated

			// entry element?
			else if (elementName.equalsIgnoreCase(XML_ENTRY_ELEMENT_NAME)) {
				// Yes
			} // entry

			// where element?
			else if (elementName.equalsIgnoreCase(XML_WHERE_ELEMENT_NAME)) {
				// Yes
			} // where

			// outerBoundaryIs element?
			else if (elementName
					.equalsIgnoreCase(XML_OUTER_BOUNDARY_ELEMENT_NAME)) {
				// Yes
			} // outerBoundaryIs

			// linearRing element?
			else if (elementName.equalsIgnoreCase(XML_LINEAR_RING_ELEMENT_NAME)) {
				// Yes
			} // linearRing

			// polygon element?
			else if (elementName.equalsIgnoreCase(XML_POLYGON_ELEMENT_NAME)) {
				// Yes
				latLongMap.put(currentPolygonId, polygonLatLong);
				currentPolygonId = null;
				polygonLatLong = null;
			} // polygon

			// posList element?
			else if (elementName.equalsIgnoreCase(XML_POSLIST_ELEMENT_NAME)) {
				// Yes
				// Parse the current characters for the latitude/longitude data
				// pairs

				final StringTokenizer st = new StringTokenizer(
						characterStringBuilder.toString(), " \n");
				characterStringBuilder = new StringBuilder();

				while (st.hasMoreTokens()) {
					final String value1 = st.nextToken();
					// Is there a matching Longitude?
					if (st.hasMoreTokens()) {
						// Yes
						// Lat
						final String value2 = st.nextToken();
						segmentBuilder.add(value1, value2);
					} else {
						// No
						// lat/long mismatch
						Activator
								.logError(
										"Latitude/Longitude data titled \""
												+ title
												+ "\" is missing a longitude  match for the latitude value \""
												+ value1 + "\" at line: "
												+ locator.getLineNumber()
												+ ", column: "
												+ locator.getColumnNumber(),
										null);
						// discard whatever we've collected so far
						segmentBuilder.clear();
						break;
					} // else
				} // while more tokens

				// Anything in the segment?
				if (segmentBuilder.size() > 0) {
					// Yes
					try {
						polygonLatLong.add(isSampling ? segmentBuilder
								.toSegment(sampleFrequency) : segmentBuilder
								.toSegment());
					} catch (IllegalArgumentException iae) {
						Activator.logError(
								"Problem processing Latitude/Longitude data titled \""
										+ title + "\"", iae);
					}
				} // if
				segmentBuilder = null;
			} // posList
			else {
				// No
				// We have no idea what this element is
				throw new SAXParseException("Invalid element name \""
						+ elementName + "\"", locator);
			} // else unrecognized element name
		} // endElement

		/**
		 * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
		 */
		@Override
		public void characters(final char[] ch, final int start,
				final int length) {
			characterStringBuilder.append(new String(ch, start, length));
		} // characters

		/**
		 * @see org.xml.sax.helpers.DefaultHandler#warning(org.xml.sax.SAXParseException)
		 */
		@Override
		public void warning(final SAXParseException spe) {
			Activator.logInformation(spe.getMessage(), spe);
		} // warning

		/**
		 * @see org.xml.sax.helpers.DefaultHandler#error(org.xml.sax.SAXParseException)
		 */
		@Override
		public void error(final SAXParseException spe) {
			Activator.logError(spe.getMessage(), spe);
		} // error

		/**
		 * @see org.xml.sax.helpers.DefaultHandler#fatalError(org.xml.sax.SAXParseException)
		 */
		@Override
		public void fatalError(final SAXParseException spe) {
			Activator.logError(spe.getMessage(), spe);
		} // fatalError

		/**
		 * @see org.xml.sax.helpers.DefaultHandler#setDocumentLocator(org.xml.sax.Locator)
		 */
		@Override
		public void setDocumentLocator(final Locator locator) {
			this.locator = locator;
		} // setDocumentLocator

	} // GMLDecoder

} // PlatformLatLongDataProvider
