sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1454130 - in /sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis: internal/converter/ util/ util/resources/
Date Thu, 07 Mar 2013 22:20:48 GMT
Author: desruisseaux
Date: Thu Mar  7 22:20:48 2013
New Revision: 1454130

URL: http://svn.apache.org/r1454130
Log:
Beginning the port of the ObjectConverter implementations as an internal package.
We need those ObjectConverters for the metadata PropertyAccessor working.
Right now, some metadata tests are disabled waiting for those converters.

Added:
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/ClassPair.java
  (with props)
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/FallbackConverter.java
  (with props)
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/package-info.java
  (with props)
Modified:
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ObjectConverter.java
    sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ObjectConverters.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

Added: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/ClassPair.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/ClassPair.java?rev=1454130&view=auto
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/ClassPair.java
(added)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/ClassPair.java
[UTF-8] Thu Mar  7 22:20:48 2013
@@ -0,0 +1,157 @@
+/*
+ * 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.internal.converter;
+
+import net.jcip.annotations.Immutable;
+import org.apache.sis.util.ObjectConverter;
+
+
+/**
+ * Holds explicit {@link #sourceClass} and {@link #targetClass} values. Used as key in a
hash
+ * map of converters. Also used as the base class for subclasses working on explicit source
and
+ * target class. We allows this opportunist leveraging of implementation because those classes
+ * are not public (otherwise a separated hierarchy may have been preferable).
+ *
+ * @param <S> The base type of source objects.
+ * @param <T> The base type of converted objects.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3 (derived from geotk-3.00)
+ * @version 0.3
+ * @module
+ */
+@Immutable
+class ClassPair<S,T> {
+    /**
+     * The source class.
+     */
+    protected final Class<S> sourceClass;
+
+    /**
+     * The target class.
+     */
+    protected final Class<T> targetClass;
+
+    /**
+     * Creates an entry for the given converter.
+     *
+     * @param converter The converter.
+     */
+    ClassPair(final ObjectConverter<S,T> converter) {
+        this(converter.getSourceClass(), converter.getTargetClass());
+    }
+
+    /**
+     * Creates an entry for the given source and target classes.
+     *
+     * @param sourceClass The {@linkplain ObjectConverter#getSourceClass() source class}.
+     * @param targetClass The {@linkplain ObjectConverter#getTargetClass() target class}.
+     */
+    ClassPair(final Class<S> sourceClass, final Class<T> targetClass) {
+        this.sourceClass = sourceClass;
+        this.targetClass = targetClass;
+    }
+
+    /**
+     * Returns a key for the parent source, or {@code null} if none.
+     * This method applies the following rules:
+     *
+     * <ul>
+     *   <li>If {@link #sourceClass} is a class and have a parent class, then returns
a new
+     *       {@code ClassPair} having that parent class as the source.</li>
+     *   <li>Otherwise if {@link #sourceClass} is an interface extending at least one
interface,
+     *       then returns a new {@code ClassPair} having the first parent interface as the
source.
+     *       we select the first interface on the assumption that it is the mean one.</li>
+     *   <li>Otherwise (i.e. if there is no parent class or interface), returns {@code
null}.</li>
+     * </ul>
+     *
+     * The target class is left unchanged.
+     *
+     * @return A key for the parent source, or {@code null}.
+     */
+    public final ClassPair<? super S, T> parentSource() {
+        final Class<? super S> source;
+        if (sourceClass.isInterface()) {
+            @SuppressWarnings({"unchecked","rawtypes"})
+            final Class<? super S>[] interfaces = (Class[]) sourceClass.getInterfaces();
+            if (interfaces.length == 0) {
+                return null;
+            }
+            source = interfaces[0]; // Take only the first interface declaration; ignore
others.
+        } else {
+            source = sourceClass.getSuperclass();
+            if (source == null) {
+                return null;
+            }
+        }
+        return new ClassPair<>(source, targetClass);
+    }
+
+    /**
+     * Casts the given converter to the source and target classes of this {@code ClassPair}.
+     * This method is not public because the checks are performed using assertions only.
+     * If this method was to goes public, the assertions would need to be replaced by
+     * unconditional checks.
+     *
+     * <p>This method is used by {@link ConverterRegistry} after fetching a value from
a hash
+     * map using this {@code ClassPair} as a key. In this context, the cast should never
fail
+     * (assuming that the converters do not change their source and target classes).</p>
+     */
+    @SuppressWarnings("unchecked")
+    final ObjectConverter<? super S, ? extends T> cast(final ObjectConverter<?,?>
converter) {
+        if (converter != null) {
+            assert converter.getSourceClass().isAssignableFrom(sourceClass) : sourceClass;
+            assert targetClass.isAssignableFrom(converter.getTargetClass()) : targetClass;
+        }
+        return (ObjectConverter<S,T>) converter;
+    }
+
+    /**
+     * Compares the given object with this entry for equality. Two entries are considered
+     * equals if they have the same source and target classes. This is required for use
+     * as {@link java.util.HashMap} keys in {@link ConverterRegistry}.
+     *
+     * @param  other The object to compare with this entry.
+     * @return {@code true} if the given object is a entry having the same source and target
classes.
+     */
+    @Override
+    public final boolean equals(final Object other) {
+        if (other instanceof ClassPair<?,?>) {
+            final ClassPair<?,?> that = (ClassPair<?,?>) other;
+            return sourceClass == that.sourceClass &&
+                   targetClass == that.targetClass;
+        }
+        return false;
+    }
+
+    /**
+     * Returns a hash code value for this entry.
+     */
+    @Override
+    public final int hashCode() {
+        return sourceClass.hashCode() + 31*targetClass.hashCode();
+    }
+
+    /**
+     * Returns a string representation for this entry.
+     * Used for formatting error messages.
+     */
+    @Override
+    public String toString() {
+        return sourceClass.getSimpleName() + " ⇨ " + targetClass.getSimpleName();
+    }
+}

Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/ClassPair.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/ClassPair.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Added: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/FallbackConverter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/FallbackConverter.java?rev=1454130&view=auto
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/FallbackConverter.java
(added)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/FallbackConverter.java
[UTF-8] Thu Mar  7 22:20:48 2013
@@ -0,0 +1,396 @@
+/*
+ * 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.internal.converter;
+
+import java.util.Set;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.io.Serializable;
+import org.apache.sis.util.Classes;
+import org.apache.sis.util.ObjectConverter;
+import org.apache.sis.math.FunctionProperty;
+import org.apache.sis.util.UnconvertibleObjectException;
+import org.apache.sis.util.resources.Errors;
+
+
+/**
+ * Fallback to be used when the first converter failed.
+ * In case of failure, the error of the first (primary) converter is reported.
+ *
+ * <p>The primary converter is expected more generic than the fallback converter. We
try the generic
+ * converter first because we expect that if the user wanted the specific subclass, he would
have
+ * asked explicitly for it. Trying the generic converter first is both closer to what the
user
+ * asked and less likely to throw many exceptions before we found a successful conversion.</p>
+ *
+ * <p>Instances are created by the {@link #merge(ObjectConverter, ObjectConverter)}
method.
+ * It is invoked when a new converter is {@linkplain ConverterRegistry#register(ObjectConverter)
+ * registered} for the same source and target class than an existing converter.</p>
+ *
+ * @param <S> The base type of source objects.
+ * @param <T> The base type of converted objects.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3 (derived from geotk-3.00)
+ * @version 0.3
+ * @module
+ */
+final class FallbackConverter<S,T> extends ClassPair<S,T> implements ObjectConverter<S,T>,
Serializable {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -6588190939281568858L;
+
+    /**
+     * The primary converter, to be tried first.
+     */
+    private ObjectConverter<S, ? extends T> primary;
+
+    /**
+     * The fallback converter. Its target type should not be assignable from the primary
target
+     * type, except if both converters have the same target type. We intend {@linkplain #primary}
+     * to be the most generic converter, because we assume that if the user wanted a more
specific
+     * type he would have asked explicitly for it. In addition this layout reduces the amount
of
+     * exceptions to be thrown and caught before we found a successful conversion.
+     */
+    private ObjectConverter<S, ? extends T> fallback;
+
+    /**
+     * Creates a converter using the given primary and fallback converters. This method may
+     * interchange the two converters in order to meet the {@linkplain #fallback} contract.
+     *
+     * @param sourceClass The {@linkplain #getSourceClass() source class}.
+     * @param targetClass The {@linkplain #getTargetClass() target class}.
+     * @param primary     A first converter.
+     * @param fallback    A second converter.
+     *
+     * @see #create(ObjectConverter, ObjectConverter)
+     */
+    private FallbackConverter(final Class<S> sourceClass, final Class<T> targetClass,
+                              final ObjectConverter<S, ? extends T> primary,
+                              final ObjectConverter<S, ? extends T> fallback)
+    {
+        super(sourceClass, targetClass);
+        if (swap(primary, fallback)) {
+            this.primary  = fallback;
+            this.fallback = primary;
+        } else {
+            this.primary  = primary;
+            this.fallback = fallback;
+        }
+        assert sourceClass.equals          (primary .getSourceClass()) : primary;
+        assert sourceClass.equals          (fallback.getSourceClass()) : fallback;
+        assert targetClass.isAssignableFrom(primary .getTargetClass()) : primary;
+        assert targetClass.isAssignableFrom(fallback.getTargetClass()) : fallback;
+    }
+
+    /**
+     * Returns {@code true} if the given primary and fallback converters should be interchanged.
+     * This method may invoke itself recursively.
+     *
+     * @param  primary  The primary converter to test.
+     * @param  fallback The fallback converter to test.
+     * @return {@code true} if the given primary and fallback converters should be interchanged.
+     */
+    private static <S> boolean swap(final ObjectConverter<S,?> primary, final
ObjectConverter<S,?> fallback) {
+        assert !primary.equals(fallback) : primary;
+        if (primary instanceof FallbackConverter<?,?>) {
+            final FallbackConverter<S,?> candidate = (FallbackConverter<S,?>)
primary;
+            return swap(candidate.primary, fallback) && swap(candidate.fallback,
fallback);
+        } else {
+            final Class<?> t1 = primary .getTargetClass();
+            final Class<?> t2 = fallback.getTargetClass();
+            return !t1.isAssignableFrom(t2) && t2.isAssignableFrom(t1);
+        }
+    }
+
+    /**
+     * Appends the given {@code converter} in the given tree of fallback converters.
+     * This method may create a new {@code FallbackConverter} if the given converter
+     * can not be inserted in the given tree.
+     *
+     * <p>This method has no information about {@code <T>} type because of parameterized
types
+     * erasure, and should not need that information if we didn't made a mistake in this
class.
+     * Nevertheless for safety, callers are encouraged to verify themselves as below:</p>
+     *
+     * {@preformat java
+     *     Class<T> targetClass = ...;
+     *     FallbackConverter<S, ? extends T> converter = merge(...);
+     *     assert targetClass.isAssignableFrom(converter.getTargetClass()) : converter;
+     * }
+     *
+     * @param  <S> The base type of source objects.
+     * @param  <T> The base type of converted objects.
+     * @param  existing The existing tree of converters, or {@code null} if none.
+     * @param  converter A new fallback to insert in the converters tree, or {@code null}.
+     * @return A tree of converters which contains the given {@code converter}. May be either
+     *         {@code existing}, {@code converter} or a new {@code FallbackConverter} instance.
+     */
+    public static <S,T> ObjectConverter<S, ? extends T> merge(
+                  final ObjectConverter<S, ? extends T> existing,
+                  final ObjectConverter<S, ? extends T> converter)
+    {
+        if (converter == null) return existing;
+        if (existing  == null) return converter;
+        if (existing instanceof FallbackConverter<?,?>) {
+            /*
+             * If we can merge into the existing tree of converters, return that tree
+             * after the merge. Otherwise we will create a new FallbackConverter instance.
+             */
+            if (((FallbackConverter<S, ? extends T>) existing).tryMerge(converter))
{
+                return existing;
+            }
+        }
+        return create(existing, converter);
+    }
+
+    /**
+     * Creates a converter using the given primary and fallback converters. This method may
+     * interchange the two converters in order to meet the {@linkplain #fallback} contract.
+     *
+     * <p>This method has no information about {@code <T>} type because of parameterized
types
+     * erasure, and should not need that information if we didn't made a mistake in this
class.
+     * Nevertheless for safety, direct or indirect callers are encouraged to verify themselves
+     * as below:</p>
+     *
+     * {@preformat java
+     *     Class<T> targetClass = ...;
+     *     FallbackConverter<S, ? extends T> converter = create(...);
+     *     assert targetClass.isAssignableFrom(converter.getTargetClass()) : converter;
+     * }
+     *
+     * @param primary  The primary converter.
+     * @param fallback The fallback converter.
+     */
+    private static <S,T> FallbackConverter<S, ? extends T> create(
+            final ObjectConverter<S, ? extends T> primary,
+            final ObjectConverter<S, ? extends T> fallback)
+    {
+        final Class<S>           source  = primary .getSourceClass();
+        final Class<? extends T> target1 = primary .getTargetClass();
+        final Class<? extends T> target2 = fallback.getTargetClass();
+        Class<?> target = Classes.findCommonClass(target1, target2);
+        if (target.equals(Object.class)) {
+            /*
+             * If there is no common parent class other than Object, looks for a common interface.
+             * We perform this special processing for Object.class because this class is
handled
+             * in a special way by the Java language anyway: all interfaces are specialization
of
+             * Object (in the sense "are assignable to"), so Object can be considered as
a common
+             * root for both classes and interfaces.
+             */
+            final Set<Class<?>> interfaces = Classes.findCommonInterfaces(target1,
target2);
+            interfaces.removeAll(Classes.getAllInterfaces(source));
+            final Iterator<Class<?>> it = interfaces.iterator();
+            if (it.hasNext()) {
+                /*
+                 * Arbitrarily retains the first interface. At this point there is hopefully
+                 * only one occurrence anyway. If there is more than one interface, they
appear
+                 * in declaration order so the first one is assumed the "main" interface.
+                 */
+                target = it.next();
+            }
+        }
+        /*
+         * We perform an unchecked cast because in theory <T> is the common super class.
+         * However we can not check at run time because generic types are implemented by
+         * erasure. If there is no logical error in our algorithm, the cast should be ok.
+         * Nevertheless callers are encouraged to verify as documented in the Javadoc.
+         */
+        @SuppressWarnings({"unchecked","rawtypes"})
+        final FallbackConverter<S, ? extends T> converter =
+                new FallbackConverter(source, target, primary, fallback);
+        return converter;
+    }
+
+    /**
+     * Tries to insert the given converter in this tree of converters. This is possible
+     * only if the target class of the given converter is equals or more specialized
+     * than the target class of this converter.
+     *
+     * @param  converter The converter to try to insert in this tree of converters.
+     * @return {@code true} if the insertion has been done, or {@code false} otherwise.
+     */
+    private boolean tryMerge(final ObjectConverter<S,?> converter) { // Do NOT synchronize
here.
+        if (!targetClass.isAssignableFrom(converter.getTargetClass())) {
+            return false; // Can not merge because of incompatible type.
+        }
+        @SuppressWarnings("unchecked")
+        final FallbackConverter<S, ? extends T> child =
+                merge((ObjectConverter<S, ? extends T>) converter);
+        if (child != null) {
+            // Didn't merged in this tree, but found a child
+            // which looks like a better insertion point.
+            return child.tryMerge(converter);
+        }
+        return true;
+    }
+
+    /**
+     * Inserts the given converter in this tree of fallback converters. If this method detects
+     * that the insertion should be done in a child of this tree, then this method returns
that
+     * child. It is caller responsibility to invoke this method again on the child. We proceed
+     * that way in order to release the synchronization lock before to acquire the child
lock,
+     * in order to reduce the risk of dead-lock.
+     *
+     * @param  converter The converter to insert in this tree of converters.
+     * @return {@code null} if the insertion has been done, or a non-null value
+     *         if the insertion should be done in the returned converter instead.
+     */
+    private synchronized FallbackConverter<S, ? extends T> merge(final ObjectConverter<S,
? extends T> converter) {
+        final Class<? extends T> childClass = converter.getTargetClass();
+        /*
+         * First searches on the fallback side of the tree since they are expected
+         * to contain the most specialized classes. Go down the tree until we find
+         * the last node capable to accept the converter. Only after that point we
+         * may switch the search to the primary side of the tree.
+         */
+        Class<? extends T> candidateClass = fallback.getTargetClass();
+        if (candidateClass.isAssignableFrom(childClass)) {
+            /*
+             * The new converter could be inserted at this point. Checks if we can
+             * continue to walk down the tree, looking for a more specialized node.
+             */
+            if (fallback instanceof FallbackConverter<?,?>) {
+                /*
+                 * If (candidateClass != childClass), we could have a situation like below:
+                 *
+                 * Adding:  String ⇨ Number
+                 * to:      String ⇨ Number            : FallbackConverter
+                 *          ├───String ⇨ Short
+                 *          └───String ⇨ Number        : FallbackConverter
+                 *              ├───String ⇨ Integer
+                 *              └───String ⇨ Long
+                 *
+                 * We don't want to insert the generic Number converter between specialized
+                 * ones (Integer and Long). So rather than going down the tree in this case,
+                 * we will stop the search as if the above "isAssignableFrom" check failed.
+                 * Otherwise return the insertion point, which is 'fallback', for recursive
+                 * invocation by the caller.
+                 */
+                if (candidateClass != childClass) {
+                    return (FallbackConverter<S, ? extends T>) fallback;
+                }
+            } else {
+                /*
+                 * Splits at this point the node in two branches. The previous converter
+                 * will be the primary branch and the new converter will be the fallback
+                 * branch. The "primary vs fallback" contract is respected since we know
+                 * at this point that the new converter is more specialized,  because of
+                 * the isAssignableFrom(...) check performed above.
+                 */
+                fallback = create(fallback, converter);
+                return null;
+            }
+        }
+        /*
+         * We were looking in the fallback branch. Now look in the primary branch
+         * of the same node. The same comments than above apply.
+         */
+        candidateClass = primary.getTargetClass();
+        if (candidateClass.isAssignableFrom(childClass)) {
+            if (primary instanceof FallbackConverter<?,?>) {
+                if (candidateClass != childClass) {
+                    return (FallbackConverter<S, ? extends T>) primary;
+                }
+            } else {
+                primary = create(primary, converter);
+                return null;
+            }
+        }
+        /*
+         * The branch can not hold the converter. If we can't go down anymore in any
+         * of the two branches, insert the converter at the point we have reached so
+         * far. If the converter is more generic, inserts it as the primary branch in
+         * order to respect the "more generic first" contract.
+         */
+        if (childClass.isAssignableFrom(primary .getTargetClass()) &&
+           !childClass.isAssignableFrom(fallback.getTargetClass()))
+        {
+            primary = create(primary, converter);
+        } else {
+            fallback = create(fallback, converter);
+        }
+        return null;
+    }
+
+    /**
+     * Returns the base type of source objects.
+     */
+    @Override
+    public final Class<S> getSourceClass() {
+        return sourceClass;
+    }
+
+    /**
+     * Returns the base type of target objects.
+     */
+    @Override
+    public final Class<T> getTargetClass() {
+        return targetClass;
+    }
+
+    /**
+     * Returns the manner in which source values (<var>S</var>) are mapped to
target values.
+     * This is the intersection of the properties of the primary and fallback converters.
+     */
+    @Override
+    public final Set<FunctionProperty> properties() {
+        final ObjectConverter<S, ? extends T> primary, fallback;
+        synchronized (this) {
+            primary  = this.primary;
+            fallback = this.fallback;
+        }
+        Set<FunctionProperty> properties = primary.properties();
+        if (!(primary instanceof FallbackConverter<?,?>)) {
+            properties = EnumSet.copyOf(properties);
+            properties.remove(FunctionProperty.INVERTIBLE);
+        }
+        properties.retainAll(fallback.properties());
+        return properties;
+    }
+
+    /**
+     * Converts the given object, using the fallback if needed.
+     */
+    @Override
+    public T convert(final S source) throws UnconvertibleObjectException {
+        final ObjectConverter<S, ? extends T> primary, fallback;
+        synchronized (this) {
+            primary  = this.primary;
+            fallback = this.fallback;
+        }
+        try {
+            return primary.convert(source);
+        } catch (UnconvertibleObjectException exception) {
+            try {
+                return fallback.convert(source);
+            } catch (UnconvertibleObjectException failure) {
+                exception.addSuppressed(failure);
+                throw exception;
+            }
+        }
+    }
+
+    /**
+     * {@code FallbackConverter} are not convertible. This is because the parameterized
+     * types are defined as {@code <S, ? extends T>}. The inverse of those types would
+     * be {@code <? extends S, T>}, which is not compatible with the design of this
class.
+     */
+    @Override
+    public ObjectConverter<T, S> inverse() throws UnsupportedOperationException {
+        throw new UnsupportedOperationException(Errors.format(Errors.Keys.NonInvertibleConversion));
+    }
+}

Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/FallbackConverter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/FallbackConverter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Added: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/package-info.java?rev=1454130&view=auto
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/package-info.java
(added)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/package-info.java
[UTF-8] Thu Mar  7 22:20:48 2013
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+/**
+ * {@link org.apache.sis.util.ObjectConverter} implementations.
+ * A system-wide set of conversions is pre-defined and available by the
+ * {@link org.apache.sis.internal.converter.ConverterRegistry#system()} method.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3 (derived from geotk-2.5)
+ * @version 0.3
+ * @module
+ */
+package org.apache.sis.internal.converter;

Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/internal/converter/package-info.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ObjectConverter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ObjectConverter.java?rev=1454130&r1=1454129&r2=1454130&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ObjectConverter.java [UTF-8]
(original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ObjectConverter.java [UTF-8]
Thu Mar  7 22:20:48 2013
@@ -25,23 +25,38 @@ import org.apache.sis.math.FunctionPrope
  * The source and target types may be the same, in which case the {@code ObjectConverter}
actually converts
  * the values rather than the type.
  *
- * <p>The main method of this interface is {@link #convert(Object)}, which receive
an object of type
- * <var>S</var> and returns an object of type <var>T</var>. Some
characteristics about the <var>S</var>
- * to <var>T</var> mapping are given by the {@link #properties()} enumeration,
together with the
- * {@link #getSourceClass()} and {@link #getTargetClass()} methods.</p>
- *
- * <p>The <cite>domain</cite> of this function is the set of all values
of type <var>S</var> for
- * which the {@link #convert(Object)} method does not throw {@link UnconvertibleObjectException}.
- * Note that values for which {@code convert(S)} returns {@code null} are considered as part
of
- * the domain, even if the {@code null} target value stands for unconvertible source values.</p>
+ * <p>The main method of this interface is {@link #convert(Object)}, which receives
an object of type
+ * <var>S</var> and returns an object of type <var>T</var>. The set
of all <var>S</var> values for which
+ * {@code convert(S)} does not throw {@link UnconvertibleObjectException} is called the <cite>domain</cite>
+ * of this function, regardless of whether the <var>T</var> result is {@code
null} or not.</p>
+ *
+ * {@section Function properties}
+ * Some characteristics about the <var>S</var> to <var>T</var> mapping
are given by the
+ * {@link #properties()} enumeration, together with the {@link #getSourceClass()} and
+ * {@link #getTargetClass()} methods. Some possible function properties are:
  *
- * <p>The above definition affects the function {@linkplain #properties() properties}
- * that this converter can declare:</p>
+ * <ul>
+ *   <li>{@linkplain FunctionProperty#INJECTIVE Injective} if no pair of <var>S</var>
can produce
+ *       the same <var>T</var> value (e.g.: conversions from {@link Integer}
to {@code String}).</li>
+ *   <li>{@linkplain FunctionProperty#SURJECTIVE Surjective} if every values of <var>T</var>
can be
+ *       created from one or many values of <var>S</var> (e.g.: conversions from
{@link String} to
+ *       {@link Integer}).</li>
+ *   <li>{@linkplain FunctionProperty#isBijective Bijective} if there is a one-to-one
+ *       relationship between the <var>S</var> and <var>T</var> values.</li>
+ *   <li>{@linkplain FunctionProperty#ORDER_PRESERVING Order preserving} if any sequence
of
+ *       increasing <var>S</var> values (in the sense of {@link Comparable})
is mapped to a
+ *       sequence of increasing <var>T</var> values.</li>
+ *   <li>{@linkplain FunctionProperty#ORDER_REVERSING Order reversing} if any sequence
of
+ *       increasing <var>S</var> values (in the sense of {@link Comparable})
is mapped to
+ *       a sequence of decreasing <var>T</var> values.</li>
+ * </ul>
+ *
+ * Below are some guidelines about the function properties that a converter can declare:
  *
  * <ul>
  *   <li>If {@code convert(S)} returns {@code null} for unconvertible objects, then
this {@code ObjectConverter}
- *       can not declare {@link FunctionProperty#INJECTIVE} in its set of {@linkplain #properties()
properties},
- *       because more than one source value can produce the same target value (namely {@code
null}).</li>
+ *       can not be declared injective because more than one <var>S</var> value
can produce the same
+ *       <var>T</var> value (namely {@code null}).</li>
  *   <li>If {@code convert(S)} throws an exception for unconvertible objects, then
this {@code ObjectConverter}
  *       can be declared as an injective function if the other values meet the criteria.
  * </ul>

Modified: sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ObjectConverters.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ObjectConverters.java?rev=1454130&r1=1454129&r2=1454130&view=diff
==============================================================================
--- sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ObjectConverters.java
[UTF-8] (original)
+++ sis/branches/JDK7/sis-utility/src/main/java/org/apache/sis/util/ObjectConverters.java
[UTF-8] Thu Mar  7 22:20:48 2013
@@ -24,6 +24,37 @@ import org.apache.sis.util.resources.Err
 
 /**
  * Creates {@link ObjectConverter} instances, or uses them for creating collection views.
+ * Converters are created by the following methods:
+ *
+ * <ul>
+ *   <li>{@link #identity(Class)}</li>
+ *   <li>{@link #find(Class, Class)}</li>
+ * </ul>
+ *
+ * Converters can be used for creating derived collections by the following methods:
+ *
+ * <ul>
+ *   <li>{@link #derivedSet(Set, ObjectConverter)}</li>
+ *   <li>{@link #derivedMap(Map, ObjectConverter, ObjectConverter)}</li>
+ *   <li>{@link #derivedKeys(Map, ObjectConverter, Class)}</li>
+ *   <li>{@link #derivedValues(Map, Class, ObjectConverter)}</li>
+ * </ul>
+ *
+ * {@section Example}
+ * The following code convert instances in a collection from type {@code S} to type {@code
T},
+ * where the types are unknown at compile-time. Note that the converter is obtained only
once
+ * before to be applied to every elements in the loop.
+ *
+ * {@preformat java
+ *     Class<S> sourceType = ...
+ *     Class<T> targetType = ...
+ *     Collection<S> sources = ...;
+ *     Collection<T> targets = ...;
+ *     ObjectConverter<S,T> converter = ObjectConverters.find(sourceType, targetType);
+ *     for (S source : sources) {
+ *         targets.add(converter.convert(source));
+ *     }
+ * }
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.3 (derived from geotk-3.00)
@@ -59,7 +90,7 @@ public final class ObjectConverters exte
      * @return The converter from the specified source class to the target class.
      * @throws UnconvertibleObjectException if no converter is found.
      */
-    public static <S,T> ObjectConverter<S,T> find(final Class<S> source,
final Class<T> target)
+    public static <S,T> ObjectConverter<? super S, ? extends T> find(final Class<S>
source, final Class<T> target)
             throws UnconvertibleObjectException
     {
         // TODO: port the implementation from Geotk

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=1454130&r1=1454129&r2=1454130&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] Thu Mar  7 22:20:48 2013
@@ -320,6 +320,16 @@ public final class Errors extends Indexe
         public static final int NonEquilibratedParenthesis_2 = 59;
 
         /**
+         * Conversion is not invertible.
+         */
+        public static final int NonInvertibleConversion = 82;
+
+        /**
+         * Transform is not invertible.
+         */
+        public static final int NonInvertibleTransform = 83;
+
+        /**
          * “{0}” is not a linear unit.
          */
         public static final int NonLinearUnit_1 = 47;

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=1454130&r1=1454129&r2=1454130&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] Thu Mar  7 22:20:48 2013
@@ -72,6 +72,8 @@ NodeHasAnotherParent_1          = Node \
 NodeHasNoParent_1               = Node \u201c{0}\u201d has no parent.
 NodeNotFound_1                  = No \u201c{0}\u201d node found.
 NonEquilibratedParenthesis_2    = Missing a \u2018{1}\u2019 parenthesis in \u201c{0}\u201d.
+NonInvertibleConversion         = Conversion is not invertible.
+NonInvertibleTransform          = Transform is not invertible.
 NonAngularUnit_1                = \u201c{0}\u201d is not an angular unit.
 NonLinearUnit_1                 = \u201c{0}\u201d is not a linear unit.
 NonScaleUnit_1                  = \u201c{0}\u201d is not a scale unit.

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=1454130&r1=1454129&r2=1454130&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] Thu Mar  7 22:20:48 2013
@@ -62,6 +62,8 @@ NodeHasAnotherParent_1          = Le n\u
 NodeHasNoParent_1               = Le n\u0153ud \u201c{0}\u201d n\u2019a pas de parent.
 NodeNotFound_1                  = Aucun n\u0153ud \u201c{0}\u201d n\u2019a \u00e9t\u00e9
trouv\u00e9.
 NonEquilibratedParenthesis_2    = Il manque une parenth\u00e8se \u2018{1}\u2019 dans \u201c{0}\u201d.
+NonInvertibleConversion         = La conversion n\u2019est pas inversible.
+NonInvertibleTransform          = La transformation n\u2019est pas inversible.
 NonAngularUnit_1                = \u201c{0}\u201d n\u2019est pas une unit\u00e9 d\u2019angles.
 NonLinearUnit_1                 = \u201c{0}\u201d n\u2019est pas une unit\u00e9 de longueurs.
 NonScaleUnit_1                  = \u201c{0}\u201d n\u2019est pas une unit\u00e9 d\u2019\u00e9chelles.



Mime
View raw message