sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1391400 - in /sis/trunk/sis-utility/src/main/java/org/apache/sis/util: resources/ type/
Date Fri, 28 Sep 2012 11:27:16 GMT
Author: desruisseaux
Date: Fri Sep 28 11:27:15 2012
New Revision: 1391400

URL: http://svn.apache.org/viewvc?rev=1391400&view=rev
Log:
Added InternationalString implementations.

Added:
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/AbstractInternationalString.java   (with props)
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/DefaultInternationalString.java   (with props)
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/ResourceInternationalString.java   (with props)
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/SimpleInternationalString.java   (with props)
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/Types.java   (with props)
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/package-info.java   (with props)
Modified:
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1391400&r1=1391399&r2=1391400&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java Fri Sep 28 11:27:15 2012
@@ -101,6 +101,11 @@ public final class Errors extends Indexe
         public static final int UnexpectedArgumentDimension_3 = 5;
 
         /**
+         * A value is already defined for “{0}”.
+         */
+        public static final int ValueAlreadyDefined_1 = 13;
+
+        /**
          * Value ‘{0}’={1} is invalid. Expected a number greater than 0.
          */
         public static final int ValueNotGreaterThanZero_2 = 7;

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1391400&r1=1391399&r2=1391400&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties Fri Sep 28 11:27:15 2012
@@ -25,5 +25,6 @@ NotANumber_1=Argument '{0}' shall not be
 NotAPrimitiveWrapper_1=Class '{0}' is not a primitive type wrapper.
 NullArgument_1=Argument \u2018{0}\u2019 shall not be null.
 UnexpectedArgumentDimension_3=Argument \u2018{0}\u2019 has {1} dimensions, while {2} was expected.
+ValueAlreadyDefined_1=A value is already defined for \u201c{0}\u201d.
 ValueNotGreaterThanZero_2=Value \u2018{0}\u2019={1} is invalid. Expected a number greater than 0.
 ValueOutOfRange_4=Value \u2018{0}\u2019={1} is invalid. Expected a value in the [{2} \u2026 {3}] range.

Modified: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1391400&r1=1391399&r2=1391400&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties (original)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties Fri Sep 28 11:27:15 2012
@@ -25,5 +25,6 @@ NotANumber_1=L\u2019argument '{0}' ne do
 NotAPrimitiveWrapper_1=La classe '{0}' n\u2019est pas un adaptateur d\u2019un type primitif.
 NullArgument_1=L\u2019argument \u2018{0}\u2019 ne doit pas \u00eatre nul.
 UnexpectedArgumentDimension_3=L\u2019argument \u2018{0}\u2019 a {1} dimensions, alors qu\u2019on en attendait {2}.
+ValueAlreadyDefined_1=Une valeur est d\u00e9j\u00e0 d\u00e9finie pour \u201c{0}\u201d.
 ValueNotGreaterThanZero_2=La valeur \u2018{0}\u2019={1} n\u2019est pas valide. On attendait un nombre positif non-nul.
 ValueOutOfRange_4=La valeur \u2018{0}\u2019={1} est invalide. Une valeur dans la plage [{2} \u2026 {3}] \u00e9tait attendue.

Added: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/AbstractInternationalString.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/AbstractInternationalString.java?rev=1391400&view=auto
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/AbstractInternationalString.java (added)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/AbstractInternationalString.java Fri Sep 28 11:27:15 2012
@@ -0,0 +1,201 @@
+/*
+ * 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.util.type;
+
+import java.util.Locale;
+import java.util.Formatter;
+import java.util.Formattable;
+import java.util.FormattableFlags;
+import org.apache.sis.util.CharSequences;
+import org.opengis.util.InternationalString;
+
+
+/**
+ * Base class for {@linkplain String string} that has been internationalized into several
+ * {@linkplain Locale locales}. The {@link InternationalString} interface is used as a replacement
+ * for the {@link String} class whenever an attribute needs to be internationalization capable.
+ * The default value (as returned by {@link #toString()} and other {@link CharSequence} methods)
+ * is the string in the current {@linkplain Locale#getDefault() system-wide default locale}.
+ * <p>
+ * The {@linkplain Comparable natural ordering} is defined by the value returned by
+ * {@link #toString()}.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.3 (derived from geotk-2.1)
+ * @version 0.3
+ * @module
+ */
+public abstract class AbstractInternationalString implements InternationalString, Formattable {
+    /**
+     * The string in the {@linkplain Locale#getDefault() system default} locale, or {@code null}
+     * if this string has not yet been determined. This is the default string returned by
+     * {@link #toString()} and others methods from the {@link CharSequence} interface.
+     * <P>
+     * This field is not serialized because serialization is often used for data transmission
+     * between a server and a client, and the client may not use the same locale than the server.
+     * We want the locale to be examined again on the client side.
+     * <P>
+     * This field is read and written by {@link SimpleInternationalString}.
+     */
+    transient String defaultValue;
+
+    /**
+     * Constructs an international string.
+     */
+    public AbstractInternationalString() {
+    }
+
+    /**
+     * Returns the length of the string in the {@linkplain Locale#getDefault() default locale}.
+     * This is the length of the string returned by {@link #toString()}.
+     *
+     * @return Length of the string in the default locale.
+     */
+    @Override
+    public int length() {
+        if (defaultValue == null) {
+            defaultValue = toString();
+            if (defaultValue == null) {
+                return 0;
+            }
+        }
+        return defaultValue.length();
+    }
+
+    /**
+     * Returns the character of the string in the {@linkplain Locale#getDefault() default locale}
+     * at the specified index. This is a character of the string returned by {@link #toString()}.
+     *
+     * @param  index The index of the character.
+     * @return The character at the specified index.
+     * @throws IndexOutOfBoundsException if the specified index is out of bounds.
+     */
+    @Override
+    public char charAt(final int index) throws IndexOutOfBoundsException {
+        if (defaultValue == null) {
+            defaultValue = toString();
+            if (defaultValue == null) {
+                throw new StringIndexOutOfBoundsException();
+            }
+        }
+        return defaultValue.charAt(index);
+    }
+
+    /**
+     * Returns a subsequence of the string in the {@linkplain Locale#getDefault() default locale}.
+     * The subsequence is a {@link String} object starting with the character value at the specified
+     * index and ending with the character value at index {@code end - 1}.
+     *
+     * @param   start The start index, inclusive.
+     * @param   end   The end index, exclusive.
+     * @return  The specified subsequence.
+     * @throws  IndexOutOfBoundsException if {@code start} or {@code end} is out of range.
+     */
+    @Override
+    public CharSequence subSequence(final int start, final int end) {
+        if (defaultValue == null) {
+            defaultValue = toString();
+            if (defaultValue == null) {
+                if (start == 0 && end == 0) {
+                    return "";
+                }
+                throw new StringIndexOutOfBoundsException();
+            }
+        }
+        return defaultValue.substring(start, end);
+    }
+
+    /**
+     * Returns this string in the given locale. If no string is available in the given locale,
+     * then some default locale is used. The default locale is implementation-dependent.
+     * It may or may not be the {@linkplain Locale#getDefault() system default}).
+     *
+     * @param  locale The desired locale for the string to be returned,
+     *         or {@code null} for a string in the implementation default locale.
+     * @return The string in the given locale if available, or in the default locale otherwise.
+     */
+    @Override
+    public abstract String toString(final Locale locale);
+
+    /**
+     * Returns this string in the default locale. Invoking this method is equivalent to invoking
+     * <code>{@linkplain #toString(Locale) toString}({@linkplain Locale#getDefault()})</code>.
+     * <p>
+     * All methods from {@link CharSequence} operate on this string.
+     * This string is also used as the criterion for {@linkplain Comparable natural ordering}.
+     *
+     * @return The string in the default locale.
+     */
+    @Override
+    public String toString() {
+        if (defaultValue == null) {
+            defaultValue = toString(Locale.getDefault());
+            if (defaultValue == null) {
+                return "";
+            }
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Formats this international string using the given formatter.
+     * This method appends the string obtained by:
+     *
+     * <blockquote><code>
+     * {@linkplain #toString(Locale) toString}(formatter.{@linkplain Formatter#locale()})
+     * </code></blockquote>
+     *
+     * @param formatter The formatter to use for formatting this string.
+     * @param flags     A bitmask of {@link FormattableFlags} values.
+     * @param width     The minimum number of characters, or -1 if none.
+     * @param precision The maximum number of characters (before expanding to the {@code width}),
+     *                  or -1 for no restriction.
+     */
+    @Override
+    public void formatTo(final Formatter formatter, final int flags, int width, final int precision) {
+        final Locale locale = formatter.locale();
+        String value = toString(locale);
+        if ((flags & FormattableFlags.UPPERCASE) != 0) {
+            value = value.toUpperCase(locale);
+        }
+        if (precision >= 0 && precision < value.length()) {
+            value = value.substring(0, precision);
+        }
+        final Object[] args = new Object[] {value, value};
+        width -= value.length();
+        String format = "%s";
+        if (width >= 0) {
+            format = "%s%s";
+            args[(flags & FormattableFlags.LEFT_JUSTIFY) != 0 ? 1 : 0] = CharSequences.spaces(width);
+        }
+        formatter.format(format, args);
+    }
+
+    /**
+     * Compares this string with the specified object for order. This method compares
+     * the string in the {@linkplain Locale#getDefault() default locale}, as returned
+     * by {@link #toString()}.
+     *
+     * @param  object The string to compare with this string.
+     * @return A negative number if this string is before the given string, a positive
+     *         number if after, or 0 if equals.
+     */
+    @Override
+    public int compareTo(final InternationalString object) {
+        return toString().compareTo(object.toString());
+    }
+}

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/AbstractInternationalString.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/AbstractInternationalString.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/DefaultInternationalString.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/DefaultInternationalString.java?rev=1391400&view=auto
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/DefaultInternationalString.java (added)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/DefaultInternationalString.java Fri Sep 28 11:27:15 2012
@@ -0,0 +1,423 @@
+/*
+ * 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.util.type;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Locale;
+import net.jcip.annotations.ThreadSafe;
+import org.opengis.util.InternationalString;
+import org.apache.sis.util.Locales;
+import org.apache.sis.util.resources.Errors;
+
+import static org.apache.sis.util.collection.Collections.isNullOrEmpty;
+
+// Related to JDK7
+import org.apache.sis.internal.Objects;
+
+
+/**
+ * An {@linkplain InternationalString international string} using a {@linkplain Map map}
+ * of strings for different {@linkplain Locale locales}. Strings for new locales can be
+ * {@linkplain #add(Locale, String) added}, but existing strings can not be removed or modified.
+ * This behavior is a compromise between making constructions easier, and being suitable for
+ * use in immutable objects.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.3 (derived from geotk-2.1)
+ * @version 0.3
+ * @module
+ */
+@ThreadSafe
+public class DefaultInternationalString extends AbstractInternationalString implements Serializable {
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = 5760033376627376938L;
+
+    /**
+     * The string values in different locales (never {@code null}).
+     */
+    private Map<Locale,String> localeMap;
+
+    /**
+     * An unmodifiable view of the entry set in {@link #localeMap}. This is the set of locales
+     * defined in this international string. Will be constructed only when first requested.
+     */
+    private transient Set<Locale> localeSet;
+
+    /**
+     * Creates an initially empty international string. Localized strings can been added
+     * using one of {@link #add add(…)} methods.
+     */
+    public DefaultInternationalString() {
+        localeMap = Collections.emptyMap();
+    }
+
+    /**
+     * Creates an international string initialized with the given string.
+     * Additional localized strings can been added using one of {@link #add add(…)} methods.
+     * The string specified to this constructor is the one that will be returned if no localized
+     * string is found for the {@link Locale} argument in a call to {@link #toString(Locale)}.
+     *
+     * @param string The string in no specific locale, or {@code null} if none.
+     */
+    public DefaultInternationalString(final String string) {
+        if (string != null) {
+            localeMap = Collections.singletonMap(null, string);
+        } else {
+            localeMap = Collections.emptyMap();
+        }
+    }
+
+    /**
+     * Creates an international string initialized with the given localized strings.
+     * The content of the given map is copied, so changes to that map after construction
+     * will not be reflected into this international string.
+     *
+     * @param strings The strings in various locales, or {@code null} if none.
+     */
+    public DefaultInternationalString(final Map<Locale,String> strings) {
+        if (isNullOrEmpty(strings)) {
+            localeMap = Collections.emptyMap();
+        } else {
+            final Iterator<Map.Entry<Locale,String>> it = strings.entrySet().iterator();
+            final Map.Entry<Locale,String> entry = it.next();
+            if (!it.hasNext()) {
+                localeMap = Collections.singletonMap(entry.getKey(), entry.getValue());
+            } else {
+                localeMap = new LinkedHashMap<Locale,String>(strings);
+                // If HashMap is replaced by an other type, please revisit 'getLocales()'.
+            }
+        }
+    }
+
+    /**
+     * Adds a string for the given locale.
+     *
+     * @param  locale The locale for the {@code string} value, or {@code null}.
+     * @param  string The localized string.
+     * @throws IllegalArgumentException if a different string value was already set for
+     *         the given locale.
+     */
+    public synchronized void add(final Locale locale, final String string) throws IllegalArgumentException {
+        if (string != null) {
+            switch (localeMap.size()) {
+                case 0: {
+                    localeMap = Collections.singletonMap(locale, string);
+                    localeSet = null;
+                    defaultValue = null; // Will be recomputed when first needed.
+                    return;
+                }
+                case 1: {
+                    // If HashMap is replaced by an other type, please revisit 'getLocales()'.
+                    localeMap = new LinkedHashMap<Locale,String>(localeMap);
+                    localeSet = null;
+                    break;
+                }
+            }
+            final String old = localeMap.put(locale, string);
+            if (old != null) {
+                localeMap.put(locale, old);
+                if (string.equals(old)) {
+                    return;
+                }
+                throw new IllegalArgumentException(Errors.format(
+                        Errors.Keys.ValueAlreadyDefined_1, locale));
+            }
+            defaultValue = null; // Will be recomputed when first needed.
+        }
+    }
+
+    /**
+     * Adds a string for the given property key. This is a convenience method for constructing an
+     * {@code AbstractInternationalString} during iteration through the
+     * {@linkplain java.util.Map.Entry entries} in a {@link Map}. It infers the {@link Locale}
+     * from the property {@code key}, using the following steps:
+     * <ul>
+     *   <li>If the {@code key} do not starts with the specified {@code prefix}, then
+     *       this method do nothing and returns {@code false}.</li>
+     *   <li>Otherwise, the characters after the {@code prefix} are parsed as an ISO language
+     *       and country code, and the {@link #add(Locale, String)} method is invoked.</li>
+     * </ul>
+     * <p>
+     * For example if the prefix is {@code "remarks"}, then the {@code "remarks_fr"} property key
+     * stands for remarks in {@linkplain Locale#FRENCH French} while the {@code "remarks_fr_CA"}
+     * property key stands for remarks in {@linkplain Locale#CANADA_FRENCH French Canadian}.
+     *
+     * @param  prefix The prefix to skip at the beginning of the {@code key}.
+     * @param  key The property key.
+     * @param  string The localized string for the specified {@code key}.
+     * @return {@code true} if the key has been recognized, or {@code false} otherwise.
+     * @throws IllegalArgumentException if the locale after the prefix is an illegal code,
+     *         or a different string value was already set for the given locale.
+     */
+    public boolean add(final String prefix, final String key, final String string)
+            throws IllegalArgumentException
+    {
+        if (key.startsWith(prefix)) {
+            Locale locale = null;
+            final int offset = prefix.length();
+            if (key.length() != offset) {
+                if (key.charAt(offset) == '_') {
+                    locale = Locales.parse(key.substring(offset + 1));
+                } else {
+                    return false;
+                }
+            }
+            add(locale, string);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns the set of locales defined in this international string.
+     *
+     * @return The set of locales.
+     *
+     * @todo Current implementation does not return a synchronized set. We should synchronize
+     *       on the same lock than the one used for accessing the internal locale map.
+     */
+    public synchronized Set<Locale> getLocales() {
+        Set<Locale> locales = localeSet;
+        if (locales == null) {
+            locales = localeMap.keySet();
+            if (localeMap instanceof HashMap<?,?>) {
+                locales = Collections.unmodifiableSet(locales);
+            }
+            localeSet = locales;
+        }
+        return locales;
+    }
+
+    /**
+     * Returns a string in the specified locale. If there is no string for that {@code locale},
+     * then this method search for a locale without the {@linkplain Locale#getVariant() variant}
+     * part. If no string are found, then this method search for a locale without the
+     * {@linkplain Locale#getCountry() country} part. If none are found, then this method returns
+     * {@code null}.
+     *
+     * @param  locale The locale to look for, or {@code null}.
+     * @return The string in the specified locale, or {@code null} if none was found.
+     */
+    private String getString(Locale locale) {
+        while (locale != null) {
+            final String text = localeMap.get(locale);
+            if (text != null) {
+                return text;
+            }
+            final String language = locale.getLanguage();
+            final String country  = locale.getCountry ();
+            final String variant  = locale.getVariant ();
+            if (!variant.isEmpty()) {
+                locale = new Locale(language, country);
+                continue;
+            }
+            if (!country.isEmpty()) {
+                locale = new Locale(language);
+                continue;
+            }
+            break;
+        }
+        return null;
+    }
+
+    /**
+     * Returns a string in the specified locale. If there is no string for that {@code locale},
+     * then this method searches for a locale without the {@linkplain Locale#getVariant() variant}
+     * part. If no string are found, then this method searches for a locale without the
+     * {@linkplain Locale#getCountry() country} part. For example if the {@code "fr_CA"} locale
+     * was requested but not found, then this method looks for the {@code "fr"} locale.
+     * The {@code null} locale (which stand for unlocalized message) is tried last.
+     *
+     * {@section Handling of <code>null</code> argument value}
+     * A {@code null} argument value can be given to this method for
+     * requesting a "unlocalized" string - typically some programmatic strings like
+     * {@linkplain org.opengis.annotation.UML#identifier() UML identifiers}. While such
+     * identifiers often look like English words, they are not considered as the
+     * {@linkplain Locale#ENGLISH English locale}. In order to produce a value close
+     * to the common practice, this method handles {@code null} argument value as below:
+     * <p>
+     * <ul>
+     *   <li>If a string has been explicitly {@linkplain #add(Locale, String) added} for the
+     *       {@code null} locale, then that string is returned.</li>
+     *   <li>Otherwise, acknowledging that UML identifiers in OGC/ISO specifications are primarily
+     *       expressed in the English language, this method looks for an English string as an
+     *       approximation of a "unlocalized" string. The {@linkplain Locale#UK} variant is
+     *       preferred because ISO specifications seem to use that language.</li>
+     *   <li>If no English string was found, this method looks for a string for the
+     *       {@linkplain Locale#getDefault() system default locale}.</li>
+     *   <li>If none of the above steps found a string, then this method returns
+     *       an arbitrary string (this behavior may change in future SIS implementation).</li>
+     * </ul>
+     *
+     * @param  locale The locale to look for, or {@code null}.
+     * @return The string in the specified locale, or in a default locale.
+     */
+    @Override
+    public synchronized String toString(final Locale locale) {
+        String text = getString(locale);
+        if (text == null) {
+            /*
+             * No string for the requested locale. Try the string in the 'null' locale first, then
+             * the string in the system-default last.  Note: in a previous version we were looking
+             * for the system default first, but it produced unexpected results in many cases. The
+             * i18n string is often constructed with an English sentence for the "null" locale (the
+             * unlocalized text) without explicit entry for the English locale since the "null" one
+             * is supposed to be the default according javadoc. If we were looking for the default
+             * locale on a system having French as the default, the effect would be to return a
+             * sentence in French when the user asked for a sentence in English (or any language
+             * not explicitly declared). Generally the "unlocalized" text is in English, so it is
+             * a better bet as a fallback.
+             */
+            text = localeMap.get(null);
+            if (text == null) {
+                Locale def = Locale.UK; // The default language for "unlocalized" string.
+                if (locale != def) { // Avoid requesting the same locale twice (optimization).
+                    text = getString(def);
+                    if (text != null) {
+                        return text;
+                    }
+                }
+                def = Locale.getDefault();
+                if (locale != def && def != Locale.UK) {
+                    text = getString(def);
+                    if (text != null) {
+                        return text;
+                    }
+                }
+                // Every else failed; pickup a random string.
+                // This behavior may change in future versions.
+                final Iterator<String> it = localeMap.values().iterator();
+                if (it.hasNext()) {
+                    text = it.next();
+                }
+            }
+        }
+        return text;
+    }
+
+    /**
+     * Returns {@code true} if all localized texts stored in this international string are
+     * contained in the specified object. More specifically:
+     *
+     * <ul>
+     *   <li><p>If {@code candidate} is an instance of {@link InternationalString}, then this method
+     *       returns {@code true} if, for all <var>{@linkplain Locale locale}</var>-<var>{@linkplain
+     *       String string}</var> pairs contained in {@code this}, <code>candidate.{@linkplain
+     *       InternationalString#toString(Locale) toString}(locale)</code> returns a string
+     *       {@linkplain String#equals equals} to {@code string}.</p></li>
+     *
+     *   <li><p>If {@code candidate} is an instance of {@link CharSequence}, then this method
+     *       returns {@code true} if {@link #toString(Locale)} returns a string {@linkplain
+     *       String#equals equals} to <code>candidate.{@linkplain CharSequence#toString()
+     *       toString()}</code> for all locales.</p></li>
+     *
+     *   <li><p>If {@code candidate} is an instance of {@link Map}, then this methods returns
+     *       {@code true} if all <var>{@linkplain Locale locale}</var>-<var>{@linkplain String
+     *       string}</var> pairs are contained into {@code candidate}.</p></li>
+     *
+     *   <li><p>Otherwise, this method returns {@code false}.</p></li>
+     * </ul>
+     *
+     * @param  candidate The object which may contains this international string.
+     * @return {@code true} if the given object contains all localized strings found in this
+     *         international string.
+     */
+    public synchronized boolean isSubsetOf(final Object candidate) {
+        if (candidate instanceof InternationalString) {
+            final InternationalString string = (InternationalString) candidate;
+            for (final Map.Entry<Locale,String> entry : localeMap.entrySet()) {
+                final Locale locale = entry.getKey();
+                final String text   = entry.getValue();
+                if (!text.equals(string.toString(locale))) {
+                    return false;
+                }
+            }
+        } else if (candidate instanceof CharSequence) {
+            final String string = candidate.toString();
+            for (final String text : localeMap.values()) {
+                if (!text.equals(string)) {
+                    return false;
+                }
+            }
+        } else if (candidate instanceof Map<?,?>) {
+            final Map<?,?> map = (Map<?,?>) candidate;
+            return map.entrySet().containsAll(localeMap.entrySet());
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Compares this international string with the specified object for equality.
+     *
+     * @param object The object to compare with this international string.
+     * @return {@code true} if the given object is equal to this string.
+     */
+    @Override
+    public boolean equals(final Object object) {
+        if (object != null && object.getClass() == getClass()) {
+            final DefaultInternationalString that = (DefaultInternationalString) object;
+            return Objects.equals(this.localeMap, that.localeMap);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a hash code value for this international text.
+     *
+     * @return A hash code value for this international text.
+     */
+    @Override
+    public synchronized int hashCode() {
+        return localeMap.hashCode() ^ (int) serialVersionUID;
+    }
+
+    /**
+     * Canonicalize the locales after deserialization.
+     */
+    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+        final int size = localeMap.size();
+        if (size == 0) {
+            return;
+        }
+        @SuppressWarnings({"unchecked","rawtypes"}) // Generic array creation.
+        Map.Entry<Locale,String>[] entries = new Map.Entry[size];
+        entries = localeMap.entrySet().toArray(entries);
+        if (size == 1) {
+            final Map.Entry<Locale,String> entry = entries[0];
+            localeMap = Collections.singletonMap(Locales.unique(entry.getKey()), entry.getValue());
+        } else {
+            localeMap.clear();
+            for (int i=0; i<entries.length; i++) {
+                final Map.Entry<Locale,String> entry = entries[i];
+                localeMap.put(Locales.unique(entry.getKey()), entry.getValue());
+            }
+        }
+    }
+}

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/DefaultInternationalString.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/DefaultInternationalString.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/ResourceInternationalString.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/ResourceInternationalString.java?rev=1391400&view=auto
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/ResourceInternationalString.java (added)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/ResourceInternationalString.java Fri Sep 28 11:27:15 2012
@@ -0,0 +1,175 @@
+/*
+ * 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.util.type;
+
+import java.io.Serializable;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.MissingResourceException;
+import net.jcip.annotations.Immutable;
+import org.opengis.util.InternationalString;
+
+import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
+
+// Related to JDK7
+import org.apache.sis.internal.Objects;
+
+
+/**
+ * An {@linkplain InternationalString international string} backed by a {@linkplain ResourceBundle
+ * resource bundle}. A resource bundle can be a Java class or a {@linkplain Properties properties}
+ * file, one for each language. The constructor expects the fully qualified class name of the base
+ * resource bundle (the one used when no resource was found in the client's language). The appropriate
+ * resource bundle is loaded at runtime for the client's language by looking for a class or a
+ * properties file with the right suffix, for example {@code "_en"} for English or {@code "_fr"}
+ * for French. This mechanism is explained in J2SE javadoc for the
+ * {@link ResourceBundle#getBundle(String,Locale,ClassLoader) getBundle} static method.
+ * <p>
+ * <b>Example:</b> If a file named "{@code MyResources.properties}" exists in the package
+ * {@code org.apache.sis.mypackage} and contains a line like "{@code MyKey = some value}",
+ * then an international string for "{@code some value}" can be created using the following
+ * code:
+ *
+ * {@preformat java
+ *     InternationalString value =
+ *         new ResourceInternationalString("org.apache.sis.mypackage.MyResources", "MyKey");
+ * }
+ *
+ * The "{@code some value}" string will be localized if the required properties files exist, for
+ * example "{@code MyResources_fr.properties}" for French, "{@code MyResources_it.properties}"
+ * for Italian, <i>etc.</i>
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @author  Johann Sorel (Geomatys)
+ * @since   0.3 (derived from geotk-2.1)
+ * @version 0.3
+ * @module
+ */
+@Immutable
+public class ResourceInternationalString extends AbstractInternationalString implements Serializable {
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = 6339944890723487336L;
+
+    /**
+     * The name of the resource bundle from which to fetch the string.
+     */
+    private final String resources;
+
+    /**
+     * The key for the resource to fetch.
+     */
+    private final String key;
+
+    /**
+     * The class loader to use for loading the resources file, or {@code null} for the default
+     * class loader.
+     */
+    private final ClassLoader loader;
+
+    /**
+     * Creates a new international string from the specified resource bundle and key.
+     *
+     * @param resources The name of the resource bundle, as a fully qualified class name.
+     * @param key The key for the resource to fetch.
+     */
+    public ResourceInternationalString(final String resources, final String key) {
+        this(resources, key, null);
+    }
+
+    /**
+     * Creates a new international string from the specified resource bundle, key and class loader.
+     *
+     * @param resources The name of the resource bundle, as a fully qualified class name.
+     * @param key The key for the resource to fetch.
+     * @param loader The class loader to use for loading the resources file,
+     *        or {@code null} for the default class loader.
+     */
+    public ResourceInternationalString(final String resources, final String key, final ClassLoader loader) {
+        this.resources = resources;
+        this.key       = key;
+        this.loader    = loader;
+        ensureNonNull("resources", resources);
+        ensureNonNull("key",       key);
+
+    }
+
+    /**
+     * Returns a string in the specified locale. If there is no string for the specified
+     * {@code locale}, then this method search for a string in an other locale as
+     * specified in the {@link ResourceBundle} class description.
+     *
+     * @param  locale The locale to look for, or {@code null} for an unlocalized version.
+     * @return The string in the specified locale, or in a default locale.
+     * @throws MissingResourceException is the key given to the constructor is invalid.
+     */
+    @Override
+    public String toString(Locale locale) throws MissingResourceException {
+        if (locale == null) {
+            // The English locale (NOT the system default) is often used
+            // as the real identifier in OGC IdentifiedObject naming. If
+            // a user wants a string in the system default locale, he
+            // should invokes the 'toString()' method instead.
+            locale = Locale.ENGLISH;
+        }
+        return getBundle(locale).getString(key);
+    }
+
+    /**
+     * Returns the resource bundle for the given locale. The default implementation fetches the
+     * bundle from the name given at {@linkplain #ResourceInternationalString(String,String)
+     * construction time}. Subclasses can override this method if they need to fetch the
+     * bundle in an other way.
+     *
+     * @param  locale The locale for which to get the resource bundle.
+     * @return The resource bundle for the given locale.
+     *
+     * @see ResourceBundle#getBundle(String,Locale)
+     */
+    protected ResourceBundle getBundle(final Locale locale) {
+        return (loader == null) ? ResourceBundle.getBundle(resources, locale) :
+                ResourceBundle.getBundle(resources, locale, loader);
+    }
+
+    /**
+     * Compares this international string with the specified object for equality.
+     *
+     * @param object The object to compare with this international string.
+     * @return {@code true} if the given object is equal to this string.
+     */
+    @Override
+    public boolean equals(final Object object) {
+        if (object != null && object.getClass() == getClass()) {
+            final ResourceInternationalString that = (ResourceInternationalString) object;
+            return Objects.equals(this.key,       that.key) &&
+                   Objects.equals(this.resources, that.resources);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a hash code value for this international text.
+     *
+     * @return A hash code value for this international text.
+     */
+    @Override
+    public int hashCode() {
+        return key.hashCode() ^ resources.hashCode() ^ (int) serialVersionUID;
+    }
+}

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/ResourceInternationalString.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/ResourceInternationalString.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/SimpleInternationalString.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/SimpleInternationalString.java?rev=1391400&view=auto
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/SimpleInternationalString.java (added)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/SimpleInternationalString.java Fri Sep 28 11:27:15 2012
@@ -0,0 +1,124 @@
+/*
+ * 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.util.type;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Locale;
+import net.jcip.annotations.Immutable;
+import org.opengis.util.InternationalString;
+import static org.apache.sis.util.ArgumentChecks.ensureNonNull;
+
+// Related to JDK7
+import org.apache.sis.internal.Objects;
+
+
+/**
+ * An {@linkplain InternationalString international string} consisting of a single string
+ * for all {@linkplain Locale locales}. For such a particular case, this implementation is
+ * more effective than other implementations provided in this package.
+ *
+ * {@section Instantiation}
+ * If the characters sequence to wrap is known to be a {@link String} instance, then
+ * the {@link #SimpleInternationalString(String)} constructor is okay. Otherwise use
+ * the {@link Types#toInternationalString(CharSequence)} method.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.3 (derived from geotk-2.1)
+ * @version 0.3
+ * @module
+ */
+@Immutable
+public class SimpleInternationalString extends AbstractInternationalString implements Serializable {
+    /**
+     * Serial number for inter-operability with different versions.
+     */
+    private static final long serialVersionUID = 3543963804501667578L;
+
+    /**
+     * Creates a new instance from the given string. If the type of the text
+     * to wrap is the more generic {@link CharSequence} interface, then use
+     * the {@link Types#toInternationalString(CharSequence)} method instead.
+     *
+     * @param text The string for all locales.
+     */
+    public SimpleInternationalString(final String text) {
+        ensureNonNull("text", text);
+        defaultValue = text;
+    }
+
+    /**
+     * Returns the string representation, which is unique for all locales.
+     */
+    @Override
+    public String toString() {
+        return defaultValue;
+    }
+
+    /**
+     * Returns the same string for all locales. This is the string given to the constructor.
+     *
+     * @param locale Ignored in the {@code SampleInternationalString} implementation.
+     */
+    @Override
+    public String toString(final Locale locale) {
+        return defaultValue;
+    }
+
+    /**
+     * Compares this international string with the specified object for equality.
+     *
+     * @param object The object to compare with this international string.
+     * @return {@code true} if the given object is equal to this string.
+     */
+    @Override
+    public boolean equals(final Object object) {
+        if (object != null && object.getClass() == getClass()) {
+            final SimpleInternationalString that = (SimpleInternationalString) object;
+            return Objects.equals(this.defaultValue, that.defaultValue);
+        }
+        return false;
+    }
+
+    /**
+     * Returns a hash code value for this international text.
+     *
+     * @return The hash code value.
+     */
+    @Override
+    public int hashCode() {
+        return defaultValue.hashCode() ^ (int) serialVersionUID;
+    }
+
+    /**
+     * Writes the string. This is required since {@link #defaultValue} is not serialized.
+     */
+    private void writeObject(final ObjectOutputStream out) throws IOException {
+        out.defaultWriteObject();
+        out.writeUTF(defaultValue);
+    }
+
+    /**
+     * Reads the string. This is required since {@link #defaultValue} is not serialized.
+     */
+    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+        defaultValue = in.readUTF();
+    }
+}

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/SimpleInternationalString.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/SimpleInternationalString.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/Types.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/Types.java?rev=1391400&view=auto
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/Types.java (added)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/Types.java Fri Sep 28 11:27:15 2012
@@ -0,0 +1,174 @@
+/*
+ * 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.util.type;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.MissingResourceException;
+import java.io.InputStream;
+
+import org.opengis.annotation.UML;
+import org.opengis.util.CodeList;
+import org.opengis.util.InternationalString;
+import org.apache.sis.util.Static;
+import org.apache.sis.util.collection.BackingStoreException;
+
+
+/**
+ * Convenience methods working on GeoAPI types.
+ * The methods in this class can be used for:
+ * <p>
+ * <ul>
+ *   <li>Creating {@link InternationalString} instances from {@link CharSequence} instances.</li>
+ *   <li>Mapping ISO identifiers to the GeoAPI types (interfaces or {@linkplain CodeList code lists}).</li>
+ * </ul>
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.3 (derived from geotk-3.19)
+ * @version 0.3
+ * @module
+ */
+public final class Types extends Static {
+    /**
+     * The types for ISO 19115 UML identifiers. The keys are UML identifiers. Values
+     * are either class names as {@link String} objects, or the {@link Class} instances.
+     *
+     * @see #forName(String)
+     */
+    private static Map<Object,Object> typeForNames;
+
+    /**
+     * Do not allow instantiation of this class.
+     */
+    private Types() {
+    }
+
+    /**
+     * Returns the ISO name for the given class, or {@code null} if none.
+     * Examples:
+     * <p>
+     * <ul>
+     *   <li><code>getStandardName({@linkplain org.opengis.metadata.citation.Citation}.class)</code>   returns {@code "CI_Citation"}.</li>
+     *   <li><code>getStandardName({@linkplain org.opengis.referencing.cs.AxisDirection}.class)</code> returns {@code "CS_AxisDirection"}. </li>
+     * </ul>
+     *
+     * @param  type The GeoAPI interface from which to get the ISO name, or {@code null}.
+     * @return The ISO name for the given interface, or {@code null} if none or if the given type is {@code null}.
+     */
+    public static String getStandardName(final Class<?> type) {
+        if (type != null) {
+            final UML uml = type.getAnnotation(UML.class);
+            if (uml != null) {
+                return uml.identifier();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the GeoAPI interface for the given ISO name, or {@code null} if none.
+     * The identifier argument shall be the value documented in the {@link UML#identifier()}
+     * annotation associated with the GeoAPI interface.
+     * Examples:
+     * <p>
+     * <ul>
+     *   <li>{@code forStandardName("CI_Citation")}      returns <code>{@linkplain org.opengis.metadata.citation.Citation}.class</code></li>
+     *   <li>{@code forStandardName("CS_AxisDirection")} returns <code>{@linkplain org.opengis.referencing.cs.AxisDirection}.class</code></li>
+     * </ul>
+     * <p>
+     * Only identifiers for the stable part of GeoAPI are recognized. This method does not handle
+     * the identifiers for the {@code geoapi-pending} module.
+     *
+     * @param  identifier The ISO {@linkplain UML} identifier, or {@code null}.
+     * @return The GeoAPI interface, or {@code null} if the given identifier is {@code null} or unknown.
+     */
+    public static synchronized Class<?> forStandardName(final String identifier) {
+        if (identifier == null) {
+            return null;
+        }
+        if (typeForNames == null) {
+            final Class<UML> c = UML.class;
+            final InputStream in = c.getResourceAsStream("class-index.properties");
+            if (in == null) {
+                throw new MissingResourceException("class-index.properties", c.getName(), identifier);
+            }
+            final Properties props = new Properties();
+            try {
+                props.load(in);
+                in.close();
+            } catch (Exception e) { // Catch IOException and IllegalArgumentException.
+                throw new BackingStoreException(e);
+            }
+            typeForNames = new HashMap<Object,Object>(props);
+        }
+        final Object value = typeForNames.get(identifier);
+        if (value == null || value instanceof Class<?>) {
+            return (Class<?>) value;
+        }
+        final Class<?> type;
+        try {
+            type = Class.forName((String) value);
+        } catch (ClassNotFoundException e) {
+            throw new TypeNotPresentException((String) value, e);
+        }
+        typeForNames.put(identifier, type);
+        return type;
+    }
+
+    /**
+     * Returns the given characters sequence as an international string. If the given sequence is
+     * null or an instance of {@link InternationalString}, this this method returns it unchanged.
+     * Otherwise, this method copies the {@link InternationalString#toString()} value in a new
+     * {@link SimpleInternationalString} instance and returns it.
+     *
+     * @param  string The characters sequence to convert, or {@code null}.
+     * @return The given sequence as an international string,
+     *         or {@code null} if the given sequence was null.
+     */
+    public static InternationalString toInternationalString(final CharSequence string) {
+        if (string == null || string instanceof InternationalString) {
+            return (InternationalString) string;
+        }
+        return new SimpleInternationalString(string.toString());
+    }
+
+    /**
+     * Returns the given array of {@code CharSequence}s as an array of {@code InternationalString}s.
+     * If the given array is null or an instance of {@code InternationalString[]}, then this method
+     * returns it unchanged. Otherwise a new array of type {@code InternationalString[]} is created
+     * and every elements from the given array is copied or
+     * {@linkplain #InternationalString(CharSequence) converted} in the new array.
+     * <p>
+     * If a defensive copy of the {@code strings} array is wanted, then the caller needs to check
+     * if the returned array is the same instance than the one given in argument to this method.
+     *
+     * @param  strings The characters sequences to convert, or {@code null}.
+     * @return The given array as an array of type {@code InternationalString[]},
+     *         or {@code null} if the given array was null.
+     */
+    public static InternationalString[] toInternationalStrings(final CharSequence... strings) {
+        if (strings == null || strings instanceof InternationalString[]) {
+            return (InternationalString[]) strings;
+        }
+        final InternationalString[] copy = new InternationalString[strings.length];
+        for (int i=0; i<strings.length; i++) {
+            copy[i] = toInternationalString(strings[i]);
+        }
+        return copy;
+    }
+}

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/Types.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/Types.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/package-info.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/package-info.java?rev=1391400&view=auto
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/package-info.java (added)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/package-info.java Fri Sep 28 11:27:15 2012
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementation of GeoAPI types from the {@link org.opengis.util} package.
+ * All those types except {@code InternationalString} are derived from the ISO 19103 specification.
+ * The main content of this package are:
+ * <p>
+ * <ul>
+ *   <li>Implementations of {@link org.opengis.util.InternationalString}:
+ *     <ul>
+ *       <li>{@link org.apache.sis.util.type.SimpleInternationalString} for wrapping a single {@link java.lang.String};</li>
+ *       <li>{@link org.apache.sis.util.type.DefaultInternationalString} for providing many localization in a {@link java.util.Map};</li>
+ *       <li>{@link org.apache.sis.util.type.ResourceInternationalString} for providing localization from a {@link java.util.ResourceBundle}.</li>
+ *     </ul>
+ *   </li>
+ *   <li>Implementations of {@link org.opengis.util.GenericName}:
+ *     <ul>
+ *       <li>{@link org.apache.sis.util.type.DefaultLocalName} for identifier within a name space.</li>
+ *       <li>{@link org.apache.sis.util.type.DefaultScopedName} for a composite of a <cite>head</cite>
+ *           name and a <cite>tail</cite> name.</li>
+ *     </ul>
+ *   </li>
+ * </ul>
+ *
+ * {@section Relationship between naming types}
+ * Names may be {@linkplain org.apache.sis.naming.AbstractName#toFullyQualifiedName()
+ * fully qualified} (like {@code "org.opengis.util.Record"}), or they may be relative to a
+ * {@linkplain org.apache.sis.naming.AbstractName#scope() scope} (like {@code "util.Record"}
+ * in the {@code "org.opengis"} scope). The illustration below shows all possible constructions
+ * for {@code "org.opengis.util.Record"}:
+ *
+ * <blockquote><table border="1" cellpadding="15"><tr><td><table border="0" cellspacing="0">
+ *   <tr>
+ *     <th align="right">org</th>
+ *     <th>.</th><th>opengis</th>
+ *     <th>.</th><th>util</th>
+ *     <th>.</th><th>Record</th>
+ *     <th width="50"></th>
+ *     <th>{@link org.apache.sis.naming.AbstractName#scope() scope()}</th>
+ *     <th>{@link org.apache.sis.naming.AbstractName#getParsedNames() getParsedNames()}</th>
+ *     <th width="50"></th>
+ *     <th>Type</th>
+ *   </tr>
+ *
+ *   <tr align="center">
+ *     <td bgcolor="palegoldenrod" colspan="1"><font size="-1">{@linkplain org.apache.sis.naming.AbstractName#head() head}</font></td><td></td>
+ *     <td bgcolor="palegoldenrod" colspan="5"><font size="-1">{@linkplain org.apache.sis.naming.DefaultScopedName#tail() tail}</font></td>
+ *     <td rowspan="2"></td>
+ *     <td rowspan="2" bgcolor="beige" align="left">{@linkplain org.apache.sis.naming.DefaultNameSpace#isGlobal() global}</td>
+ *     <td rowspan="2" bgcolor="beige" align="right">{@literal {"org", "opengis", "util", "Record"}}</td>
+ *     <td rowspan="2"></td>
+ *     <td rowspan="2">{@link org.apache.sis.naming.DefaultScopedName ScopedName}</td>
+ *   </tr>
+ *   <tr align="center">
+ *     <td bgcolor="wheat" colspan="5"><font size="-1">{@linkplain org.apache.sis.naming.DefaultScopedName#path() path}</font></td><td></td>
+ *     <td bgcolor="wheat" colspan="1"><font size="-1">{@linkplain org.apache.sis.naming.AbstractName#tip() tip}</font></td>
+ *   </tr>
+ *
+ *   <tr><td colspan="9" height="2"></td></tr>
+ *   <tr align="center">
+ *     <td bgcolor="palegoldenrod" colspan="1" rowspan="2"><font size="-1">{@linkplain org.apache.sis.naming.AbstractName#scope() scope}</font></td><td rowspan="2"></td>
+ *     <td bgcolor="palegoldenrod" colspan="1"><font size="-1">head</font></td><td></td>
+ *     <td bgcolor="palegoldenrod" colspan="3"><font size="-1">tail</font></td>
+ *     <td rowspan="2"></td>
+ *     <td rowspan="2" bgcolor="beige" align="left">{@literal "org"}</td>
+ *     <td rowspan="2" bgcolor="beige" align="right">{@literal {"opengis", "util", "Record"}}</td>
+ *     <td rowspan="2"></td>
+ *     <td rowspan="2">{@code ScopedName}</td>
+ *   </tr>
+ *   <tr align="center">
+ *     <td bgcolor="wheat" colspan="3"><font size="-1">path</font></td><td></td>
+ *     <td bgcolor="wheat" colspan="1"><font size="-1">tip</font></td>
+ *   </tr>
+ *
+ *   <tr><td colspan="9" height="3"></td></tr>
+ *   <tr align="center">
+ *     <td bgcolor="palegoldenrod" colspan="3" rowspan="2"><font size="-1">scope</font></td><td rowspan="2"></td>
+ *     <td bgcolor="palegoldenrod" colspan="1"><font size="-1">head</font></td><td></td>
+ *     <td bgcolor="palegoldenrod" colspan="1"><font size="-1">tail</font></td>
+ *     <td rowspan="2"></td>
+ *     <td rowspan="2" bgcolor="beige" align="left">{@literal "org.opengis"}</td>
+ *     <td rowspan="2" bgcolor="beige" align="right">{@literal {"util", "Record"}}</td>
+ *     <td rowspan="2"></td>
+ *     <td rowspan="2">{@code ScopedName}</td>
+ *   </tr>
+ *   <tr align="center">
+ *     <td bgcolor="wheat" colspan="1"><font size="-1">path</font></td><td></td>
+ *     <td bgcolor="wheat" colspan="1"><font size="-1">tip</font></td>
+ *   </tr>
+ *
+ *   <tr><td colspan="9" height="3"></td></tr>
+ *   <tr align="center">
+ *     <td bgcolor="palegoldenrod" colspan="5" rowspan="2"><font size="-1">scope</font></td><td rowspan="2"></td>
+ *     <td bgcolor="palegoldenrod" colspan="1"><font size="-1">head</font></td>
+ *     <td rowspan="2"></td>
+ *     <td rowspan="2" bgcolor="beige" align="left">{@literal "org.opengis.util"}</td>
+ *     <td rowspan="2" bgcolor="beige" align="right">{@literal {"Record"}}</td>
+ *     <td rowspan="2"></td>
+ *     <td rowspan="2">{@link org.apache.sis.naming.DefaultLocalName LocalName}</td>
+ *   </tr>
+ *   <tr align="center">
+ *     <td bgcolor="wheat" colspan="1"><font size="-1">tip</font></td>
+ *   </tr>
+ * </table></td></tr></table></blockquote>
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.3 (derived from geotk-3.00)
+ * @version 0.3
+ * @module
+ */
+package org.apache.sis.util.type;

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/type/package-info.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message