package mil.nga.giat.geowave.adapter.vector.plugin;
import java.sql.Timestamp;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.geotools.data.Query;
import org.geotools.filter.visitor.NullFilterVisitor;
import org.geotools.util.Converters;
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.Expression;
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;
import org.opengis.temporal.Instant;
import org.opengis.temporal.Period;
import org.opengis.temporal.Position;
import mil.nga.giat.geowave.adapter.vector.utils.TimeDescriptors;
import mil.nga.giat.geowave.core.geotime.store.query.TemporalConstraints;
import mil.nga.giat.geowave.core.geotime.store.query.TemporalConstraintsSet;
import mil.nga.giat.geowave.core.geotime.store.query.TemporalRange;
/**
* This class can be used to get Time range from an OpenGIS filter object.
* GeoWave then uses this time range to perform a spatial intersection query.
*
* Only those time elements associated with an index are extracted. At the
* moment, the adapter only supports temporal indexing on a single attribute or
* a pair of attributes representing a time range.
*
*/
public class ExtractTimeFilterVisitor extends
NullFilterVisitor
{
private final List<String[]> validParamRanges = new LinkedList<String[]>();
private boolean approximation = false;
public ExtractTimeFilterVisitor() {}
public ExtractTimeFilterVisitor(
final TimeDescriptors timeDescriptors ) {
if (timeDescriptors.hasTime() && (timeDescriptors.getStartRange() != null)
&& (timeDescriptors.getEndRange() != null)) {
addRangeVariables(
timeDescriptors.getStartRange().getLocalName(),
timeDescriptors.getEndRange().getLocalName());
}
}
public void addRangeVariables(
final String start,
final String end ) {
validParamRanges.add(new String[] {
start,
end
});
}
public TemporalConstraintsSet getConstraints(
final Filter filter ) {
final TemporalConstraintsSet constrainsSet = getRawConstraints(filter);
constrainsSet.setExact(!approximation);
for (final String[] range : validParamRanges) {
if (constrainsSet.hasConstraintsFor(range[0]) || constrainsSet.hasConstraintsFor(range[1])) {
final TemporalConstraints start = (constrainsSet.hasConstraintsFor(range[0])) ? constrainsSet
.getConstraintsFor(range[0]) : constrainsSet.getConstraintsFor(range[1]);
// Note: getConstraints has a side effect that is returns a
// constraint--full range, if necessary
// so if start and end are both not specific, the prior line
// would create the end
// thus sconstraints and econstraints will be identical
final TemporalConstraints end = (constrainsSet.hasConstraintsFor(range[1])) ? constrainsSet
.getConstraintsFor(range[1]) : start;
constrainsSet.removeConstraints(
range[0],
range[1]);
final TemporalConstraints constraintsForRange = constrainsSet.getConstraintsForRange(
range[0],
range[1]);
constraintsForRange.replaceWithIntersections(new TemporalConstraints(
new TemporalRange(
start.getStartRange().getStartTime(),
end.getEndRange().getEndTime()),
constraintsForRange.getName()));
}
}
return constrainsSet;
}
public TemporalConstraintsSet getConstraints(
final Query query ) {
return getConstraints(query.getFilter());
}
private TemporalConstraintsSet getRawConstraints(
final Filter filter ) {
final Object output = filter.accept(
this,
null);
if (output instanceof TemporalConstraintsSet) {
return (TemporalConstraintsSet) output;
}
else if (output instanceof ParameterTimeConstraint) {
final ParameterTimeConstraint paramConstraint = (ParameterTimeConstraint) output;
final TemporalConstraintsSet constraintSet = new TemporalConstraintsSet();
constraintSet.getConstraintsFor(
paramConstraint.getName()).replaceWithMerged(
paramConstraint);
return constraintSet;
}
return new TemporalConstraintsSet();
}
/**
* Produce an ReferencedEnvelope from the provided data parameter.
*
* @param data
* @return ReferencedEnvelope
*/
private TemporalConstraints btime(
final Object data ) {
if (data == null) {
return null;
}
if (data instanceof Date) {
return toSet(new TemporalRange(
(Date) data,
(Date) data));
}
else if (data instanceof Timestamp) {
return toSet(new TemporalRange(
(Timestamp) data,
(Timestamp) data));
}
else if (data instanceof Number) {
final long val = ((Number) data).longValue();
return toSet(new TemporalRange(
new Date(
val),
new Date(
val)));
}
else if (data instanceof TemporalRange) {
return toSet((TemporalRange) data);
}
else if (data instanceof TemporalConstraints) {
return (TemporalConstraints) data;
}
else if (data instanceof Period) {
// all periods are exclusive
final Position beginPosition = ((Period) data).getBeginning().getPosition();
final Position endPosition = ((Period) data).getEnding().getPosition();
Date s = TemporalRange.START_TIME, e = TemporalRange.START_TIME;
if (beginPosition.getDate() != null) {
// make it exclusive on start
s = new Date(
beginPosition.getDate().getTime() + 1);
}
else if (beginPosition.getTime() != null) {
// make it exclusive on start
s = new Date(
beginPosition.getTime().getTime() + 1);
}
if (endPosition.getDate() != null) {
// make it exclusive on end
e = new Date(
endPosition.getDate().getTime() - 1);
}
else if (endPosition.getTime() != null) {
// make it exclusive on end
e = new Date(
endPosition.getTime().getTime() - 1);
}
if (s.getTime() > e.getTime()) {
return new TemporalConstraints();
}
return toSet(new TemporalRange(
s,
e));
}
else if (data instanceof Instant) {
final Position beginPosition = ((Instant) data).getPosition();
Date s = TemporalRange.START_TIME;
if (beginPosition.getDate() != null) {
s = beginPosition.getDate();
}
else if (beginPosition.getTime() != null) {
s = beginPosition.getTime();
}
return toSet(new TemporalRange(
s,
s));
}
final Date convertedDate = Converters.convert(
data,
Date.class);
if (convertedDate != null) {
return btime(convertedDate);
}
return new TemporalConstraints();
}
@Override
public Object visit(
final ExcludeFilter filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final IncludeFilter filter,
final Object data ) {
return new TemporalConstraints();
}
private TemporalConstraints toSet(
final TemporalRange range ) {
final TemporalConstraints contraints = new TemporalConstraints();
contraints.add(range);
return contraints;
}
/**
* 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 btime(value);
}
@Override
public Object visit(
final And filter,
final Object data ) {
final TemporalConstraintsSet constraints = new TemporalConstraintsSet();
for (final Filter f : filter.getChildren()) {
final Object output = f.accept(
this,
data);
if (output instanceof ParameterTimeConstraint) {
final ParameterTimeConstraint ranges = (ParameterTimeConstraint) output;
constraints.getConstraintsFor(
ranges.getName()).replaceWithIntersections(
ranges);
}
else if (output instanceof TemporalConstraintsSet) {
final TemporalConstraintsSet rangeSet = (TemporalConstraintsSet) output;
for (final Map.Entry<String, TemporalConstraints> entry : rangeSet.getSet()) {
constraints.getConstraintsFor(
entry.getKey()).replaceWithIntersections(
entry.getValue());
}
}
}
for (final String[] range : validParamRanges) {
if (constraints.hasConstraintsFor(range[0]) && constraints.hasConstraintsFor(range[1])) {
final TemporalConstraints start = constraints.getConstraintsFor(range[0]);
final TemporalConstraints end = constraints.getConstraintsFor(range[1]);
constraints.removeConstraints(
range[0],
range[1]);
// TODO: make this logic more robust
if (start.getEndRange().getEndTime().after(
end.getStartRange().getStartTime())) {
constraints.getConstraintsForRange(
range[0],
range[1]).add(
new TemporalRange(
end.getStartRange().getStartTime(),
start.getEndRange().getEndTime()));
}
else {
// if there are multiple non-instersecting ranges, this is
// an approximation
approximation |= start.getRanges().size() > 1 || end.getRanges().size() > 1;
constraints.getConstraintsForRange(
range[0],
range[1]).add(
new TemporalRange(
start.getStartRange().getStartTime(),
end.getEndRange().getEndTime()));
}
}
}
return constraints;
}
public boolean isApproximation() {
return approximation;
}
@Override
public Object visit(
final Not filter,
final Object data ) {
final Object output = filter.getFilter().accept(
this,
data);
if (output instanceof ParameterTimeConstraint) {
return not((ParameterTimeConstraint) output);
}
else if (output instanceof TemporalConstraintsSet) {
final TemporalConstraintsSet newRangeSet = new TemporalConstraintsSet();
final TemporalConstraintsSet rangeSet = (TemporalConstraintsSet) output;
for (final Map.Entry<String, TemporalConstraints> entry : rangeSet.getSet()) {
newRangeSet.getConstraintsFor(
entry.getKey()).replaceWithMerged(
not(entry.getValue()));
}
return newRangeSet;
}
return output;
}
private TemporalConstraints not(
final TemporalConstraints constraints ) {
final ParameterTimeConstraint notRanges = new ParameterTimeConstraint(
constraints.getName());
notRanges.empty();
Date lastMax = TemporalRange.START_TIME;
for (final TemporalRange range : constraints.getRanges()) {
if (range.getStartTime().after(
TemporalRange.START_TIME)) {
notRanges.add(new TemporalRange(
lastMax,
new Date(
range.getStartTime().getTime() - 1)));
}
lastMax = range.getEndTime();
}
if (!constraints.isEmpty() && (TemporalRange.END_TIME.after(constraints.getEndRange().getEndTime()))) {
notRanges.add(new TemporalRange(
lastMax,
TemporalRange.END_TIME));
}
return notRanges;
}
@Override
public Object visit(
final Or filter,
final Object data ) {
final TemporalConstraintsSet constraints = new TemporalConstraintsSet();
for (final Filter f : filter.getChildren()) {
final Object output = f.accept(
this,
data);
if (output instanceof ParameterTimeConstraint) {
final ParameterTimeConstraint ranges = (ParameterTimeConstraint) output;
constraints.getConstraintsFor(
ranges.getName()).replaceWithMerged(
ranges);
}
else if (output instanceof TemporalConstraintsSet) {
final TemporalConstraintsSet rangeSet = (TemporalConstraintsSet) output;
for (final Map.Entry<String, TemporalConstraints> entry : rangeSet.getSet()) {
constraints.getConstraintsFor(
entry.getKey()).replaceWithMerged(
entry.getValue());
}
}
}
return constraints;
}
// t1 > t2
// t1.start > t2
// t1 > t2.end
// t1.start > t2.end
@Override
public Object visit(
final After after,
final Object data ) {
final TemporalConstraints leftResult = btime(after.getExpression1().accept(
this,
data));
final TemporalConstraints rightResult = btime(after.getExpression2().accept(
this,
data));
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// property after value
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
rightResult.getMaxOr(
TemporalRange.START_TIME,
1),
TemporalRange.END_TIME),
leftResult.getName());
}
else if (rightResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
leftResult.getMinOr(
TemporalRange.END_TIME,
-1)),
rightResult.getName());
}
// property after property
return new TemporalConstraints();
}
@Override
public Object visit(
final AnyInteracts anyInteracts,
final Object data ) {
return new TemporalConstraints();
}
// 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 ) {
final TemporalConstraints leftResult = btime(before.getExpression1().accept(
this,
data));
final TemporalConstraints rightResult = btime(before.getExpression2().accept(
this,
data));
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// property before value
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
rightResult.getMinOr(
TemporalRange.END_TIME,
-1)),
leftResult.getName());
}
else if (rightResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
leftResult.getMaxOr(
TemporalRange.START_TIME,
1),
TemporalRange.END_TIME),
rightResult.getName());
}
// property after property
return new TemporalConstraints();
}
// t1 = t2.start
// t1.start = t2.start and t1.end < t2.end
@Override
public Object visit(
final Begins begins,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) begins.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) begins.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// property begins value
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
rightResult.getRanges(),
leftResult.getName());
}
else if (rightResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
leftResult.getMinOr(
TemporalRange.START_TIME,
0),
TemporalRange.END_TIME),
rightResult.getName());
}
// property begins property
return new TemporalConstraints();
}
// t1.start = t2
// t1.start = t2.start and t1.end > t2.end
@Override
public Object visit(
final BegunBy begunBy,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) begunBy.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) begunBy.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// property begun by value
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
rightResult.getMinOr(
TemporalRange.START_TIME,
0),
TemporalRange.END_TIME),
leftResult.getName());
}
else if (rightResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
leftResult.getRanges(),
rightResult.getName());
}
// property begins property
return new TemporalConstraints();
}
// t2.start < t1 < t2.end
// t1.start > t2.start and t1.end < t2.end
@Override
public Object visit(
final During during,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) during.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) during.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// property during value
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
rightResult.getRanges(),
leftResult.getName());
}
// value during property
else if (rightResult instanceof ParameterTimeConstraint) {
return rightResult;
}
// property during property
return new TemporalConstraints();
}
// t1.end = t2
// t1.start < t2.start and t1.end = t2.end
@Override
public Object visit(
final EndedBy endedBy,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) endedBy.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) endedBy.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// property ended by value
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
rightResult.getMaxOr(
TemporalRange.END_TIME,
0)),
leftResult.getName());
}
else if (rightResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
leftResult.getRanges(),
rightResult.getName());
}
// property ended by property
return new TemporalConstraints();
}
// t1 = t2.end
// t1.start > t2.start and t1.end = t2.end
@Override
public Object visit(
final Ends ends,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) ends.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) ends.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// property ends value
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
rightResult.getRanges(),
leftResult.getName());
}
else if (rightResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
leftResult.getMaxOr(
TemporalRange.END_TIME,
0)),
rightResult.getName());
}
// property ended by property
return new TemporalConstraints();
}
// t1.end = t2.start
@Override
public Object visit(
final Meets meets,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) meets.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) meets.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// property ends value
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
rightResult.getMinOr(
TemporalRange.END_TIME,
0)),
leftResult.getName());
}
else if (rightResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
rightResult.getName());
}
// property ended by property
return new TemporalConstraints();
}
// t1.start = t2.end
// met by
@Override
public Object visit(
final MetBy metBy,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) metBy.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) metBy.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// property ends value
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
rightResult.getMaxOr(
TemporalRange.START_TIME,
0),
TemporalRange.END_TIME),
leftResult.getName());
}
else if (rightResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
leftResult.getMinOr(
TemporalRange.END_TIME,
0)),
rightResult.getName());
}
// property ends property
return new TemporalConstraints();
}
// t1.start > t2.start and t1.start < t2.end and t1.end > t2.end
@Override
public Object visit(
final OverlappedBy overlappedBy,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) overlappedBy.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) overlappedBy.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// property overlappedBy value
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
rightResult.getMinOr(
TemporalRange.START_TIME,
1),
TemporalRange.END_TIME),
leftResult.getName());
}
else if (rightResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
leftResult.getMaxOr(
TemporalRange.END_TIME,
-1)),
rightResult.getName());
}
// property overlappedBy property
return new TemporalConstraints();
}
// t1.start < t2 < t1.end
// t1.start < t2.start and t2.end < t1.end
@Override
public Object visit(
final TContains contains,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) contains.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) contains.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// property contains value
if (leftResult instanceof ParameterTimeConstraint) {
return new TemporalConstraints(
new TemporalRange(
TemporalRange.START_TIME,
rightResult.getMaxOr(
TemporalRange.END_TIME,
-1)),
leftResult.getName());
}
else if (rightResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
leftResult.getRanges(),
rightResult.getName());
}
// property contains property
return new TemporalConstraints();
}
@Override
public Object visit(
final TEquals equals,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) equals.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) equals.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// property contains value
if (leftResult instanceof ParameterTimeConstraint) {
return rightResult;
}
// value contains property
if (rightResult instanceof ParameterTimeConstraint) {
return leftResult;
}
// property contains property
return new TemporalConstraints();
}
// t1.start < t2.start and t1.end > t2.start and t1.end < t2.end
@Override
public Object visit(
final TOverlaps overlaps,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) overlaps.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) overlaps.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
// according to geotools documentation this is exclusive even though
// "overlaps" seems it should imply inclusive
// property overlappedBy value
if (leftResult instanceof ParameterTimeConstraint) {
return new TemporalConstraints(
new TemporalRange(
TemporalRange.START_TIME,
rightResult.getMaxOr(
TemporalRange.END_TIME,
-1)),
leftResult.getName());
}
else if (rightResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
leftResult.getMaxOr(
TemporalRange.START_TIME,
-1),
TemporalRange.END_TIME),
rightResult.getName());
}
// property overlappedBy property
return new TemporalConstraints();
}
@Override
public Object visit(
final Id filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final PropertyIsBetween filter,
final Object data ) {
final TemporalConstraints propertyExp = (TemporalConstraints) filter.getExpression().accept(
this,
data);
final TemporalConstraints lowerBound = (TemporalConstraints) filter.getLowerBoundary().accept(
this,
data);
final TemporalConstraints upperBound = (TemporalConstraints) filter.getUpperBoundary().accept(
this,
data);
if (propertyExp.isEmpty()) {
return new TemporalConstraints();
}
return new ParameterTimeConstraint(
new TemporalRange(
lowerBound.getStartRange().getStartTime(),
upperBound.getEndRange().getEndTime()),
propertyExp.getName());
}
@Override
public Object visit(
final PropertyIsEqualTo filter,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) filter.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) filter.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
rightResult.getStartRange().getStartTime(),
rightResult.getEndRange().getEndTime()),
leftResult.getName());
}
else {
return new ParameterTimeConstraint(
new TemporalRange(
leftResult.getStartRange().getStartTime(),
leftResult.getEndRange().getEndTime()),
rightResult.getName());
}
}
@Override
public Object visit(
final PropertyIsNotEqualTo filter,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) filter.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) filter.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
if (leftResult instanceof ParameterTimeConstraint) {
final ParameterTimeConstraint constraints = new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
rightResult.getStartRange().getStartTime()),
leftResult.getName());
constraints.add(new TemporalRange(
rightResult.getEndRange().getEndTime(),
TemporalRange.END_TIME));
return constraints;
}
else {
final ParameterTimeConstraint constraints = new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
leftResult.getStartRange().getStartTime()),
rightResult.getName());
constraints.add(new TemporalRange(
leftResult.getEndRange().getEndTime(),
TemporalRange.END_TIME));
return constraints;
}
}
@Override
public Object visit(
final PropertyIsGreaterThan filter,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) filter.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) filter.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
new Date(
rightResult.getStartRange().getStartTime().getTime() + 1),
TemporalRange.END_TIME),
leftResult.getName());
}
else {
return new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
new Date(
leftResult.getStartRange().getStartTime().getTime() - 1)),
rightResult.getName());
}
}
@Override
public Object visit(
final PropertyIsGreaterThanOrEqualTo filter,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) filter.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) filter.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
rightResult.getStartRange().getStartTime(),
TemporalRange.END_TIME),
leftResult.getName());
}
else {
return new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
leftResult.getStartRange().getStartTime()),
rightResult.getName());
}
}
@Override
public Object visit(
final PropertyIsLessThan filter,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) filter.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) filter.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
new Date(
rightResult.getStartRange().getStartTime().getTime() - 1)),
leftResult.getName());
}
else {
return new ParameterTimeConstraint(
new TemporalRange(
new Date(
leftResult.getStartRange().getStartTime().getTime() + 1),
TemporalRange.END_TIME),
rightResult.getName());
}
}
@Override
public Object visit(
final PropertyIsLessThanOrEqualTo filter,
final Object data ) {
final TemporalConstraints leftResult = (TemporalConstraints) filter.getExpression1().accept(
this,
data);
final TemporalConstraints rightResult = (TemporalConstraints) filter.getExpression2().accept(
this,
data);
if (leftResult.isEmpty() || rightResult.isEmpty()) {
return new TemporalConstraints();
}
if (leftResult instanceof ParameterTimeConstraint) {
return new ParameterTimeConstraint(
new TemporalRange(
TemporalRange.START_TIME,
rightResult.getStartRange().getStartTime()),
leftResult.getName());
}
else {
return new ParameterTimeConstraint(
new TemporalRange(
leftResult.getStartRange().getStartTime(),
TemporalRange.END_TIME),
rightResult.getName());
}
}
@Override
public Object visit(
final PropertyIsLike filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final PropertyIsNull filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final PropertyIsNil filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final BBOX filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final Beyond filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final Contains filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final Crosses filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final Disjoint filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final DWithin filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final Equals filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final Intersects filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final Overlaps filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final Touches filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final Within filter,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visitNullFilter(
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final NilExpression expression,
final Object data ) {
return new TemporalConstraints();
}
@Override
public Object visit(
final Add expression,
final Object data ) {
return expression.accept(
this,
data);
}
@Override
public Object visit(
final Divide expression,
final Object data ) {
return expression.accept(
this,
data);
}
@Override
public Object visit(
final Function expression,
final Object data ) {
// used force full range if the expression contains a time
// property...which is correct?
return new TemporalConstraints();
}
private boolean validateName(
final String name ) {
return true;
}
@Override
public Object visit(
final PropertyName expression,
final Object data ) {
final String name = expression.getPropertyName();
if (validateName(expression.getPropertyName())) {
// for (final String[] range : validParamRanges) {
// if (range[0].equals(name) || range[1].equals(name)) {
// return new ParameterTimeConstraint(
// range[0] + "_" + range[1]);
// }
// }
return new ParameterTimeConstraint(
name);
}
return new TemporalConstraints();
}
@Override
public Object visit(
final Subtract expression,
final Object data ) {
return expression.accept(
this,
data);
}
private boolean expressionContainsTime(
final Expression expression ) {
return !((TemporalConstraints) expression.accept(
this,
null)).isEmpty();
}
private boolean containsTime(
final Function function ) {
boolean yes = false;
for (final Expression expression : function.getParameters()) {
yes |= expressionContainsTime(expression);
}
return yes;
}
private static class ParameterTimeConstraint extends
TemporalConstraints
{
public ParameterTimeConstraint(
final String name ) {
super(
TemporalConstraints.FULL_RANGE,
name);
}
public ParameterTimeConstraint(
final List<TemporalRange> ranges,
final String name ) {
super(
ranges,
name);
}
public ParameterTimeConstraint(
final TemporalRange range,
final String name ) {
super(
range,
name);
}
public TemporalConstraints bounds(
final TemporalConstraints other ) {
return other;
}
}
}