/* * This file is hereby placed into the Public Domain. This means anyone is * free to do whatever they wish with this file. */ package mil.nga.giat.data.elasticsearch; import java.util.HashMap; import java.util.Map; import org.geotools.filter.Capabilities; import org.geotools.filter.capability.FilterCapabilitiesImpl; import org.geotools.filter.capability.TemporalCapabilitiesImpl; import org.geotools.filter.capability.TemporalOperatorImpl; import org.geotools.filter.visitor.IsFullySupportedFilterVisitor; import org.opengis.filter.ExcludeFilter; import org.opengis.filter.Filter; import org.opengis.filter.Id; import org.opengis.filter.IncludeFilter; import org.opengis.filter.PropertyIsBetween; import org.opengis.filter.PropertyIsLike; import org.opengis.filter.PropertyIsNull; import org.opengis.filter.capability.TemporalCapabilities; import org.opengis.filter.capability.TemporalOperators; import org.opengis.filter.spatial.BBOX; import org.opengis.filter.spatial.Beyond; import org.opengis.filter.spatial.Contains; import org.opengis.filter.spatial.DWithin; import org.opengis.filter.spatial.Disjoint; import org.opengis.filter.spatial.Intersects; 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.BinaryTemporalOperator; 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; /** * Custom {@link Capabilities} supporting temporal capabilities and operators. Uses a custom {@link IsFullySupportedFilterVisitor} * to enable support for {@link IncludeFilter}, {@link ExcludeFilter} and {@link BegunBy}. * */ class ElasticCapabilities extends Capabilities { private static final Map<Class<?>,String> temporalNames; static { temporalNames = new HashMap<>(); temporalNames.put(After.class, After.NAME ); temporalNames.put(AnyInteracts.class, AnyInteracts.NAME ); temporalNames.put(Before.class, Before.NAME ); temporalNames.put(Begins.class, Begins.NAME ); temporalNames.put(BegunBy.class, BegunBy.NAME ); temporalNames.put(During.class, During.NAME ); temporalNames.put(EndedBy.class, EndedBy.NAME ); temporalNames.put(Ends.class, Ends.NAME ); temporalNames.put(Meets.class, Meets.NAME ); temporalNames.put(MetBy.class, MetBy.NAME ); temporalNames.put(OverlappedBy.class, OverlappedBy.NAME ); temporalNames.put(TContains.class, TContains.NAME ); temporalNames.put(TEquals.class, TEquals.NAME ); temporalNames.put(TOverlaps.class, TOverlaps.NAME ); } private IsFullySupportedFilterVisitor fullySupportedVisitor; public ElasticCapabilities() { super(new ElasticFilterCapabilities()); addAll(LOGICAL_OPENGIS); addAll(SIMPLE_COMPARISONS_OPENGIS); addType(PropertyIsNull.class); addType(PropertyIsBetween.class); addType(Id.class); addType(IncludeFilter.class); addType(ExcludeFilter.class); addType(PropertyIsLike.class); // spatial filters addType(BBOX.class); addType(Contains.class); //addType(Crosses.class); addType(Disjoint.class); //addType(Equals.class); addType(Intersects.class); //addType(Overlaps.class); //addType(Touches.class); addType(Within.class); addType(DWithin.class); addType(Beyond.class); //temporal filters addType(After.class); addType(Before.class); addType(Begins.class); addType(BegunBy.class); addType(During.class); addType(Ends.class); addType(EndedBy.class); addType(TContains.class); addType(TEquals.class); } @Override public boolean fullySupports(Filter filter) { if( fullySupportedVisitor == null ){ fullySupportedVisitor = new ElasticIsFullySupportedFilterVisitor(); } return filter != null ? (Boolean) filter.accept( fullySupportedVisitor, null ) : false; } @Override public String toOperationName( @SuppressWarnings("rawtypes") Class filterType ) { if (filterType != null && temporalNames.containsKey(filterType)) { return temporalNames.get(filterType); } return super.toOperationName(filterType); } @Override public void addName( String name ) { if (name != null && temporalNames.containsValue(name)) { final TemporalOperators operators = getContents().getTemporalCapabilities().getTemporalOperators(); operators.getOperators().add(new TemporalOperatorImpl(name)); } else { super.addName(name); } } private static class ElasticFilterCapabilities extends FilterCapabilitiesImpl { TemporalCapabilitiesImpl temporal; @Override public TemporalCapabilities getTemporalCapabilities() { if( temporal == null ){ temporal = new TemporalCapabilitiesImpl(); super.setTemporal(temporal); } return temporal; } } private class ElasticIsFullySupportedFilterVisitor extends IsFullySupportedFilterVisitor { ElasticIsFullySupportedFilterVisitor() { super(getContents()); } public Object visit( ExcludeFilter filter, Object extraData ) { return true; } public Object visit( IncludeFilter filter, Object extraData ) { return true; } public Object visit(BegunBy begunBy, Object extraData) { return visit((BinaryTemporalOperator)begunBy, BegunBy.NAME); } } }