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 2013/05/02 00:14:48 UTC
svn commit: r1478218 [1/2] - in /sis/trunk: ./
sis-metadata/src/main/java/org/apache/sis/metadata/
sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/
sis-metadata/src/main/java/org/apache/sis/metadata/iso/doc-files/
sis-metadata/src/main/...
Author: desruisseaux
Date: Wed May 1 22:14:47 2013
New Revision: 1478218
URL: http://svn.apache.org/r1478218
Log:
Merge from the JDK6 branch. Includes a preliminary version of metadata tree table,
which implies a first working version of AbstractMetadata.toString().
Added:
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeChildren.java
- copied unchanged from r1478216, sis/branches/JDK6/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeChildren.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeNode.java
- copied unchanged from r1478216, sis/branches/JDK6/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeNode.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeTable.java
- copied unchanged from r1478216, sis/branches/JDK6/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataTreeTable.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/doc-files/
- copied from r1478216, sis/branches/JDK6/sis-metadata/src/main/java/org/apache/sis/metadata/iso/doc-files/
sis/trunk/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTestCase.java
- copied unchanged from r1478216, sis/branches/JDK6/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTestCase.java
sis/trunk/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeChildrenTest.java
- copied unchanged from r1478216, sis/branches/JDK6/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeChildrenTest.java
sis/trunk/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeNodeTest.java
- copied unchanged from r1478216, sis/branches/JDK6/sis-metadata/src/test/java/org/apache/sis/metadata/MetadataTreeNodeTest.java
sis/trunk/sis-metadata/src/test/java/org/apache/sis/metadata/iso/AllMetadataTest.java
- copied unchanged from r1478216, sis/branches/JDK6/sis-metadata/src/test/java/org/apache/sis/metadata/iso/AllMetadataTest.java
sis/trunk/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/
- copied from r1478216, sis/branches/JDK6/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/
sis/trunk/sis-utility/src/test/java/org/apache/sis/test/AnnotationsTestCase.java
- copied unchanged from r1478216, sis/branches/JDK6/sis-utility/src/test/java/org/apache/sis/test/AnnotationsTestCase.java
Modified:
sis/trunk/ (props changed)
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/AbstractMetadata.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyMap.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ValueExistencePolicy.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultOnlineResource.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/package-info.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java
sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java
sis/trunk/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java
sis/trunk/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
sis/trunk/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedArrayList.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedHashSet.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/UnmodifiableArrayList.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/About.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Classes.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/TableColumn.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTableFormat.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTables.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/iso/AbstractInternationalString.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/iso/ResourceInternationalString.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
sis/trunk/sis-utility/src/test/java/org/apache/sis/test/TestUtilities.java
sis/trunk/sis-utility/src/test/java/org/apache/sis/util/CharSequencesTest.java
sis/trunk/sis-utility/src/test/java/org/apache/sis/util/ClassesTest.java
sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/DefaultTreeTableTest.java
sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTableFormatTest.java
sis/trunk/sis-utility/src/test/java/org/apache/sis/util/collection/TreeTablesTest.java
Propchange: sis/trunk/
------------------------------------------------------------------------------
Merged /sis/branches/JDK7:r1470196-1478202
Merged /sis/branches/JDK6:r1470199-1478216
Modified: sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/AbstractMetadata.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/AbstractMetadata.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/AbstractMetadata.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/AbstractMetadata.java [UTF-8] Wed May 1 22:14:47 2013
@@ -186,6 +186,7 @@ public abstract class AbstractMetadata i
* the UML identifier.</p>
*
* <p>The default implementation is equivalent to the following method call:</p>
+ *
* {@preformat java
* return getStandard().asValueMap(this, KeyNamePolicy.JAVABEANS_PROPERTY, ValueExistencePolicy.NON_EMPTY);
* }
@@ -203,13 +204,21 @@ public abstract class AbstractMetadata i
/**
* Returns the property types and values as a tree table.
- * In the current implementation, the tree is not live (i.e. changes in metadata are not
- * reflected in the tree). However it may be improved in a future SIS implementation.
+ * The tree table is backed by the metadata object using Java reflection, so changes in the
+ * underlying metadata object are immediately reflected in the tree table and conversely.
+ *
+ * <p>The default implementation is equivalent to the following method call:</p>
+ *
+ * {@preformat java
+ * return getStandard().asTreeTable(this, ValueExistencePolicy.NON_EMPTY);
+ * }
+ *
+ * @return A tree table representation of the specified metadata.
*
- * @return The property types and values as a tree table.
+ * @see MetadataStandard#asTreeTable(Object, ValueExistencePolicy)
*/
public TreeTable asTreeTable() {
- return getStandard().asTreeTable(this);
+ return getStandard().asTreeTable(this, ValueExistencePolicy.NON_EMPTY);
}
/**
Modified: sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java [UTF-8] Wed May 1 22:14:47 2013
@@ -431,13 +431,13 @@ public class MetadataStandard {
* {@linkplain KeyNamePolicy#METHOD_NAME method names} or {@linkplain KeyNamePolicy#SENTENCE
* sentences} (usually in English).
*
- * <p><b>Example:</b> The {@code value} in the following code is
- * <code>"alternateTitle<u>s</u>"</code> (note the plural):</p>
+ * <p><b>Example:</b> the following code prints <code>"alternateTitle<u>s</u>"</code> (note the plural):</p>
*
* {@preformat java
* MetadataStandard standard = MetadataStandard.ISO_19115;
* Map<String, String> names = standard.asNameMap(Citation.class, UML_IDENTIFIER, JAVABEANS_PROPERTY);
- * String value = names.get("alternateTitle"); // alternateTitles
+ * String value = names.get("alternateTitle");
+ * System.out.println(value); // alternateTitles
* }
*
* The {@code keyPolicy} argument specify only the string representation of keys returned by the iterators.
@@ -471,12 +471,14 @@ public class MetadataStandard {
* argument, which can be {@linkplain TypeValuePolicy#ELEMENT_TYPE element type} or the
* {@linkplain TypeValuePolicy#DECLARING_INTERFACE declaring interface} among others.
*
- * <p><b>Example:</b> The {@code value} in the following code is {@code InternationalString.class}:</p>
+ * <p><b>Example:</b> the following code prints the
+ * {@link org.opengis.util.InternationalString} class name:</p>
*
* {@preformat java
* MetadataStandard standard = MetadataStandard.ISO_19115;
* Map<String,Class<?>> types = standard.asTypeMap(Citation.class, UML_IDENTIFIER, ELEMENT_TYPE);
- * Class<?> value = names.get("alternateTitle"); // InternationalString.class
+ * Class<?> value = types.get("alternateTitle");
+ * System.out.println(value); // class org.opengis.util.InternationalString
* }
*
* @param type The interface or implementation class of a metadata.
@@ -521,15 +523,15 @@ public class MetadataStandard {
* <ul>
* <li>The {@linkplain CheckedContainer#getElementType() element type} is the type of property values
* as defined by {@link TypeValuePolicy#ELEMENT_TYPE}.</li>
- *
- * {@note The rational for implementing <code>CheckedContainer</code> is to consider each
- * <code>ExtendedElementInformation</code> instance as the set of all possible values for
- * the property. If the information had a <code>contains(E)</code> method, it would return
- * <code>true</code> if the given value is valid for that property.}
* </ul>
* </li>
* </ul>
*
+ * {@note The rational for implementing <code>CheckedContainer</code> is to consider each
+ * <code>ExtendedElementInformation</code> instance as the set of all possible values for
+ * the property. If the information had a <code>contains(E)</code> method, it would return
+ * <code>true</code> if the given value is valid for that property.}
+ *
* In addition, for each map entry the value returned by {@link ExtendedElementInformation#getDomainValue()}
* may optionally be an instance of any of the following classes:
*
@@ -542,6 +544,8 @@ public class MetadataStandard {
* @return Information about all properties defined in the given metadata type.
* @throws ClassCastException if the given type doesn't implement a metadata
* interface of the expected package.
+ *
+ * @see org.apache.sis.metadata.iso.DefaultExtendedElementInformation
*/
public Map<String,ExtendedElementInformation> asInformationMap(Class<?> type,
final KeyNamePolicy keyPolicy) throws ClassCastException
@@ -591,18 +595,24 @@ public class MetadataStandard {
/**
* Returns the specified metadata object as a tree table.
- * In the current implementation, the tree is not live (i.e. changes in metadata are not
- * reflected in the tree). However it may be improved in a future SIS implementation.
+ * The tree table is backed by the metadata object using Java reflection, so changes in the
+ * underlying metadata object are immediately reflected in the tree table and conversely.
*
- * @param metadata The metadata object to formats as a tree table.
+ * @param metadata The metadata object to view as a tree table.
+ * @param valuePolicy Whether the property having null value or empty collection shall be
+ * included in the tree.
* @return A tree table representation of the specified metadata.
* @throws ClassCastException if the metadata object doesn't implement a metadata
* interface of the expected package.
*
* @see AbstractMetadata#asTreeTable()
*/
- public TreeTable asTreeTable(final Object metadata) throws ClassCastException {
- throw new UnsupportedOperationException("Not yet implemented"); // TODO
+ public TreeTable asTreeTable(final Object metadata, final ValueExistencePolicy valuePolicy)
+ throws ClassCastException
+ {
+ ensureNonNull("metadata", metadata);
+ ensureNonNull("valuePolicy", valuePolicy);
+ return new MetadataTreeTable(this, metadata, valuePolicy);
}
/**
Modified: sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ModifiableMetadata.java [UTF-8] Wed May 1 22:14:47 2013
@@ -28,9 +28,7 @@ import org.apache.sis.util.resources.Err
import org.apache.sis.internal.util.CheckedHashSet;
import org.apache.sis.internal.util.CheckedArrayList;
-import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
-import static org.apache.sis.util.collection.Containers.hashMapCapacity;
import static org.apache.sis.internal.jaxb.MarshalContext.isMarshalling;
@@ -85,6 +83,12 @@ import static org.apache.sis.internal.ja
@ThreadSafe
public abstract class ModifiableMetadata extends AbstractMetadata implements Cloneable {
/**
+ * Initial capacity of lists and sets. We use a small value because those
+ * collections will typically contain few elements (often just a singleton).
+ */
+ private static final int INITIAL_CAPACITY = 4;
+
+ /**
* A null implementation for the {@link #FREEZING} constant.
*/
private static final class Null extends ModifiableMetadata {
@@ -266,7 +270,7 @@ public abstract class ModifiableMetadata
if (target != null) {
target.clear();
} else {
- target = new MutableList<E>(elementType, source.size());
+ target = new CheckedArrayList<E>(elementType, source.size());
}
target.addAll(source);
}
@@ -314,7 +318,7 @@ public abstract class ModifiableMetadata
if (target != null) {
target.clear();
} else {
- target = new MutableSet<E>(elementType, source.size());
+ target = new CheckedHashSet<E>(elementType, source.size());
}
target.addAll(source);
}
@@ -379,9 +383,9 @@ public abstract class ModifiableMetadata
} else {
final int capacity = source.size();
if (useSet(elementType)) {
- target = new MutableSet<E>(elementType, capacity);
+ target = new CheckedHashSet<E>(elementType, capacity);
} else {
- target = new MutableList<E>(elementType, capacity);
+ target = new CheckedArrayList<E>(elementType, capacity);
}
}
target.addAll(source);
@@ -405,7 +409,7 @@ public abstract class ModifiableMetadata
if (isNullOrEmpty(source)) {
return null;
}
- final List<E> target = new MutableList<E>(elementType, source.size());
+ final List<E> target = new CheckedArrayList<E>(elementType, source.size());
target.addAll(source);
return target;
}
@@ -425,7 +429,7 @@ public abstract class ModifiableMetadata
if (isNullOrEmpty(source)) {
return null;
}
- final Set<E> target = new MutableSet<E>(elementType, source.size());
+ final Set<E> target = new CheckedHashSet<E>(elementType, source.size());
target.addAll(source);
return target;
}
@@ -451,9 +455,9 @@ public abstract class ModifiableMetadata
final Collection<E> target;
final int capacity = source.size();
if (useSet(elementType)) {
- target = new MutableSet<E>(elementType, capacity);
+ target = new CheckedHashSet<E>(elementType, capacity);
} else {
- target = new MutableList<E>(elementType, capacity);
+ target = new CheckedArrayList<E>(elementType, capacity);
}
target.addAll(source);
return target;
@@ -478,9 +482,9 @@ public abstract class ModifiableMetadata
}
final Collection<E> collection;
if (useSet(elementType)) {
- collection = new MutableSet<E>(elementType);
+ collection = new CheckedHashSet<E>(elementType, INITIAL_CAPACITY);
} else {
- collection = new MutableList<E>(elementType);
+ collection = new CheckedArrayList<E>(elementType, INITIAL_CAPACITY);
}
collection.add(value);
return collection;
@@ -503,7 +507,7 @@ public abstract class ModifiableMetadata
return null;
}
if (isModifiable()) {
- return new MutableList<E>(elementType);
+ return new CheckedArrayList<E>(elementType, INITIAL_CAPACITY);
}
return Collections.emptyList();
}
@@ -525,7 +529,7 @@ public abstract class ModifiableMetadata
return null;
}
if (isModifiable()) {
- return new MutableSet<E>(elementType);
+ return new CheckedHashSet<E>(elementType, INITIAL_CAPACITY);
}
return Collections.emptySet();
}
@@ -558,13 +562,13 @@ public abstract class ModifiableMetadata
final boolean isModifiable = isModifiable();
if (useSet(elementType)) {
if (isModifiable) {
- return new MutableSet<E>(elementType);
+ return new CheckedHashSet<E>(elementType, INITIAL_CAPACITY);
} else {
return Collections.emptySet();
}
} else {
if (isModifiable) {
- return new MutableList<E>(elementType);
+ return new CheckedArrayList<E>(elementType, INITIAL_CAPACITY);
} else {
return Collections.emptyList();
}
@@ -572,58 +576,6 @@ public abstract class ModifiableMetadata
}
/**
- * A set checking element validity and write permission before to change any value.
- */
- private final class MutableSet<E> extends CheckedHashSet<E> {
- private static final long serialVersionUID = 3032602282358733056L;
-
- MutableSet(Class<E> type) {
- super(type, 4); // Use a small capacity because we typically have few elements.
- }
-
- MutableSet(Class<E> type, int capacity) {
- super(type, hashMapCapacity(capacity));
- }
-
- @Override
- protected void checkWritePermission() throws UnsupportedOperationException {
- ModifiableMetadata.this.checkWritePermission();
- }
-
- @Override
- protected void ensureValid(final E element) throws IllegalArgumentException {
- ensureNonNull("element", element);
- super.ensureValid(element);
- }
- }
-
- /**
- * A list checking element validity and write permission before to change any value.
- */
- private final class MutableList<E> extends CheckedArrayList<E> {
- private static final long serialVersionUID = 5800381255701183058L;
-
- MutableList(Class<E> type) {
- super(type, 4); // Use a small capacity because we typically have few elements.
- }
-
- MutableList(Class<E> type, int capacity) {
- super(type, capacity);
- }
-
- @Override
- protected void checkWritePermission() throws UnsupportedOperationException {
- ModifiableMetadata.this.checkWritePermission();
- }
-
- @Override
- protected void ensureValid(final E element) throws IllegalArgumentException {
- ensureNonNull("element", element);
- super.ensureValid(element);
- }
- }
-
- /**
* Returns {@code true} if we should use a {@link Set} instead than a {@link List}
* for elements of the given type.
*/
Modified: sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java [UTF-8] Wed May 1 22:14:47 2013
@@ -16,7 +16,6 @@
*/
package org.apache.sis.metadata;
-import java.util.Set;
import java.util.Map;
import java.util.List;
import java.util.Arrays;
@@ -31,7 +30,9 @@ import net.jcip.annotations.ThreadSafe;
import org.opengis.annotation.UML;
import org.opengis.metadata.citation.Citation;
import org.opengis.metadata.ExtendedElementInformation;
+import org.apache.sis.internal.util.Citations;
import org.apache.sis.measure.ValueRange;
+import org.apache.sis.util.Debug;
import org.apache.sis.util.Classes;
import org.apache.sis.util.Numbers;
import org.apache.sis.util.ArraysExt;
@@ -97,6 +98,12 @@ final class PropertyAccessor {
private static final Map<Class<?>, Method[]> SHARED_GETTERS = new IdentityHashMap<Class<?>, Method[]>();
/**
+ * Enumeration constants for the {@code mode} argument in the
+ * {@link #count(Object, ValueExistencePolicy, int)} method.
+ */
+ static final int COUNT_FIRST=0, COUNT_SHALLOW=1, COUNT_DEEP=2;
+
+ /**
* Additional getter to declare in every list of getter methods that do not already provide
* their own {@code getIdentifiers()} method. We handle this method specially because it is
* needed for XML marshalling in ISO 19139 compliant document, while not part of abstract
@@ -124,7 +131,8 @@ final class PropertyAccessor {
final Class<?> type;
/**
- * The implementation class. The following condition must hold:
+ * The implementation class, or {@link #type} if none.
+ * The following condition must hold:
*
* {@preformat java
* type.isAssignableFrom(implementation);
@@ -218,7 +226,7 @@ final class PropertyAccessor {
* @param standard The standard which define the {@code type} interface.
* @param type The interface implemented by the metadata, which must be
* the value returned by {@link #getStandardType(Class, String)}.
- * @param implementation The class of metadata implementations.
+ * @param implementation The class of metadata implementations, or {@code type} if none.
*/
PropertyAccessor(final Citation standard, final Class<?> type, final Class<?> implementation) {
assert type.isAssignableFrom(implementation) : implementation;
@@ -431,6 +439,8 @@ final class PropertyAccessor {
/**
* Returns the number of properties that can be read.
+ *
+ * @see #count(Object, ValueExistencePolicy, int)
*/
final int count() {
return standardCount;
@@ -548,6 +558,16 @@ final class PropertyAccessor {
}
/**
+ * Returns {@code true} if the type at the given index is {@link Collection}.
+ */
+ final boolean isCollection(final int index) {
+ if (index >= 0 && index < standardCount) {
+ return Collection.class.isAssignableFrom(getters[index].getReturnType());
+ }
+ return false;
+ }
+
+ /**
* Returns the information for the property at the given index.
* The information are created when first needed.
*
@@ -590,6 +610,13 @@ final class PropertyAccessor {
}
/**
+ * Returns {@code true} if the property at the given index is writable.
+ */
+ final boolean isWritable(final int index) {
+ return (index >= 0) && (index < standardCount) && (setters != null) && (setters[index] != null);
+ }
+
+ /**
* Returns the value for the specified metadata, or {@code null} if none.
* If the given index is out of bounds, then this method returns {@code null},
* so it is safe to invoke this method even if {@link #indexOf(String, boolean)}
@@ -666,25 +693,28 @@ final class PropertyAccessor {
final Method getter = getters[index];
final Method setter = setters[index];
if (setter != null) {
- Object old;
+ final Object old;
+ final Object copy;
if (getOld) {
old = get(getter, metadata);
if (old instanceof Collection<?>) {
if (old instanceof List<?>) {
- old = snapshot((List<?>) old);
+ copy = snapshot((List<?>) old);
} else {
- old = modifiableCopy((Collection<?>) old);
+ copy = modifiableCopy((Collection<?>) old);
}
} else if (old instanceof Map<?,?>) {
- old = modifiableCopy((Map<?,?>) old);
+ copy = modifiableCopy((Map<?,?>) old);
+ } else {
+ copy = old;
}
} else {
- old = null;
+ copy = old = null;
}
final Object[] newValues = new Object[] {value};
- converter = convert(getter, metadata, newValues, elementTypes[index], converter);
+ converter = convert(getter, metadata, old, newValues, elementTypes[index], converter);
set(setter, metadata, newValues);
- return old;
+ return copy;
}
}
throw new UnmodifiableMetadataException(Errors.format(Errors.Keys.CanNotSetPropertyValue_1, names[index]));
@@ -732,6 +762,9 @@ final class PropertyAccessor {
*
* @param getter The method to use for fetching the previous value.
* @param metadata The metadata object to query.
+ * @param oldValue The value returned by {@code get(getter, metadata)}, or {@code null} if unknown.
+ * This parameter is only an optimization for avoiding to invoke the getter method
+ * twice if the value is already known.
* @param newValues The argument to convert. It must be an array of length 1.
* The content of this array will be modified in-place.
* @param elementType The type required by the setter method.
@@ -742,8 +775,8 @@ final class PropertyAccessor {
* @throws BackingStoreException If the implementation threw a checked exception.
*/
private static ObjectConverter<?,?> convert(final Method getter, final Object metadata,
- final Object[] newValues, Class<?> elementType, ObjectConverter<?,?> converter)
- throws ClassCastException, BackingStoreException
+ final Object oldValue, final Object[] newValues, Class<?> elementType,
+ ObjectConverter<?,?> converter) throws ClassCastException, BackingStoreException
{
assert newValues.length == 1;
Object newValue = newValues[0];
@@ -804,7 +837,7 @@ final class PropertyAccessor {
addTo = null;
} else {
elements = new Object[] {newValue};
- newValue = addTo = (Collection<?>) get(getter, metadata);
+ newValue = addTo = (Collection<?>) (oldValue != null ? oldValue : get(getter, metadata));
if (addTo == null) {
// No previous collection. Create one.
newValue = Arrays.asList(elements);
@@ -883,6 +916,56 @@ final class PropertyAccessor {
}
/**
+ * Counts the number of non-null or non-empty properties.
+ * The {@code mode} argument can be one of the following:
+ *
+ * <ul>
+ * <li>COUNT_FIRST: stop at the first property found. This mode is used for testing if a
+ * metadata is empty or not, without the need to known the exact count.</li>
+ * <li>COUNT_SHALLOW: count all properties, counting collections as one property.</li>
+ * <li>COUNT_DEEP: count all properties, counting collections as the number of
+ * properties returned by {@link Collection#size()}.</li>
+ * </ul>
+ *
+ * @param mode Kinds of count, as described above.
+ * @param valuePolicy The behavior of the count toward null or empty values.
+ * @throws BackingStoreException If the implementation threw a checked exception.
+ *
+ * @see #count()
+ */
+ public int count(final Object metadata, final ValueExistencePolicy valuePolicy, final int mode)
+ throws BackingStoreException
+ {
+ assert type.isInstance(metadata) : metadata;
+ if (valuePolicy == ValueExistencePolicy.ALL && mode != COUNT_DEEP) {
+ return count();
+ }
+ int count = 0;
+ for (int i=0; i<standardCount; i++) {
+ final Object value = get(getters[i], metadata);
+ if (!valuePolicy.isSkipped(value)) {
+ switch (mode) {
+ case COUNT_FIRST:{
+ return 1;
+ }
+ case COUNT_SHALLOW:{
+ count++;
+ break;
+ }
+ case COUNT_DEEP: {
+ // Count always at least one element because if the user wanted to skip null or empty
+ // collections, then 'valuePolicy.isSkipped(value)' above would have returned 'true'.
+ count += (value != null && isCollection(i)) ? Math.max(((Collection<?>) value).size(), 1) : 1;
+ break;
+ }
+ default: throw new AssertionError(mode);
+ }
+ }
+ }
+ return count;
+ }
+
+ /**
* Compares the two specified metadata objects. This method implements a <cite>shallow</cite>
* comparison, i.e. all metadata properties are compared using their {@code properties.equals(…)}
* method without explicit calls to this {@code accessor.equals(…)} method for children.
@@ -953,7 +1036,7 @@ final class PropertyAccessor {
}
final Method setter = setters[i];
if (setter != null) {
- converter = convert(getter, target, arguments, elementTypes[i], converter);
+ converter = convert(getter, target, null, arguments, elementTypes[i], converter);
set(setter, target, arguments);
} else {
success = false;
@@ -1021,21 +1104,35 @@ final class PropertyAccessor {
}
/**
- * Counts the number of non-empty properties.
+ * Returns a string representation of this accessor for debugging purpose.
+ * Output example:
*
- * @param max Stop the count if we reach that value.
- * @throws BackingStoreException If the implementation threw a checked exception.
+ * {@preformat text
+ * PropertyAccessor[13 getters & 13 setters in DefaultCitation:Citation from “ISO 19115”]
+ * }
*/
- public int count(final Object metadata, final int max) throws BackingStoreException {
- assert type.isInstance(metadata) : metadata;
- int count = 0;
- for (int i=0; i<standardCount; i++) {
- if (!isNullOrEmpty(get(getters[i], metadata))) {
- if (++count >= max) {
- break;
+ @Debug
+ @Override
+ public String toString() {
+ final StringBuilder buffer = new StringBuilder(60);
+ buffer.append("PropertyAccessor[").append(standardCount).append(" getters");
+ final int extra = allCount - standardCount;
+ if (extra != 0) {
+ buffer.append(" (+").append(extra).append(" ext.)");
+ }
+ if (setters != null) {
+ int c = 0;
+ for (final Method setter : setters) {
+ if (setter != null) {
+ c++;
}
}
+ buffer.append(" & ").append(c).append(" setters");
}
- return count;
+ buffer.append(" in ").append(Classes.getShortName(implementation));
+ if (type != implementation) {
+ buffer.append(':').append(Classes.getShortName(type));
+ }
+ return buffer.append(" from “").append(Citations.getIdentifier(standard)).append("”]").toString();
}
}
Modified: sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyMap.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyMap.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyMap.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyMap.java [UTF-8] Wed May 1 22:14:47 2013
@@ -43,7 +43,7 @@ import java.util.Iterator;
*/
abstract class PropertyMap<V> extends AbstractMap<String,V> {
/**
- * The accessor to use for the metadata.
+ * The accessor to use for accessing the property names, types or values.
*/
final PropertyAccessor accessor;
Modified: sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ValueExistencePolicy.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ValueExistencePolicy.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ValueExistencePolicy.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ValueExistencePolicy.java [UTF-8] Wed May 1 22:14:47 2013
@@ -23,9 +23,9 @@ import java.lang.reflect.Array;
/**
* Whatever {@link MetadataStandard#asValueMap MetadataStandard.asValueMap(…)} shall contain
- * entries for null values or empty collections. By default the map does not provide
+ * entries for null or empty values. By default the map does not provide
* {@linkplain java.util.Map.Entry entries} for {@code null} metadata properties or
- * {@linkplain java.util.Collection#isEmpty() empty} collections.
+ * {@linkplain java.util.Collection#isEmpty() empty collections}.
* This enumeration allows control on this behavior.
*
* @author Martin Desruisseaux (Geomatys)
@@ -40,21 +40,75 @@ public enum ValueExistencePolicy {
* Includes all entries in the map, including those having a null value or an
* empty collection.
*/
- ALL,
+ ALL() {
+ /** Never skip values. */
+ @Override boolean isSkipped(final Object value) {
+ return false;
+ }
+
+ /** Substitutes null or empty collections by a null singleton element
+ in order to make the property visible in {@link MetadataTreeNode}. */
+ @Override boolean substituteByNullElement(final Collection<?> values) {
+ return (values == null) || values.isEmpty();
+ }
+ },
/**
* Includes only the non-null properties.
* Collections are included no matter if they are empty or not.
*/
- NON_NULL,
+ NON_NULL() {
+ /** Skips all null values. */
+ @Override boolean isSkipped(final Object value) {
+ return (value == null);
+ }
+
+ /** Substitutes empty collections by a null singleton element, but not
+ null references since they are supposed to be skipped by this policy. */
+ @Override boolean substituteByNullElement(final Collection<?> values) {
+ return (values != null) && values.isEmpty();
+ }
+ },
/**
- * Includes only the properties that are non-null and, in the case of collections,
- * non-{@linkplain java.util.Collection#isEmpty() empty}.
+ * Includes only the properties that are non-null and non empty.
+ * A non-null property is considered empty if:
+ *
+ * <ul>
+ * <li>It is a character sequence containing only {@linkplain Character#isWhitespace(int) whitespaces}.</li>
+ * <li>It is an {@linkplain Collection#isEmpty() empty collection}.</li>
+ * <li>It is an {@linkplain Map#isEmpty() empty map}.</li>
+ * <li>It is an empty array (of length 0).</li>
+ * </ul>
+ *
* This is the default behavior of {@link AbstractMetadata#asMap()}.
*/
- NON_EMPTY;
+ NON_EMPTY() {
+ /** Skips all null or empty values. */
+ @Override boolean isSkipped(final Object value) {
+ return isNullOrEmpty(value);
+ }
+ /** Never substitute null or empty collections since they should be skipped. */
+ @Override boolean substituteByNullElement(final Collection<?> values) {
+ return false;
+ }
+ };
+
+ /**
+ * Returns {@code true} if the given value shall be skipped for this policy.
+ */
+ abstract boolean isSkipped(Object value);
+
+ /**
+ * Returns {@code true} if {@link MetadataTreeNode} shall substitute the given collection by
+ * a singleton containing only a null element.
+ *
+ * <p><b>Purpose:</b>
+ * When a collection is null or empty, while not excluded according this {@code ValueExistencePolicy},
+ * we need an empty space for making the metadata property visible in {@code MetadataTreeNode}.</p>
+ */
+ abstract boolean substituteByNullElement(Collection<?> values);
/**
* Returns {@code true} if the specified object is null or an empty collection, array or string.
Modified: sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java [UTF-8] Wed May 1 22:14:47 2013
@@ -49,7 +49,7 @@ final class ValueMap extends PropertyMap
final ValueExistencePolicy valuePolicy;
/**
- * Creates a property map for the specified metadata and accessor.
+ * Creates a map of values for the specified metadata and accessor.
*
* @param metadata The metadata object to wrap.
* @param accessor The accessor to use for the metadata.
@@ -65,18 +65,11 @@ final class ValueMap extends PropertyMap
}
/**
- * Returns {@code true} if the given value should be ignored.
- */
- final boolean ignore(final Object value) {
- return valuePolicy == ValueExistencePolicy.NON_EMPTY && ValueExistencePolicy.isNullOrEmpty(value);
- }
-
- /**
* Returns {@code true} if this map contains no key-value mappings.
*/
@Override
public boolean isEmpty() {
- return accessor.count(metadata, 1) == 0;
+ return accessor.count(metadata, valuePolicy, PropertyAccessor.COUNT_FIRST) == 0;
}
/**
@@ -84,7 +77,7 @@ final class ValueMap extends PropertyMap
*/
@Override
public int size() {
- return accessor.count(metadata, Integer.MAX_VALUE);
+ return accessor.count(metadata, valuePolicy, PropertyAccessor.COUNT_SHALLOW);
}
/**
@@ -103,7 +96,7 @@ final class ValueMap extends PropertyMap
public Object get(final Object key) {
if (key instanceof String) {
final Object value = accessor.get(accessor.indexOf((String) key, false), metadata);
- if (!ignore(value)) {
+ if (!valuePolicy.isSkipped(value)) {
return value;
}
}
@@ -120,7 +113,7 @@ final class ValueMap extends PropertyMap
@Override
public Object put(final String key, final Object value) {
final Object old = accessor.set(accessor.indexOf(key, true), metadata, value, true);
- return ignore(old) ? null : old;
+ return valuePolicy.isSkipped(old) ? null : old;
}
/**
@@ -147,7 +140,7 @@ final class ValueMap extends PropertyMap
public Object remove(final Object key) throws UnsupportedOperationException {
if (key instanceof String) {
final Object old = accessor.set(accessor.indexOf((String) key, false), metadata, null, true);
- if (!ignore(old)) {
+ if (!valuePolicy.isSkipped(old)) {
return old;
}
}
@@ -219,7 +212,7 @@ final class ValueMap extends PropertyMap
@Override
public Object getValue() {
final Object value = accessor.get(index, metadata);
- return ignore(value) ? null : value;
+ return valuePolicy.isSkipped(value) ? null : value;
}
/**
@@ -299,26 +292,7 @@ final class ValueMap extends PropertyMap
private void move(int index) {
final int count = accessor.count();
while (index < count) {
- final Object value = accessor.get(index, metadata);
- final boolean skip;
- switch (valuePolicy) {
- case ALL: {
- skip = false; // Never skip entries.
- break;
- }
- case NON_NULL: {
- skip = (value == null); // Skip only null values (not empty collections).
- break;
- }
- case NON_EMPTY: {
- skip = ValueExistencePolicy.isNullOrEmpty(value);
- break;
- }
- default: {
- throw new AssertionError(valuePolicy);
- }
- }
- if (!skip) {
+ if (!valuePolicy.isSkipped(accessor.get(index, metadata))) {
next = new Property(index);
return;
}
Modified: sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultOnlineResource.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultOnlineResource.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultOnlineResource.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/DefaultOnlineResource.java [UTF-8] Wed May 1 22:14:47 2013
@@ -222,7 +222,7 @@ public class DefaultOnlineResource exten
/**
* Returns the location (address) for on-line access using a Uniform Resource Locator address or
- * similar addressing scheme such as @{@code http://www.statkart.no/isotc211}".
+ * similar addressing scheme such as "{@code http://www.statkart.no/isotc211}".
*/
@Override
@XmlElement(name = "linkage", required = true)
@@ -242,11 +242,18 @@ public class DefaultOnlineResource exten
}
/**
- * Returns the connection protocol to be used.
+ * Returns the connection protocol to be used. If no protocol has been {@linkplain #setProtocol(String)
+ * explicitely set}, then this method returns the {@linkplain #getLinkage() linkage}
+ * {@linkplain URI#getScheme() scheme} (if any).
+ *
+ * @see <a href="../doc-files/auto-properties.html">List of automatic properties</a>
*/
@Override
@XmlElement(name = "protocol")
public String getProtocol() {
+ if (protocol == null && linkage != null) {
+ return linkage.getScheme();
+ }
return protocol;
}
Modified: sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/package-info.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/package-info.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/package-info.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/citation/package-info.java [UTF-8] Wed May 1 22:14:47 2013
@@ -64,6 +64,11 @@
* except at XML marshalling time (for ISO 19139 compliance).
* See {@link org.apache.sis.xml.IdentifierMap} for more information.
*
+ * {@section Automatic properties}
+ * Some properties provide default value based on the value of other properties.
+ * See the <a href="../doc-files/auto-properties.html">list of automatic properties</a>
+ * page for more information.
+ *
* {@section Null values, nil objects and collections}
* All constructors (except the <cite>copy constructors</cite>) and setter methods accept {@code null} arguments.
* A null argument value means that the metadata element can not be provided, and the reason for that is unspecified.
Modified: sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/maintenance/DefaultScopeDescription.java [UTF-8] Wed May 1 22:14:47 2013
@@ -218,6 +218,8 @@ public class DefaultScopeDescription ext
c = cast(value, type);
} else if (isNullOrEmpty(newValue)) {
return;
+ } else {
+ property = code;
}
value = writeSet(newValue, c, type);
}
@@ -343,6 +345,7 @@ public class DefaultScopeDescription ext
public void setDataset(final String newValue) {
checkWritePermission();
if (newValue != null || property == DATASET) {
+ property = DATASET;
value = newValue;
}
}
@@ -370,6 +373,7 @@ public class DefaultScopeDescription ext
public void setOther(final String newValue) {
checkWritePermission();
if (newValue != null || property == OTHER) {
+ property = OTHER;
value = newValue;
}
}
Modified: sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java [UTF-8] Wed May 1 22:14:47 2013
@@ -17,10 +17,10 @@
package org.apache.sis.metadata.iso.quality;
import java.util.Date;
-import java.util.Arrays;
import java.util.Iterator;
import java.util.Collection;
-import java.util.Collections;
+import java.util.AbstractList;
+import java.io.Serializable;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@@ -38,8 +38,12 @@ import org.opengis.metadata.quality.Logi
import org.opengis.metadata.quality.EvaluationMethodType;
import org.opengis.util.InternationalString;
import org.apache.sis.metadata.iso.ISOMetadata;
+import org.apache.sis.util.collection.CheckedContainer;
import org.apache.sis.util.resources.Errors;
+import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
+import static org.apache.sis.internal.jaxb.MarshalContext.isMarshalling;
+
/**
* Type of test applied to the data specified by a data quality scope.
@@ -107,10 +111,171 @@ public class AbstractElement extends ISO
private Citation evaluationProcedure;
/**
- * Start time ({@code date1}) and end time ({@code date2}) on which a data quality measure
- * was applied. Value is {@link Long#MIN_VALUE} if this information is not available.
+ * Start time ({@code date1}) and end time ({@code date2}) on which a data quality measure was applied.
*/
- private long date1, date2;
+ private Dates dates;
+
+ /**
+ * The start and end times as a list of O, 1 or 2 elements.
+ */
+ private static final class Dates extends AbstractList<Date>
+ implements CheckedContainer<Date>, Cloneable, Serializable
+ {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = 1210175223467194009L;
+
+ /**
+ * Start time ({@code date1}) and end time ({@code date2}) on which a data quality measure
+ * was applied. Value is {@link Long#MIN_VALUE} if this information is not available.
+ */
+ private long date1, date2;
+
+ /**
+ * Creates a new list initialized with no dates.
+ */
+ Dates() {
+ clear();
+ }
+
+ /**
+ * Returns the type of elements in this list.
+ * @return
+ */
+ @Override
+ public Class<Date> getElementType() {
+ return Date.class;
+ }
+
+ /**
+ * Removes all dates in this list.
+ */
+ @Override
+ public void clear() {
+ date1 = Long.MIN_VALUE;
+ date2 = Long.MIN_VALUE;
+ }
+
+ /**
+ * Returns the number of elements in this list.
+ */
+ @Override
+ public int size() {
+ if (date2 != Long.MIN_VALUE) return 2;
+ if (date1 != Long.MIN_VALUE) return 1;
+ return 0;
+ }
+
+ /**
+ * Returns the value at the given index.
+ */
+ @Override
+ @SuppressWarnings("fallthrough")
+ public Date get(final int index) {
+ long date = date1;
+ switch (index) {
+ case 1: date = date2; // Fall through
+ case 0: if (date != Long.MIN_VALUE) return new Date(date); // else fallthrough.
+ default: throw new IndexOutOfBoundsException(Errors.format(Errors.Keys.IndexOutOfBounds_1, index));
+ }
+ }
+
+ /**
+ * Sets the value at the given index.
+ * Null values are not allowed.
+ */
+ @Override
+ public Date set(final int index, final Date value) {
+ final long date = value.getTime();
+ final Date previous = get(index);
+ switch (index) {
+ case 0: date1 = date; break;
+ case 1: date2 = date; break;
+ }
+ modCount++;
+ return previous;
+ }
+
+ /**
+ * Removes the value at the given index.
+ */
+ @Override
+ @SuppressWarnings("fallthrough")
+ public Date remove(final int index) {
+ final Date previous = get(index);
+ switch (index) {
+ case 0: date1 = date2; // Fallthrough
+ case 1: date2 = Long.MIN_VALUE; break;
+ }
+ modCount++;
+ return previous;
+ }
+
+ /**
+ * Adds a date at the given position.
+ * Null values are not allowed.
+ */
+ @Override
+ public void add(final int index, final Date value) {
+ final long date = value.getTime();
+ if (date2 == Long.MIN_VALUE) {
+ switch (index) {
+ case 0: {
+ date2 = date1;
+ date1 = date;
+ modCount++;
+ return;
+ }
+ case 1: {
+ if (date1 == Long.MIN_VALUE) {
+ break; // Exception will be thrown below.
+ }
+ date2 = date;
+ modCount++;
+ return;
+ }
+ }
+ }
+ throw new IndexOutOfBoundsException(Errors.format(Errors.Keys.IndexOutOfBounds_1, index));
+ }
+
+ /**
+ * Adds all content from the given collection into this collection.
+ */
+ @Override
+ @SuppressWarnings("fallthrough")
+ public boolean addAll(final Collection<? extends Date> dates) {
+ final int c = modCount;
+ if (dates != null) {
+ final Iterator<? extends Date> it = dates.iterator();
+ switch (size()) { // Fallthrough everywhere.
+ case 0: if (!it.hasNext()) break;
+ date1 = it.next().getTime();
+ modCount++;
+ case 1: if (!it.hasNext()) break;
+ date2 = it.next().getTime();
+ modCount++;
+ default: if (!it.hasNext()) break;
+ throw new IllegalArgumentException(Errors.format(
+ Errors.Keys.ExcessiveArgumentSize_3, "dates", 2, dates.size()));
+ }
+ }
+ return modCount != c;
+ }
+
+ /**
+ * Returns a clone of this list.
+ */
+ @Override
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
/**
* Value (or set of values) obtained from applying a data quality measure or the out
@@ -123,8 +288,6 @@ public class AbstractElement extends ISO
* Constructs an initially empty element.
*/
public AbstractElement() {
- date1 = Long.MIN_VALUE;
- date2 = Long.MIN_VALUE;
}
/**
@@ -331,15 +494,13 @@ public class AbstractElement extends ISO
@Override
@XmlElement(name = "dateTime")
public Collection<Date> getDates() {
- if (date1 == Long.MIN_VALUE) {
- return Collections.emptyList();
+ if (isMarshalling()) {
+ return isNullOrEmpty(dates) ? null : dates;
}
- if (date2 == Long.MIN_VALUE) {
- return Collections.singleton(new Date(date1));
+ if (dates == null) {
+ dates = new Dates();
}
- return Arrays.asList(
- new Date[] {new Date(date1), new Date(date2)}
- );
+ return dates;
}
/**
@@ -350,26 +511,23 @@ public class AbstractElement extends ISO
*/
public void setDates(final Collection<? extends Date> newValues) {
checkWritePermission();
- writeDates(newValues);
+ if (newValues != dates) { // Mandatory check for avoiding the call to 'dates.clear()'.
+ writeDates(newValues);
+ }
}
/**
* Implementation of {@link #setDates(Collection)}.
*/
private void writeDates(final Collection<? extends Date> newValues) {
- date1 = date2 = Long.MIN_VALUE;
- if (newValues != null) {
- final Iterator<? extends Date> it = newValues.iterator();
- if (it.hasNext()) {
- date1 = it.next().getTime();
- if (it.hasNext()) {
- date2 = it.next().getTime();
- if (it.hasNext()) {
- throw new IllegalArgumentException(Errors.format(
- Errors.Keys.ExcessiveArgumentSize_3, "dates", 2, newValues.size()));
- }
- }
+ if (isNullOrEmpty(newValues)) {
+ dates = null;
+ } else {
+ if (dates == null) {
+ dates = new Dates();
}
+ dates.clear();
+ dates.addAll(newValues);
}
}
Modified: sis/trunk/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/test/java/org/apache/sis/metadata/PropertyAccessorTest.java [UTF-8] Wed May 1 22:14:47 2013
@@ -399,4 +399,14 @@ public final strictfp class PropertyAcce
hashCode = accessor.hashCode(instance);
assertEquals("Metadata with two values.", baseCode + title.hashCode() + Arrays.asList(alternateTitle).hashCode(), hashCode);
}
+
+ /**
+ * Tests {@link PropertyAccessor#toString()}. The {@code toString()}
+ * method is only for debugging purpose, but we test it anyway.
+ */
+ @Test
+ public void testToString() {
+ final PropertyAccessor accessor = createPropertyAccessor();
+ assertEquals("PropertyAccessor[13 getters & 13 setters in DefaultCitation:Citation from “ISO 19115”]", accessor.toString());
+ }
}
Modified: sis/trunk/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java [UTF-8] (original)
+++ sis/trunk/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java [UTF-8] Wed May 1 22:14:47 2013
@@ -33,6 +33,7 @@ import org.junit.BeforeClass;
org.apache.sis.internal.metadata.MetadataUtilitiesTest.class,
org.apache.sis.metadata.iso.citation.DefaultCitationDateTest.class,
org.apache.sis.metadata.iso.citation.DefaultCitationTest.class,
+ org.apache.sis.metadata.iso.quality.AbstractElementTest.class,
// Classes using Java reflection.
org.apache.sis.metadata.PropertyInformationTest.class,
@@ -41,8 +42,11 @@ import org.junit.BeforeClass;
org.apache.sis.metadata.TypeMapTest.class,
org.apache.sis.metadata.InformationMapTest.class,
org.apache.sis.metadata.ValueMapTest.class,
+ org.apache.sis.metadata.MetadataTreeChildrenTest.class,
+ org.apache.sis.metadata.MetadataTreeNodeTest.class,
org.apache.sis.metadata.MetadataStandardTest.class,
- org.apache.sis.metadata.PrunerTest.class
+ org.apache.sis.metadata.PrunerTest.class,
+ org.apache.sis.metadata.iso.AllMetadataTest.class
})
public final strictfp class MetadataTestSuite extends TestSuite {
/**
Modified: sis/trunk/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java [UTF-8] (original)
+++ sis/trunk/sis-referencing/src/test/java/org/apache/sis/geometry/GeneralEnvelopeTest.java [UTF-8] Wed May 1 22:14:47 2013
@@ -20,6 +20,7 @@ import org.opengis.geometry.Envelope;
import org.opengis.geometry.DirectPosition;
import org.apache.sis.test.DependsOn;
import org.apache.sis.test.TestCase;
+import org.apache.sis.test.DependsOnMethod;
import org.junit.Ignore;
import org.junit.Test;
@@ -451,9 +452,25 @@ public strictfp class GeneralEnvelopeTes
}
/**
+ * Tests the {@link GeneralEnvelope#toString()} method.
+ */
+ @Test
+ public void testToString() {
+ GeneralEnvelope envelope = new GeneralEnvelope(new double[] {-180, -90}, new double[] {180, 90});
+ assertEquals("BOX(-180 -90, 180 90)", envelope.toString());
+
+ envelope = new GeneralEnvelope(3);
+ envelope.setRange(0, -180, +180);
+ envelope.setRange(1, -90, +90);
+ envelope.setRange(2, 10, 30);
+ assertEquals("BOX3D(-180 -90 10, 180 90 30)", envelope.toString());
+ }
+
+ /**
* Tests the {@link GeneralEnvelope#GeneralEnvelope(CharSequence)} constructor.
*/
@Test
+ @DependsOnMethod("testToString")
public void testWktParsing() {
GeneralEnvelope envelope = new GeneralEnvelope("BOX(-180 -90,180 90)");
assertEquals(2, envelope.getDimension());
Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedArrayList.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedArrayList.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedArrayList.java [UTF-8] (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedArrayList.java [UTF-8] Wed May 1 22:14:47 2013
@@ -17,13 +17,9 @@
package org.apache.sis.internal.util;
import java.util.List;
-import java.util.Iterator;
-import java.util.ListIterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.NoSuchElementException;
-import org.apache.sis.util.Decorator;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.collection.CheckedContainer;
@@ -35,12 +31,11 @@ import static org.apache.sis.util.Argume
* The type checks are performed at run-time in addition to the compile-time checks.
*
* <p>Using this class is similar to wrapping an {@link ArrayList} using the methods provided
- * in the standard {@link Collections} class, except for the following advantages:</p>
+ * in the standard {@link Collections} class, except for the following differences:</p>
*
* <ul>
* <li>Avoid one level of indirection.</li>
- * <li>Checks for write permission.</li>
- * <li>Overrideable methods for controlling the type checks and write permission checks.</li>
+ * <li>Does not accept null elements.</li>
* </ul>
*
* @param <E> The type of elements in the list.
@@ -52,7 +47,7 @@ import static org.apache.sis.util.Argume
*
* @see Collections#checkedList(List, Class)
*/
-public class CheckedArrayList<E> extends ArrayList<E> implements CheckedContainer<E>, Cloneable {
+public final class CheckedArrayList<E> extends ArrayList<E> implements CheckedContainer<E> {
/**
* Serial version UID for compatibility with different versions.
*/
@@ -95,16 +90,15 @@ public class CheckedArrayList<E> extends
}
/**
- * Ensures that the given element can be added to this list.
- * The default implementation ensures that the object is {@code null} or assignable
- * to the type specified at construction time. Subclasses can override this method
- * if they need to perform additional checks.
+ * Ensures that the given element is non-null and assignable to the type
+ * specified at construction time.
*
* @param element the object to check, or {@code null}.
* @throws IllegalArgumentException if the specified element can not be added to this list.
*/
- protected void ensureValid(final E element) throws IllegalArgumentException {
- if (element != null && !type.isInstance(element)) {
+ private void ensureValid(final E element) throws IllegalArgumentException {
+ if (!type.isInstance(element)) {
+ ensureNonNull("element", element);
throw new IllegalArgumentException(Errors.format(
Errors.Keys.IllegalArgumentClass_3, "element", type, element.getClass()));
}
@@ -123,143 +117,6 @@ public class CheckedArrayList<E> extends
}
/**
- * Checks if changes in this list are allowed. This method is automatically invoked before any
- * operation that may change the content. If the write operation is allowed, then this method
- * shall returns normally. Otherwise an {@link UnsupportedOperationException} is thrown.
- *
- * <p>The default implementation does nothing, thus allowing this list to be modified.
- * Subclasses can override this method if they want to control write permissions.</p>
- *
- * @throws UnsupportedOperationException if this list is unmodifiable.
- */
- protected void checkWritePermission() throws UnsupportedOperationException {
- }
-
- /**
- * An iterator with a check for write permission prior element removal.
- * This class wraps the iterator provided by {@link ArrayList#iterator()}, and is
- * also the base class for the wrapper around {@link ArrayList#listIterator()}.
- *
- * @see CheckedArrayList#iterator()
- */
- @Decorator(Iterator.class)
- private class Iter<I extends Iterator<E>> implements Iterator<E> {
- /** The {@link ArrayList} iterator. */
- protected final I iterator;
-
- /** Creates a new wrapper for the given {@link ArrayList} iterator. */
- Iter(final I iterator) {
- this.iterator = iterator;
- }
-
- /** Returns {@code true} if there is more elements in the iteration. */
- @Override
- public final boolean hasNext() {
- return iterator.hasNext();
- }
-
- /** Returns the next element in the iteration. */
- @Override
- public final E next() throws NoSuchElementException {
- return iterator.next();
- }
-
- /** Removes the previous element if the enclosing {@link CheckedArrayList} allows write operations. */
- @Override
- public final void remove() throws UnsupportedOperationException {
- checkWritePermission();
- iterator.remove();
- }
- }
-
- /**
- * A list iterator with a check for write permission prior element removal.
- * This class wraps the iterator provided by {@link ArrayList#listIterator()}.
- *
- * @see CheckedArrayList#listIterator()
- * @see CheckedArrayList#listIterator(int)
- */
- @Decorator(ListIterator.class)
- private class ListIter extends Iter<ListIterator<E>> implements ListIterator<E> {
- /** Creates a new wrapper for the given {@link ArrayList} list iterator. */
- ListIter(final ListIterator<E> iterator) {
- super(iterator);
- }
-
- /** Returns the index of the element to be returned by {@link #next()}. */
- @Override
- public int nextIndex() {
- return iterator.nextIndex();
- }
-
- /** Returns the index of the element to be returned by {@link #previous()}. */
- @Override
- public int previousIndex() {
- return iterator.previousIndex();
- }
-
- /** Returns {@code true} if there is elements before current position. */
- @Override
- public boolean hasPrevious() {
- return iterator.hasPrevious();
- }
-
- /** Returns the previous element in the iteration. */
- @Override
- public E previous() throws NoSuchElementException {
- return iterator.previous();
- }
-
- /** See the {@link CheckedArrayList#set(int, Object)} method contract. */
- @Override
- public void set(final E element) throws IllegalArgumentException, UnsupportedOperationException {
- ensureValid(element);
- checkWritePermission();
- iterator.set(element);
- }
-
- /** See the {@link CheckedArrayList#add(Object)} method contract. */
- @Override
- public void add(final E element) throws IllegalArgumentException, UnsupportedOperationException {
- ensureValid(element);
- checkWritePermission();
- iterator.add(element);
- }
- }
-
- /**
- * Returns an iterator over the elements in this list.
- * The returned iterator will support {@linkplain Iterator#remove() element removal}
- * only if the {@link #checkWritePermission()} method does not throw exception.
- */
- @Override
- public Iterator<E> iterator() {
- return new Iter<Iterator<E>>(super.iterator());
- }
-
- /**
- * Returns an iterator over the elements in this list.
- * The returned iterator will support {@linkplain ListIterator#remove() element removal},
- * {@linkplain ListIterator#add(Object) addition} or {@linkplain ListIterator#set(Object)
- * modification} only if the {@link #checkWritePermission()} method does not throw exception.
- */
- @Override
- public ListIterator<E> listIterator() {
- return new ListIter(super.listIterator());
- }
-
- /**
- * Returns an iterator over the elements in this list, starting at the given index.
- * The returned iterator will support {@linkplain ListIterator#remove() element removal},
- * {@linkplain ListIterator#add(Object) addition} or {@linkplain ListIterator#set(Object)
- * modification} only if the {@link #checkWritePermission()} method does not throw exception.
- */
- @Override
- public ListIterator<E> listIterator(final int index) {
- return new ListIter(super.listIterator(index));
- }
-
- /**
* Replaces the element at the specified position in this list with the specified element.
*
* @param index index of element to replace.
@@ -267,14 +124,10 @@ public class CheckedArrayList<E> extends
* @return the element previously at the specified position.
* @throws IndexOutOfBoundsException if index out of range.
* @throws IllegalArgumentException if the specified element is not of the expected type.
- * @throws UnsupportedOperationException if this collection is unmodifiable.
*/
@Override
- public E set(final int index, final E element)
- throws IllegalArgumentException, UnsupportedOperationException
- {
+ public E set(final int index, final E element) throws IllegalArgumentException {
ensureValid(element);
- checkWritePermission();
return super.set(index, element);
}
@@ -284,14 +137,10 @@ public class CheckedArrayList<E> extends
* @param element element to be appended to this list.
* @return always {@code true}.
* @throws IllegalArgumentException if the specified element is not of the expected type.
- * @throws UnsupportedOperationException if this collection is unmodifiable.
*/
@Override
- public boolean add(final E element)
- throws IllegalArgumentException, UnsupportedOperationException
- {
+ public boolean add(final E element) throws IllegalArgumentException {
ensureValid(element);
- checkWritePermission();
return super.add(element);
}
@@ -302,14 +151,10 @@ public class CheckedArrayList<E> extends
* @param element element to be inserted.
* @throws IndexOutOfBoundsException if index out of range.
* @throws IllegalArgumentException if the specified element is not of the expected type.
- * @throws UnsupportedOperationException if this collection is unmodifiable.
*/
@Override
- public void add(final int index, final E element)
- throws IllegalArgumentException, UnsupportedOperationException
- {
+ public void add(final int index, final E element) throws IllegalArgumentException {
ensureValid(element);
- checkWritePermission();
super.add(index, element);
}
@@ -320,14 +165,10 @@ public class CheckedArrayList<E> extends
* @param collection the elements to be inserted into this list.
* @return {@code true} if this list changed as a result of the call.
* @throws IllegalArgumentException if at least one element is not of the expected type.
- * @throws UnsupportedOperationException if this collection is unmodifiable.
*/
@Override
- public boolean addAll(final Collection<? extends E> collection)
- throws IllegalArgumentException, UnsupportedOperationException
- {
+ public boolean addAll(final Collection<? extends E> collection) throws IllegalArgumentException {
ensureValidCollection(collection);
- checkWritePermission();
return super.addAll(collection);
}
@@ -339,69 +180,10 @@ public class CheckedArrayList<E> extends
* @param collection elements to be inserted into this list.
* @return {@code true} if this list changed as a result of the call.
* @throws IllegalArgumentException if at least one element is not of the expected type.
- * @throws UnsupportedOperationException if this collection is unmodifiable.
*/
@Override
- public boolean addAll(final int index, final Collection<? extends E> collection)
- throws IllegalArgumentException, UnsupportedOperationException
- {
+ public boolean addAll(final int index, final Collection<? extends E> collection) throws IllegalArgumentException {
ensureValidCollection(collection);
- checkWritePermission();
return super.addAll(index, collection);
}
-
- /**
- * Removes the element at the specified position in this list.
- *
- * @throws UnsupportedOperationException if this collection is unmodifiable.
- */
- @Override
- public E remove(int index) throws UnsupportedOperationException {
- checkWritePermission();
- return super.remove(index);
- }
-
- /**
- * Removes the first occurrence of the specified element from this list.
- *
- * @throws UnsupportedOperationException if this collection is unmodifiable.
- */
- @Override
- public boolean remove(Object o) throws UnsupportedOperationException {
- checkWritePermission();
- return super.remove(o);
- }
-
- /**
- * Removes all of this list's elements that are also contained in the specified collection.
- *
- * @throws UnsupportedOperationException if this collection is unmodifiable.
- */
- @Override
- public boolean removeAll(Collection<?> c) throws UnsupportedOperationException {
- checkWritePermission();
- return super.removeAll(c);
- }
-
- /**
- * Retains only the elements in this list that are contained in the specified collection.
- *
- * @throws UnsupportedOperationException if this collection is unmodifiable.
- */
- @Override
- public boolean retainAll(Collection<?> c) throws UnsupportedOperationException {
- checkWritePermission();
- return super.retainAll(c);
- }
-
- /**
- * Removes all of the elements from this list.
- *
- * @throws UnsupportedOperationException if this collection is unmodifiable.
- */
- @Override
- public void clear() throws UnsupportedOperationException {
- checkWritePermission();
- super.clear();
- }
}
Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedHashSet.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedHashSet.java?rev=1478218&r1=1478217&r2=1478218&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedHashSet.java [UTF-8] (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/CheckedHashSet.java [UTF-8] Wed May 1 22:14:47 2013
@@ -17,12 +17,8 @@
package org.apache.sis.internal.util;
import java.util.Set;
-import java.util.Iterator;
-import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
-import java.util.NoSuchElementException;
-import org.apache.sis.util.Decorator;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.collection.CheckedContainer;
@@ -34,12 +30,11 @@ import static org.apache.sis.util.Argume
* The type checks are performed at run-time in addition to the compile-time checks.
*
* <p>Using this class is similar to wrapping a {@link LinkedHashSet} using the methods provided
- * in the standard {@link Collections} class, except for the following advantages:</p>
+ * in the standard {@link Collections} class, except for the following differences:</p>
*
* <ul>
* <li>Avoid one level of indirection.</li>
- * <li>Checks for write permission.</li>
- * <li>Overrideable methods for controlling the type checks and write permission checks.</li>
+ * <li>Does not accept null elements.</li>
* </ul>
*
* @param <E> The type of elements in the set.
@@ -51,7 +46,7 @@ import static org.apache.sis.util.Argume
*
* @see Collections#checkedSet(Set, Class)
*/
-public class CheckedHashSet<E> extends LinkedHashSet<E> implements CheckedContainer<E>, Cloneable {
+public final class CheckedHashSet<E> extends LinkedHashSet<E> implements CheckedContainer<E> {
/**
* Serial version UID for compatibility with different versions.
*/
@@ -94,167 +89,23 @@ public class CheckedHashSet<E> extends L
}
/**
- * Ensures that the given element can be added to this set.
- * The default implementation ensures that the object is {@code null} or assignable
- * to the type specified at construction time. Subclasses can override this method
- * if they need to perform additional checks.
- *
- * @param element the object to check, or {@code null}.
- * @throws IllegalArgumentException if the specified element can not be added to this set.
- */
- protected void ensureValid(final E element) throws IllegalArgumentException {
- if (element != null && !type.isInstance(element)) {
- throw new IllegalArgumentException(Errors.format(
- Errors.Keys.IllegalArgumentClass_3, "element", type, element.getClass()));
- }
- }
-
- /**
- * Ensures that all elements of the given collection can be added to this set.
- *
- * @param collection the collection to check, or {@code null}.
- * @throws IllegalArgumentException if at least one element can not be added to this set.
- */
- private void ensureValidCollection(final Collection<? extends E> collection) throws IllegalArgumentException {
- for (final E element : collection) {
- ensureValid(element);
- }
- }
-
- /**
- * Checks if changes in this set are allowed. This method is automatically invoked before any
- * operation that may change the content. If the write operation is allowed, then this method
- * shall returns normally. Otherwise an {@link UnsupportedOperationException} is thrown.
- *
- * <p>The default implementation does nothing, thus allowing this set to be modified.
- * Subclasses can override this method if they want to control write permissions.</p>
- *
- * @throws UnsupportedOperationException if this set is unmodifiable.
- */
- protected void checkWritePermission() throws UnsupportedOperationException {
- }
-
- /**
- * An iterator with a check for write permission prior element removal.
- * This class wraps the iterator provided by {@link LinkedHashSet#iterator()}.
- *
- * @see CheckedHashSet#iterator()
- */
- @Decorator(Iterator.class)
- private final class Iter implements Iterator<E> {
- /** The {@link LinkedHashSet} iterator. */
- private final Iterator<E> iterator;
-
- /** Creates a new wrapper for the given {@link LinkedHashSet} iterator. */
- Iter(final Iterator<E> iterator) {
- this.iterator = iterator;
- }
-
- /** Returns {@code true} if there is more elements in the iteration. */
- @Override
- public boolean hasNext() {
- return iterator.hasNext();
- }
-
- /** Returns the next element in the iteration. */
- @Override
- public E next() throws NoSuchElementException {
- return iterator.next();
- }
-
- /** Removes the previous element if the enclosing {@link CheckedHashSet} allows write operations. */
- @Override
- public void remove() throws UnsupportedOperationException {
- checkWritePermission();
- iterator.remove();
- }
- }
-
- /**
- * Returns an iterator over the elements in this set.
- * The returned iterator will support {@linkplain Iterator#remove() element removal}
- * only if the {@link #checkWritePermission()} method does not throw exception.
- */
- @Override
- public Iterator<E> iterator() {
- return new Iter(super.iterator());
- }
-
- /**
* Adds the specified element to this set if it is not already present.
*
* @param element element to be added to this set.
* @return {@code true} if the set did not already contain the specified element.
* @throws IllegalArgumentException if the specified element is not of the expected type.
- * @throws UnsupportedOperationException if this collection is unmodifiable.
*/
@Override
- public boolean add(final E element)
- throws IllegalArgumentException, UnsupportedOperationException
- {
- ensureValid(element);
- checkWritePermission();
+ public boolean add(final E element) throws IllegalArgumentException {
+ if (!type.isInstance(element)) {
+ ensureNonNull("element", element);
+ throw new IllegalArgumentException(Errors.format(
+ Errors.Keys.IllegalArgumentClass_3, "element", type, element.getClass()));
+ }
return super.add(element);
}
- /**
- * Appends all of the elements in the specified collection to this set.
- *
- * @param collection the elements to be inserted into this set.
- * @return {@code true} if this set changed as a result of the call.
- * @throws IllegalArgumentException if at least one element is not of the expected type.
- * @throws UnsupportedOperationException if this collection is unmodifiable.
- */
- @Override
- public boolean addAll(final Collection<? extends E> collection)
- throws IllegalArgumentException, UnsupportedOperationException
- {
- ensureValidCollection(collection);
- checkWritePermission();
- return super.addAll(collection);
- }
-
- /**
- * Removes the specified element from this set.
- *
- * @throws UnsupportedOperationException if this collection is unmodifiable.
- */
- @Override
- public boolean remove(Object o) throws UnsupportedOperationException {
- checkWritePermission();
- return super.remove(o);
- }
-
- /**
- * Removes all of this set's elements that are also contained in the specified collection.
- *
- * @throws UnsupportedOperationException if this collection is unmodifiable.
- */
- @Override
- public boolean removeAll(Collection<?> c) throws UnsupportedOperationException {
- checkWritePermission();
- return super.removeAll(c);
- }
-
- /**
- * Retains only the elements in this set that are contained in the specified collection.
- *
- * @throws UnsupportedOperationException if this collection is unmodifiable.
+ /*
+ * No need to override 'addAll', since it is implemented on top of 'add'.
*/
- @Override
- public boolean retainAll(Collection<?> c) throws UnsupportedOperationException {
- checkWritePermission();
- return super.retainAll(c);
- }
-
- /**
- * Removes all of the elements from this set.
- *
- * @throws UnsupportedOperationException if this collection is unmodifiable.
- */
- @Override
- public void clear() throws UnsupportedOperationException {
- checkWritePermission();
- super.clear();
- }
}