/* * Copyright (c) 2012 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * 1Spatial PLC <http://www.1spatial.com> * HUMBOLDT EU Integrated Project #030962 * Data Harmonisation Panel <http://www.dhpanel.eu> */ package com.onespatial.jrc.tns.oml_to_rif.digest; import java.util.List; import org.geotools.filter.AttributeExpressionImpl; import org.geotools.filter.CompareFilterImpl; import org.geotools.filter.GeometryFilterImpl; import org.geotools.filter.LikeFilterImpl; import org.geotools.filter.LiteralExpressionImpl; import org.geotools.filter.LogicFilterImpl; import org.geotools.filter.spatial.ContainsImpl; import org.geotools.filter.spatial.IntersectsImpl; import org.geotools.filter.spatial.WithinImpl; import org.opengis.filter.Filter; import org.opengis.filter.expression.Expression; import com.onespatial.jrc.tns.oml_to_rif.api.AbstractFollowableTranslator; import com.onespatial.jrc.tns.oml_to_rif.api.TranslationException; import com.onespatial.jrc.tns.oml_to_rif.model.alignment.ModelMappingCondition; import com.onespatial.jrc.tns.oml_to_rif.model.rif.filter.nonterminal.FilterNode; import com.onespatial.jrc.tns.oml_to_rif.model.rif.filter.nonterminal.comparison.AbstractComparisonNode; import com.onespatial.jrc.tns.oml_to_rif.model.rif.filter.nonterminal.geometric.AbstractGeometricNode; import com.onespatial.jrc.tns.oml_to_rif.model.rif.filter.terminal.LeafNode; import com.onespatial.jrc.tns.oml_to_rif.model.rif.filter.terminal.LiteralValue; /** * CQL {@link Filter} to model RIF translator. * <p> * CQL = OGC Common Query Language, see <a * href="http://docs.codehaus.org/display/GEOTDOC/14+CQL">here</a> for more * information. * * @author Simon Payne (Simon.Payne@1spatial.com) / 1Spatial Group Ltd. * @author Richard Sunderland (Richard.Sunderland@1spatial.com) / 1Spatial Group Ltd. */ public class CqlToMappingConditionTranslator extends AbstractFollowableTranslator<Filter, ModelMappingCondition> { private FilterNodeFactory factory; /** * Default constructor. */ public CqlToMappingConditionTranslator() { factory = new FilterNodeFactory(); } /** * {@inheritDoc} */ @Override public ModelMappingCondition translate(Filter source) throws TranslationException { ModelMappingCondition filter = new ModelMappingCondition(); FilterNode root = null; if (isLogical(source)) { LogicFilterImpl logicFilter = (LogicFilterImpl) source; root = factory.createLogicNode(logicFilter); List<?> children = logicFilter.getChildren(); for (Object child : children) { createNode(root, (Filter) child); } } // if it's a comparison filter we assume we are at the start of the tree else if (isComparison(source)) { CompareFilterImpl compare = (CompareFilterImpl) source; AbstractComparisonNode cn = factory.createComparisonNode(compare); cn.setLeft(getLeftContents((AttributeExpressionImpl) compare.getExpression1())); cn.setRight(getRightContents(compare.getExpression2())); root = cn; } // likewise if it's a geometric filter else if (isGeometric(source)) { GeometryFilterImpl geometric = (GeometryFilterImpl) source; AbstractGeometricNode gn = factory.createGeometricNode(geometric); gn.setLeft(getLeftContents((AttributeExpressionImpl) geometric.getExpression1())); gn.setRight(getRightContents(geometric.getExpression2())); setGeometricOperationSpecifics(gn, geometric); root = gn; } filter.setRoot(root); return filter; } private void setGeometricOperationSpecifics(AbstractGeometricNode node, GeometryFilterImpl geometric) { if (geometric instanceof WithinImpl) { // ok and nothing needed here // NB below code was for use of DWITHIN which is not // the correct CQL predicate to use, WITHIN is the right one // DWithinImpl within = (DWithinImpl) geometric; // assert node instanceof WithinNode; // WithinNode withinNode = (WithinNode) node; // withinNode.setDistance(within.getDistance()); // withinNode.setDistanceUnits(getDistanceUnits(within. // getDistanceUnits())); } else if (geometric instanceof ContainsImpl) { // ok and nothing required here } else if (geometric instanceof IntersectsImpl) { // ok and nothing required here } else { throw new UnsupportedOperationException("Filter operation is not supported: " //$NON-NLS-1$ + node.getClass().getCanonicalName()); } } private LeafNode getLeftContents(AttributeExpressionImpl expression) { LeafNode node = new LeafNode(); node.setPropertyName(expression.getPropertyName()); return node; } private LeafNode getRightContents(Expression expression) { LeafNode node = new LeafNode(); if (LiteralExpressionImpl.class.isAssignableFrom(expression.getClass())) { LiteralExpressionImpl literal = (LiteralExpressionImpl) expression; if (literal.getValue() instanceof com.vividsolutions.jts.geom.Geometry) { throw new IllegalArgumentException("Geometric literals are " //$NON-NLS-1$ + "not supported! Found " //$NON-NLS-1$ + literal.getValue().getClass().getCanonicalName()); } node.setLiteralValue(LiteralValue.getNew(literal.getValue())); } else if (AttributeExpressionImpl.class.isAssignableFrom(expression.getClass())) { AttributeExpressionImpl attribute = (AttributeExpressionImpl) expression; node.setPropertyName(attribute.getPropertyName()); } else { throw new IllegalArgumentException("Unsupported expression type: " //$NON-NLS-1$ + expression.getClass().getCanonicalName()); } return node; } private FilterNode createNode(FilterNode parent, Filter child) { FilterNode childNode = null; if (isLogical(child)) { LogicFilterImpl logicFilter = (LogicFilterImpl) child; childNode = factory.createLogicNode(logicFilter); List<?> children = logicFilter.getChildren(); for (Object c : children) { createNode(childNode, (Filter) c); } } else if (isComparison(child)) { AbstractComparisonNode comparisonNode = null; if (LikeFilterImpl.class.isAssignableFrom(child.getClass())) { LikeFilterImpl like = (LikeFilterImpl) child; comparisonNode = factory.createComparisonNode(like); comparisonNode.setLeft(getLeftContents((AttributeExpressionImpl) like .getExpression())); LeafNode node = new LeafNode(); node.setLiteralValue(LiteralValue.getNew(like.getLiteral())); comparisonNode.setRight(node); } else { CompareFilterImpl compare = (CompareFilterImpl) child; comparisonNode = factory.createComparisonNode(compare); comparisonNode.setLeft(getLeftContents((AttributeExpressionImpl) compare .getExpression1())); comparisonNode.setRight(getRightContents(compare.getExpression2())); } childNode = comparisonNode; } else if (isGeometric(child)) { childNode = factory.createGeometricNode((GeometryFilterImpl) child); } if (parent != null) { parent.addChild(childNode); } return childNode; } private boolean isGeometric(Filter source) { return source instanceof GeometryFilterImpl; } private boolean isComparison(Filter source) { return source instanceof CompareFilterImpl || source instanceof LikeFilterImpl; } private boolean isLogical(Filter source) { return source instanceof LogicFilterImpl; } }