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.