/** * Copyright (C) 2014 Cohesive Integrations, LLC (info@cohesiveintegrations.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. The ASF licenses this file to You * under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. For additional information regarding * copyright in this work, please see the NOTICE file in the top level * directory of this distribution. */ package net.di2e.ecdr.search.transform.atom.geo; import org.apache.abdera.ext.geo.Box; import org.apache.abdera.ext.geo.Coordinate; import org.apache.abdera.ext.geo.Line; import org.apache.abdera.ext.geo.Multiple; import org.apache.abdera.ext.geo.Point; import org.apache.abdera.ext.geo.Polygon; import org.apache.abdera.ext.geo.Position; import org.apache.abdera.model.Element; import org.apache.abdera.model.ExtensibleElement; import org.apache.abdera.util.Constants; import javax.xml.namespace.QName; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public final class GeoHelper { public static final String W3C_GEO_NS = "http://www.w3.org/2003/01/geo/wgs84_pos#"; public static final String SIMPLE_GEO_NS = "http://www.georss.org/georss"; public static final String GML_NS = "http://www.opengis.net/gml"; public static final QName QNAME_W3C_POINT = new QName(W3C_GEO_NS, "Point", "geo"); public static final QName QNAME_W3C_LAT = new QName(W3C_GEO_NS, "lat", "geo"); public static final QName QNAME_W3C_LONG = new QName(W3C_GEO_NS, "long", "geo"); public static final QName QNAME_SIMPLE_POINT = new QName(SIMPLE_GEO_NS, "point", "georss"); public static final QName QNAME_SIMPLE_LINE = new QName(SIMPLE_GEO_NS, "line", "georss"); public static final QName QNAME_SIMPLE_POLYGON = new QName(SIMPLE_GEO_NS, "polygon", "georss"); public static final QName QNAME_SIMPLE_BOX = new QName(SIMPLE_GEO_NS, "box", "georss"); public static final QName QNAME_WHERE = new QName(SIMPLE_GEO_NS, "where", "georss"); public static final QName QNAME_GML_POINT = new QName(GML_NS, "Point", "gml"); public static final QName QNAME_GML_POS = new QName(GML_NS, "pos", "gml"); public static final QName QNAME_GML_LINESTRING = new QName(GML_NS, "LineString", "gml"); public static final QName QNAME_GML_POSLIST = new QName(GML_NS, "posList", "gml"); public static final QName QNAME_GML_POLYGON = new QName(GML_NS, "Polygon", "gml"); public static final QName QNAME_GML_EXTERIOR = new QName(GML_NS, "exterior", "gml"); public static final QName QNAME_GML_LINEARRING = new QName(GML_NS, "LinearRing", "gml"); public static final QName QNAME_GML_ENVELOPE = new QName(GML_NS, "Envelope", "gml"); public static final QName QNAME_GML_LOWERCORNER = new QName(GML_NS, "lowerCorner", "gml"); public static final QName QNAME_GML_UPPERCORNER = new QName(GML_NS, "upperCorner", "gml"); private GeoHelper() { } public enum Encoding { SIMPLE, W3C, GML } public static void addPosition(ExtensibleElement element, Position position) { addPosition(element, position, Encoding.SIMPLE); } public static void addPosition(ExtensibleElement element, Position position, Encoding encoding) { switch (encoding) { default: break; case SIMPLE: addSimplePosition(element, position); break; case GML: addGmlPosition(element, position); break; case W3C: addW3CPosition(element, position); break; } } private static void setPositionAttributes(Element pos, Position position) { if (pos != null) { if (position.getFeatureTypeTag() != null) { pos.setAttributeValue("featuretypetag", position.getFeatureTypeTag()); } if (position.getRelationshipTag() != null) { pos.setAttributeValue("relationshiptag", position.getRelationshipTag()); } if (position.getElevation() != null) { pos.setAttributeValue("elev", position.getElevation().toString()); } if (position.getFloor() != null) { pos.setAttributeValue("floor", position.getFloor().toString()); } if (position.getRadius() != null) { pos.setAttributeValue("radius", position.getRadius().toString()); } } } private static void addGmlPosition(ExtensibleElement element, Position position) { ExtensibleElement pos = element.addExtension(QNAME_WHERE); if (position instanceof Point) { Point point = (Point) position; ExtensibleElement p = pos.addExtension(QNAME_GML_POINT); p.addSimpleExtension(QNAME_GML_POS, point.getCoordinate().toString()); } else if (position instanceof Line) { Multiple m = (Multiple) position; ExtensibleElement p = pos.addExtension(QNAME_GML_LINESTRING); p.addSimpleExtension(QNAME_GML_POSLIST, m.getCoordinates().toString()); } else if (position instanceof Polygon) { Multiple m = (Multiple) position; ExtensibleElement p = pos.addExtension(QNAME_GML_POLYGON); p = p.addExtension(QNAME_GML_EXTERIOR); p = p.addExtension(QNAME_GML_LINEARRING); p.addSimpleExtension(QNAME_GML_POSLIST, m.getCoordinates().toString()); } else if (position instanceof Box) { Box m = (Box) position; ExtensibleElement p = pos.addExtension(QNAME_GML_ENVELOPE); if (m.getLowerCorner() != null) { p.addSimpleExtension(QNAME_GML_LOWERCORNER, m.getLowerCorner().toString()); } if (m.getUpperCorner() != null) { p.addSimpleExtension(QNAME_GML_UPPERCORNER, m.getUpperCorner().toString()); } } setPositionAttributes(pos, position); } private static void addSimplePosition(ExtensibleElement element, Position position) { Element pos = null; if (position instanceof Point) { Point point = (Point) position; pos = element.addSimpleExtension(QNAME_SIMPLE_POINT, point.getCoordinate().toString()); } else if (position instanceof Multiple) { Multiple line = (Multiple) position; QName qname = position instanceof Line ? QNAME_SIMPLE_LINE : position instanceof Box ? QNAME_SIMPLE_BOX : position instanceof Polygon ? QNAME_SIMPLE_POLYGON : null; if (qname != null) { pos = element.addSimpleExtension(qname, line.getCoordinates().toString()); } } setPositionAttributes(pos, position); } private static void addW3CPosition(ExtensibleElement element, Position position) { if (!(position instanceof Point)) { throw new IllegalArgumentException("The W3C Encoding only supports Points"); } Element el = element.getExtension(QNAME_W3C_LAT); if (el != null) { el.discard(); } el = element.getExtension(QNAME_W3C_LONG); if (el != null) { el.discard(); } Point point = (Point) position; ExtensibleElement p = element.addExtension(QNAME_W3C_POINT); p.addSimpleExtension(QNAME_W3C_LAT, Double.toString(point.getCoordinate().getLatitude())); p.addSimpleExtension(QNAME_W3C_LONG, Double.toString(point.getCoordinate().getLongitude())); } private static List<Position> getPositionsList(ExtensibleElement element) { List<Position> list = new ArrayList<Position>(); getW3CPosition(element, list); getSimplePosition(element, list); getGMLPosition(element, list); return list; } public static boolean isGeotagged(ExtensibleElement element) { if (element.getExtensions(QNAME_SIMPLE_POINT).size() > 0) { return true; } if (element.getExtensions(QNAME_SIMPLE_LINE).size() > 0) { return true; } if (element.getExtensions(QNAME_SIMPLE_BOX).size() > 0) { return true; } if (element.getExtensions(QNAME_SIMPLE_POLYGON).size() > 0) { return true; } if (element.getExtensions(QNAME_WHERE).size() > 0) { return true; } if (element.getExtensions(QNAME_W3C_POINT).size() > 0) { return true; } if (element.getExtensions(QNAME_W3C_LAT).size() > 0 && element.getExtensions(QNAME_W3C_LONG).size() > 0) { return true; } return false; } public static Iterator<Position> listPositions(ExtensibleElement element) { return getPositionsList(element).iterator(); } public static Position getAsPosition(Element element) { Position pos = null; QName qname = element.getQName(); String text = element.getText(); if (qname.equals(QNAME_GML_POINT)) { element = traverse((ExtensibleElement) element, QNAME_GML_POS); if (element != null) { text = element.getText(); if (text != null) { pos = new Point(text.trim()); } } } else if (qname.equals(QNAME_GML_LINESTRING)) { element = traverse((ExtensibleElement) element, QNAME_GML_POSLIST); if (element != null) { text = element.getText(); if (text != null) { pos = new Line(text.trim()); } } } else if (qname.equals(QNAME_GML_POLYGON)) { element = traverse((ExtensibleElement) element, QNAME_GML_EXTERIOR, QNAME_GML_LINEARRING, QNAME_GML_POSLIST); if (element != null) { text = element.getText(); if (text != null) { pos = new Polygon(text.trim()); } } } else if (qname.equals(QNAME_GML_ENVELOPE)) { String lc = ((ExtensibleElement) element).getSimpleExtension(QNAME_GML_LOWERCORNER); String uc = ((ExtensibleElement) element).getSimpleExtension(QNAME_GML_UPPERCORNER); if (lc != null && uc != null) { Coordinate c1 = new Coordinate(lc); Coordinate c2 = new Coordinate(uc); pos = new Box(c1, c2); } } else if (qname.equals(QNAME_SIMPLE_POINT) && text != null) { pos = new Point(text.trim()); } else if (qname.equals(QNAME_SIMPLE_LINE) && text != null) { pos = new Line(text.trim()); } else if (qname.equals(QNAME_SIMPLE_BOX) && text != null) { pos = new Box(text.trim()); } else if (qname.equals(QNAME_SIMPLE_POLYGON) && text != null) { pos = new Polygon(text.trim()); } else if (qname.equals(QNAME_W3C_POINT) || qname.equals(Constants.ENTRY)) { List<Position> list = new ArrayList<Position>(); getW3CPosition((ExtensibleElement) element, list); if (list != null && list.size() > 0) { pos = list.get(0); } } return pos; } public static Position[] getPositions(ExtensibleElement element) { List<Position> positions = getPositionsList(element); return positions.toArray(new Position[positions.size()]); } private static void getSimplePosition(ExtensibleElement element, List<Position> list) { List<Element> elements = element.getExtensions(SIMPLE_GEO_NS); for (Element el : elements) { Position pos = getAsPosition(el); if (pos != null) { getPositionAttributes(el, pos); list.add(pos); } } } private static void getGMLPosition(ExtensibleElement element, List<Position> list) { List<ExtensibleElement> elements = element.getExtensions(QNAME_WHERE); for (ExtensibleElement where : elements) { Position pos = null; List<ExtensibleElement> children = where.getElements(); for (ExtensibleElement el : children) { pos = getAsPosition(el); if (pos != null) { getPositionAttributes(el, pos); list.add(pos); } } } } private static ExtensibleElement traverse(ExtensibleElement element, QName... qnames) { for (QName qname : qnames) { element = element.getExtension(qname); if (element == null) { break; } } return element; } private static void getPositionAttributes(Element pos, Position position) { if (position != null) { String featuretypetag = pos.getAttributeValue("featuretypetag"); String relationshiptag = pos.getAttributeValue("relationshiptag"); String elevation = pos.getAttributeValue("elev"); String floor = pos.getAttributeValue("floor"); String radius = pos.getAttributeValue("radius"); if (featuretypetag != null) { position.setFeatureTypeTag(featuretypetag); } if (featuretypetag != null) { position.setRelationshipTag(relationshiptag); } if (elevation != null) { position.setElevation(Double.valueOf(elevation)); } if (floor != null) { position.setFloor(Double.valueOf(floor)); } if (radius != null) { position.setRadius(Double.valueOf(radius)); } } } private static void getW3CPosition(ExtensibleElement element, List<Position> list) { getSimpleW3CPosition(element, list); List<ExtensibleElement> points = element.getExtensions(QNAME_W3C_POINT); for (ExtensibleElement point : points) { getSimpleW3CPosition(point, list); } } private static void getSimpleW3CPosition(ExtensibleElement el, List<Position> list) { String slat = el.getSimpleExtension(QNAME_W3C_LAT); String slong = el.getSimpleExtension(QNAME_W3C_LONG); if (slat != null && slong != null) { Point point = new Point(slat.trim() + " " + slong.trim()); list.add(point); } } }