/** * 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.v002.filter.spatial; import net.opengis.fes.x20.DistanceBufferType; 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.io.parser.GML32Parser; import org.n52.ses.api.event.MapEvent; import org.n52.ses.api.exception.GMLParseException; import org.n52.ses.eml.v002.filter.spatial.methods.ICreateBuffer; import org.n52.ses.eml.v002.filter.spatial.methods.PostGisCreateBuffer; import org.n52.ses.eml.v002.filterlogic.esper.customFunctions.MethodNames; 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"; /** * 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 ICreateBuffer buffering; private String crs = ""; private double distance; private String uom; private Geometry geom; private Geometry originalGeometry; /** * * Constructor * * @param dbOp distance buffer type */ public ADistanceBufferFilter(DistanceBufferType dbOp) { this.distanceBufferType = dbOp; this.buffering = new PostGisCreateBuffer(); } /** * 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(); this.distance = Double.parseDouble(val); this.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 (this.uom.equals("nautical mile")) { this.uom = "[nmi_i]"; } Node dbNode = this.distanceBufferType.getDomNode(); NodeList nodes = dbNode.getChildNodes(); for (int i = 0; i < nodes.getLength(); i++) { this.geom = this.parseGeometry(nodes.item(i)); if (this.geom != null) { break; } } if (this.geom == null) { logger.info("geometry not found"); return null; } //copy the original geom this.originalGeometry = this.geom; //do the buffer this.geom = this.buffering.buffer(this.geom, this.distance, this.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(\""+ this.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 (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; } /** * @return the distance of this buffer */ public double getDistance() { return this.distance; } /** * @return the uom of this buffer */ public String getUom() { return this.uom; } /** * @return the geometry of this buffer */ public Geometry getOriginalGeometry() { return this.originalGeometry; } /** * @return the coordinate reference system of this distancebuffer */ public String getCRS() { return this.crs; } }