sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1451725 - in /sis/branches/JDK7: ide-project/NetBeans/nbproject/ sis-metadata/src/main/java/org/apache/sis/metadata/ sis-utility/src/main/java/org/apache/sis/util/resources/
Date Fri, 01 Mar 2013 21:41:45 GMT
Author: desruisseaux
Date: Fri Mar  1 21:41:44 2013
New Revision: 1451725

URL: http://svn.apache.org/r1451725
Log:
Partial port of the MetadataStandard class.

Added:
    sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java
  (with props)
    sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/StandardImplementation.java
  (with props)
Modified:
    sis/branches/JDK7/ide-project/NetBeans/nbproject/project.xml
    sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/AbstractMetadata.java
    sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/PropertyAccessor.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties

Modified: sis/branches/JDK7/ide-project/NetBeans/nbproject/project.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/ide-project/NetBeans/nbproject/project.xml?rev=1451725&r1=1451724&r2=1451725&view=diff
==============================================================================
--- sis/branches/JDK7/ide-project/NetBeans/nbproject/project.xml (original)
+++ sis/branches/JDK7/ide-project/NetBeans/nbproject/project.xml Fri Mar  1 21:41:44 2013
@@ -21,6 +21,7 @@
         <spellchecker-wordlist xmlns="http://www.netbeans.org/ns/spellchecker-wordlist/1">
             <word>bitmask</word>
             <word>classname</word>
+            <word>classnames</word>
             <word>classpath</word>
             <word>deserialization</word>
             <word>deserialized</word>

Modified: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/AbstractMetadata.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/AbstractMetadata.java?rev=1451725&r1=1451724&r2=1451725&view=diff
==============================================================================
--- sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/AbstractMetadata.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/AbstractMetadata.java
[UTF-8] Fri Mar  1 21:41:44 2013
@@ -57,9 +57,11 @@ public abstract class AbstractMetadata i
      *
      * @see <a href="http://jira.geotoolkit.org/browse/GEOTK-48">GEOTK-48</a>
      */
-    private static Class<?> getClass(final Object metadata) {
+    private static Class<?> getPublicClass(final Object metadata) {
         Class<?> type = metadata.getClass();
-        while (!Modifier.isPublic(type.getModifiers()) && type.getName().startsWith("org.apache.sis.metadata.iso."))
{ // TODO
+        while (!Modifier.isPublic(type.getModifiers()) &&
+                type.getName().startsWith(MetadataStandard.SIS_PACKAGE))
+        {
             type = type.getSuperclass();
         }
         return type;
@@ -85,7 +87,7 @@ public abstract class AbstractMetadata i
             return true;
         }
         if (mode == ComparisonMode.STRICT) {
-            if (object == null || getClass(object) != getClass(this)) {
+            if (object == null || getPublicClass(object) != getPublicClass(this)) {
                 return false;
             }
         }

Added: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java?rev=1451725&view=auto
==============================================================================
--- sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java
(added)
+++ sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java
[UTF-8] Fri Mar  1 21:41:44 2013
@@ -0,0 +1,509 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.metadata;
+
+import java.util.Set;
+import java.util.Map;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashSet;
+import java.util.Collection;
+import java.util.Iterator;
+import net.jcip.annotations.ThreadSafe;
+import org.opengis.metadata.citation.Citation;
+import org.apache.sis.util.Classes;
+import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.util.resources.Errors;
+
+import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
+
+
+/**
+ * Enumeration of some metadata standards. A standard is defined by a set of Java interfaces
+ * in a specific package or sub-packages. For example the {@linkplain #ISO_19115 ISO 19115}
+ * standard is defined by <a href="http://www.geoapi.org">GeoAPI</a> interfaces
in the
+ * {@link org.opengis.metadata} package and sub-packages.
+ *
+ * <p>This class provides some methods operating on metadata instances through
+ * {@linkplain java.lang.reflect Java reflection}. The following rules are assumed:</p>
+ *
+ * <ul>
+ *   <li>Properties (or metadata attributes) are defined by the collection of {@code
get*()}
+ *       methods with arbitrary return type, or {@code is*()} methods with boolean return
type,
+ *       found in the <strong>interface</strong>. Getters declared only in the
implementation
+ *       are ignored.</li>
+ *   <li>Every properties are <cite>readable</cite>.</li>
+ *   <li>A property is <cite>writable</cite> if a {@code set*(...)} method
is defined
+ *       in the implementation class for the corresponding {@code get*()} method. The
+ *       setter doesn't need to be defined in the interface.</li>
+ * </ul>
+ *
+ * An instance of {@code MetadataStandard} is associated to every {@link AbstractMetadata}
objects.
+ * The {@code AbstractMetadata} base class usually form the basis of ISO 19115 implementations
but
+ * can also be used for other standards. An instance of {@code MetadataStandard} is also
associated
+ * with Image I/O {@link org.apache.sis.image.io.metadata.SpatialMetadataFormat} in order
to define
+ * the tree of XML nodes to be associated with raster data.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3 (derived from geotk-2.4)
+ * @version 0.3
+ * @module
+ */
+@ThreadSafe
+public class MetadataStandard {
+    /**
+     * The package of SIS implementation of ISO 19115.
+     * This package name has a trailing dot.
+     */
+    static final String SIS_PACKAGE = "org.apache.sis.metadata.iso.";
+
+    /**
+     * Metadata instances defined in this class. The current implementation does not yet
+     * contains the user-defined instances. However this may be something we will need to
+     * do in the future.
+     */
+    private static final MetadataStandard[] INSTANCES;
+
+    /**
+     * An instance working on ISO 19123 standard as defined by GeoAPI interfaces
+     * in the {@link org.opengis.referencing} package and sub-packages.
+     */
+    public static final MetadataStandard ISO_19111;
+
+    /**
+     * An instance working on ISO 19115 standard as defined by GeoAPI interfaces
+     * in the {@link org.opengis.metadata} package and sub-packages.
+     */
+    public static final MetadataStandard ISO_19115;
+
+    /**
+     * An instance working on ISO 19119 standard as defined by GeoAPI interfaces
+     * in the {@link org.opengis.service} package and sub-packages.
+     */
+    public static final MetadataStandard ISO_19119;
+
+    /**
+     * An instance working on ISO 19123 standard as defined by GeoAPI interfaces
+     * in the {@link org.opengis.coverage} package and sub-packages.
+     */
+    public static final MetadataStandard ISO_19123;
+    static {
+        final String[] prefix = {"Default", "Abstract"};
+        final String[] acronyms = {"CoordinateSystem", "CS", "CoordinateReferenceSystem",
"CRS"};
+        ISO_19111 = new StandardImplementation("ISO 19111", "org.opengis.referencing.", "org.apache.sis.referencing.",
prefix, acronyms);
+        ISO_19115 = new StandardImplementation("ISO 19115", "org.opengis.metadata.", SIS_PACKAGE,
prefix, null);
+        ISO_19119 = new StandardImplementation("ISO 19119", "org.opengis.service.",  null,
null, null);
+        ISO_19123 = new StandardImplementation("ISO 19123", "org.opengis.coverage.", null,
null, null);
+        INSTANCES = new MetadataStandard[] {
+            ISO_19111,
+            ISO_19115,
+            ISO_19119,
+            ISO_19123
+        };
+    }
+
+    /**
+     * Bibliographical reference to the international standard.
+     *
+     * @see #getCitation()
+     */
+    private final Citation citation;
+
+    /**
+     * The root packages for metadata interfaces. Must have a trailing {@code '.'}.
+     */
+    final String interfacePackage;
+
+    /**
+     * Accessors for the specified implementations.
+     * The only legal value types are:
+     *
+     * <ul>
+     *   <li>{@link Class} if we have determined the standard interface for a given
type
+     *       but did not yet created the {@link PropertyAccessor} for it.</li>
+     *   <li>{@link PropertyAccessor} otherwise.</li>
+     * </ul>
+     */
+    private final Map<Class<?>, Object> accessors;
+
+    /**
+     * Creates a new instance working on implementation of interfaces defined
+     * in the specified package. For the ISO 19115 standard reflected by GeoAPI
+     * interfaces, it should be the {@link org.opengis.metadata} package.
+     *
+     * @param citation         Bibliographical reference to the international standard.
+     * @param interfacePackage The root package for metadata interfaces.
+     */
+    public MetadataStandard(final Citation citation, final Package interfacePackage) {
+        ensureNonNull("citation", citation);
+        ensureNonNull("interfacePackage", interfacePackage);
+        this.citation         = citation;
+        this.interfacePackage = interfacePackage.getName() + '.';
+        this.accessors        = new IdentityHashMap<>();
+    }
+
+    /**
+     * Creates a new instance working on implementation of interfaces defined in the
+     * specified package. This constructor is used only for the pre-defined constants.
+     *
+     * @param citation         Bibliographical reference to the international standard.
+     * @param interfacePackage The root package for metadata interfaces.
+     */
+    MetadataStandard(final Citation citation, final String interfacePackage) {
+        this.citation         = citation;
+        this.interfacePackage = interfacePackage;
+        this.accessors        = new IdentityHashMap<>();
+    }
+
+    /**
+     * Returns the metadata standard for the given class. The argument given to this method
can be
+     * either an interface defined by the standard, or a class implementing such interface.
If the
+     * class implements more than one interface, then the first interface recognized by this
method,
+     * in declaration order, will be retained.
+     *
+     * <p>The current implementation recognizes only the standards defined by the public
static
+     * constants defined in this class. A future SIS version may recognize user-defined constants.</p>
+     *
+     * @param  type The metadata standard interface, or an implementation class.
+     * @return The metadata standard for the given type, or {@code null} if not found.
+     */
+    public static MetadataStandard forClass(final Class<?> type) {
+        String name = type.getName();
+        for (final MetadataStandard candidate : INSTANCES) {
+            if (name.startsWith(candidate.interfacePackage)) {
+                return candidate;
+            }
+        }
+        for (final Class<?> interf : Classes.getAllInterfaces(type)) {
+            name = interf.getName();
+            for (final MetadataStandard candidate : INSTANCES) {
+                if (name.startsWith(candidate.interfacePackage)) {
+                    return candidate;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a bibliographical reference to the international standard.
+     * The default implementation return the citation given at construction time.
+     *
+     * @return Bibliographical reference to the international standard.
+     */
+    public Citation getCitation() {
+        return citation;
+    }
+
+    /**
+     * Returns the accessor for the specified implementation class, or {@code null} if none.
+     * The given class shall not be the standard interface, unless the metadata is read-only.
+     * More specifically, the given {@code type} shall be one of the following:
+     *
+     * <ul>
+     *   <li>The value of {@code metadata.getClass()};</li>
+     *   <li>The value of {@link #getImplementation(Class)} after check for non-null
value.</li>
+     * </ul>
+     *
+     * @param  implementation The implementation class.
+     * @return The accessor for the given implementation, or {@code null} if the given class
does
+     *         not implement a metadata interface of the expected package and {@code mandatory}
+     *         is {@code false}.
+     * @throws ClassCastException if the specified class does not implement a metadata interface
+     *         of the expected package and {@code mandatory} is {@code true}.
+     */
+    final PropertyAccessor getAccessor(final Class<?> implementation, final boolean
mandatory) {
+        synchronized (accessors) {
+            // Check for previously created accessors.
+            final Object value = accessors.get(implementation);
+            if (value instanceof PropertyAccessor) {
+                return (PropertyAccessor) value;
+            }
+            // Check if we started some computation that we can finish.
+            final Class<?> type;
+            if (value != null) {
+                type = (Class<?>) value;
+            } else {
+                // Nothing were computed. Try to compute now.
+                type = findInterface(implementation);
+                if (type == null) {
+                    if (!mandatory) {
+                        return null;
+                    }
+                    throw new ClassCastException(Errors.format(Errors.Keys.UnknownType_1,
type));
+                }
+            }
+            final PropertyAccessor accessor = new PropertyAccessor(citation, type, implementation);
+            accessors.put(implementation, accessor);
+            return accessor;
+        }
+    }
+
+    /**
+     * Returns {@code true} if the given type is assignable to a type from this standard.
+     * If this method returns {@code true}, then invoking {@link #getInterface(Class)} is
+     * guaranteed to succeed without throwing an exception.
+     *
+     * @param  type The implementation class (can be {@code null}).
+     * @return {@code true} if the given class is an interface of this standard,
+     *         or implements an interface of this standard.
+     */
+    public boolean isMetadata(final Class<?> type) {
+        if (type != null) {
+            // Checks if the class is an interface from the standard.
+            if (type.isInterface() && type.getName().startsWith(interfacePackage))
{
+                return true;
+            }
+            // Checks if the class is an implementation of the standard.
+            synchronized (accessors) {
+                if (accessors.containsKey(type)) {
+                    return true;
+                }
+                final Class<?> standard = findInterface(type);
+                if (standard != null) {
+                    accessors.put(type, standard);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns the metadata interface implemented by the specified implementation.
+     * Only one metadata interface can be implemented. If the given type is already
+     * an interface from the standard, then it is returned directly.
+     *
+     * @param  type The standard interface or the implementation class.
+     * @return The single interface, or {@code null} if none where found.
+     */
+    private Class<?> findInterface(Class<?> type) {
+        if (type != null) {
+            if (type.isInterface()) {
+                if (type.getName().startsWith(interfacePackage)) {
+                    return type;
+                }
+            } else {
+                /*
+                 * Gets every interfaces from the supplied package in declaration order,
+                 * including the ones declared in the super-class.
+                 */
+                final Set<Class<?>> interfaces = new LinkedHashSet<>();
+                do {
+                    getInterfaces(type, interfaces);
+                    type = type.getSuperclass();
+                } while (type != null);
+                /*
+                 * If we found more than one interface, removes the
+                 * ones that are sub-interfaces of the other.
+                 */
+                for (final Iterator<Class<?>> it=interfaces.iterator(); it.hasNext();)
{
+                    final Class<?> candidate = it.next();
+                    for (final Class<?> child : interfaces) {
+                        if (candidate != child && candidate.isAssignableFrom(child))
{
+                            it.remove();
+                            break;
+                        }
+                    }
+                }
+                final Iterator<Class<?>> it = interfaces.iterator();
+                if (it.hasNext()) {
+                    final Class<?> candidate = it.next();
+                    if (!it.hasNext()) {
+                        return candidate;
+                    }
+                    // Found more than one interface; we don't know which one to pick.
+                    // Returns 'null' for now; the caller will thrown an exception.
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Puts every interfaces for the given type in the specified collection.
+     * This method invokes itself recursively for scanning parent interfaces.
+     *
+     * @see Classes#getAllInterfaces(Class)
+     */
+    private void getInterfaces(final Class<?> type, final Collection<Class<?>>
interfaces) {
+        for (final Class<?> candidate : type.getInterfaces()) {
+            if (candidate.getName().startsWith(interfacePackage)) {
+                interfaces.add(candidate);
+            }
+            getInterfaces(candidate, interfaces);
+        }
+    }
+
+    /**
+     * Returns the metadata interface implemented by the specified implementation class.
+     * If the given type is already an interface from this standard, then it is returned
+     * unchanged.
+     *
+     * {@note The word "interface" may be taken in a looser sense than the usual Java sense
+     *        because if the given type is defined in this standard package, then it is returned
+     *        unchanged. The standard package is usually made of interfaces and code lists
only,
+     *        but this is not verified by this method.}
+     *
+     * @param  type The implementation class.
+     * @return The interface implemented by the given implementation class.
+     * @throws ClassCastException if the specified implementation class does
+     *         not implement an interface of this standard.
+     *
+     * @see AbstractMetadata#getInterface
+     */
+    public Class<?> getInterface(final Class<?> type) throws ClassCastException
{
+        ensureNonNull("type", type);
+        if (type.getName().startsWith(interfacePackage)) {
+            return type;
+        }
+        throw new UnsupportedOperationException(); // TODO: port Geotk code here.
+    }
+
+    /**
+     * Returns the implementation class for the given interface, or {@code null} if none.
+     * The default implementation returns {@code null} if every cases. Subclasses shall
+     * override this method in order to map GeoAPI interfaces to their implementation.
+     *
+     * @param  type The interface, typically from the {@code org.opengis.metadata} package.
+     * @return The implementation class, or {@code null} if none.
+     */
+    protected Class<?> getImplementation(final Class<?> type) {
+        return null;
+    }
+
+    /**
+     * Returns {@code true} if this metadata is modifiable. This method is not public because
it
+     * uses heuristic rules. In case of doubt, this method conservatively returns {@code
true}.
+     *
+     * @throws ClassCastException if the specified implementation class do
+     *         not implements a metadata interface of the expected package.
+     *
+     * @see ModifiableMetadata#isModifiable()
+     */
+    final boolean isModifiable(final Class<?> implementation) throws ClassCastException
{
+        return getAccessor(implementation, true).isModifiable();
+    }
+
+    /**
+     * Replaces every properties in the specified metadata by their
+     * {@linkplain ModifiableMetadata#unmodifiable() unmodifiable variant}.
+     *
+     * @throws ClassCastException if the specified implementation class do
+     *         not implements a metadata interface of the expected package.
+     *
+     * @see ModifiableMetadata#freeze()
+     */
+    final void freeze(final Object metadata) throws ClassCastException {
+        getAccessor(metadata.getClass(), true).freeze(metadata);
+    }
+
+    /**
+     * Copies all metadata from source to target.
+     * The source must implements the same metadata interface than the target.
+     *
+     * @param  source The metadata to copy.
+     * @param  target The target metadata.
+     * @param  skipNulls If {@code true}, only non-null values will be copied.
+     * @throws ClassCastException if the source or target object don't
+     *         implements a metadata interface of the expected package.
+     * @throws UnmodifiableMetadataException if the target metadata is unmodifiable,
+     *         or if at least one setter method was required but not found.
+     *
+     * @see ModifiableMetadata#clone()
+     */
+    public void shallowCopy(final Object source, final Object target, final boolean skipNulls)
+            throws ClassCastException, UnmodifiableMetadataException
+    {
+        ensureNonNull("target", target);
+        final PropertyAccessor accessor = getAccessor(target.getClass(), true);
+        if (!accessor.type.isInstance(source)) {
+            ensureNonNull("source", source);
+            throw new ClassCastException(Errors.format(Errors.Keys.IllegalArgumentClass_3,
+                    "source", accessor.type, source.getClass()));
+        }
+        if (!accessor.shallowCopy(source, target, skipNulls)) {
+            throw new UnmodifiableMetadataException(Errors.format(Errors.Keys.UnmodifiableMetadata));
+        }
+    }
+
+    /**
+     * Compares the two specified metadata objects.
+     * The comparison is <cite>shallow</cite>, i.e. all metadata attributes are
compared using the
+     * {@link LenientComparable#equals(Object, ComparisonMode)} method if possible, or the
+     * {@link Object#equals(Object)} method otherwise, without explicit recursive call to
+     * this {@code shallowEquals(...)} method for child metadata.
+     *
+     * <p>This method can optionally excludes null values from the comparison. In metadata,
+     * null value often means "don't know", so in some occasion we want to consider two
+     * metadata as different only if a property value is know for sure to be different.</p>
+     *
+     * <p>The first arguments must be an implementation of a metadata interface, otherwise
an
+     * exception will be thrown. The two arguments do not need to be the same implementation
+     * however.</p>
+     *
+     * @param metadata1 The first metadata object to compare.
+     * @param metadata2 The second metadata object to compare.
+     * @param mode      The strictness level of the comparison.
+     * @param skipNulls If {@code true}, only non-null values will be compared.
+     * @return {@code true} if the given metadata objects are equals.
+     * @throws ClassCastException if at least one metadata object don't
+     *         implements a metadata interface of the expected package.
+     *
+     * @see AbstractMetadata#equals(Object, ComparisonMode)
+     */
+    public boolean shallowEquals(final Object metadata1, final Object metadata2,
+            final ComparisonMode mode, final boolean skipNulls) throws ClassCastException
+    {
+        if (metadata1 == metadata2) {
+            return true;
+        }
+        if (metadata1 == null || metadata2 == null) {
+            return false;
+        }
+        final PropertyAccessor accessor = getAccessor(metadata1.getClass(), true);
+        if (accessor.type != findInterface(metadata2.getClass())) {
+            return false;
+        }
+        return accessor.shallowEquals(metadata1, metadata2, mode, skipNulls);
+    }
+
+    /**
+     * Computes a hash code for the specified metadata. The hash code is defined as the
+     * sum of hash code values of all non-null properties. This is the same contract than
+     * {@link java.util.Set#hashCode} and ensure that the hash code value is insensitive
+     * to the ordering of properties.
+     *
+     * @param  metadata The metadata object to compute hash code.
+     * @return A hash code value for the specified metadata.
+     * @throws ClassCastException if the metadata object doesn't implement a metadata
+     *         interface of the expected package.
+     *
+     * @see AbstractMetadata#hashCode()
+     */
+    public int hashCode(final Object metadata) throws ClassCastException {
+        return getAccessor(metadata.getClass(), true).hashCode(metadata);
+    }
+
+    /**
+     * Returns a string representation of this metadata standard.
+     * This is for debugging purpose only and may change in any future version.
+     */
+    @Override
+    public String toString() {
+        return Classes.getShortClassName(this) + '[' + citation.getTitle() + ']';
+    }
+}

Propchange: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/MetadataStandard.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

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=1451725&r1=1451724&r2=1451725&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 Mar  1 21:41:44 2013
@@ -21,9 +21,9 @@ import java.util.Map;
 import java.util.Arrays;
 import java.util.Locale;
 import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.Collection;
-import java.util.LinkedHashSet;
 import java.lang.reflect.Array;
 import java.lang.reflect.Method;
 import java.lang.reflect.InvocationTargetException;
@@ -97,7 +97,7 @@ final class PropertyAccessor {
      * Getters shared between many instances of this class. Two different implementations
      * may share the same getters but different setters.
      */
-    private static final Map<Class<?>, Method[]> SHARED_GETTERS = new HashMap<>();
+    private static final Map<Class<?>, Method[]> SHARED_GETTERS = new IdentityHashMap<>();
 
     /**
      * Additional getter to declare in every list of getter methods that do not already provide
@@ -357,73 +357,6 @@ final class PropertyAccessor {
     }
 
     /**
-     * Returns the metadata interface implemented by the specified implementation type.
-     * Only one metadata interface can be implemented. If the given type is already an
-     * interface from the standard, it is returned directly.
-     *
-     * @param  type The type of the implementation (could also be the interface type).
-     * @param  interfacePackage The root package for metadata interfaces.
-     * @return The single interface, or {@code null} if none where found.
-     */
-    static Class<?> getStandardType(Class<?> type, final String interfacePackage)
{
-        if (type != null) {
-            if (type.isInterface()) {
-                if (type.getName().startsWith(interfacePackage)) {
-                    return type;
-                }
-            } else {
-                /*
-                 * Gets every interfaces from the supplied package in declaration order,
-                 * including the ones declared in the super-class.
-                 */
-                final Set<Class<?>> interfaces = new LinkedHashSet<>();
-                do {
-                    getInterfaces(type, interfacePackage, interfaces);
-                    type = type.getSuperclass();
-                } while (type != null);
-                /*
-                 * If we found more than one interface, removes the
-                 * ones that are sub-interfaces of the other.
-                 */
-                for (final Iterator<Class<?>> it=interfaces.iterator(); it.hasNext();)
{
-                    final Class<?> candidate = it.next();
-                    for (final Class<?> child : interfaces) {
-                        if (candidate != child && candidate.isAssignableFrom(child))
{
-                            it.remove();
-                            break;
-                        }
-                    }
-                }
-                final Iterator<Class<?>> it = interfaces.iterator();
-                if (it.hasNext()) {
-                    final Class<?> candidate = it.next();
-                    if (!it.hasNext()) {
-                        return candidate;
-                    }
-                    // Found more than one interface; we don't know which one to pick.
-                    // Returns 'null' for now; the caller will thrown an exception.
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Puts every interfaces for the given type in the specified collection.
-     * This method invokes itself recursively for scanning parent interfaces.
-     */
-    private static void getInterfaces(final Class<?> type, final String interfacePackage,
-            final Collection<Class<?>> interfaces)
-    {
-        for (final Class<?> candidate : type.getInterfaces()) {
-            if (candidate.getName().startsWith(interfacePackage)) {
-                interfaces.add(candidate);
-            }
-            getInterfaces(candidate, interfacePackage, interfaces);
-        }
-    }
-
-    /**
      * Returns the getters. The returned array should never be modified,
      * since it may be shared among many instances of {@code PropertyAccessor}.
      *

Added: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/StandardImplementation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/StandardImplementation.java?rev=1451725&view=auto
==============================================================================
--- sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/StandardImplementation.java
(added)
+++ sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/StandardImplementation.java
[UTF-8] Fri Mar  1 21:41:44 2013
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.metadata;
+
+import java.util.Map;
+import java.util.IdentityHashMap;
+import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.logging.Logging;
+import org.apache.sis.internal.simple.SimpleCitation;
+
+
+/**
+ * Information about an Apache SIS metadata standard implementation.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3 (derived from geotk-2.4)
+ * @version 0.3
+ * @module
+ */
+final class StandardImplementation extends MetadataStandard {
+    /**
+     * The root packages for metadata implementations, or {@code null} if none.
+     * If non-null, then this string must ends with a trailing {@code "."}.
+     */
+    private final String implementationPackage;
+
+    /**
+     * The prefixes that implementation classes may have.
+     * The most common prefixes should be first, since the prefixes will be tried in that
order.
+     */
+    private final String[] prefix;
+
+    /**
+     * The acronyms that implementation classes may have, or {@code null} if none. If non-null,
+     * then this array shall contain (<var>full text</var>, <var>acronym</var>)
pairs. The full
+     * text shall appear to the end of the class name, otherwise it is not replaced. This
is
+     * necessary in order to avoid the replacement of {@code "DefaultCoordinateSystemAxis"}
by
+     * {@code "DefaultCSAxis"}.
+     */
+    private final String[] acronyms;
+
+    /**
+     * Implementations for a given interface, computed when first needed then cached.
+     */
+    private final Map<Class<?>,Class<?>> implementations;
+
+    /**
+     * Creates a new instance working on implementation of interfaces defined in the
+     * specified package. This constructor is used only for the pre-defined constants.
+     *
+     * @param citation              The title of the standard.
+     * @param interfacePackage      The root package for metadata interfaces, with a trailing
{@code '.'}.
+     * @param implementationPackage The root package for metadata implementations. with a
trailing {@code '.'}.
+     * @param prefix                The prefix of implementation class. This array is not
cloned.
+     * @param acronyms              An array of (full text, acronyms) pairs. This array is
not cloned.
+     */
+    StandardImplementation(final String citation, final String interfacePackage,
+            final String implementationPackage, final String[] prefix, final String[] acronyms)
+    {
+        super(new SimpleCitation(citation), interfacePackage);
+        this.implementationPackage = implementationPackage;
+        this.prefix                = prefix;
+        this.acronyms              = acronyms;
+        this.implementations       = new IdentityHashMap<>();
+    }
+
+    /**
+     * Returns the implementation class for the given interface, or {@code null} if none.
+     * This class uses heuristic rules based on naming conventions.
+     *
+     * @param  type The interface, typically from the {@code org.opengis.metadata} package.
+     * @return The implementation class, or {@code null} if none.
+     */
+    @Override
+    protected Class<?> getImplementation(final Class<?> type) {
+        /*
+         * We require the type to be an interface in order to exclude
+         * CodeLists, Enums and Exceptions.
+         */
+        if (type != null && type.isInterface()) {
+            String name = type.getName();
+            if (name.startsWith(interfacePackage)) {
+                synchronized (implementations) {
+                    Class<?> candidate = implementations.get(type);
+                    if (candidate != null) {
+                        return (candidate != Void.TYPE) ? candidate : null;
+                    }
+                    /*
+                     * Prepares a buffer with a copy of the class name in which the interface
+                     * package has been replaced by the implementation package, and some
text
+                     * have been replaced by their acronym (if any).
+                     */
+                    final StringBuilder buffer = new StringBuilder(implementationPackage)
+                            .append(name, interfacePackage.length(), name.length());
+                    if (acronyms != null) {
+                        for (int i=0; i<acronyms.length; i+=2) {
+                            final String acronym = acronyms[i];
+                            if (CharSequences.endsWith(buffer, acronym, false)) {
+                                buffer.setLength(buffer.length() - acronym.length());
+                                buffer.append(acronyms[i+1]);
+                                break;
+                            }
+                        }
+                    }
+                    /*
+                     * Try to insert a prefix in front of the class name, until a match is
found.
+                     */
+                    final int prefixPosition = buffer.lastIndexOf(".") + 1;
+                    int length = 0;
+                    for (final String p : prefix) {
+                        name = buffer.replace(prefixPosition, prefixPosition + length, p).toString();
+                        try {
+                            candidate = Class.forName(name);
+                        } catch (ClassNotFoundException e) {
+                            Logging.recoverableException(MetadataStandard.class, "getImplementation",
e);
+                            length = p.length();
+                            continue;
+                        }
+                        if (candidate.isAnnotationPresent(Deprecated.class)) {
+                            // Skip deprecated implementations.
+                            length = p.length();
+                            continue;
+                        }
+                        implementations.put(type, candidate);
+                        return candidate;
+                    }
+                    implementations.put(type, Void.TYPE); // Marker for "class not found".
+                }
+            }
+        }
+        return null;
+    }
+}

Propchange: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/StandardImplementation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/sis-metadata/src/main/java/org/apache/sis/metadata/StandardImplementation.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1451725&r1=1451724&r2=1451725&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
[UTF-8] Fri Mar  1 21:41:44 2013
@@ -380,6 +380,11 @@ public final class Errors extends Indexe
         public static final int UnexpectedEndOfString_1 = 30;
 
         /**
+         * Type ‘{0}’ is unknown in this context.
+         */
+        public static final int UnknownType_1 = 76;
+
+        /**
          * This affine transform is unmodifiable.
          */
         public static final int UnmodifiableAffineTransform = 23;

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1451725&r1=1451724&r2=1451725&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
[ISO-8859-1] Fri Mar  1 21:41:44 2013
@@ -88,6 +88,7 @@ StalledThread_1                 = Thread
 UndefinedOrderingForElements_2  = Ordering between \u201c{0}\u201d and \u201c{1}\u201d elements
is undefined.
 UnexpectedChange_1              = Unexpected change in \u2018{0}\u2019.
 UnexpectedEndOfString_1         = More characters were expected at the end of \u201c{0}\u201d.
+UnknownType_1                   = Type \u2018{0}\u2019 is unknown in this context.
 UnmodifiableAffineTransform     = This affine transform is unmodifiable.
 UnmodifiableGeometry            = This geometry is unmodifiable.
 UnmodifiableMetadata            = This metadata is unmodifiable.

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1451725&r1=1451724&r2=1451725&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
[ISO-8859-1] Fri Mar  1 21:41:44 2013
@@ -77,6 +77,7 @@ StalledThread_1                 = La t\u
 UndefinedOrderingForElements_2  = L\u2019ordre entre les \u00e9l\u00e9ments \u201c{0}\u201d
et \u201c{1}\u201d n\u2019est pas d\u00e9fini.
 UnexpectedChange_1              = Changement inattendu dans \u2018{0}\u2019.
 UnexpectedEndOfString_1         = D\u2019autres caract\u00e8res \u00e9taient attendus \u00e0
la fin du texte \u201c{0}\u201d.
+UnknownType_1                   = Le type \u2018{0}\u2019 n\u2019est pas reconnu dans ce
contexte.
 UnmodifiableAffineTransform     = Cette transformation affine n\u2019est pas modifiable.
 UnmodifiableGeometry            = Cette g\u00e9om\u00e9trie n\u2019est pas modifiable.
 UnmodifiableMetadata            = Cette m\u00e9ta-donn\u00e9e n\u2019est pas modifiable.



Mime
View raw message