sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1755171 - in /sis/branches/JDK8/core/sis-feature/src: main/java/org/apache/sis/feature/builder/ test/java/org/apache/sis/feature/builder/
Date Thu, 04 Aug 2016 09:52:40 GMT
Author: desruisseaux
Date: Thu Aug  4 09:52:40 2016
New Revision: 1755171

URL: http://svn.apache.org/viewvc?rev=1755171&view=rev
Log:
Make the PropertyType.build() method public, and fix a bug about a cache value not cleared.

Modified:
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/AssociationRoleBuilder.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/AttributeTypeBuilder.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/CharacteristicTypeBuilder.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/OperationWrapper.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/PropertyTypeBuilder.java
    sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/TypeBuilder.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/builder/AssociationRoleBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/AssociationRoleBuilder.java?rev=1755171&r1=1755170&r2=1755171&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/AssociationRoleBuilder.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/AssociationRoleBuilder.java
[UTF-8] Thu Aug  4 09:52:40 2016
@@ -21,7 +21,6 @@ import org.apache.sis.feature.DefaultAss
 
 // Branch-dependent imports
 import org.opengis.feature.FeatureType;
-import org.opengis.feature.PropertyType;
 import org.opengis.feature.FeatureAssociationRole;
 
 
@@ -53,6 +52,12 @@ public final class AssociationRoleBuilde
     private final GenericName typeName;
 
     /**
+     * The association created by this builder, or {@code null} if not yet created.
+     * This field must be cleared every time that a setter method is invoked on this builder.
+     */
+    private transient FeatureAssociationRole property;
+
+    /**
      * Creates a new {@code AssociationRole} builder for values of the given type.
      * The {@code type} argument can be null if unknown, but {@code typeName} is mandatory.
      *
@@ -71,6 +76,7 @@ public final class AssociationRoleBuilde
      */
     AssociationRoleBuilder(final FeatureTypeBuilder owner, final FeatureAssociationRole template)
{
         super(owner, template);
+        property      = template;
         minimumOccurs = template.getMinimumOccurs();
         maximumOccurs = template.getMaximumOccurs();
         type          = template.getValueType();
@@ -78,6 +84,16 @@ public final class AssociationRoleBuilde
     }
 
     /**
+     * If the {@code FeatureAssociationRole} created by the last call to {@link #build()}
has been cached,
+     * clears that cache. This method must be invoked every time that a setter method is
invoked.
+     */
+    @Override
+    final void clearCache() {
+        property = null;
+        super.clearCache();
+    }
+
+    /**
      * Appends a text inside the value returned by {@link #toString()}, before the closing
bracket.
      */
     @Override
@@ -164,14 +180,21 @@ public final class AssociationRoleBuilde
     }
 
     /**
-     * Creates a new property type from the current setting.
+     * Builds the association role from the information specified to this builder.
+     * If a role has already been built and this builder state has not changed since the
role creation,
+     * then the previously created {@code FeatureAssociationRole} instance is returned.
+     *
+     * @return the association role.
      */
     @Override
-    final PropertyType create() {
-        if (type != null) {
-            return new DefaultAssociationRole(identification(), type, minimumOccurs, maximumOccurs);
-        } else {
-            return new DefaultAssociationRole(identification(), typeName, minimumOccurs,
maximumOccurs);
+    public FeatureAssociationRole build() {
+        if (property == null) {
+            if (type != null) {
+                property = new DefaultAssociationRole(identification(), type, minimumOccurs,
maximumOccurs);
+            } else {
+                property = new DefaultAssociationRole(identification(), typeName, minimumOccurs,
maximumOccurs);
+            }
         }
+        return property;
     }
 }

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/AttributeTypeBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/AttributeTypeBuilder.java?rev=1755171&r1=1755170&r2=1755171&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/AttributeTypeBuilder.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/AttributeTypeBuilder.java
[UTF-8] Thu Aug  4 09:52:40 2016
@@ -40,7 +40,6 @@ import org.apache.sis.util.Unconvertible
 // Branch-dependent imports
 import java.util.Objects;
 import org.opengis.feature.AttributeType;
-import org.opengis.feature.PropertyType;
 
 
 /**
@@ -100,6 +99,12 @@ public final class AttributeTypeBuilder<
     final List<CharacteristicTypeBuilder<?>> characteristics;
 
     /**
+     * The attribute type created by this builder, or {@code null} if not yet created.
+     * This field must be cleared every time that a setter method is invoked on this builder.
+     */
+    private transient AttributeType<V> property;
+
+    /**
      * Creates a new builder initialized to the values of the given builder.
      * This constructor is for {@link #setValueClass(Class)} implementation only.
      *
@@ -134,6 +139,7 @@ public final class AttributeTypeBuilder<
      */
     AttributeTypeBuilder(final FeatureTypeBuilder owner, final AttributeType<V> template)
{
         super(owner, template);
+        property      = template;
         minimumOccurs = template.getMinimumOccurs();
         maximumOccurs = template.getMaximumOccurs();
         valueClass    = template.getValueClass();
@@ -146,6 +152,16 @@ public final class AttributeTypeBuilder<
     }
 
     /**
+     * If the {@code AttributeType} created by the last call to {@link #build()} has been
cached,
+     * clears that cache. This method must be invoked every time that a setter method is
invoked.
+     */
+    @Override
+    final void clearCache() {
+        property = null;
+        super.clearCache();
+    }
+
+    /**
      * Returns a default name to use if the user did not specified a name. The first letter
will be changed to
      * lower case (unless the name looks like an acronym) for compliance with Java convention
on attribute names.
      */
@@ -230,8 +246,7 @@ public final class AttributeTypeBuilder<
         for (final CharacteristicTypeBuilder<?> c : characteristics) {
             c.owner(newb);
         }
-        owner.properties.set(owner.properties.lastIndexOf(this), newb);
-        // Note: a negative lastIndexOf(old) would be a bug in our algorithm.
+        owner.replace(this, newb);
         dispose();
         return newb;
     }
@@ -611,14 +626,40 @@ public final class AttributeTypeBuilder<
     }
 
     /**
-     * Creates a new attribute type from the current setting.
+     * Builds the attribute type from the information specified to this builder.
+     * If a type has already been built and this builder state has not changed since the
type creation,
+     * then the previously created {@code AttributeType} instance is returned.
+     *
+     * <div class="note"><b>Example:</b>
+     * the following lines of code add a "name" attribute to a "City" feature, then get the
corresponding
+     * {@code AttributeType<String>} instance. If no setter method is invoked on the
builder of the "name"
+     * attribute after those lines, then the {@code name} variable below will reference the
same instance
+     * than the "name" attribute in the {@code city} type.
+     *
+     * {@preformat java
+     *   FeatureTypeBuilder builder = new FeatureTypeBuilder().setName("City");
+     *   AttributeType<String> name = builder.addAttribute(String.class).setName("name").build();
+     *   FeatureType city = builder.build();
+     *
+     *   assert city.getProperty("name") == name : "AttributeType instance should be the
same.";
+     * }
+     *
+     * Note that {@code city.getProperty("name")} returns {@code AttributeType<?>},
+     * i.e. the {@linkplain #getValueClass() value class} is lost at compile-time.
+     * By comparison, this {@code build()} method has a more accurate return type.
+     * </div>
+     *
+     * @return the attribute type.
      */
     @Override
-    final PropertyType create() {
-        final AttributeType<?>[] chrts = new AttributeType<?>[characteristics.size()];
-        for (int i=0; i<chrts.length; i++) {
-            chrts[i] = characteristics.get(i).build();
+    public AttributeType<V> build() {
+        if (property == null) {
+            final AttributeType<?>[] chrts = new AttributeType<?>[characteristics.size()];
+            for (int i=0; i<chrts.length; i++) {
+                chrts[i] = characteristics.get(i).build();
+            }
+            property = new DefaultAttributeType<>(identification(), valueClass, minimumOccurs,
maximumOccurs, defaultValue, chrts);
         }
-        return new DefaultAttributeType<>(identification(), valueClass, minimumOccurs,
maximumOccurs, defaultValue, chrts);
+        return property;
     }
 }

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/CharacteristicTypeBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/CharacteristicTypeBuilder.java?rev=1755171&r1=1755170&r2=1755171&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/CharacteristicTypeBuilder.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/CharacteristicTypeBuilder.java
[UTF-8] Thu Aug  4 09:52:40 2016
@@ -107,9 +107,9 @@ public final class CharacteristicTypeBui
     CharacteristicTypeBuilder(final AttributeTypeBuilder<?> owner, final AttributeType<V>
template) {
         super(template, owner.getLocale());
         this.owner     = owner;
+        characteristic = template;
         valueClass     = template.getValueClass();
         defaultValue   = template.getDefaultValue();
-        characteristic = template;
     }
 
     /**
@@ -282,9 +282,14 @@ public final class CharacteristicTypeBui
     }
 
     /**
-     * Creates a new characteristic from the current setting.
+     * Builds the characteristic type from the information specified to this builder.
+     * If a type has already been built and this builder state has not changed since the
type creation,
+     * then the previously created {@code AttributeType} instance is returned.
+     *
+     * @return the characteristic type.
      */
-    final AttributeType<V> build() {
+    @Override
+    public AttributeType<V> build() {
         if (characteristic == null) {
             characteristic = new DefaultAttributeType<>(identification(), valueClass,
0, 1, defaultValue);
         }

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java?rev=1755171&r1=1755170&r2=1755171&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/FeatureTypeBuilder.java
[UTF-8] Thu Aug  4 09:52:40 2016
@@ -70,7 +70,7 @@ public class FeatureTypeBuilder extends
     /**
      * Builders for the properties (attributes, associations or operations) of this feature.
      */
-    final List<PropertyTypeBuilder> properties;
+    private final List<PropertyTypeBuilder> properties;
 
     /**
      * The parent of the feature to create. By default, new features have no parent.
@@ -607,10 +607,13 @@ public class FeatureTypeBuilder extends
      * One of the {@code setName(…)} methods must have been invoked before this {@code
build()} method (mandatory).
      * All other methods are optional, but some calls to a {@code add} method are usually
needed.
      *
-     * @return the new feature type.
-     * @throws IllegalStateException if the feature type contains incompatible
-     *         {@linkplain AttributeTypeBuilder#setCRS CRS characteristics}.
+     * <p>If a feature type has already been built and this builder state has not changed
since the
+     * feature type creation, then the previously created {@code FeatureType} instance is
returned.</p>
+     *
+     * @return the feature type.
+     * @throws IllegalStateException if the builder contains inconsistent information.
      */
+    @Override
     public FeatureType build() throws IllegalStateException {
         if (feature == null) {
             /*
@@ -708,11 +711,28 @@ public class FeatureTypeBuilder extends
     /**
      * Helper method for creating identification info of synthetic attributes.
      */
-    static Map<String,?> name(final GenericName name) {
+    private static Map<String,?> name(final GenericName name) {
         return Collections.singletonMap(AbstractOperation.NAME_KEY, name);
     }
 
     /**
+     * Replaces the given builder instance by a new instance, or delete the old instance.
+     * This builder should contain exactly one instance of the given {@code old} builder.
+     *
+     * @param old  the instance to replace.
+     * @param replacement  the replacement, or {@code null} for deleting the old instance.
+     */
+    final void replace(final PropertyTypeBuilder old, final PropertyTypeBuilder replacement)
{
+        final int index = properties.lastIndexOf(old);
+        if (index < 0 || (replacement != null ? properties.set(index, replacement) : properties.remove(index))
!= old) {
+            // Assuming that there is no bug in our algorithm, this exception should never
happen
+            // unless builder state has been changed in another thread before this method
completed.
+            throw new CorruptedObjectException();
+        }
+        clearCache();
+    }
+
+    /**
      * Formats a string representation of this builder for debugging purpose.
      */
     @Override

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/OperationWrapper.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/OperationWrapper.java?rev=1755171&r1=1755170&r2=1755171&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/OperationWrapper.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/OperationWrapper.java
[UTF-8] Thu Aug  4 09:52:40 2016
@@ -52,7 +52,7 @@ final class OperationWrapper extends Pro
      * Returns the wrapped operation.
      */
     @Override
-    PropertyType create() {
+    public PropertyType build() {
         return operation;
     }
 

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/PropertyTypeBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/PropertyTypeBuilder.java?rev=1755171&r1=1755170&r2=1755171&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/PropertyTypeBuilder.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/PropertyTypeBuilder.java
[UTF-8] Thu Aug  4 09:52:40 2016
@@ -71,12 +71,6 @@ public abstract class PropertyTypeBuilde
     int maximumOccurs;
 
     /**
-     * The attribute or association created by this builder, or {@code null} if not yet created.
-     * This field must be cleared every time that a setter method is invoked on this builder.
-     */
-    private transient PropertyType property;
-
-    /**
      * Creates a new builder initialized to the values of the given builder.
      * This constructor is for {@link AttributeTypeBuilder#setValueClass(Class)} implementation.
      *
@@ -101,7 +95,6 @@ public abstract class PropertyTypeBuilde
         this.owner    = owner;
         minimumOccurs = owner.defaultMinimumOccurs;
         maximumOccurs = owner.defaultMaximumOccurs;
-        property      = template;
     }
 
     /**
@@ -157,27 +150,22 @@ public abstract class PropertyTypeBuilde
      * clears that cache. This method must be invoked every time that a setter method is
invoked.
      */
     @Override
-    final void clearCache() {
-        property = null;
+    void clearCache() {
         ensureAlive(owner);
         owner.clearCache();
     }
 
     /**
-     * Returns the property type from the current setting.
-     * This method may return an existing property if it was already created.
-     */
-    final PropertyType build() {
-        if (property == null) {
-            property = create();
-        }
-        return property;
-    }
-
-    /**
-     * Creates a new property type from the current setting.
+     * Builds the property type from the information specified to this builder.
+     * If a type has already been built and this builder state has not changed since the
type creation,
+     * then the previously created {@code PropertyType} instance is returned
+     * (see {@link AttributeTypeBuilder#build()} for more information).
+     *
+     * @return the property type.
+     * @throws IllegalStateException if the builder contains inconsistent information.
      */
-    abstract PropertyType create();
+    @Override
+    public abstract PropertyType build() throws IllegalStateException;
 
     /**
      * Flags this builder as a disposed one. The builder should not be used anymore after
this method call.
@@ -196,8 +184,7 @@ public abstract class PropertyTypeBuilde
      */
     public void remove() {
         if (owner != null) {
-            owner.properties.remove(owner.properties.lastIndexOf(this));
-            // Note: a negative lastIndexOf(old) would be a bug in our algorithm.
+            owner.replace(this, null);
             dispose();
         }
     }

Modified: sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/TypeBuilder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/TypeBuilder.java?rev=1755171&r1=1755170&r2=1755171&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/TypeBuilder.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/builder/TypeBuilder.java
[UTF-8] Thu Aug  4 09:52:40 2016
@@ -459,4 +459,14 @@ public abstract class TypeBuilder implem
      */
     void dispose() {
     }
+
+    /**
+     * Builds the feature or property type from the information specified to this builder.
+     * If a type has already been built and this builder state has not changed since the
type creation,
+     * then the previously created {@code IdentifiedType} instance is returned.
+     *
+     * @return the feature or property type.
+     * @throws IllegalStateException if the builder contains inconsistent information.
+     */
+    public abstract IdentifiedType build() throws IllegalStateException;
 }

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=1755171&r1=1755170&r2=1755171&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] Thu Aug  4 09:52:40 2016
@@ -225,4 +225,27 @@ public final strictfp class FeatureTypeB
         assertEquals("superTypes", "City",    TestUtilities.getSingleton(builder.getSuperTypes()).getName().toString());
         assertFalse ("isAbstract",            builder.isAbstract());
     }
+
+    /**
+     * Verifies that {@code build()} method returns the previously created instance when
possible.
+     * See {@link AttributeTypeBuilder#build()} javadoc for a rational.
+     */
+    @Test
+    @DependsOnMethod("testAddAttribute")
+    public void testBuildCache() {
+        final FeatureTypeBuilder builder = new FeatureTypeBuilder().setName("City");
+        final AttributeType<String> name = builder.addAttribute(String.class).setName("name").build();
+        final FeatureType city = builder.build();
+        assertSame("Should return the existing AttributeType.", name, city.getProperty("name"));
+        assertSame("Should return the existing FeatureType.", city, builder.build());
+
+        assertSame("Should return the existing AttributeType since we didn't changed anything.",
+                   name, builder.getProperty("name").build());
+
+        assertNotSame("Should return a new AttributeType since we changed something.",
+                      name, builder.getProperty("name").setDescription("Name of the city").build());
+
+        assertNotSame("Should return a new FeatureType since we changed an attribute.",
+                      city, builder.build());
+    }
 }



Mime
View raw message