package mil.nga.giat.geowave.adapter.vector.query.cql; import mil.nga.giat.geowave.core.index.ByteArrayId; import mil.nga.giat.geowave.core.store.index.numeric.NumericEqualsConstraint; import mil.nga.giat.geowave.core.store.index.numeric.NumericGreaterThanConstraint; import mil.nga.giat.geowave.core.store.index.numeric.NumericGreaterThanOrEqualToConstraint; import mil.nga.giat.geowave.core.store.index.numeric.NumericLessThanConstraint; import mil.nga.giat.geowave.core.store.index.numeric.NumericLessThanOrEqualToConstraint; import mil.nga.giat.geowave.core.store.index.numeric.NumericQueryConstraint; import mil.nga.giat.geowave.core.store.index.text.TextExactMatchFilter; import mil.nga.giat.geowave.core.store.index.text.TextQueryConstraint; import org.geotools.filter.visitor.NullFilterVisitor; import org.opengis.filter.And; import org.opengis.filter.ExcludeFilter; import org.opengis.filter.Filter; import org.opengis.filter.Id; import org.opengis.filter.IncludeFilter; import org.opengis.filter.Not; import org.opengis.filter.Or; import org.opengis.filter.PropertyIsBetween; import org.opengis.filter.PropertyIsEqualTo; import org.opengis.filter.PropertyIsGreaterThan; import org.opengis.filter.PropertyIsGreaterThanOrEqualTo; import org.opengis.filter.PropertyIsLessThan; import org.opengis.filter.PropertyIsLessThanOrEqualTo; import org.opengis.filter.PropertyIsLike; import org.opengis.filter.PropertyIsNil; import org.opengis.filter.PropertyIsNotEqualTo; import org.opengis.filter.PropertyIsNull; import org.opengis.filter.expression.Add; import org.opengis.filter.expression.Divide; import org.opengis.filter.expression.Function; import org.opengis.filter.expression.Literal; import org.opengis.filter.expression.NilExpression; import org.opengis.filter.expression.PropertyName; import org.opengis.filter.expression.Subtract; import org.opengis.filter.spatial.BBOX; import org.opengis.filter.spatial.Beyond; import org.opengis.filter.spatial.Contains; import org.opengis.filter.spatial.Crosses; import org.opengis.filter.spatial.DWithin; import org.opengis.filter.spatial.Disjoint; import org.opengis.filter.spatial.Equals; import org.opengis.filter.spatial.Intersects; import org.opengis.filter.spatial.Overlaps; import org.opengis.filter.spatial.Touches; import org.opengis.filter.spatial.Within; import org.opengis.filter.temporal.After; import org.opengis.filter.temporal.AnyInteracts; import org.opengis.filter.temporal.Before; import org.opengis.filter.temporal.Begins; import org.opengis.filter.temporal.BegunBy; import org.opengis.filter.temporal.During; import org.opengis.filter.temporal.EndedBy; import org.opengis.filter.temporal.Ends; import org.opengis.filter.temporal.Meets; import org.opengis.filter.temporal.MetBy; import org.opengis.filter.temporal.OverlappedBy; import org.opengis.filter.temporal.TContains; import org.opengis.filter.temporal.TEquals; import org.opengis.filter.temporal.TOverlaps; /** * CQL visitor to extract constraints for secondary indexing queries. * * TODO: compare operators for text (e.g. <,>,<=,>=) TODO: Temporal * */ public class PropertyFilterVisitor extends NullFilterVisitor { public PropertyFilterVisitor() { super(); } @Override public Object visit( final ExcludeFilter filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final IncludeFilter filter, final Object data ) { return new PropertyConstraintSet(); } /** * Please note we are only visiting literals involved in spatial operations. * * @param literal * , hopefully a Geometry or Envelope * @param data * Incoming BoundingBox (or Envelope or CRS) * * @return ReferencedEnvelope updated to reflect literal */ @Override public Object visit( final Literal expression, final Object data ) { final Object value = expression.getValue(); return value; } @Override public Object visit( final And filter, final Object data ) { final PropertyConstraintSet constraints = new PropertyConstraintSet(); for (final Filter f : filter.getChildren()) { final Object output = f.accept( this, data); if (output instanceof PropertyConstraintSet) { constraints.intersect((PropertyConstraintSet) output); } } return constraints; } @Override public Object visit( final Not filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Or filter, final Object data ) { final PropertyConstraintSet constraints = new PropertyConstraintSet(); for (final Filter f : filter.getChildren()) { final Object output = f.accept( this, data); if (output instanceof PropertyConstraintSet) { constraints.union((PropertyConstraintSet) output); } } return constraints; } // t1 > t2 // t1.start > t2 // t1 > t2.end // t1.start > t2.end @Override public Object visit( final After after, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final AnyInteracts anyInteracts, final Object data ) { return new PropertyConstraintSet(); } // t1 < t2 // t1.end < t2 // t1 < t2.start // t1.end < t2.start // t1.end < t2.start @Override public Object visit( final Before before, final Object data ) { return new PropertyConstraintSet(); } // t1 = t2.start // t1.start = t2.start and t1.end < t2.end @Override public Object visit( final Begins begins, final Object data ) { return new PropertyConstraintSet(); } // t1.start = t2 // t1.start = t2.start and t1.end > t2.end @Override public Object visit( final BegunBy begunBy, final Object data ) { return new PropertyConstraintSet(); } // t2.start < t1 < t2.end // t1.start > t2.start and t1.end < t2.end @Override public Object visit( final During during, final Object data ) { return new PropertyConstraintSet(); } // t1.end = t2 // t1.start < t2.start and t1.end = t2.end @Override public Object visit( final EndedBy endedBy, final Object data ) { return new PropertyConstraintSet(); } // t1 = t2.end // t1.start > t2.start and t1.end = t2.end @Override public Object visit( final Ends ends, final Object data ) { return new PropertyConstraintSet(); } // t1.end = t2.start @Override public Object visit( final Meets meets, final Object data ) { return new PropertyConstraintSet(); } // t1.start = t2.end // met by @Override public Object visit( final MetBy metBy, final Object data ) { return new PropertyConstraintSet(); } // t1.start > t2.start and t1.start < t2.end and t1.end > t2.end @Override public Object visit( final OverlappedBy overlappedBy, final Object data ) { return new PropertyConstraintSet(); } // t1.start < t2 < t1.end // t1.start < t2.start and t2.end < t1.end @Override public Object visit( final TContains contains, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final TEquals equals, final Object data ) { return new PropertyConstraintSet(); } // t1.start < t2.start and t1.end > t2.start and t1.end < t2.end @Override public Object visit( final TOverlaps overlaps, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Id filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final PropertyIsBetween filter, final Object data ) { final ByteArrayId leftResult = (ByteArrayId) filter.getExpression().accept( this, data); final Object lower = filter.getLowerBoundary().accept( this, data); final Object upper = filter.getUpperBoundary().accept( this, data); if (lower instanceof Number) { return new PropertyConstraintSet( new NumericQueryConstraint( leftResult, (Number) lower, (Number) upper, true, true)); } return new PropertyConstraintSet(); } @Override public Object visit( final PropertyIsEqualTo filter, final Object data ) { final ByteArrayId leftResult = (ByteArrayId) filter.getExpression1().accept( this, data); final Object value = filter.getExpression2().accept( this, data); if (value instanceof Number) { return new PropertyConstraintSet( new NumericEqualsConstraint( leftResult, (Number) value)); } else if (value instanceof String) { return new PropertyConstraintSet( new TextQueryConstraint( leftResult, (String) value, true)); } else { return new PropertyConstraintSet(); } } @Override public Object visit( final PropertyIsNotEqualTo filter, final Object data ) { return filter.getExpression1().accept( this, data); } @Override public Object visit( final PropertyIsGreaterThan filter, final Object data ) { final ByteArrayId leftResult = (ByteArrayId) filter.getExpression1().accept( this, data); final Object value = filter.getExpression2().accept( this, data); if (value instanceof Number) { return new PropertyConstraintSet( new NumericGreaterThanConstraint( leftResult, (Number) value)); } return new PropertyConstraintSet(); } @Override public Object visit( final PropertyIsGreaterThanOrEqualTo filter, final Object data ) { final ByteArrayId leftResult = (ByteArrayId) filter.getExpression1().accept( this, data); final Object value = filter.getExpression2().accept( this, data); if (value instanceof Number) { return new PropertyConstraintSet( new NumericGreaterThanOrEqualToConstraint( leftResult, (Number) value)); } return new PropertyConstraintSet(); } @Override public Object visit( final PropertyIsLessThan filter, final Object data ) { final ByteArrayId leftResult = (ByteArrayId) filter.getExpression1().accept( this, data); final Object value = filter.getExpression2().accept( this, data); if (value instanceof Number) { return new PropertyConstraintSet( new NumericLessThanConstraint( leftResult, (Number) value)); } return new PropertyConstraintSet(); } @Override public Object visit( final PropertyIsLessThanOrEqualTo filter, final Object data ) { final ByteArrayId leftResult = (ByteArrayId) filter.getExpression1().accept( this, data); final Object value = filter.getExpression2().accept( this, data); if (value instanceof Number) { return new PropertyConstraintSet( new NumericLessThanOrEqualToConstraint( leftResult, (Number) value)); } return new PropertyConstraintSet(); } @Override public Object visit( final PropertyIsLike filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final PropertyIsNull filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final PropertyIsNil filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final BBOX filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Beyond filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Contains filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Crosses filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Disjoint filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final DWithin filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Equals filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Intersects filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Overlaps filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Touches filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Within filter, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visitNullFilter( final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final NilExpression expression, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Add expression, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Divide expression, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final Function expression, final Object data ) { return new PropertyConstraintSet(); } @Override public Object visit( final PropertyName expression, final Object data ) { return new ByteArrayId( expression.getPropertyName()); } @Override public Object visit( final Subtract expression, final Object data ) { return expression.accept( this, data); } }