/** * Copyright (C) 2008 - 2014 52°North Initiative for Geospatial Open Source * Software GmbH * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. * * If the program is linked with libraries which are licensed under one of * the following licenses, the combination of the program with the linked * library is not considered a "derivative work" of the program: * * - Apache License, version 2.0 * - Apache Software License, version 1.0 * - GNU Lesser General Public License, version 3 * - Mozilla Public License, versions 1.0, 1.1 and 2.0 * - Common Development and Distribution License (CDDL), version 1.0 * * Therefore the distribution of the program linked with libraries licensed * under the aforementioned licenses, is permitted by the copyright holders * if the distribution is compliant with both the GNU General Public * icense version 2 and the aforementioned licenses. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. */ package org.n52.ses.eml.v001.filter.spatial; import net.opengis.fes.x20.DistanceBufferType; import net.opengis.gml.x32.GeodesicStringDocument; import net.opengis.gml.x32.LineStringDocument; import net.opengis.gml.x32.LineStringType; import net.opengis.gml.x32.LinearRingDocument; import net.opengis.gml.x32.LinearRingType; import net.opengis.gml.x32.PointDocument; import net.opengis.gml.x32.PointType; import net.opengis.gml.x32.PolygonDocument; import net.opengis.gml.x32.PolygonType; import org.apache.muse.util.xml.XmlUtils; import org.apache.xmlbeans.XmlException; import org.n52.ses.api.event.MapEvent; import org.n52.ses.api.exception.GMLParseException; import org.n52.ses.eml.v001.filterlogic.esper.customFunctions.MethodNames; import org.n52.ses.io.parser.GML32Parser; import org.n52.ses.util.geometry.SpatialAnalysisTools; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.ParseException; /** * * @author Matthes Rieke <m.rieke@uni-muenster.de> * */ public abstract class ADistanceBufferFilter extends ASpatialFilter { private static final Logger logger = LoggerFactory .getLogger(ADistanceBufferFilter.class); private static final String GML_NAMESPACE = "http://www.opengis.net/gml/3.2"; /** * qualified name of GML Point */ protected static final String POINT_NAME = "Point"; /** * name of GML LinearRing */ protected static final String LINEAR_RING_NAME = "LinearRing"; /** * name of GML GeodesicString */ protected static final String GEODESIC_STRING_NAME = "GeodesicString"; /** * qualified name of GML LineString */ protected static final String LINE_STRING_NAME = "LineString"; /** * qualified name of GML Polygon */ protected static final String POLYGON_NAME = "Polygon"; /** * the type of this filter. */ protected DistanceBufferType distanceBufferType; private String crs = ""; /** * * Constructor * * @param dbOp distance buffer type */ public ADistanceBufferFilter(DistanceBufferType dbOp) { this.distanceBufferType = dbOp; } /** * creates the esper sub-expression * * @param methodName the java method name * @return the sub-expression */ protected String createExpressionForDistanceFilter(String methodName) { boolean isNot = false; Element elem = (Element) this.distanceBufferType.getDistance().getDomNode(); String val = XmlUtils.toString(elem.getFirstChild()).trim(); double distance = Double.parseDouble(val); String uom = this.distanceBufferType.getDistance().getUom(); // XmlObject elem2 = this.distanceBufferType.getDistance().selectAttribute(new QName("", "uom")); // if (elem2 != null) { // Node child = elem2.getDomNode().getFirstChild(); // if (child != null) { // uom = XmlUtils.toString(child).trim(); // } // } //hack for snowflakes "nautical miles"........... if (uom.equals("nautical mile")) { uom = "[nmi_i]"; } //extract geometry Geometry geom = null; Node dbNode = this.distanceBufferType.getDomNode(); NodeList nodes = dbNode.getChildNodes(); for (int i = 0; i < nodes.getLength(); i++) { geom = this.parseGeometry(nodes.item(i)); if (geom != null) { break; } } if (geom == null) { logger.info("geometry not found"); return null; } //do the buffer geom = SpatialAnalysisTools.buffer(geom, distance, uom, this.crs); String mName; if (methodName.equals("beyond")) { //Buffer and NOT(intersect) isNot = true; } //we do an intersect to the buffer in the end mName = "intersects"; StringBuilder sb = new StringBuilder(); if (isNot) sb.append("not("); sb.append(MethodNames.SPATIAL_METHODS_PREFIX); sb.append(mName+ "("); sb.append(MethodNames.SPATIAL_METHODS_PREFIX); //create WKT from corners sb.append("fromWKT(\""+ geom.toText() +"\")"); sb.append(", "); sb.append(MapEvent.GEOMETRY_KEY +")"); if (isNot) sb.append(")"); return sb.toString(); } private Geometry parseGeometry (Node node) { if (node == null) { return null; } if (node.getNamespaceURI() == null) { return null; } if (!node.getNamespaceURI().equals(GML_NAMESPACE)) { //unsupported encoding return null; } Geometry result = null; String nodeName = node.getLocalName(); if (LINEAR_RING_NAME.equals(nodeName)) { try { LinearRingDocument lrdoc = LinearRingDocument.Factory.parse(node); LinearRingType lrt = lrdoc.getLinearRing(); result = GML32Parser.parseGeometry(lrt); /* * get the srsName from posList or others */ if (lrt.isSetPosList()) { this.crs = lrt.getPosList().getSrsName(); } else { if (lrt.getPointPropertyArray().length > 0) { if (lrt.getPointPropertyArray()[0].isSetPoint()) this.crs = lrt.getPointPropertyArray()[0].getPoint().getSrsName(); } else if (lrt.getPosArray().length > 0) { this.crs = lrt.getPosArray()[0].getSrsName(); } else if (lrt.getPointRepArray().length > 0) { if (lrt.getPointRepArray()[0].isSetPoint()) this.crs = lrt.getPointRepArray()[0].getPoint().getSrsName(); } } } catch (ParseException e) { logger.warn("could not parse the geometry: " + e.getMessage()); } catch (GMLParseException e) { throw new UnsupportedOperationException(e); } catch (XmlException e) { logger.warn("could not parse the geometry: " + e.getMessage()); } } else if (GEODESIC_STRING_NAME.equals(nodeName)) { try { GeodesicStringDocument geodesic = GeodesicStringDocument.Factory.parse(node); if (geodesic.getGeodesicString().isSetPosList()) { this.crs = geodesic.getGeodesicString().getPosList().getSrsName(); } return GML32Parser.parseGeometry(geodesic); } catch (XmlException e) { logger.warn("could not parse the geometry: " + e.getMessage()); } catch (ParseException e) { throw new UnsupportedOperationException(e); } catch (GMLParseException e) { throw new UnsupportedOperationException(e); } } else if (POINT_NAME.equals(nodeName)) { try { PointDocument pdoc = PointDocument.Factory.parse(node); PointType pt = pdoc.getPoint(); this.crs = pt.getSrsName(); result = GML32Parser.parseGeometry(pt); } catch (ParseException e) { logger.warn("could not parse the geometry: " + e.getMessage()); } catch (GMLParseException e) { throw new UnsupportedOperationException(e); } catch (XmlException e) { logger.warn("could not parse the geometry: " + e.getMessage()); } } else if (LINE_STRING_NAME.equals(nodeName)) { logger.debug("extract line string"); try { LineStringDocument lsdoc = LineStringDocument.Factory.parse(node); LineStringType lst = lsdoc.getLineString(); this.crs = lst.getSrsName(); result = GML32Parser.parseGeometry(lst); } catch (ParseException e) { logger.warn("could not parse the geometry: " + e.getMessage()); } catch (GMLParseException e) { logger.warn("could not parse the geometry: " + e.getMessage()); throw new UnsupportedOperationException(e); } catch (XmlException e) { logger.warn("could not parse the geometry: " + e.getMessage()); } } else if (POLYGON_NAME.equals(nodeName)) { try { PolygonDocument pdoc = PolygonDocument.Factory.parse(node); PolygonType pt = pdoc.getPolygon(); this.crs = pt.getSrsName(); result = GML32Parser.parseGeometry(pt); } catch (ParseException e) { logger.warn("could not parse the geometry: " + e.getMessage()); } catch (GMLParseException e) { throw new UnsupportedOperationException(e); } catch (XmlException e) { logger.warn("could not parse the geometry: " + e.getMessage()); } } return result; } }