This is an automated email from the ASF dual-hosted git repository.

jsorel pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 04d422a  Feature : add FeatureComparator utility test class
04d422a is described below

commit 04d422a52ebefff4be2d25e442f63dfeaba02412
Author: jsorel <[email protected]>
AuthorDate: Wed Apr 15 14:25:36 2020 +0200

    Feature : add FeatureComparator utility test class
---
 .../org/apache/sis/feature/FeatureComparator.java  | 310 +++++++++++++++++++++
 1 file changed, 310 insertions(+)

diff --git 
a/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureComparator.java 
b/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureComparator.java
new file mode 100644
index 0000000..5176a7f
--- /dev/null
+++ 
b/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureComparator.java
@@ -0,0 +1,310 @@
+/*
+ * 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.feature;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringJoiner;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.Deprecable;
+import org.junit.Assert;
+import org.opengis.feature.AttributeType;
+import org.opengis.feature.Feature;
+import org.opengis.feature.FeatureAssociationRole;
+import org.opengis.feature.FeatureType;
+import org.opengis.feature.IdentifiedType;
+import org.opengis.feature.Operation;
+import org.opengis.feature.PropertyType;
+import org.opengis.util.GenericName;
+
+/**
+ * Tool to compare feature and feature types.
+ *
+ * @author Johann Sorel (Geomatys)
+ * @version 2.0
+ * @since   2.0
+ * @module
+ */
+public class FeatureComparator {
+
+    private final Object obj1;
+    private final Object obj2;
+
+    /**
+     * The fully-qualified name of properties to ignore in comparisons. This
+     * collection is initially empty. Users can add or remove elements in this
+     * collection as they wish.
+     *
+     * <p>
+     * The elements shall be names in the form {@code "namespace:name"}, or 
only
+     * {@code "name"} if there is no namespace.</p>
+     */
+    public final Set<String> ignoredProperties = new HashSet<>();
+    /**
+     * The fully-qualified name of characteristics to ignore in comparisons.
+     * This collection is initially empty. Users can add or remove elements in
+     * this collection as they wish.
+     *
+     * <p>
+     * The elements shall be names in the form {@code "namespace:name"}, or 
only
+     * {@code "name"} if there is no namespace.</p>
+     */
+    public final Set<String> ignoredCharacteristics = new HashSet<>();
+
+    public boolean ignoreDefinition = false;
+    public boolean ignoreDesignation = false;
+    public boolean ignoreDescription = false;
+
+    public FeatureComparator(Feature expected, Feature result) {
+        ArgumentChecks.ensureNonNull("expected", expected);
+        ArgumentChecks.ensureNonNull("result", result);
+        this.obj1 = expected;
+        this.obj2 = result;
+    }
+
+    public FeatureComparator(FeatureType expected, FeatureType result) {
+        ArgumentChecks.ensureNonNull("expected", expected);
+        ArgumentChecks.ensureNonNull("result", result);
+        this.obj1 = expected;
+        this.obj2 = result;
+    }
+
+    /**
+     * Compare the features or feature types specified at construction time.
+     */
+    public void compare() {
+        final Path path = new Path();
+        if (obj1 instanceof FeatureType) {
+            compareFeatureType(path, (FeatureType) obj1, (FeatureType) obj2);
+        } else {
+            compareFeature(path, (Feature) obj1, (Feature) obj2);
+        }
+    }
+
+    private void compareType(Path path, IdentifiedType expected, 
IdentifiedType result) {
+        if (expected instanceof FeatureType) {
+            compareFeatureType(path, (FeatureType) expected, (FeatureType) 
result);
+        } else if (expected instanceof PropertyType) {
+            comparePropertyType(path, (PropertyType) expected, (PropertyType) 
result);
+        } else {
+            Assert.fail(msg(path, "Unexpected type " + expected));
+        }
+    }
+
+    private void compareFeatureType(Path path, FeatureType expected, 
FeatureType result) {
+        compareIdentifiedType(path, expected, result);
+
+        Assert.assertEquals(msg(path, "Abstract state differ"), 
expected.isAbstract(), result.isAbstract());
+        Assert.assertEquals(msg(path, "Super types differ"), 
expected.getSuperTypes(), result.getSuperTypes());
+
+        List<? extends PropertyType> expectedProperties = new 
ArrayList<>(expected.getProperties(false));
+        List<? extends PropertyType> resultProperties = new 
ArrayList<>(result.getProperties(false));
+
+        while (!expectedProperties.isEmpty()) {
+            final PropertyType pte = expectedProperties.remove(0);
+            if (ignoredProperties.contains(pte.getName().toString())) {
+                continue;
+            }
+            Path sub = path.sub(pte.getName().toString());
+            PropertyType ptr = find(sub, resultProperties, pte.getName());
+            resultProperties.remove(ptr);
+            comparePropertyType(sub, pte, ptr);
+        }
+        while (!resultProperties.isEmpty()) {
+            final PropertyType pte = resultProperties.remove(0);
+            if (ignoredProperties.contains(pte.getName().toString())) {
+                continue;
+            }
+            Path sub = path.sub(pte.getName().toString());
+            Assert.fail(msg(sub, "Result type contains a property not declared 
in expected type : " + pte.getName()));
+        }
+
+    }
+
+    private void compareFeature(Path path, Feature expected, Feature result) {
+        compareFeatureType(path, expected.getType(), result.getType());
+
+        Collection<? extends PropertyType> properties = 
expected.getType().getProperties(true);
+        for (PropertyType pte : properties) {
+            if (ignoredProperties.contains(pte.getName().toString())) {
+                continue;
+            }
+            Path sub = path.sub(pte.getName().toString());
+
+            Object expectedValue = 
expected.getPropertyValue(pte.getName().toString());
+            Object resultValue = 
result.getPropertyValue(pte.getName().toString());
+            if (!(expectedValue instanceof Collection)) {
+                expectedValue = (expectedValue == null) ? 
Collections.EMPTY_LIST : Arrays.asList(expectedValue);
+            }
+            if (!(resultValue instanceof Collection)) {
+                resultValue = (resultValue == null) ? Collections.EMPTY_LIST : 
Arrays.asList(resultValue);
+            }
+
+            Collection<?> expectedCol = (Collection) expectedValue;
+            Collection<?> resultCol = (Collection) resultValue;
+
+            if (expectedCol.size() != resultCol.size()) {
+                Assert.fail(msg(sub, "Number of values differ, expected " + 
expectedCol.size() + " but was " + resultCol.size()));
+            }
+
+            Iterator<?> expectedIte = expectedCol.iterator();
+            Iterator<?> resultIte = resultCol.iterator();
+
+            while (expectedIte.hasNext()) {
+                Object subExpVal = expectedIte.next();
+                Object subResVal = resultIte.next();
+
+                if (subExpVal instanceof Feature) {
+                    compareFeature(path, (Feature) subExpVal, (Feature) 
subResVal);
+                } else {
+                    Assert.assertEquals(subExpVal, subResVal);
+                }
+            }
+        }
+    }
+
+    private void comparePropertyType(Path path, PropertyType expected, 
PropertyType result) {
+
+        if (expected instanceof AttributeType) {
+            if (!(result instanceof AttributeType)) {
+                Assert.fail(msg(path, "Expected an AttributeType for name " + 
((AttributeType) expected).getName() + " but found a " + result));
+            }
+            compareAttribute(path, (AttributeType) expected, (AttributeType) 
result);
+
+        } else if (expected instanceof FeatureAssociationRole) {
+            if (!(result instanceof FeatureAssociationRole)) {
+                Assert.fail(msg(path, "Expected a FeatureAssociationRole for 
name " + ((AttributeType) expected).getName() + " but found a " + result));
+            }
+            compareFeatureAssociationRole(path, (FeatureAssociationRole) 
expected, (FeatureAssociationRole) result);
+
+        } else if (expected instanceof Operation) {
+            if (!(result instanceof Operation)) {
+                Assert.fail(msg(path, "Expected an Operation for name " + 
((AttributeType) expected).getName() + " but found a " + result));
+            }
+            compareOperation(path, (Operation) expected, (Operation) result);
+        }
+    }
+
+    private void compareAttribute(Path path, AttributeType expected, 
AttributeType result) {
+        compareIdentifiedType(path, expected, result);
+        Assert.assertEquals(msg(path, "Value classe differ"), 
expected.getValueClass(), expected.getValueClass());
+        Assert.assertEquals(msg(path, "Default value differ"), 
expected.getDefaultValue(), expected.getDefaultValue());
+
+        Map<String, AttributeType<?>> expCharacteristics = 
expected.characteristics();
+        Map<String, AttributeType<?>> resCharacteristics = 
result.characteristics();
+
+        final List<String> expKeys = new 
ArrayList<>(expCharacteristics.keySet());
+        final List<String> resKeys = new 
ArrayList<>(resCharacteristics.keySet());
+
+        while (!expKeys.isEmpty()) {
+            final String pte = expKeys.remove(0);
+            if (ignoredCharacteristics.contains(pte)) {
+                continue;
+            }
+            AttributeType<?> exp = expCharacteristics.get(pte);
+            AttributeType<?> res = resCharacteristics.get(pte);
+            resKeys.remove(pte);
+            comparePropertyType(path.sub("characteristic(" + pte + ")"), exp, 
res);
+        }
+        while (!resKeys.isEmpty()) {
+            final String pte = resKeys.remove(0);
+            if (ignoredCharacteristics.contains(pte)) {
+                continue;
+            }
+            Assert.fail(msg(path, "Result type contains a characteristic not 
declared in expected type : " + pte));
+        }
+
+    }
+
+    private void compareFeatureAssociationRole(Path path, 
FeatureAssociationRole expected, FeatureAssociationRole result) {
+        compareIdentifiedType(path, expected, result);
+
+        Assert.assertEquals(msg(path, "Minimum occurences differ"), 
expected.getMinimumOccurs(), result.getMinimumOccurs());
+        Assert.assertEquals(msg(path, "Maximum occurences differ"), 
expected.getMaximumOccurs(), result.getMaximumOccurs());
+        compareFeatureType(path.sub("association-valuetype"), 
expected.getValueType(), result.getValueType());
+    }
+
+    private void compareOperation(Path path, Operation expected, Operation 
result) {
+        compareIdentifiedType(path, expected, result);
+        Assert.assertEquals(expected.getParameters(), result.getParameters());
+        compareType(path.sub("operation-result(" + 
expected.getResult().getName().toString() + ")"), expected.getResult(), 
result.getResult());
+    }
+
+    private void compareIdentifiedType(Path path, IdentifiedType expected, 
IdentifiedType result) {
+        Assert.assertEquals(msg(path, "Name differ"), expected.getName(), 
result.getName());
+        if (!ignoreDefinition) {
+            Assert.assertEquals(msg(path, "Definition differ"), 
expected.getDefinition(), result.getDefinition());
+        }
+        if (!ignoreDesignation) {
+            Assert.assertEquals(msg(path, "Designation differ"), 
expected.getDesignation(), result.getDesignation());
+        }
+        if (!ignoreDescription) {
+            Assert.assertEquals(msg(path, "Description differ"), 
expected.getDescription(), result.getDescription());
+        }
+
+        //check deprecable
+        if (expected instanceof Deprecable) {
+            if (result instanceof Deprecable) {
+                boolean dep1 = ((Deprecable) expected).isDeprecated();
+                boolean dep2 = ((Deprecable) result).isDeprecated();
+                if (dep1 != dep2) {
+                    Assert.fail(msg(path, "Deprecated state differ, " + dep1 + 
" in expected " + dep2 + " in result"));
+                }
+            }
+        }
+    }
+
+    private static PropertyType find(Path path, Collection<? extends 
PropertyType> properties, GenericName name) {
+        for (PropertyType pt : properties) {
+            if (pt.getName().equals(name)) {
+                return pt;
+            }
+        }
+        Assert.fail(msg(path, "Property not found for name " + name));
+        return null;
+    }
+
+    private static String msg(Path path, String errorMessage) {
+        return path.toString() + " " + errorMessage;
+    }
+
+    private static class Path {
+
+        private final List<String> segments = new ArrayList<>();
+
+        public Path sub(String segment) {
+            Path p = new Path();
+            p.segments.addAll(segments);
+            p.segments.add(segment);
+            return p;
+        }
+
+        @Override
+        public String toString() {
+            final StringJoiner sj = new StringJoiner(" > ");
+            segments.stream().forEach(sj::add);
+            return "[" + sj.toString() + "]";
+        }
+    }
+}

Reply via email to