Author: desruisseaux
Date: Fri Apr 26 13:44:11 2013
New Revision: 1476199
URL: http://svn.apache.org/r1476199
Log:
Minor adjustment for the upcomming MetadataTreeTable.
Modified:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/Classes.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/ClassesTest.java
Modified:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java?rev=1476199&r1=1476198&r2=1476199&view=diff
==============================================================================
---
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
[UTF-8] Fri Apr 26 13:44:11 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;
@@ -97,6 +96,12 @@ final class PropertyAccessor {
private static final Map<Class<?>, Method[]> SHARED_GETTERS = new
IdentityHashMap<>();
/**
+ * 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
@@ -551,6 +556,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.
*
@@ -900,26 +915,48 @@ 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 max Stop the count if we reach that value (indicative purpose
only).
+ * @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 max)
+ public int count(final Object metadata, final ValueExistencePolicy
valuePolicy, final int mode)
throws BackingStoreException
{
assert type.isInstance(metadata) : metadata;
- if (valuePolicy == ValueExistencePolicy.ALL) {
+ 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)) {
- if (++count >= max) {
- break;
+ switch (mode) {
+ case COUNT_FIRST:{
+ return 1;
+ }
+ case COUNT_SHALLOW:{
+ count++;
+ break;
+ }
+ case COUNT_DEEP: {
+ if (value != null) {
+ count += isCollection(i) ? ((Collection<?>)
value).size() : 1;
+ }
+ break;
+ }
+ default: throw new AssertionError(mode);
}
}
}
Modified:
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java?rev=1476199&r1=1476198&r2=1476199&view=diff
==============================================================================
---
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/ValueMap.java
[UTF-8] Fri Apr 26 13:44:11 2013
@@ -69,7 +69,7 @@ final class ValueMap extends PropertyMap
*/
@Override
public boolean isEmpty() {
- return accessor.count(metadata, valuePolicy, 1) == 0;
+ return accessor.count(metadata, valuePolicy,
PropertyAccessor.COUNT_FIRST) == 0;
}
/**
@@ -77,7 +77,7 @@ final class ValueMap extends PropertyMap
*/
@Override
public int size() {
- return accessor.count(metadata, valuePolicy, Integer.MAX_VALUE);
+ return accessor.count(metadata, valuePolicy,
PropertyAccessor.COUNT_SHALLOW);
}
/**
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/Classes.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/Classes.java?rev=1476199&r1=1476198&r2=1476199&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/Classes.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/Classes.java
[UTF-8] Fri Apr 26 13:44:11 2013
@@ -560,20 +560,55 @@ cmp: for (final Class<?> c : c1) {
}
/**
- * Returns a short class name for the specified class. This method will
- * omit the package name. For example, it will return {@code "String"}
instead
- * of {@code "java.lang.String"} for a {@link String} object. It will also
name
- * array according Java language usage, for example {@code "double[]"}
instead
- * of {@code "[D"}.
- *
- * <p>This method is similar to the {@link Class#getSimpleName()} method,
except that
- * if the given class is an inner class, then the returned value is
prefixed with the
- * outer class name. For example this method returns {@code
"Point2D.Double"} instead
- * of {@code "Double"}.</p>
+ * Returns the name of the given class without package name, but including
the names of enclosing
+ * classes if any. This method is similar to the {@link
Class#getSimpleName()} method, except that
+ * if the given class is an inner class, then the returned value is
prefixed with the outer class
+ * name. An other difference is that if the given class is local or
anonymous, then this method
+ * returns the name of the parent class.
+ *
+ * <p>The following table compares the various kind of names for some
examples:</p>
+ *
+ * <table class="sis">
+ * <tr>
+ * <td>Class</td>
+ * <td>{@code getName()}</td>
+ * <td>{@code getSimpleName()}</td>
+ * <td>{@code getCanonicalName()}</td>
+ * <td>{@code getShortName()}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link String}</td>
+ * <td>{@code "java.lang.String"}</td>
+ * <td>{@code "String"}</td>
+ * <td>{@code "java.lang.String"}</td>
+ * <td>{@code "String"}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link double[]}</td>
+ * <td>{@code "[D"}</td>
+ * <td>{@code "double[]"}</td>
+ * <td>{@code "double[]"}</td>
+ * <td>{@code "double[]"}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link java.awt.geom.Point2D.Double}</td>
+ * <td>{@code "java.awt.geom.Point2D$Double"}</td>
+ * <td>{@code "Double"}</td>
+ * <td>{@code "java.awt.geom.Point2D.Double"}</td>
+ * <td>{@code "Point2D.Double"}</td>
+ * </tr>
+ * <tr>
+ * <td>Anonymous {@link Comparable}</td>
+ * <td>{@code "com.mycompany.myclass$1"}</td>
+ * <td>{@code ""}</td>
+ * <td>{@code null}</td>
+ * <td>{@code "Object"}</td>
+ * </tr>
+ * </table>
*
* @param classe The object class (may be {@code null}).
- * @return A short class name for the specified object, or {@code "<*>"}
if the
- * given class was null.
+ * @return The simple name with outer class name (if any) of the first
non-anonymous
+ * class in the hierarchy, or {@code "<*>"} if the given class is
null.
*
* @see #getShortClassName(Object)
* @see Class#getSimpleName()
@@ -594,12 +629,14 @@ cmp: for (final Class<?> c : c1) {
}
/**
- * Returns a short class name for the specified object. This method will
- * omit the package name. For example, it will return {@code "String"}
- * instead of {@code "java.lang.String"} for a {@link String} object.
+ * Returns the class name of the given object without package name, but
including the enclosing class names
+ * if any. Invoking this method is equivalent to invoking {@code
getShortName(object.getClass())} except for
+ * {@code null} value. See {@link #getShortName(Class)} for more
information on the class name returned by
+ * this method.
*
* @param object The object (may be {@code null}).
- * @return A short class name for the specified object.
+ * @return The simple class name with outer class name (if any) of the
first non-anonymous
+ * class in the hierarchy, or {@code "<*>"} if the given object is
null.
*
* @see #getShortName(Class)
*/
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java?rev=1476199&r1=1476198&r2=1476199&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/DefaultTreeTable.java
[UTF-8] Fri Apr 26 13:44:11 2013
@@ -502,9 +502,27 @@ public class DefaultTreeTable implements
}
/**
- * Returns the node children. This list is modifiable and updates
automatically the
- * {@linkplain #getParent() parent} reference of any {@code Node}
instance added to
- * ore removed from this list.
+ * Returns {@code true} if this node can not have any children. The
default implementation
+ * unconditionally returns {@code false} even if the list of children
is empty, because the
+ * list is allowed to grow at any time.
+ *
+ * <p>Subclasses can override this method if they can determine which
nodes are leaves.
+ * In the current implementation, the return value shall be stable
(i.e. a node can not
+ * alternate between leaf and non-leaf state). However this
restriction may be relaxed
+ * in a future SIS version.</p>
+ */
+ @Override
+ public boolean isLeaf() {
+ return false;
+ }
+
+ /**
+ * Returns the children of this node. For non-leaf nodes, the list is
modifiable and will
+ * automatically updates the {@linkplain #getParent() parent}
reference of any {@code Node}
+ * instance added to or removed from the list.
+ *
+ * <p>For leaf nodes, this method returns an unmodifiable
+ * {@linkplain Collections#emptyList() empty list}.</p>
*/
/* NOTE: If a future version removes the "final" keyword, then search
for calls to
* this method where the return value is casted to TreeNodeList. Any
unconditional
@@ -513,7 +531,11 @@ public class DefaultTreeTable implements
@Override
public final List<TreeTable.Node> getChildren() {
if (children == null) {
- children = new Children(this);
+ if (isLeaf()) {
+ children = Collections.emptyList();
+ } else {
+ children = new Children(this);
+ }
}
return children;
}
Modified:
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java?rev=1476199&r1=1476198&r2=1476199&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/collection/TreeTable.java
[UTF-8] Fri Apr 26 13:44:11 2013
@@ -135,6 +135,18 @@ public interface TreeTable {
Node getParent();
/**
+ * Returns {@code true} if this node can not have any children. The
{@linkplain #getChildren()
+ * children list} of a leaf node can only be empty, and adding
{@linkplain #newChild() new child}
+ * is an unsupported operation.
+ *
+ * <p>This value is provided as a tip for graphical user interfaces,
in order to determine if
+ * a node is expandable (even if empty). {@link TreeTableFormat} does
not use this value.</p>
+ *
+ * @return {@code true} if this node can not have any children.
+ */
+ boolean isLeaf();
+
+ /**
* Returns the children of this node. The returned list may or may not
be modifiable, at
* implementation choice. If the list is modifiable, then it shall be
<cite>live</cite>,
* i.e. any modification to the returned list are reflected
immediately in the tree.
Modified:
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/ClassesTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/ClassesTest.java?rev=1476199&r1=1476198&r2=1476199&view=diff
==============================================================================
---
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/ClassesTest.java
[UTF-8] (original)
+++
sis/branches/JDK7/sis-utility/src/test/java/org/apache/sis/util/ClassesTest.java
[UTF-8] Fri Apr 26 13:44:11 2013
@@ -43,6 +43,7 @@ import java.io.ObjectStreamException;
import java.io.InvalidObjectException;
import java.io.NotSerializableException;
import java.io.Serializable;
+import java.awt.geom.Point2D;
import org.opengis.referencing.IdentifiedObject;
import org.opengis.referencing.crs.SingleCRS;
import org.opengis.referencing.crs.GeographicCRS;
@@ -224,4 +225,36 @@ public final strictfp class ClassesTest
public void setter2(Set<? extends Short> dummy) {}
public void setter3(Set<? super Double> dummy) {}
}
+
+ /**
+ * Tests the {@link Classes#getShortName(Class)}, in particular the
example values
+ * given in the javadoc.
+ */
+ @Test
+ public void testGetShortName() {
+ assertEquals("java.lang.String", String.class.getName());
+ assertEquals("String", String.class.getSimpleName());
+ assertEquals("java.lang.String", String.class.getCanonicalName());
+ assertEquals("String", getShortName(String.class));
+
+ assertEquals("[D", double[].class.getName());
+ assertEquals("double[]", double[].class.getSimpleName());
+ assertEquals("double[]", double[].class.getCanonicalName());
+ assertEquals("double[]", getShortName(double[].class));
+
+ assertEquals("java.awt.geom.Point2D$Double",
Point2D.Double.class.getName());
+ assertEquals("Double",
Point2D.Double.class.getSimpleName());
+ assertEquals("java.awt.geom.Point2D.Double",
Point2D.Double.class.getCanonicalName());
+ assertEquals("Point2D.Double",
getShortName(Point2D.Double.class));
+
+ final Class<?> anonymous = new Comparable<Object>() {
+ @Override public int compareTo(final Object o) {
+ return 0; // Not the purpose of this test.
+ }
+ }.getClass();
+
assertTrue(anonymous.getName().startsWith("org.apache.sis.util.ClassesTest$"));
+ assertEquals("", anonymous.getSimpleName());
+ assertEquals(null, anonymous.getCanonicalName());
+ assertEquals("Object", getShortName(anonymous));
+ }
}