This is an automated email from the ASF dual-hosted git repository. jsorel pushed a commit to branch feat/filtercopy in repository https://gitbox.apache.org/repos/asf/sis.git
commit bd9026738e42ae325eb9c1acb1ea7396d867668b Author: jsorel <johann.so...@geomatys.com> AuthorDate: Mon May 2 14:44:25 2022 +0200 Filter: add CopyVisitor implementation --- .../apache/sis/internal/filter/CopyVisitor.java | 232 ++++++++++++ .../sis/internal/filter/CopyVisitorTest.java | 403 +++++++++++++++++++++ .../apache/sis/test/suite/FeatureTestSuite.java | 1 + 3 files changed, 636 insertions(+) diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/filter/CopyVisitor.java b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/CopyVisitor.java new file mode 100644 index 0000000000..a3847de3c6 --- /dev/null +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/filter/CopyVisitor.java @@ -0,0 +1,232 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sis.internal.filter; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; +import org.apache.sis.util.ArgumentChecks; +import org.opengis.filter.BetweenComparisonOperator; +import org.opengis.filter.BinaryComparisonOperator; +import org.opengis.filter.DistanceOperator; +import org.opengis.filter.Expression; +import org.opengis.filter.Filter; +import org.opengis.filter.FilterFactory; +import org.opengis.filter.LikeOperator; +import org.opengis.filter.Literal; +import org.opengis.filter.LogicalOperator; +import org.opengis.filter.MatchAction; +import org.opengis.filter.NilOperator; +import org.opengis.filter.NullOperator; +import org.opengis.filter.ValueReference; +import org.opengis.geometry.Envelope; +import org.opengis.util.CodeList; + +/** + * Visitor used to copy expressions and filters from one factory to another. + * This class purpose is to offer a way to convert filters to different and + * often more specialized and efficient implementations such as for Coverages or SQL. + * + * @author Johann Sorel (Geomatys) + */ +public final class CopyVisitor<R,T> extends Visitor<R,AtomicReference> { + + private final FilterFactory<T,Object,Object> targetFactory; + + /** + * Create a new copy visitor with given factory. + * + * @param targetFactory not null + */ + public CopyVisitor(FilterFactory<T,?,?> targetFactory) { + ArgumentChecks.ensureNonNull("factory", targetFactory); + this.targetFactory = (FilterFactory<T, Object, Object>) targetFactory; + setBinaryComparisonHandlers(this::copyBinaryComparison); + setBinaryTemporalHandlers(this::copyBinaryTemporal); + setLogicalHandlers(this::copyLogical); + setSpatialHandlers(this::copySpatial); + setMathHandlers(this::copyMath); + } + + /** + * Copy given filter using given factory. + * + * @param filter filter to copy + * @return copied filter. + */ + public Filter<T> copy(Filter<R> filter) { + final AtomicReference ref = new AtomicReference(); + visit(filter, ref); + return (Filter) ref.get(); + } + + /** + * Copy given expression using given factory. + * + * @param expression expression to copy + * @return copied expression. + */ + public Expression<T,Object> copy(Expression expression) { + final AtomicReference<Expression<T, Object>> ref = new AtomicReference(); + visit(expression, ref); + return ref.get(); + } + + private List<Expression<T,Object>> copyExpressions(List<Expression<? super R,?>> source) { + final List<Expression<T,Object>> results = new ArrayList<>(source.size()); + for (Expression e : source) { + results.add(copy(e)); + } + return results; + } + + private List<Filter<T>> copyOperands(List<Filter<R>> source) { + final List<Filter<T>> results = new ArrayList<>(source.size()); + for (Filter<R> e : source) { + results.add(copy(e)); + } + return results; + } + + private void copyBinaryComparison(Filter<R> t, AtomicReference u) { + final BinaryComparisonOperator co = (BinaryComparisonOperator) t; + final List<Expression<T, Object>> exps = copyExpressions(t.getExpressions()); + final MatchAction ma = co.getMatchAction(); + final boolean mc = co.isMatchingCase(); + final Filter<T> result; + switch (t.getOperatorType().identifier()) { + case "PropertyIsEqualTo" : result = targetFactory.equal(exps.get(0), exps.get(1), mc, ma); break; + case "PropertyIsNotEqualTo" : result = targetFactory.notEqual(exps.get(0), exps.get(1), mc, ma); break; + case "PropertyIsLessThan" : result = targetFactory.less(exps.get(0), exps.get(1), mc, ma); break; + case "PropertyIsGreaterThan" : result = targetFactory.greater(exps.get(0), exps.get(1), mc, ma); break; + case "PropertyIsLessThanOrEqualTo" : result = targetFactory.lessOrEqual(exps.get(0), exps.get(1), mc, ma); break; + case "PropertyIsGreaterThanOrEqualTo" : result = targetFactory.greaterOrEqual(exps.get(0), exps.get(1), mc, ma); break; + default : throw new IllegalArgumentException("Unknowned filter type " + t.getOperatorType().identifier()); + } + u.set(result); + } + + private void copyBinaryTemporal(Filter<R> t, AtomicReference u) { + final List<Expression<T, Object>> exps = copyExpressions(t.getExpressions()); + final Filter<T> result; + switch (t.getOperatorType().identifier()) { + case "After" : result = targetFactory.after(exps.get(0), exps.get(1)); break; + case "Before" : result = targetFactory.before(exps.get(0), exps.get(1)); break; + case "Begins" : result = targetFactory.begins(exps.get(0), exps.get(1)); break; + case "BegunBy" : result = targetFactory.begunBy(exps.get(0), exps.get(1)); break; + case "TContains" : result = targetFactory.tcontains(exps.get(0), exps.get(1)); break; + case "During" : result = targetFactory.during(exps.get(0), exps.get(1)); break; + case "TEquals" : result = targetFactory.tequals(exps.get(0), exps.get(1)); break; + case "TOverlaps" : result = targetFactory.toverlaps(exps.get(0), exps.get(1)); break; + case "Meets" : result = targetFactory.meets(exps.get(0), exps.get(1)); break; + case "Ends" : result = targetFactory.ends(exps.get(0), exps.get(1)); break; + case "OverlappedBy" : result = targetFactory.overlappedBy(exps.get(0), exps.get(1)); break; + case "MetBy" : result = targetFactory.metBy(exps.get(0), exps.get(1)); break; + case "EndedBy" : result = targetFactory.endedBy(exps.get(0), exps.get(1)); break; + case "AnyInteracts" : result = targetFactory.anyInteracts(exps.get(0), exps.get(1)); break; + default : throw new IllegalArgumentException("Unknowned filter type " + t.getOperatorType().identifier()); + } + u.set(result); + } + + private void copyLogical(Filter<R> t, AtomicReference u) { + final LogicalOperator co = (LogicalOperator) t; + final List<Filter<T>> ops = copyOperands(co.getOperands()); + final Filter<T> result; + switch (t.getOperatorType().identifier()) { + case "And" : result = targetFactory.and(ops); break; + case "Or" : result = targetFactory.or(ops); break; + case "Not" : result = targetFactory.not(ops.get(0)); break; + default : throw new IllegalArgumentException("Unknowned filter type " + t.getOperatorType().identifier()); + } + u.set(result); + } + + private void copySpatial(Filter<R> t, AtomicReference u) { + final List<Expression<T, Object>> exps = copyExpressions(t.getExpressions()); + final Filter<T> result; + switch (t.getOperatorType().identifier()) { + case "BBOX" : result = targetFactory.bbox(exps.get(0), (Envelope) exps.get(1).apply(null)); break; + case "Equals" : result = targetFactory.equals(exps.get(0), exps.get(1)); break; + case "Disjoint" : result = targetFactory.disjoint(exps.get(0), exps.get(1)); break; + case "Intersects" : result = targetFactory.intersects(exps.get(0), exps.get(1)); break; + case "Touches" : result = targetFactory.touches(exps.get(0), exps.get(1)); break; + case "Crosses" : result = targetFactory.crosses(exps.get(0), exps.get(1)); break; + case "Within" : result = targetFactory.within(exps.get(0), exps.get(1)); break; + case "Contains" : result = targetFactory.contains(exps.get(0), exps.get(1)); break; + case "Overlaps" : result = targetFactory.overlaps(exps.get(0), exps.get(1)); break; + case "DWithin" : result = targetFactory.within(exps.get(0), exps.get(1), ((DistanceOperator) t).getDistance()); break; + case "Beyond" : result = targetFactory.beyond(exps.get(0), exps.get(1), ((DistanceOperator) t).getDistance()); break; + default : throw new IllegalArgumentException("Unknowned filter type " + t.getOperatorType().identifier()); + } + u.set(result); + } + + private void copyMath(Expression<R,?> t, AtomicReference u) { + final List<Expression> exps = (List) copyExpressions(t.getParameters()); + final Expression<T,?> result; + switch (t.getFunctionName().toString()) { + case FunctionNames.Add : result = targetFactory.add(exps.get(0), exps.get(1)); break; + case FunctionNames.Subtract : result = targetFactory.subtract(exps.get(0), exps.get(1)); break; + case FunctionNames.Multiply : result = targetFactory.multiply(exps.get(0), exps.get(1)); break; + case FunctionNames.Divide : result = targetFactory.divide(exps.get(0), exps.get(1)); break; + default : throw new IllegalArgumentException("Unknowned expression type " + t.getFunctionName().toString()); + } + u.set(result); + } + + @Override + protected void typeNotFound(CodeList<?> type, Filter<R> filter, AtomicReference u) { + if (filter instanceof BetweenComparisonOperator) { + final BetweenComparisonOperator op = (BetweenComparisonOperator) filter; + u.set(targetFactory.between(copy(op.getExpression()), copy(op.getLowerBoundary()), copy(op.getUpperBoundary()))); + } else if (filter instanceof LikeOperator) { + final LikeOperator<R> op = (LikeOperator) filter; + u.set(targetFactory.like( + copy(op.getExpressions().get(0)), + (String) copy(op.getExpressions().get(1)).apply(null), + op.getWildCard(), + op.getSingleChar(), + op.getEscapeChar(), + op.isMatchingCase())); + } else if (filter instanceof NilOperator) { + final NilOperator<R> op = (NilOperator) filter; + u.set(targetFactory.isNil( + copy(op.getExpressions().get(0)), + op.getNilReason().orElse(null))); + } else if (filter instanceof NullOperator) { + final NullOperator<R> op = (NullOperator) filter; + u.set(targetFactory.isNull(copy(op.getExpressions().get(0)))); + } else { + super.typeNotFound(type, filter, u); + } + } + + @Override + protected void typeNotFound(String type, Expression<R, ?> expression, AtomicReference u) { + if (expression instanceof Literal) { + final Literal exp = (Literal) expression; + u.set(targetFactory.literal(exp.getValue())); + } else if (expression instanceof ValueReference) { + final ValueReference exp = (ValueReference) expression; + u.set(targetFactory.property(exp.getXPath())); + } else { + u.set(targetFactory.function(type, copyExpressions(expression.getParameters()).toArray(new Expression[0]))); + } + } + +} diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/filter/CopyVisitorTest.java b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/CopyVisitorTest.java new file mode 100644 index 0000000000..5fc1ee494b --- /dev/null +++ b/core/sis-feature/src/test/java/org/apache/sis/internal/filter/CopyVisitorTest.java @@ -0,0 +1,403 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.sis.internal.filter; + +import java.time.Instant; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import javax.measure.Quantity; +import javax.measure.quantity.Length; +import org.apache.sis.filter.DefaultFilterFactory; +import org.apache.sis.test.TestCase; +import org.apache.sis.util.iso.Names; +import static org.junit.Assert.*; +import org.junit.Test; +import org.opengis.feature.Feature; +import org.opengis.filter.BetweenComparisonOperator; +import org.opengis.filter.BinaryComparisonOperator; +import org.opengis.filter.BinarySpatialOperator; +import org.opengis.filter.DistanceOperator; +import org.opengis.filter.Expression; +import org.opengis.filter.Filter; +import org.opengis.filter.FilterFactory; +import org.opengis.filter.InvalidFilterValueException; +import org.opengis.filter.LikeOperator; +import org.opengis.filter.Literal; +import org.opengis.filter.LogicalOperator; +import org.opengis.filter.MatchAction; +import org.opengis.filter.NilOperator; +import org.opengis.filter.NullOperator; +import org.opengis.filter.ResourceId; +import org.opengis.filter.SortOrder; +import org.opengis.filter.SortProperty; +import org.opengis.filter.TemporalOperator; +import org.opengis.filter.ValueReference; +import org.opengis.filter.Version; +import org.opengis.filter.capability.FilterCapabilities; +import org.opengis.geometry.Envelope; +import org.opengis.metadata.citation.Citation; +import org.opengis.util.ScopedName; + +/** + * Verifies copy from {@link CopyVisitor}. + * + * @author Johann Sorel (Geomatys) + */ +public class CopyVisitorTest extends TestCase { + + /** + * Test copy a value reference. + */ + @Test + public void copyValueReference() { + final FilterFactory<Feature,Object,?> source = DefaultFilterFactory.forFeatures(); + final FilterFactory<Map,Object,Object> target = new MockFactory(); + + final Expression<Feature,?> exp = source.property("name"); + final Expression<Map, Object> result = new CopyVisitor<>(target).copy(exp); + + assertTrue(result instanceof MockValueReference); + } + + /** + * Test copy a function. + */ + @Test + public void copyFunction() { + final FilterFactory<Feature,Object,?> source = DefaultFilterFactory.forFeatures(); + final FilterFactory<Map,Object,Object> target = new MockFactory(); + + final Expression<Feature,?> exp1 = source.property("name"); + final Expression<Feature,?> exp2 = source.property("crs"); + final Expression<Feature,?> fct = source.function("ST_GeomFromText", exp1, exp2); + final Expression<Map, Object> result = new CopyVisitor<>(target).copy(fct); + + assertTrue(result instanceof MockFunction); + final MockFunction resultfct = (MockFunction) result; + assertEquals(2, resultfct.getParameters().size()); + assertTrue(resultfct.getParameters().get(0) instanceof MockValueReference); + assertTrue(resultfct.getParameters().get(1) instanceof MockValueReference); + } +} + +final class MockFactory implements FilterFactory<Map, Object, Object>{ + + @Override + public FilterCapabilities getCapabilities() { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public ResourceId<Map> resourceId(String rid, Version version, Instant startTime, Instant endTime) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public <V> ValueReference property(String xpath, Class<V> type) { + return new MockValueReference(xpath); + } + + @Override + public <V> Literal<Map, V> literal(V value) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinaryComparisonOperator<Map> equal(Expression<? super Map, ?> expression1, Expression<? super Map, ?> expression2, boolean isMatchingCase, MatchAction matchAction) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinaryComparisonOperator<Map> notEqual(Expression<? super Map, ?> expression1, Expression<? super Map, ?> expression2, boolean isMatchingCase, MatchAction matchAction) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinaryComparisonOperator<Map> less(Expression<? super Map, ?> expression1, Expression<? super Map, ?> expression2, boolean isMatchingCase, MatchAction matchAction) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinaryComparisonOperator<Map> greater(Expression<? super Map, ?> expression1, Expression<? super Map, ?> expression2, boolean isMatchingCase, MatchAction matchAction) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinaryComparisonOperator<Map> lessOrEqual(Expression<? super Map, ?> expression1, Expression<? super Map, ?> expression2, boolean isMatchingCase, MatchAction matchAction) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinaryComparisonOperator<Map> greaterOrEqual(Expression<? super Map, ?> expression1, Expression<? super Map, ?> expression2, boolean isMatchingCase, MatchAction matchAction) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BetweenComparisonOperator<Map> between(Expression<? super Map, ?> expression, Expression<? super Map, ?> lowerBoundary, Expression<? super Map, ?> upperBoundary) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public LikeOperator<Map> like(Expression<? super Map, ?> expression, String pattern, char wildcard, char singleChar, char escape, boolean isMatchingCase) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public NullOperator<Map> isNull(Expression<? super Map, ?> expression) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public NilOperator<Map> isNil(Expression<? super Map, ?> expression, String nilReason) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public LogicalOperator<Map> and(Collection<? extends Filter<? super Map>> operands) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public LogicalOperator<Map> or(Collection<? extends Filter<? super Map>> operands) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public LogicalOperator<Map> not(Filter<? super Map> operand) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinarySpatialOperator<Map> bbox(Expression<? super Map, ? extends Object> geometry, Envelope bounds) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinarySpatialOperator<Map> equals(Expression<? super Map, ? extends Object> geometry1, Expression<? super Map, ? extends Object> geometry2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinarySpatialOperator<Map> disjoint(Expression<? super Map, ? extends Object> geometry1, Expression<? super Map, ? extends Object> geometry2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinarySpatialOperator<Map> intersects(Expression<? super Map, ? extends Object> geometry1, Expression<? super Map, ? extends Object> geometry2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinarySpatialOperator<Map> touches(Expression<? super Map, ? extends Object> geometry1, Expression<? super Map, ? extends Object> geometry2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinarySpatialOperator<Map> crosses(Expression<? super Map, ? extends Object> geometry1, Expression<? super Map, ? extends Object> geometry2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinarySpatialOperator<Map> within(Expression<? super Map, ? extends Object> geometry1, Expression<? super Map, ? extends Object> geometry2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinarySpatialOperator<Map> contains(Expression<? super Map, ? extends Object> geometry1, Expression<? super Map, ? extends Object> geometry2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public BinarySpatialOperator<Map> overlaps(Expression<? super Map, ? extends Object> geometry1, Expression<? super Map, ? extends Object> geometry2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public DistanceOperator<Map> beyond(Expression<? super Map, ? extends Object> geometry1, Expression<? super Map, ? extends Object> geometry2, Quantity<Length> distance) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public DistanceOperator<Map> within(Expression<? super Map, ? extends Object> geometry1, Expression<? super Map, ? extends Object> geometry2, Quantity<Length> distance) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> after(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> before(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> begins(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> begunBy(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> tcontains(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> during(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> tequals(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> toverlaps(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> meets(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> ends(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> overlappedBy(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> metBy(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> endedBy(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public TemporalOperator<Map> anyInteracts(Expression<? super Map, ? extends Object> time1, Expression<? super Map, ? extends Object> time2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Expression<Map, Number> add(Expression<? super Map, ? extends Number> operand1, Expression<? super Map, ? extends Number> operand2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Expression<Map, Number> subtract(Expression<? super Map, ? extends Number> operand1, Expression<? super Map, ? extends Number> operand2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Expression<Map, Number> multiply(Expression<? super Map, ? extends Number> operand1, Expression<? super Map, ? extends Number> operand2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Expression<Map, Number> divide(Expression<? super Map, ? extends Number> operand1, Expression<? super Map, ? extends Number> operand2) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Expression<Map, ?> function(String name, Expression<? super Map, ?>[] parameters) { + return new MockFunction(name, Arrays.asList(parameters)); + } + + @Override + public SortProperty<Map> sort(ValueReference<? super Map, ?> property, SortOrder order) { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public Citation getVendor() { + throw new UnsupportedOperationException("Not supported."); + } + +} + +final class MockValueReference implements ValueReference<Map, Object> { + + private final String xpath; + + public MockValueReference(String xpath) { + this.xpath = xpath; + } + + @Override + public String getXPath() { + return xpath; + } + + @Override + public Object apply(Map input) throws InvalidFilterValueException { + return input.get(xpath); + } + + @Override + public <N> Expression<Map, N> toValueType(Class<N> target) { + throw new UnsupportedOperationException("Not supported."); + } + +} + +final class MockFunction implements Expression<Map,Object> { + + private final String name; + private final List<Expression<? super Map, ?>> parameters; + + public MockFunction(String name, List<Expression<? super Map, ?>> parameters) { + this.name = name; + this.parameters = parameters; + } + + @Override + public ScopedName getFunctionName() { + return Names.createScopedName(null, null, name); + } + + @Override + public List<Expression<? super Map, ?>> getParameters() { + return parameters; + } + + @Override + public Object apply(Map input) throws InvalidFilterValueException { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public <N> Expression<Map, N> toValueType(Class<N> target) { + throw new UnsupportedOperationException("Not supported."); + } + +} diff --git a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java index eaa9d26d14..16a86d5a21 100644 --- a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java +++ b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java @@ -63,6 +63,7 @@ import org.junit.runners.Suite; org.apache.sis.filter.BinarySpatialFilterUsingJava2D_Test.class, org.apache.sis.internal.feature.AttributeConventionTest.class, org.apache.sis.internal.feature.GeometryTypeTest.class, + org.apache.sis.internal.filter.CopyVisitorTest.class, org.apache.sis.internal.filter.FunctionNamesTest.class, org.apache.sis.internal.filter.sqlmm.SQLMMTest.class, org.apache.sis.internal.filter.sqlmm.RegistryUsingJTS_Test.class,