// Created by plusminus on 18:06:19 - 07.11.2008
package org.androad.sys.ors.aas;
import java.util.ArrayList;
import org.osmdroid.util.BoundingBoxE6;
import org.osmdroid.util.GeoPoint;
import org.androad.sys.ors.adt.Error;
import org.androad.sys.ors.adt.aoi.Polygon;
import org.androad.sys.ors.exceptions.ORSException;
import org.androad.util.constants.Constants;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
/**
* Parses XML-Data like:
* <pre><?xml version="1.0" encoding="UTF-8"?>
* <aas:AAS xmlns:aas="http://www.geoinform.fh-mainz.de/aas" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" version="1.0" xsi:schemaLocation="http://www.geoinform.fh-mainz.de/aas D:/Schemata/AAS1.0/AccessibilityService.xsd">
* <aas:ResponseHeader xsi:type="aas:ResponseHeaderType"/>
* <aas:Response xsi:type="aas:ResponseType" requestID="123456789" version="1.0">
* <aas:AccessibilityResponse xsi:type="aas:AccessibilityResponseType">
* <aas:AccessibilitySummary>
* <aas:NumberOfLocations>0</aas:NumberOfLocations>
* <aas:BoundingBox srsName="EPSG:4326">
* <gml:pos>8.6450233 49.4681933</gml:pos>
* <gml:pos>8.6630108 49.4786068</gml:pos>
* </aas:BoundingBox>
* </aas:AccessibilitySummary>
* <aas:AccessibilityGeometry>
* <gml:Polygon srsName="EPSG:EPSG:4326">
* <gml:exterior>
* <gml:LinearRing xsi:type="gml:LinearRingType">
* <gml:pos>8.6506844 49.4682097</gml:pos>
* <gml:pos>8.6506481 49.4681933</gml:pos>
* ...
* <gml:pos>8.6506844 49.4682097</gml:pos>
* </gml:LinearRing>
* </gml:exterior>
* </gml:Polygon>
* <gml:Polygon srsName="EPSG:EPSG:4326">
* <gml:exterior>
* <gml:LinearRing xsi:type="gml:LinearRingType">
* <gml:pos>8.6570897 49.4783262</gml:pos>
* <gml:pos>8.6574036 49.4777484</gml:pos>
* ...
* <gml:pos>8.6570897 49.4783262</gml:pos>
* </gml:LinearRing>
* </gml:exterior>
* </gml:Polygon>
* ....</pre>
*
* @author Nicolas Gramlich
*
*/
public class AASParser extends DefaultHandler implements Constants {
// ====================================
// Constants
// ====================================
// ====================================
// Fields
// ====================================
private final StringBuilder sb = new StringBuilder();
private final ArrayList<Error> mErrors = new ArrayList<Error>();
private ArrayList<Polygon> mPolygons;
private Polygon mTmpPolygon;
private ArrayList<GeoPoint> mTmpLinearRing;
private AASResponse mAASResponse;
private GeoPoint mTmpGeoPoint;
private boolean inAAS = false;
private boolean inRepsonseHeader = false;
private boolean inRepsonse = false;
private boolean inAccessibilityResponse = false;
private boolean inAccessibilitySummary = false;
private boolean inNumberOfLocations = false;
private boolean inBoundingBox = false;
private boolean inPos = false;
private boolean inAccessibilityGeometry = false;
private boolean inPolygon = false;
private boolean inExterior = false;
private boolean inLinearRing = false;
private boolean inInterior = false;
// ===========================================================
// Getter & Setter
// ===========================================================
public ArrayList<Error> getErrors(){
return this.mErrors;
}
public AASResponse getASSResponse() throws ORSException{
if(this.mErrors != null && this.mErrors.size() > 0) {
throw new ORSException(this.mErrors);
}
return this.mAASResponse;
}
// ====================================
// Methods from Superclasses
// ====================================
@Override
public void startDocument() throws SAXException {
super.startDocument();
this.mAASResponse = new AASResponse();
}
@Override
public void startElement(final String uri, final String localName, final String name, final Attributes attributes) throws SAXException {
if(localName.equals("Error") || name.equals("Error")){
final String errorCode = attributes.getValue("", "errorCode");
final String severity = attributes.getValue("", "severity");
final String locationPath = attributes.getValue("", "locationPath");
final String message = attributes.getValue("", "message");
this.mErrors.add(new Error(errorCode, severity, locationPath, message));
}
this.sb.setLength(0);
if(localName.equals("AAS")){
this.inAAS = true;
} else if(localName.equals("ResponseHeader")){
this.inRepsonseHeader = true;
} else if(localName.equals("Response")){
this.inRepsonse = true;
} else if(localName.equals("AccessibilityResponse")){
this.inAccessibilityResponse = true;
} else if(localName.equals("AccessibilitySummary")){
this.inAccessibilitySummary = true;
} else if(localName.equals("NumberOfLocations")){
this.inNumberOfLocations = true;
} else if(localName.equals("BoundingBox")){
this.inBoundingBox = true;
} else if(localName.equals("AccessibilityGeometry")){
this.inAccessibilityGeometry = true;
this.mPolygons = new ArrayList<Polygon>();
this.mAASResponse.setPolygons(this.mPolygons);
} else if(localName.equals("pos")){
this.inPos = true;
} else if(localName.equals("Polygon")){
this.inPolygon = true;
this.mTmpPolygon = new Polygon();
this.mPolygons.add(this.mTmpPolygon);
} else if(localName.equals("exterior")){
this.inExterior = true;
} else if(localName.equals("LinearRing")){
this.inLinearRing = true;
this.mTmpLinearRing = new ArrayList<GeoPoint>();
if(this.inExterior){
this.mTmpPolygon.setExterior(this.mTmpLinearRing);
} else {
this.mTmpPolygon.addInterior(this.mTmpLinearRing);
}
} else if(localName.equals("interior")){
this.inInterior = true;
} else {
Log.w(DEBUGTAG, "Unexpected tag: '" + name + "'");
}
super.startElement(uri, localName, name, attributes);
}
@Override
public void characters(final char[] chars, final int start, final int length) throws SAXException {
this.sb.append(chars, start, length);
super.characters(chars, start, length);
}
@Override
public void endElement(final String uri, final String localName, final String name) throws SAXException {
if(localName.equals("AAS")){
this.inAAS = false;
} else if(localName.equals("ResponseHeader")){
this.inRepsonseHeader = false;
} else if(localName.equals("Response")){
this.inRepsonse = false;
} else if(localName.equals("AccessibilityResponse")){
this.inAccessibilityResponse = false;
} else if(localName.equals("AccessibilitySummary")){
this.inAccessibilitySummary = false;
} else if(localName.equals("NumberOfLocations")){
this.inNumberOfLocations = false;
} else if(localName.equals("BoundingBox")){
this.inBoundingBox = false;
} else if(localName.equals("AccessibilityGeometry")){
this.inAccessibilityGeometry = false;
} else if(localName.equals("pos")){
this.inPos = false;
final GeoPoint gp = GeoPoint.fromInvertedDoubleString(this.sb.toString(), ' ');
if(this.inAccessibilityGeometry){
this.mTmpLinearRing.add(gp);
} else if(this.inBoundingBox){
if(this.mTmpGeoPoint == null){ // First GeoPoint
this.mTmpGeoPoint = gp;
}else{ // Second one
final int mFirstLatE6 = this.mTmpGeoPoint.getLatitudeE6();
final int mFirstLonE6 = this.mTmpGeoPoint.getLongitudeE6();
this.mTmpGeoPoint = gp;
final int mSecondLatE6 = this.mTmpGeoPoint.getLatitudeE6();
final int mSecondLonE6 = this.mTmpGeoPoint.getLongitudeE6();
this.mAASResponse.setBoundingBoxE6(new BoundingBoxE6(Math.max(mFirstLatE6, mSecondLatE6),
Math.max(mFirstLonE6, mSecondLonE6),
Math.min(mFirstLatE6, mSecondLatE6),
Math.min(mFirstLonE6, mSecondLonE6)));
}
}
} else if(localName.equals("Polygon")){
this.inPolygon = false;
} else if(localName.equals("exterior")){
this.inExterior = false;
} else if(localName.equals("LinearRing")){
this.inLinearRing = false;
} else if(localName.equals("interior")){
this.inInterior = false;
} else {
Log.w(DEBUGTAG, "Unexpected end-tag: '" + name + "'");
}
// Reset the stringbuffer
this.sb.setLength(0);
super.endElement(uri, localName, name);
}
@Override
public void endDocument() throws SAXException {
if(this.mErrors == null || this.mErrors.size() == 0){
// Maybe do some finalization or similar...
}
super.endDocument();
}
}