Author: desruisseaux
Date: Thu May 29 19:03:14 2014
New Revision: 1598371
URL: http://svn.apache.org/r1598371
Log:
DefaultFeatureType now implements FeatureType.
We had to disable the check against infinite recursivity in 'isAssignableFrom'.
The previous check was wrong anyway (we need to compare feature pairs, not only
the base feature type). We will implement a new recursivity check later.
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultFeatureType.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/package-info.java
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java?rev=1598371&r1=1598370&r2=1598371&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractAssociation.java
[UTF-8] Thu May 29 19:03:14 2014
@@ -25,6 +25,9 @@ import org.apache.sis.util.Debug;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.resources.Errors;
+// Branch-dependent imports
+import org.opengis.feature.FeatureType;
+
/**
* Indicates the role played by the association between two features.
@@ -185,8 +188,8 @@ public abstract class AbstractAssociatio
* Ensures that storing a feature of the given type is valid for an
association
* expecting the given base type.
*/
- final void ensureValid(final DefaultFeatureType base, final
DefaultFeatureType type) {
- if (base != type && !base.maybeAssignableFrom(type)) {
+ final void ensureValid(final FeatureType base, final FeatureType type) {
+ if (base != type && !DefaultFeatureType.maybeAssignableFrom(base,
type)) {
throw new IllegalArgumentException(
Errors.format(Errors.Keys.IllegalArgumentClass_3,
getName(), base.getName(), type.getName()));
}
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java?rev=1598371&r1=1598370&r2=1598371&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/AbstractFeature.java
[UTF-8] Thu May 29 19:03:14 2014
@@ -31,6 +31,7 @@ import org.apache.sis.internal.util.Chec
// Branch-dependent imports
import org.opengis.feature.PropertyType;
import org.opengis.feature.AttributeType;
+import org.opengis.feature.FeatureType;
/**
@@ -79,7 +80,7 @@ public abstract class AbstractFeature im
/**
* Information about the feature (name, characteristics, <i>etc.</i>).
*/
- final DefaultFeatureType type;
+ final FeatureType type;
/**
* Creates a new feature of the given type.
@@ -88,7 +89,7 @@ public abstract class AbstractFeature im
*
* @see DefaultFeatureType#newInstance()
*/
- protected AbstractFeature(final DefaultFeatureType type) {
+ protected AbstractFeature(final FeatureType type) {
ArgumentChecks.ensureNonNull("type", type);
this.type = type;
}
@@ -109,26 +110,11 @@ public abstract class AbstractFeature im
*
* @return Information about the feature.
*/
- public DefaultFeatureType getType() {
+ public FeatureType getType() {
return type;
}
/**
- * Returns the type for the property of the given name.
- *
- * @param name The property name.
- * @return The type for the property of the given name (never {@code
null}).
- * @throws IllegalArgumentException If the given argument is not a
property name of this feature.
- */
- final PropertyType getPropertyType(final String name) throws
IllegalArgumentException {
- final PropertyType pt = type.getProperty(name);
- if (pt != null) {
- return pt;
- }
- throw new
IllegalArgumentException(Errors.format(Errors.Keys.PropertyNotFound_2,
getName(), name));
- }
-
- /**
* Returns the property (attribute, operation or association) of the given
name.
*
* <div class="warning"><b>Warning:</b> In a future SIS version, the
return type may be changed
@@ -153,13 +139,13 @@ public abstract class AbstractFeature im
* <ul>
* <li>It must be non-null.</li>
* <li>Its {@linkplain Property#getName() name} shall be the name of the
property to set in this feature.</li>
- * <li>Its type shall be the same instance than the {@linkplain
AbstractFeature#getPropertyType(String)
+ * <li>Its type shall be the same instance than the {@linkplain
DefaultFeatureType#getProperty(String)
* property type} defined by the feature type for the above name.
* In other words, the following condition shall hold:</li>
* </ul>
*
* {@preformat java
- * assert property.getType() ==
getType().getPropertyType(property.getName());
+ * assert property.getType() ==
getType().getProperty(property.getName());
* }
*
* <div class="note"><b>Note:</b> This method is useful for storing
non-default {@code Attribute} or
@@ -186,7 +172,7 @@ public abstract class AbstractFeature im
* @return A {@code Property} wrapping the given value.
*/
final Property createProperty(final String name, final Object value) {
- final PropertyType pt = getPropertyType(name);
+ final PropertyType pt = type.getProperty(name);
if (pt instanceof AttributeType<?>) {
return AbstractAttribute.create((AttributeType<?>) pt, value);
} else if (pt instanceof DefaultAssociationRole) {
@@ -205,7 +191,7 @@ public abstract class AbstractFeature im
* @throws IllegalArgumentException If the given argument is not an
attribute or association name of this feature.
*/
final Property createProperty(final String name) throws
IllegalArgumentException {
- final PropertyType pt = getPropertyType(name);
+ final PropertyType pt = type.getProperty(name);
if (pt instanceof AttributeType<?>) {
return AbstractAttribute.create((AttributeType<?>) pt);
} else if (pt instanceof DefaultAssociationRole) {
@@ -224,7 +210,7 @@ public abstract class AbstractFeature im
* @throws IllegalArgumentException If the given argument is not an
attribute or association name of this feature.
*/
final Object getDefaultValue(final String name) throws
IllegalArgumentException {
- final PropertyType pt = getPropertyType(name);
+ final PropertyType pt = type.getProperty(name);
if (pt instanceof AttributeType<?>) {
return getDefaultValue((AttributeType<?>) pt);
} else if (pt instanceof DefaultAssociationRole) {
@@ -358,10 +344,10 @@ public abstract class AbstractFeature im
private static void setAssociationValue(final AbstractAssociation
association, final Object value) {
if (value != null) {
final DefaultAssociationRole role = association.getRole();
- final DefaultFeatureType base = role.getValueType();
+ final FeatureType base = role.getValueType();
if (value instanceof AbstractFeature) {
- final DefaultFeatureType actual = ((AbstractFeature)
value).getType();
- if (!base.maybeAssignableFrom(actual)) {
+ final FeatureType actual = ((AbstractFeature) value).getType();
+ if (base != actual &&
!DefaultFeatureType.maybeAssignableFrom(base, actual)) {
throw illegalPropertyType(role.getName(),
actual.getName());
}
} else if (value instanceof Collection<?>) {
@@ -404,15 +390,15 @@ public abstract class AbstractFeature im
* @param property The property to verify.
*/
final void verifyPropertyType(final String name, final Property property) {
- final PropertyType type, base = getPropertyType(name);
+ final PropertyType pt, base = type.getProperty(name);
if (property instanceof AbstractAttribute<?>) {
- type = ((AbstractAttribute<?>) property).getType();
+ pt = ((AbstractAttribute<?>) property).getType();
} else if (property instanceof AbstractAssociation) {
- type = ((AbstractAssociation) property).getRole();
+ pt = ((AbstractAssociation) property).getRole();
} else {
throw illegalPropertyType(base.getName(), property.getClass());
}
- if (type != base) {
+ if (pt != base) {
throw new
IllegalArgumentException(Errors.format(Errors.Keys.MismatchedPropertyType_1,
name));
}
}
@@ -422,7 +408,7 @@ public abstract class AbstractFeature im
* to store. The returned value is usually the same than the given one,
except in the case of collections.
*/
final Object verifyPropertyValue(final String name, final Object value) {
- final PropertyType pt = getPropertyType(name);
+ final PropertyType pt = type.getProperty(name);
if (pt instanceof AttributeType<?>) {
if (value != null) {
return verifyAttributeValue((AttributeType<?>) pt, value);
@@ -476,8 +462,9 @@ public abstract class AbstractFeature im
* If the user gave us a single value, first verify its validity.
* Then wrap it in a list of 1 element if this property is
multi-valued.
*/
- final DefaultFeatureType valueType = ((AbstractFeature)
value).getType();
- if (role.getValueType().maybeAssignableFrom(valueType)) {
+ final FeatureType valueType = ((AbstractFeature) value).getType();
+ final FeatureType base = role.getValueType();
+ if (base != valueType &&
DefaultFeatureType.maybeAssignableFrom(base, valueType)) {
return isSingleton ? value :
singletonList(AbstractFeature.class, role.getMinimumOccurs(), value);
} else {
throw illegalPropertyType(role.getName(), valueType.getName());
@@ -494,15 +481,15 @@ public abstract class AbstractFeature im
* Verifies if all values in the given collection are valid instances of
feature for the given association role.
*/
private static void verifyAssociationValues(final DefaultAssociationRole
role, final Collection<?> values) {
- final DefaultFeatureType base = role.getValueType();
+ final FeatureType base = role.getValueType();
int index = 0;
for (final Object value : values) {
ArgumentChecks.ensureNonNullElement("values", index, value);
if (!(value instanceof AbstractFeature)) {
throw illegalValueClass(role.getName(), value);
}
- final DefaultFeatureType type = ((AbstractFeature)
value).getType();
- if (!base.maybeAssignableFrom(type)) {
+ final FeatureType type = ((AbstractFeature) value).getType();
+ if (base != type && !DefaultFeatureType.maybeAssignableFrom(base,
type)) {
throw illegalPropertyType(role.getName(), type.getName());
}
index++;
@@ -595,8 +582,8 @@ public abstract class AbstractFeature im
*/
public DataQuality quality() {
final Validator v = new Validator(ScopeCode.FEATURE);
- for (final String name : type.indices().keySet()) {
- final Property property = (Property) getProperty(name);
+ for (final PropertyType pt : type.getProperties(true)) {
+ final Property property = (Property)
getProperty(pt.getName().toString());
final DataQuality quality;
if (property instanceof AbstractAttribute<?>) {
quality = ((AbstractAttribute<?>) property).quality();
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java?rev=1598371&r1=1598370&r2=1598371&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DefaultAssociationRole.java
[UTF-8] Thu May 29 19:03:14 2014
@@ -26,6 +26,7 @@ import static org.apache.sis.util.Argume
// Branch-dependent imports
import org.opengis.feature.PropertyType;
import org.opengis.feature.AttributeType;
+import org.opengis.feature.FeatureType;
/**
@@ -63,7 +64,7 @@ public class DefaultAssociationRole exte
*
* @see #getValueType()
*/
- private final DefaultFeatureType valueType;
+ private final FeatureType valueType;
/**
* The name of the property to use as a title for the associated feature,
or an empty string if none.
@@ -114,7 +115,7 @@ public class DefaultAssociationRole exte
* @param maximumOccurs The maximum number of occurrences of the
association within its containing entity,
* or {@link Integer#MAX_VALUE} if there is no
restriction.
*/
- public DefaultAssociationRole(final Map<String,?> identification, final
DefaultFeatureType valueType,
+ public DefaultAssociationRole(final Map<String,?> identification, final
FeatureType valueType,
final int minimumOccurs, final int maximumOccurs)
{
super(identification, minimumOccurs, maximumOccurs);
@@ -130,7 +131,7 @@ public class DefaultAssociationRole exte
*
* @return The type of feature values.
*/
- public final DefaultFeatureType getValueType() {
+ public final FeatureType getValueType() {
return valueType;
}
@@ -142,7 +143,7 @@ public class DefaultAssociationRole exte
String p = titleProperty; // No synchronization - not a big deal if
computed twice.
if (p == null) {
p = "";
- for (final PropertyType type : valueType.getPropertyTypes(true)) {
+ for (final PropertyType type : valueType.getProperties(true)) {
if (type instanceof AttributeType<?>) {
final AttributeType<?> pt = (AttributeType<?>) type;
if (pt.getMaximumOccurs() != 0 &&
CharSequence.class.isAssignableFrom(pt.getValueClass())) {
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=1598371&r1=1598370&r2=1598371&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] Thu May 29 19:03:14 2014
@@ -23,7 +23,6 @@ import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.util.LinkedHashMap;
-import java.util.IdentityHashMap;
import java.util.Collection;
import java.util.Collections;
import java.io.IOException;
@@ -37,8 +36,10 @@ import org.apache.sis.internal.util.Coll
import org.apache.sis.internal.util.UnmodifiableArrayList;
// Branch-dependent imports
+import java.util.Objects;
import org.opengis.feature.PropertyType;
import org.opengis.feature.AttributeType;
+import org.opengis.feature.FeatureType;
/**
@@ -49,18 +50,13 @@ import org.opengis.feature.AttributeType
* compared to the Java language, {@code FeatureType} is equivalent to {@link
Class} while
* {@code Feature} instances are equivalent to {@link Object} instances of
that class.</div>
*
- * <div class="warning"><b>Warning:</b>
- * This class is expected to implement a GeoAPI {@code FeatureType} interface
in a future version.
- * When such interface will be available, most references to {@code
DefaultFeatureType} in the API
- * will be replaced by references to the {@code FeatureType} interface.</div>
- *
* {@section Naming}
* The feature type {@linkplain #getName() name} is mandatory and should be
unique. Those names are the main
* criterion used for deciding if a feature type {@linkplain #isAssignableFrom
is assignable from} another type.
* Names can be {@linkplain org.apache.sis.util.iso.DefaultScopedName scoped}
for avoiding name collision.
*
* {@section Properties and inheritance}
- * Each feature type can provide descriptions for the following {@linkplain
#getPropertyTypes(boolean) properties}:
+ * Each feature type can provide descriptions for the following {@linkplain
#getProperties(boolean) properties}:
*
* <ul>
* <li>{@linkplain DefaultAttributeType Attributes}</li>
@@ -91,7 +87,7 @@ import org.opengis.feature.AttributeType
*
* @see AbstractFeature
*/
-public class DefaultFeatureType extends AbstractIdentifiedType {
+public class DefaultFeatureType extends AbstractIdentifiedType implements
FeatureType {
/**
* For cross-version compatibility.
*/
@@ -123,13 +119,13 @@ public class DefaultFeatureType extends
*
* @see #getSuperTypes()
*/
- private final Set<DefaultFeatureType> superTypes;
+ private final Set<FeatureType> superTypes;
/**
- * The names of all parents of this feature type, including parents of
parents. This is used
- * for a more efficient implementation of {@link
#isAssignableFrom(DefaultFeatureType)}.
+ * The names of all parents of this feature type, including parents of
parents.
+ * This is used for a more efficient implementation of {@link
#isAssignableFrom(FeatureType)}.
*
- * @see #isAssignableFrom(DefaultFeatureType)
+ * @see #isAssignableFrom(FeatureType)
*/
private transient Set<GenericName> assignableTo;
@@ -137,7 +133,7 @@ public class DefaultFeatureType extends
* Any feature operation, any feature attribute type and any feature
association role
* that carries characteristics of a feature type.
*
- * @see #getPropertyTypes(boolean)
+ * @see #getProperties(boolean)
*/
private final List<PropertyType> properties;
@@ -145,7 +141,7 @@ public class DefaultFeatureType extends
* All properties, including the ones declared in the super-types.
* This is an unmodifiable view of the {@link #byName} values.
*
- * @see #getPropertyTypes(boolean)
+ * @see #getProperties(boolean)
*/
private transient Collection<PropertyType> allProperties;
@@ -207,13 +203,13 @@ public class DefaultFeatureType extends
* association role that carries characteristics of
a feature type.
*/
public DefaultFeatureType(final Map<String,?> identification, final
boolean isAbstract,
- final DefaultFeatureType[] superTypes, final PropertyType...
properties)
+ final FeatureType[] superTypes, final PropertyType... properties)
{
super(identification);
ArgumentChecks.ensureNonNull("properties", properties);
this.isAbstract = isAbstract;
- this.superTypes = (superTypes == null) ?
Collections.<DefaultFeatureType>emptySet() :
-
CollectionsExt.<DefaultFeatureType>immutableSet(true, superTypes);
+ this.superTypes = (superTypes == null) ?
Collections.<FeatureType>emptySet() :
+ CollectionsExt.<FeatureType>immutableSet(true,
superTypes);
switch (properties.length) {
case 0: this.properties = Collections.emptyList(); break;
case 1: this.properties =
Collections.singletonList(properties[0]); break;
@@ -318,28 +314,23 @@ public class DefaultFeatureType extends
* This method invokes itself recursively in order to use the information
provided in super-types.
* This method also performs an opportunist verification of argument
validity.
*/
- private void scanPropertiesFrom(final DefaultFeatureType source) {
- for (final DefaultFeatureType parent : source.getSuperTypes()) {
+ private void scanPropertiesFrom(final FeatureType source) {
+ for (final FeatureType parent : source.getSuperTypes()) {
if (assignableTo.add(parent.getName())) {
scanPropertiesFrom(parent);
}
}
int index = -1;
- Map<DefaultFeatureType,Boolean> done = null;
- for (final PropertyType property : source.properties) {
+ for (final PropertyType property : source.getProperties(false)) {
ArgumentChecks.ensureNonNullElement("properties", ++index,
property);
final String name = toString(property.getName(), source, index);
final PropertyType previous = byName.put(name, property);
if (previous != null) {
- if (done == null) {
- done = new IdentityHashMap<>(4); // Guard against infinite
recursivity.
- }
- if (!isAssignableIgnoreName(previous, property, done)) {
- final GenericName owner = ownerOf(previous);
+ if (!isAssignableIgnoreName(previous, property)) {
+ final GenericName owner = ownerOf(this, previous);
throw new
IllegalArgumentException(Errors.format(Errors.Keys.PropertyAlreadyExists_2,
(owner != null) ? owner : "?", name));
}
- done.clear();
}
}
}
@@ -349,12 +340,12 @@ public class DefaultFeatureType extends
* This method is for information purpose when producing an error message
- its implementation does
* not need to be efficient.
*/
- private GenericName ownerOf(final PropertyType property) {
- if (properties.contains(property)) {
- return getName();
+ private static GenericName ownerOf(final FeatureType type, final
PropertyType property) {
+ if (type.getProperties(false).contains(property)) {
+ return type.getName();
}
- for (final DefaultFeatureType type : superTypes) {
- final GenericName owner = type.ownerOf(property);
+ for (final FeatureType superType : type.getSuperTypes()) {
+ final GenericName owner = ownerOf(superType, property);
if (owner != null) {
return owner;
}
@@ -370,7 +361,7 @@ public class DefaultFeatureType extends
* @param source The feature which contains the property (typically {@code
this}).
* @param index Index of the property having the given name.
*/
- private String toString(final GenericName name, final DefaultFeatureType
source, final int index) {
+ private String toString(final GenericName name, final FeatureType source,
final int index) {
short key = Errors.Keys.MissingValueForProperty_1;
if (name != null) {
final String s = name.toString();
@@ -397,6 +388,7 @@ public class DefaultFeatureType extends
*
* @return {@code true} if the feature type acts as an abstract super-type.
*/
+ @Override
public final boolean isAbstract() {
return isAbstract;
}
@@ -415,16 +407,31 @@ public class DefaultFeatureType extends
*
* @return {@code true} if this feature type contains only simple
attributes or operations.
*/
+ @Override
public boolean isSimple() {
return isSimple;
}
/**
- * Returns {@code true} if this type may be the same or a super-type of
the given type, using only
- * the name as a criterion. This is a faster check than {@link
#isAssignableFrom(DefaultFeatureType)}
+ * Returns {@code true} if the given base type may be the same or a
super-type of the given type, using only
+ * the name as a criterion. This is a faster check than {@link
#isAssignableFrom(FeatureType)}.
+ *
+ * <p>Performance note: callers should verify that {@code base != type}
before to invoke this method.</p>
*/
- final boolean maybeAssignableFrom(final DefaultFeatureType type) {
- return type.assignableTo.contains(getName());
+ static boolean maybeAssignableFrom(final FeatureType base, final
FeatureType type) {
+ if (type instanceof DefaultFeatureType) {
+ return ((DefaultFeatureType)
type).assignableTo.contains(base.getName());
+ }
+ // Slower path for non-SIS implementations.
+ if (Objects.equals(base.getName(), type.getName())) {
+ return true;
+ }
+ for (final FeatureType superType : type.getSuperTypes()) {
+ if (base == superType || maybeAssignableFrom(base, superType)) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -440,32 +447,35 @@ public class DefaultFeatureType extends
* @param type The type to be checked.
* @return {@code true} if instances of the given type can be assigned to
association of this type.
*/
- public boolean isAssignableFrom(final DefaultFeatureType type) {
+ @Override
+ public boolean isAssignableFrom(final FeatureType type) {
if (type == this) {
return true; // Optimization for a common case.
}
ArgumentChecks.ensureNonNull("type", type);
- return maybeAssignableFrom(type) && isAssignableIgnoreName(type, new
IdentityHashMap<>(4));
- }
-
- /**
- * Return {@code true} if all properties in this type are also properties
in the given type.
- * This method does not compare the names — this verification is presumed
already done by the caller.
- *
- * @param type The type to check.
- * @param done An initially empty map to be used for avoiding infinite
recursivity.
- */
- private boolean isAssignableIgnoreName(final DefaultFeatureType type,
final Map<DefaultFeatureType,Boolean> done) {
- if (done.put(this, Boolean.TRUE) == null) {
- /*
- * Ensures that all properties defined in this feature type is
also defined
- * in the given property, and that the former is assignable from
the later.
- */
- for (final Map.Entry<String, PropertyType> entry :
byName.entrySet()) {
- final PropertyType other = type.getProperty(entry.getKey());
- if (other == null || !isAssignableIgnoreName(entry.getValue(),
other, done)) {
- return false;
- }
+ if (!maybeAssignableFrom(this, type)) {
+ return false;
+ }
+ /*
+ * Ensures that all properties defined in this feature type is also
defined
+ * in the given property, and that the former is assignable from the
later.
+ */
+ for (final Map.Entry<String, PropertyType> entry : byName.entrySet()) {
+ final PropertyType other;
+ try {
+ other = type.getProperty(entry.getKey());
+ } catch (IllegalArgumentException e) {
+ /*
+ * A property in this FeatureType does not exist in the given
FeatureType.
+ * Catching exceptions is not an efficient way to perform this
check, but
+ * actually this case should be rare because we verified
before this loop
+ * that the names match. If the names are unique (as
recommended), then
+ * this exception should never happen.
+ */
+ return false;
+ }
+ if (!isAssignableIgnoreName(entry.getValue(), other)) {
+ return false;
}
}
return true;
@@ -475,14 +485,8 @@ public class DefaultFeatureType extends
* Returns {@code true} if instances of the {@code other} type are
assignable to the given {@code base} type.
* This method does not compare the names — this verification is presumed
already done by the caller.
*/
- private static boolean isAssignableIgnoreName(final PropertyType base,
final PropertyType other,
- final Map<DefaultFeatureType,Boolean> done)
- {
+ private static boolean isAssignableIgnoreName(final PropertyType base,
final PropertyType other) {
if (base != other) {
- /*
- * TODO: DefaultAssociationRole to be replaced by GeoAPI interfaces
- * (pending GeoAPI review).
- */
if (base instanceof AttributeType<?>) {
if (!(other instanceof AttributeType<?>)) {
return false;
@@ -507,10 +511,12 @@ public class DefaultFeatureType extends
{
return false;
}
- final DefaultFeatureType f0 = p0.getValueType();
- final DefaultFeatureType f1 = p1.getValueType();
- if (!f0.maybeAssignableFrom(f1) ||
!f0.isAssignableIgnoreName(f1, done)) {
- return false;
+ final FeatureType f0 = p0.getValueType();
+ final FeatureType f1 = p1.getValueType();
+ if (f0 != f1) {
+ if (!f0.isAssignableFrom(f1)) {
+ return false;
+ }
}
}
}
@@ -530,7 +536,8 @@ public class DefaultFeatureType extends
*
* @return The parents of this feature type, or an empty set if none.
*/
- public Set<DefaultFeatureType> getSuperTypes() {
+ @Override
+ public Set<FeatureType> getSuperTypes() {
return superTypes;
}
@@ -545,7 +552,8 @@ public class DefaultFeatureType extends
* @return Feature operation, attribute type and association role that
carries characteristics of this
* feature type (not including parent types).
*/
- public Collection<PropertyType> getPropertyTypes(final boolean
includeSuperTypes) {
+ @Override
+ public Collection<PropertyType> getProperties(final boolean
includeSuperTypes) {
return includeSuperTypes ? allProperties : properties;
}
@@ -554,9 +562,15 @@ public class DefaultFeatureType extends
*
* @param name The name of the property to search.
* @return The property for the given name, or {@code null} if none.
+ * @throws IllegalArgumentException If the given argument is not a
property name of this feature.
*/
- final PropertyType getProperty(final String name) {
- return byName.get(name);
+ @Override
+ public PropertyType getProperty(final String name) throws
IllegalArgumentException {
+ final PropertyType pt = byName.get(name);
+ if (pt != null) {
+ return pt;
+ }
+ throw new
IllegalArgumentException(Errors.format(Errors.Keys.PropertyNotFound_2,
getName(), name));
}
/**
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java?rev=1598371&r1=1598370&r2=1598371&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/DenseFeature.java
[UTF-8] Thu May 29 19:03:14 2014
@@ -219,7 +219,7 @@ final class DenseFeature extends Abstrac
if (properties != null && !(properties instanceof Property[])) {
final Validator v = new Validator(ScopeCode.FEATURE);
for (final Map.Entry<String, Integer> entry : indices.entrySet()) {
- v.validateAny(getPropertyType(entry.getKey()),
properties[entry.getValue()]);
+ v.validateAny(type.getProperty(entry.getKey()),
properties[entry.getValue()]);
}
return v.quality;
}
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java?rev=1598371&r1=1598370&r2=1598371&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/FeatureFormat.java
[UTF-8] Thu May 29 19:03:14 2014
@@ -36,6 +36,7 @@ import org.apache.sis.util.resources.Voc
import org.opengis.feature.IdentifiedType;
import org.opengis.feature.PropertyType;
import org.opengis.feature.AttributeType;
+import org.opengis.feature.FeatureType;
/**
@@ -153,13 +154,13 @@ public class FeatureFormat extends Tabul
public void format(final Object object, final Appendable toAppendTo)
throws IOException {
ArgumentChecks.ensureNonNull("object", object);
ArgumentChecks.ensureNonNull("toAppendTo", toAppendTo);
- final DefaultFeatureType featureType;
- final AbstractFeature feature;
+ final FeatureType featureType;
+ final AbstractFeature feature;
if (object instanceof AbstractFeature) {
feature = (AbstractFeature) object;
featureType = feature.getType();
- } else if (object instanceof DefaultFeatureType) {
- featureType = (DefaultFeatureType) object;
+ } else if (object instanceof FeatureType) {
+ featureType = (FeatureType) object;
feature = null;
} else {
throw new
IllegalArgumentException(Errors.getResources(displayLocale)
@@ -189,7 +190,7 @@ header: for (int i=0; ; i++) {
* Done writing the header. Now write all property rows.
* Rows without value will be skipped only if optional.
*/
- for (final PropertyType propertyType :
featureType.getPropertyTypes(true)) {
+ for (final PropertyType propertyType :
featureType.getProperties(true)) {
Object value;
if (feature != null) {
value =
feature.getPropertyValue(propertyType.getName().toString());
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java?rev=1598371&r1=1598370&r2=1598371&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/MultiValuedAssociation.java
[UTF-8] Thu May 29 19:03:14 2014
@@ -21,6 +21,9 @@ import org.apache.sis.internal.util.Chec
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.resources.Errors;
+// Branch-dependent imports
+import org.opengis.feature.FeatureType;
+
/**
* An instance of an {@linkplain DefaultAssociationRole association role}
containing an arbitrary amount of values.
@@ -129,7 +132,7 @@ final class MultiValuedAssociation exten
@Override
public void setValues(final Collection<? extends AbstractFeature> values) {
ArgumentChecks.ensureNonNull("values", values);
- final DefaultFeatureType base = role.getValueType();
+ final FeatureType base = role.getValueType();
this.values.clear();
for (final AbstractFeature value : values) {
ensureValid(base, value.getType());
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java?rev=1598371&r1=1598370&r2=1598371&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/SparseFeature.java
[UTF-8] Thu May 29 19:03:14 2014
@@ -25,6 +25,10 @@ import org.apache.sis.internal.util.Clon
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.CorruptedObjectException;
+// Branch-dependent imports
+import org.opengis.feature.PropertyType;
+import org.opengis.feature.FeatureType;
+
/**
* A feature in which only a small fraction of properties are expected to be
provided. This implementation uses
@@ -89,7 +93,7 @@ final class SparseFeature extends Abstra
*
* @param type Information about the feature (name, characteristics,
<i>etc.</i>).
*/
- public SparseFeature(final DefaultFeatureType type) {
+ public SparseFeature(final FeatureType type) {
super(type);
properties = new HashMap<>();
}
@@ -248,8 +252,8 @@ final class SparseFeature extends Abstra
public DataQuality quality() {
if (valuesKind == VALUES) {
final Validator v = new Validator(ScopeCode.FEATURE);
- for (final String name : type.indices().keySet()) {
- v.validateAny(getPropertyType(name), properties.get(name));
+ for (final PropertyType pt : type.getProperties(true)) {
+ v.validateAny(pt, properties.get(pt.getName().toString()));
}
return v.quality;
}
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java?rev=1598371&r1=1598370&r2=1598371&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/Validator.java
[UTF-8] Thu May 29 19:03:14 2014
@@ -34,6 +34,7 @@ import org.apache.sis.util.resources.Err
// Branch-dependent imports
import org.opengis.feature.PropertyType;
import org.opengis.feature.AttributeType;
+import org.opengis.feature.FeatureType;
/**
@@ -147,7 +148,7 @@ final class Validator {
void validate(final DefaultAssociationRole role, final Collection<?>
values) {
AbstractElement report = null;
for (final Object value : values) {
- final DefaultFeatureType type = ((AbstractFeature)
value).getType();
+ final FeatureType type = ((AbstractFeature) value).getType();
if (!role.getValueType().isAssignableFrom(type)) {
report = addViolationReport(report, role,
Errors.formatInternational(
Errors.Keys.IllegalPropertyClass_2, role.getName(),
type.getName()));
Modified:
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/package-info.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/package-info.java?rev=1598371&r1=1598370&r2=1598371&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/package-info.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/main/java/org/apache/sis/feature/package-info.java
[UTF-8] Thu May 29 19:03:14 2014
@@ -26,7 +26,7 @@
* {@linkplain org.apache.sis.feature.DefaultAttributeType attributes},
* {@linkplain org.apache.sis.feature.DefaultOperation operations} or
* {@linkplain org.apache.sis.feature.DefaultAssociationRole
associations to other features}
- * (collectively called “{@linkplain
org.apache.sis.feature.DefaultFeatureType#getPropertyTypes(boolean) properties}”
+ * (collectively called “{@linkplain
org.apache.sis.feature.DefaultFeatureType#getProperties(boolean) properties}”
* or “characteristics”) that a feature can have.</p>
*
* <div class="note"><b>Analogy:</b> a {@code FeatureType} in a Spatial
Information System is equivalent to a
Modified:
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java?rev=1598371&r1=1598370&r2=1598371&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/DefaultFeatureTypeTest.java
[UTF-8] Thu May 29 19:03:14 2014
@@ -152,8 +152,8 @@ public final strictfp class DefaultFeatu
*/
private static void assertUnmodifiable(final DefaultFeatureType feature) {
final Collection<?> superTypes = feature.getSuperTypes();
- final Collection<?> declaredProperties =
feature.getPropertyTypes(false);
- final Collection<?> allProperties =
feature.getPropertyTypes(true);
+ final Collection<?> declaredProperties = feature.getProperties(false);
+ final Collection<?> allProperties = feature.getProperties(true);
if (!superTypes.isEmpty()) try {
superTypes.clear();
fail("Super-types collection shall not be modifiable.");
@@ -182,7 +182,7 @@ public final strictfp class DefaultFeatu
* This method tests the following {@code FeatureType} methods:
*
* <ul>
- * <li>{@link DefaultFeatureType#getPropertyTypes(boolean)}</li>
+ * <li>{@link DefaultFeatureType#getProperties(boolean)}</li>
* <li>{@link DefaultFeatureType#getProperty(String)}</li>
* </ul>
*
@@ -195,7 +195,7 @@ public final strictfp class DefaultFeatu
final String... expected)
{
int index = 0;
- for (final PropertyType property :
feature.getPropertyTypes(includeSuperTypes)) {
+ for (final PropertyType property :
feature.getProperties(includeSuperTypes)) {
assertTrue("Found more properties than expected.", index <
expected.length);
final String name = expected[index++];
assertNotNull(name, property);
@@ -203,7 +203,14 @@ public final strictfp class DefaultFeatu
assertSame (name, property, feature.getProperty(name));
}
assertEquals("Unexpected number of properties.", expected.length,
index);
- assertNull("Shall not found a non-existent property.",
feature.getProperty("apple"));
+ try {
+ feature.getProperty("apple");
+ fail("Shall not found a non-existent property.");
+ } catch (IllegalArgumentException e) {
+ final String message = e.getMessage();
+ assertTrue(message, message.contains("apple"));
+ assertTrue(message,
message.contains(feature.getName().toString()));
+ }
}
/**
@@ -261,7 +268,7 @@ public final strictfp class DefaultFeatu
false, null, city, population, festival);
assertUnmodifiable(complex);
- final Collection<PropertyType> properties =
complex.getPropertyTypes(false);
+ final Collection<PropertyType> properties =
complex.getProperties(false);
final Iterator<PropertyType> it = properties.iterator();
assertEquals("name", "Festival",
complex.getName().toString());
@@ -327,8 +334,8 @@ public final strictfp class DefaultFeatu
assertPropertiesEquals(capital, true, "city", "population",
"parliament");
// Check based only on name.
- assertTrue ("maybeAssignableFrom", city.maybeAssignableFrom(capital));
- assertFalse("maybeAssignableFrom", capital.maybeAssignableFrom(city));
+ assertTrue ("maybeAssignableFrom",
DefaultFeatureType.maybeAssignableFrom(city, capital));
+ assertFalse("maybeAssignableFrom",
DefaultFeatureType.maybeAssignableFrom(capital, city));
// Public API.
assertTrue ("isAssignableFrom", city.isAssignableFrom(capital));
@@ -363,10 +370,10 @@ public final strictfp class DefaultFeatu
((DefaultAttributeType)
metroCapital.getProperty("region")).getValueClass());
// Check based only on name.
- assertTrue ("maybeAssignableFrom",
capital.maybeAssignableFrom(metroCapital));
- assertFalse("maybeAssignableFrom",
metroCapital.maybeAssignableFrom(capital));
- assertTrue ("maybeAssignableFrom",
metropolis.maybeAssignableFrom(metroCapital));
- assertFalse("maybeAssignableFrom",
metroCapital.maybeAssignableFrom(metropolis));
+ assertTrue ("maybeAssignableFrom",
DefaultFeatureType.maybeAssignableFrom(capital, metroCapital));
+ assertFalse("maybeAssignableFrom",
DefaultFeatureType.maybeAssignableFrom(metroCapital, capital));
+ assertTrue ("maybeAssignableFrom",
DefaultFeatureType.maybeAssignableFrom(metropolis, metroCapital));
+ assertFalse("maybeAssignableFrom",
DefaultFeatureType.maybeAssignableFrom(metroCapital, metropolis));
// Public API.
assertTrue ("isAssignableFrom",
capital.isAssignableFrom(metroCapital));
@@ -406,8 +413,8 @@ public final strictfp class DefaultFeatu
((DefaultAttributeType)
worldMetropolis.getProperty("region")).getValueClass());
// Check based only on name.
- assertTrue ("maybeAssignableFrom",
metropolis.maybeAssignableFrom(worldMetropolis));
- assertFalse("maybeAssignableFrom",
worldMetropolis.maybeAssignableFrom(metropolis));
+ assertTrue ("maybeAssignableFrom",
DefaultFeatureType.maybeAssignableFrom(metropolis, worldMetropolis));
+ assertFalse("maybeAssignableFrom",
DefaultFeatureType.maybeAssignableFrom(worldMetropolis, metropolis));
// Public API.
assertTrue ("isAssignableFrom",
metropolis.isAssignableFrom(worldMetropolis));
Modified:
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java?rev=1598371&r1=1598370&r2=1598371&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-feature/src/test/java/org/apache/sis/feature/FeatureTestCase.java
[UTF-8] Thu May 29 19:03:14 2014
@@ -32,6 +32,9 @@ import org.junit.Test;
import static org.apache.sis.test.Assert.*;
import static java.util.Collections.singletonMap;
+// Branch-dependent imports
+import org.opengis.feature.FeatureType;
+
/**
* Tests common to {@link DenseFeatureTest} and {@link SparseFeatureTest}.
@@ -64,10 +67,10 @@ public abstract strictfp class FeatureTe
*/
static AbstractFeature twinTown(final boolean isSparse) {
final DefaultAssociationRole twinTown =
DefaultAssociationRoleTest.twinTown();
- final DefaultFeatureType city = twinTown.getValueType();
+ final FeatureType city = twinTown.getValueType();
final DefaultFeatureType type = new DefaultFeatureType(
singletonMap(DefaultFeatureType.NAME_KEY, "Twin town"), false,
- new DefaultFeatureType[] {city}, twinTown);
+ new FeatureType[] {city}, twinTown);
final AbstractFeature leMans = isSparse ? new SparseFeature(type) :
new DenseFeature(type);
leMans.setPropertyValue("city", "Le Mans");