sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1799348 - in /sis/branches/JDK8/core/sis-feature/src: main/java/org/apache/sis/feature/DefaultFeatureType.java test/java/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java
Date Tue, 20 Jun 2017 14:34:41 GMT
Author: desruisseaux
Date: Tue Jun 20 14:34:41 2017
New Revision: 1799348

URL: http://svn.apache.org/viewvc?rev=1799348&view=rev
Log:
Allow to override Feature attribute by an operation, and conversely.

Modified:
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java
    sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java?rev=1799348&r1=1799347&r2=1799348&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java
[UTF-8] Tue Jun 20 14:34:41 2017
@@ -712,27 +712,59 @@ public class DefaultFeatureType extends
      */
     private static boolean isAssignableIgnoreName(final PropertyType base, final PropertyType
other) {
         if (base != other) {
+            /*
+             * If the base property is an attribute, then the overriding property shall be
either an attribute
+             * or a parameterless operation producing an attribute.  The parameterless operation
is considered
+             * has having a [1…1] cardinality.
+             */
             if (base instanceof AttributeType<?>) {
-                if (!(other instanceof AttributeType<?>)) {
+                final AttributeType<?> p0 = (AttributeType<?>) base;
+                final AttributeType<?> p1;
+                if (other instanceof AttributeType<?>) {
+                    p1 = (AttributeType<?>) other;
+                } else if (isParameterlessOperation(other)) {
+                    final IdentifiedType result = ((Operation) other).getResult();
+                    if (result instanceof AttributeType<?>) {
+                        p1 = (AttributeType<?>) result;
+                    } else {
+                        return false;
+                    }
+                } else {
                     return false;
                 }
-                final AttributeType<?> p0 = (AttributeType<?>) base;
-                final AttributeType<?> p1 = (AttributeType<?>) other;
-                if (!p0.getValueClass().isAssignableFrom(p1.getValueClass()) ||
-                     p0.getMinimumOccurs() > p1.getMinimumOccurs() ||
-                     p0.getMaximumOccurs() < p1.getMaximumOccurs())
+                final int minOccurs, maxOccurs;
+                if (!p0.getValueClass().isAssignableFrom(p1.getValueClass())    ||
+                    (minOccurs = p0.getMinimumOccurs()) > p1.getMinimumOccurs() ||
+                    (maxOccurs = p0.getMaximumOccurs()) < p1.getMaximumOccurs() ||
+                    (p1 != other && (minOccurs > 1 || maxOccurs < 1)))    
        // [1…1] cardinality for operations.
                 {
                     return false;
                 }
             }
+            /*
+             * Unconditionally test for associations even if we executed the previous block
for attributes,
+             * because an implementation could implement both AttributeType and AssociationRole
interfaces.
+             * This is not recommended, but if it happen we want a behavior as consistent
as possible.
+             */
             if (base instanceof FeatureAssociationRole) {
-                if (!(other instanceof FeatureAssociationRole)) {
+                final FeatureAssociationRole p0 = (FeatureAssociationRole) base;
+                final FeatureAssociationRole p1;
+                if (other instanceof FeatureAssociationRole) {
+                    p1 = (FeatureAssociationRole) other;
+                } else if (isParameterlessOperation(other)) {
+                    final IdentifiedType result = ((Operation) other).getResult();
+                    if (result instanceof FeatureAssociationRole) {
+                        p1 = (FeatureAssociationRole) result;
+                    } else {
+                        return false;
+                    }
+                } else {
                     return false;
                 }
-                final FeatureAssociationRole p0 = (FeatureAssociationRole) base;
-                final FeatureAssociationRole p1 = (FeatureAssociationRole) other;
-                if (p0.getMinimumOccurs() > p1.getMinimumOccurs() ||
-                    p0.getMaximumOccurs() < p1.getMaximumOccurs())
+                final int minOccurs, maxOccurs;
+                if ((minOccurs = p0.getMinimumOccurs()) > p1.getMinimumOccurs() ||
+                    (maxOccurs = p0.getMaximumOccurs()) < p1.getMaximumOccurs() ||
+                    (p1 != other && (minOccurs > 1 || maxOccurs < 1)))    
        // [1…1] cardinality for operations.
                 {
                     return false;
                 }
@@ -742,17 +774,26 @@ public class DefaultFeatureType extends
                     return false;
                 }
             }
+            /*
+             * Operations can be overridden by other operations having the same parameters.
+             * In the special case of parameterless operations, can also be overridden by
+             * AttributeType or FeatureAssociationRole.
+             */
             if (base instanceof Operation) {
-                if (!(other instanceof Operation)) {
-                    return false;
-                }
                 final Operation p0 = (Operation) base;
-                final Operation p1 = (Operation) other;
-                if (!Objects.equals(p0.getParameters(), p1.getParameters())) {
+                final IdentifiedType r1;
+                if (other instanceof Operation) {
+                    final Operation p1 = (Operation) other;
+                    if (!Objects.equals(p0.getParameters(), p1.getParameters())) {
+                        return false;
+                    }
+                    r1 = p1.getResult();
+                } else if (isParameterlessOperation(base)) {
+                    r1 = other;
+                } else {
                     return false;
                 }
                 final IdentifiedType r0 = p0.getResult();
-                final IdentifiedType r1 = p1.getResult();
                 if (r0 != r1) {
                     if (r0 instanceof FeatureType) {
                         if (!(r1 instanceof FeatureType) || !((FeatureType) r0).isAssignableFrom((FeatureType)
r1)) {
@@ -764,6 +805,11 @@ public class DefaultFeatureType extends
                             return false;
                         }
                     }
+                    if (r0 instanceof Operation) {
+                        if (!(r1 instanceof Operation) || !isAssignableIgnoreName((Operation)
r0, (Operation) r1)) {
+                            return false;
+                        }
+                    }
                 }
             }
         }

Modified: sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java?rev=1799348&r1=1799347&r2=1799348&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/builder/FeatureTypeBuilderTest.java
[UTF-8] Tue Jun 20 14:34:41 2017
@@ -17,10 +17,14 @@
 package org.apache.sis.feature.builder;
 
 import java.util.Iterator;
+import java.util.Collections;
 import com.esri.core.geometry.Geometry;
 import com.esri.core.geometry.Point;
+import org.apache.sis.feature.AbstractOperation;
+import org.opengis.geometry.Envelope;
 import org.apache.sis.internal.feature.AttributeConvention;
 import org.apache.sis.feature.DefaultFeatureTypeTest;
+import org.apache.sis.feature.FeatureOperations;
 import org.apache.sis.referencing.crs.HardCodedCRS;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.DependsOn;
@@ -33,7 +37,9 @@ import static org.junit.Assert.*;
 // Branch-dependent imports
 import org.opengis.feature.AttributeType;
 import org.opengis.feature.FeatureType;
+import org.opengis.feature.IdentifiedType;
 import org.opengis.feature.PropertyType;
+import org.opengis.feature.Operation;
 
 
 /**
@@ -288,4 +294,56 @@ public final strictfp class FeatureTypeB
         assertNotSame("Should return a new FeatureType since we changed an attribute.",
                       city, builder.build());
     }
+
+    /**
+     * Tests overriding the "sis:envelope" property. This may happen when the user wants
to specify
+     * envelope himself instead than relying on the automatically computed value.
+     */
+    @Test
+    public void testEnvelopeOverride() {
+        FeatureTypeBuilder builder = new FeatureTypeBuilder().setName("CoverageRecord").setAbstract(true);
+        builder.addAttribute(Geometry.class).setName(AttributeConvention.GEOMETRY_PROPERTY).addRole(AttributeRole.DEFAULT_GEOMETRY);
+        final FeatureType parentType = builder.build();
+
+        builder = new FeatureTypeBuilder().setName("Record").setSuperTypes(parentType);
+        builder.addAttribute(Envelope.class).setName(AttributeConvention.ENVELOPE_PROPERTY);
+        final FeatureType childType = builder.build();
+
+        final Iterator<? extends PropertyType> it = childType.getProperties(true).iterator();
+        assertPropertyEquals("sis:envelope", Envelope.class, it.next());
+        assertPropertyEquals("sis:geometry", Geometry.class, it.next());
+        assertFalse(it.hasNext());
+    }
+
+    /**
+     * Tests overriding an attribute by an operation.
+     * This is the converse of {@link #testEnvelopeOverride()}.
+     */
+    @Test
+    public void testOverrideByOperation() {
+        FeatureTypeBuilder builder = new FeatureTypeBuilder().setName("Parent").setAbstract(true);
+        final AttributeType<Integer> pa = builder.addAttribute(Integer.class).setName("A").build();
+        builder.addAttribute(Integer.class).setName("B");
+        final FeatureType parentType = builder.build();
+
+        builder = new FeatureTypeBuilder().setName("Child").setSuperTypes(parentType);
+        builder.addProperty(FeatureOperations.link(Collections.singletonMap(AbstractOperation.NAME_KEY,
"B"), pa));
+        final FeatureType childType = builder.build();
+
+        final Iterator<? extends PropertyType> it = childType.getProperties(true).iterator();
+        assertPropertyEquals("A", Integer.class, it.next());
+        assertPropertyEquals("B", Integer.class, it.next());
+        assertFalse(it.hasNext());
+    }
+
+    /**
+     * Verifies that the given property is an attribute with the given name and value class.
+     */
+    private static void assertPropertyEquals(final String name, final Class<?> valueClass,
IdentifiedType property) {
+        assertEquals("name", name, property.getName().toString());
+        if (property instanceof Operation) {
+            property = ((Operation) property).getResult();
+        }
+        assertEquals("valueClass", valueClass, ((AttributeType<?>) property).getValueClass());
+    }
 }



Mime
View raw message