You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2016/08/04 09:52:40 UTC
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/
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(\u2026)} 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());
+ }
}