You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2013/08/30 23:00:41 UTC
svn commit: r1519087 [2/2] - in /sis/trunk: ./ application/sis-console/
application/sis-console/src/main/java/org/apache/sis/console/
application/sis-console/src/test/java/org/apache/sis/console/
application/sis-console/src/test/java/org/apache/sis/tes...
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/internal/util/CollectionsExt.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -50,7 +50,7 @@ import org.apache.sis.internal.jdk8.Func
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @since 0.3 (derived from geotk-3.00)
- * @version 0.3
+ * @version 0.4
* @module
*/
public final class CollectionsExt extends Static {
@@ -92,25 +92,79 @@ public final class CollectionsExt extend
}
/**
+ * Returns the given collection if non-empty, or {@code null} if the given collection is null or empty.
+ * This method is generally not recommended, since public API should prefer empty collection instead of
+ * null. However it is occasionally useful for managing private fields, especially for inter-operability
+ * with frameworks that may expect or return null (e.g. if we want to exclude completely an empty collection
+ * from marshalling with JAXB).
+ *
+ * @param <T> The type of the collection.
+ * @param <E> The type of elements in the collection.
+ * @param c The collection, or {@code null}.
+ * @return The given collection, or an empty set of the given collection was null.
+ */
+ public static <T extends Collection<E>, E> T nonEmpty(final T c) {
+ return (c != null && c.isEmpty()) ? null : c;
+ }
+
+ /**
+ * Returns the given collection, or {@link Collections#EMPTY_SET} if the given collection is null.
+ *
+ * @param <E> The type of elements in the collection.
+ * @param c The collection, or {@code null}.
+ * @return The given collection, or an empty set of the given collection was null.
+ */
+ public static <E> Collection<E> nonNull(final Collection<E> c) {
+ return (c != null) ? c : Collections.<E>emptySet();
+ }
+
+ /**
+ * Returns the given set, or {@link Collections#EMPTY_SET} if the given set is null.
+ *
+ * @param <E> The type of elements in the collection.
+ * @param c The collection, or {@code null}.
+ * @return The given collection, or an empty set of the given collection was null.
+ */
+ public static <E> Set<E> nonNull(final Set<E> c) {
+ return (c != null) ? c : Collections.<E>emptySet();
+ }
+
+ /**
* Returns the specified array as an immutable set, or {@code null} if the array is null.
* If the given array contains duplicated elements, i.e. elements that are equal in the
* sense of {@link Object#equals(Object)}, then only the last instance of the duplicated
* values will be included in the returned set.
*
- * @param <E> The type of array elements.
- * @param array The array to copy in a set. May be {@code null}.
+ * @param <E> The type of array elements.
+ * @param excludeNull {@code true} for excluding the {@code null} element from the returned set.
+ * @param array The array to copy in a set. May be {@code null} or contain null elements.
* @return A set containing the array elements, or {@code null} if the given array was null.
*
* @see Collections#unmodifiableSet(Set)
*/
- public static <E> Set<E> immutableSet(final E... array) {
+ @SuppressWarnings("fallthrough")
+ public static <E> Set<E> immutableSet(final boolean excludeNull, final E... array) {
if (array == null) {
return null;
}
switch (array.length) {
- case 0: return Collections.emptySet();
- case 1: return Collections.singleton(array[0]);
- default: return Collections.unmodifiableSet(new LinkedHashSet<E>(Arrays.asList(array)));
+ case 1: {
+ final E element = array[0];
+ if (element != null || !excludeNull) {
+ return Collections.singleton(element);
+ }
+ // Fallthrough for an empty set.
+ }
+ case 0: {
+ return Collections.emptySet();
+ }
+ default: {
+ final Set<E> set = new LinkedHashSet<E>(Arrays.asList(array));
+ if (excludeNull) {
+ set.remove(null);
+ }
+ return unmodifiableOrCopy(set);
+ }
}
}
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/FunctionProperty.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/FunctionProperty.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/FunctionProperty.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/math/FunctionProperty.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -140,7 +140,7 @@ public enum FunctionProperty {
ORDER_REVERSING;
/**
- * Bijective functions shall contains all the value in this set.
+ * Bijective functions shall contain all the value in this set.
*
* @see #isBijective(Set)
*/
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/ArgumentChecks.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -16,6 +16,7 @@
*/
package org.apache.sis.util;
+import java.util.Map; // For javadoc
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.geometry.Envelope;
@@ -155,8 +156,9 @@ public final class ArgumentChecks extend
* Can be {@code null} if the name is unknown.
* @param expectedType the expected type (class or interface).
* @param value The value to check, or {@code null}.
- * @throws IllegalArgumentException if {@code value} is non-null and is not assignable
- * to the given type.
+ * @throws IllegalArgumentException if {@code value} is non-null and is not assignable to the given type.
+ *
+ * @see org.apache.sis.util.collection.Containers#property(Map, Object, Class)
*/
public static void ensureCanCast(final String name, final Class<?> expectedType, final Object value)
throws IllegalArgumentException
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/CharSequences.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -1518,7 +1518,7 @@ cmp: while (ia < lga) {
* Unicode identifier start} and all remaining characters (if any) are
* {@linkplain Character#isUnicodeIdentifierPart(int) Unicode identifier parts}.
*
- * @param identifier The character sequence to test.
+ * @param identifier The character sequence to test.
* @return {@code true} if the given character sequence is a legal Unicode identifier.
* @throws NullPointerException if the argument is null.
*/
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Locales.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Locales.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Locales.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/Locales.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -208,20 +208,33 @@ public final class Locales extends Stati
* anyway.</p>
*
* @param code The language code, which may be followed by country code.
- * @return The language for the given code.
+ * @return The language for the given code (never {@code null}).
* @throws IllegalArgumentException If the given code doesn't seem to be a valid locale.
*
* @see Locale#forLanguageTag(String)
*/
public static Locale parse(final String code) throws IllegalArgumentException {
+ ArgumentChecks.ensureNonNull("code", code);
+ return parse(code, 0);
+ }
+
+ /**
+ * Implementation of {@link #parse(String)} which start the parsing process from the given {@code fromIndex}.
+ *
+ * @param code The language code, which may be followed by country code.
+ * @param fromIndex Index of the first character to parse.
+ * @return The language for the given code (never {@code null}).
+ * @throws IllegalArgumentException If the given code doesn't seem to be a valid locale.
+ */
+ private static Locale parse(final String code, final int fromIndex) throws IllegalArgumentException {
final String language, country, variant;
- int ci = code.indexOf('_');
+ int ci = code.indexOf('_', fromIndex);
if (ci < 0) {
- language = trimWhitespaces(code);
+ language = (String) trimWhitespaces(code, fromIndex, code.length());
country = "";
variant = "";
} else {
- language = (String) trimWhitespaces(code, 0, ci);
+ language = (String) trimWhitespaces(code, fromIndex, ci);
int vi = code.indexOf('_', ++ci);
if (vi < 0) {
country = (String) trimWhitespaces(code, ci, code.length());
@@ -230,7 +243,8 @@ public final class Locales extends Stati
country = (String) trimWhitespaces(code, ci, vi);
variant = (String) trimWhitespaces(code, ++vi, code.length());
if (code.indexOf('_', vi) >= 0) {
- throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalLanguageCode_1, code));
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalLanguageCode_1,
+ code.substring(fromIndex)));
}
}
}
@@ -289,18 +303,23 @@ public final class Locales extends Stati
* </ul>
*
* @param prefix The prefix to skip at the beginning of the {@code key}.
- * @param key The property key from which to extract the locale.
- * @return {@code true} if the key has been recognized, or {@code false} otherwise.
+ * @param key The property key from which to extract the locale, or {@code null}.
+ * @return The locale encoded in the given key name, or {@code null} if the key has not been recognized.
* @throws IllegalArgumentException if the locale after the prefix is an illegal code.
+ *
+ * @see org.apache.sis.util.iso.Types#toInternationalString(Map, String)
*/
public static Locale parseSuffix(final String prefix, final String key) throws IllegalArgumentException {
- if (key.startsWith(prefix)) {
- final int offset = prefix.length();
- if (key.length() == offset) {
- return Locale.ROOT;
- }
- if (key.charAt(offset) == '_') {
- return parse(key.substring(offset + 1));
+ ArgumentChecks.ensureNonNull("prefix", prefix);
+ if (key != null) { // Tolerance for Map that accept null keys.
+ if (key.startsWith(prefix)) {
+ final int offset = prefix.length();
+ if (key.length() == offset) {
+ return Locale.ROOT;
+ }
+ if (key.charAt(offset) == '_') {
+ return parse(key, offset + 1);
+ }
}
}
return null;
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/Containers.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/Containers.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/Containers.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/collection/Containers.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -23,17 +23,18 @@ import java.util.Collection;
import org.apache.sis.util.Static;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.ObjectConverter;
+import org.apache.sis.util.resources.Errors;
import org.apache.sis.internal.util.UnmodifiableArrayList;
/**
* Static methods working on {@link Collection} or {@link CheckedContainer} objects.
- * Unless otherwise noted in the javadoc, every collections except {@link Map} returned
- * by the methods in this class implement the {@code CheckedContainer} interface.
+ * Unless otherwise noted in the javadoc, every collections returned by the methods
+ * in this class implement the {@code CheckedContainer} interface.
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @since 0.3 (derived from geotk-3.00)
- * @version 0.3
+ * @version 0.4
* @module
*/
public final class Containers extends Static {
@@ -184,6 +185,10 @@ public final class Containers extends St
* <p>The returned map can be serialized if the given map and converters are serializable.
* The returned map is <strong>not</strong> thread-safe.</p>
*
+ * <p>The returned map does not implement the {@link CheckedContainer} interface since {@code Map}
+ * is not {@code Collection} sub-type, but the derived map {@linkplain Map#keySet() key set} and
+ * {@linkplain Map#entrySet() entry set} do.</p>
+ *
* @param <SK> The type of keys in the storage map.
* @param <SV> The type of values in the storage map.
* @param <K> The type of keys in the derived map.
@@ -211,6 +216,41 @@ public final class Containers extends St
}
/**
+ * Returns the value mapped to the given key casted to the given type,
+ * or {@code null} if the map is null or does not contain a value for the key.
+ * If the mapped value is non-null but can not be casted to the given type, then this
+ * method throws an {@link IllegalArgumentException} with a message of the form
+ * "<cite>Property ‘{@code key}’ does not accept instances of ‘{@code value.class}’.</cite>".
+ *
+ * <p>This is a helper method for processing a {@code Map} argument containing property values of various
+ * kinds, as in the {@link org.apache.sis.referencing.AbstractIdentifiedObject#AbstractIdentifiedObject(Map)
+ * AbstractIdentifiedObject} constructor.</p>
+ *
+ * @param <T> The compile-time value of the {@code type} argument.
+ * @param properties The map of properties from which to get a value, or {@code null} if none.
+ * @param key The key of the property value to return. Can be {@code null} if the map supports null key.
+ * @param type The expected type of the property value. Can not be null.
+ * @return The property value for the given key casted to the given type, or {@code null} if none.
+ * @throws IllegalArgumentException If a non-null property value exists for the given key but can
+ * not be casted to the given type.
+ *
+ * @see ArgumentChecks#ensureCanCast(String, Class, Object)
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T property(final Map<?,?> properties, final Object key, final Class<T> type)
+ throws IllegalArgumentException
+ {
+ if (properties == null) {
+ return null;
+ }
+ final Object value = properties.get(key);
+ if (value != null && !type.isInstance(value)) {
+ throw new IllegalArgumentException(Errors.format(Errors.Keys.IllegalPropertyClass_2, key, value.getClass()));
+ }
+ return (T) value;
+ }
+
+ /**
* Returns the capacity to be given to the {@link java.util.HashMap#HashMap(int) HashMap}
* constructor for holding the given number of elements. This method computes the capacity
* for the default <cite>load factor</cite>, which is 0.75.
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultInternationalString.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultInternationalString.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultInternationalString.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultInternationalString.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -26,11 +26,15 @@ import java.util.LinkedHashMap;
import java.util.Collections;
import java.util.Iterator;
import java.util.Locale;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
import org.opengis.util.InternationalString;
import org.apache.sis.util.Locales;
import org.apache.sis.util.ThreadSafe;
import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Messages;
import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
@@ -49,6 +53,8 @@ import org.apache.sis.internal.jdk7.Obje
* @since 0.3 (derived from geotk-2.1)
* @version 0.3
* @module
+ *
+ * @see Types#toInternationalString(Map, String)
*/
@ThreadSafe
public class DefaultInternationalString extends AbstractInternationalString implements Serializable {
@@ -98,6 +104,8 @@ public class DefaultInternationalString
* will not be reflected into this international string.
*
* @param strings The strings in various locales, or {@code null} if none.
+ *
+ * @see Types#toInternationalString(Map, String)
*/
public DefaultInternationalString(final Map<Locale,String> strings) {
if (isNullOrEmpty(strings)) {
@@ -124,8 +132,7 @@ public class DefaultInternationalString
*
* @param locale The locale for the {@code string} value.
* @param string The localized string.
- * @throws IllegalArgumentException if a different string value was already set for
- * the given locale.
+ * @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 {
ArgumentChecks.ensureNonNull("locale", locale);
@@ -157,6 +164,32 @@ public class DefaultInternationalString
}
/**
+ * Adds the given character sequence. If the given sequence is an other {@link InternationalString} instance,
+ * then only the string for the given locale is added. This method is for {@link Types} internal usage only.
+ *
+ * @param locale The locale for the {@code string} value.
+ * @param string The character sequence to add.
+ * @throws IllegalArgumentException if a different string value was already set for the given locale.
+ */
+ final void add(final Locale locale, final CharSequence string) throws IllegalArgumentException {
+ final boolean i18n = (string instanceof InternationalString);
+ add(locale, i18n ? ((InternationalString) string).toString(locale) : string.toString());
+ if (i18n && !(string instanceof SimpleInternationalString)) {
+ /*
+ * If the string may have more than one locale, log a warning telling that some locales
+ * may have been ignored. We declare Types.toInternationalString(…) as the source since
+ * it is the public facade invoking this method. We declare the source class using only
+ * its name rather than Types.class in order to avoid unnecessary real dependency.
+ */
+ final LogRecord record = Messages.getResources(null).getLogRecord(Level.WARNING, Messages.Keys.LocalesDiscarded);
+ record.setSourceClassName("org.apache.sis.util.iso.Types");
+ record.setSourceMethodName("toInternationalString");
+ record.setLoggerName("org.apache.sis.util.iso");
+ Logging.getLogger("org.apache.sis.util.iso").log(record);
+ }
+ }
+
+ /**
* Returns the set of locales defined in this international string.
*
* @return The set of locales.
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameFactory.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameFactory.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameFactory.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/DefaultNameFactory.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -221,10 +221,10 @@ public class DefaultNameFactory extends
* array is 1, or an instance of {@link DefaultScopedName} if the length of the array is 2
* or more.
*
- * @param scope The {@linkplain AbstractName#scope() scope} of the generic name to
- * be created, or {@code null} for a global namespace.
- * @param parsedNames The local names as an array of {@link String} or {@link InternationalString}
- * instances. This array shall contains at least one element.
+ * @param scope The {@linkplain AbstractName#scope() scope} of the generic name to be created,
+ * or {@code null} for a global namespace.
+ * @param parsedNames The local names as an array of {@link String} or {@link InternationalString} instances.
+ * This array shall contain at least one element.
* @return The generic name for the given parsed names.
* @throws NullArgumentException If the given array is empty.
*/
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/Types.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/Types.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/Types.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/iso/Types.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -18,6 +18,7 @@ package org.apache.sis.util.iso;
import java.util.Map;
import java.util.HashMap;
+import java.util.SortedMap;
import java.util.Collection;
import java.util.Locale;
import java.util.Properties;
@@ -35,7 +36,9 @@ import org.opengis.util.GenericName;
import org.opengis.util.InternationalString;
import org.opengis.metadata.Identifier;
import org.apache.sis.util.Static;
+import org.apache.sis.util.Locales;
import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.collection.BackingStoreException;
@@ -59,7 +62,7 @@ import org.apache.sis.internal.system.De
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @since 0.3 (derived from geotk-3.19)
- * @version 0.3
+ * @version 0.4
* @module
*/
public final class Types extends Static {
@@ -552,6 +555,102 @@ public final class Types extends Static
}
/**
+ * Returns an international strings for the values in the given properties map, or {@code null} if none.
+ * If the given map is {@code null}, then this method returns {@code null}.
+ * Otherwise this method iterates over the entries having a key that starts with the specified prefix.
+ * For each such key:
+ *
+ * <ul>
+ * <li>The part after the prefix is parsed as specified by the {@link Locales#parseSuffix(String, String)}
+ * method.</li>
+ * <li>If {@code parseSuffix(…)} returned a non-null locale, then the value for that locale is added in the
+ * international string to be returned.</li>
+ * </ul>
+ *
+ * For example the given map may contains a {@code "remarks"} property defined by values associated to the
+ * {@code "remarks_en"} and {@code "remarks_fr"} keys, for English and French locales respectively.
+ *
+ * @param properties The map from which to get the string values for an international string, or {@code null}.
+ * @param prefix The prefix of keys to use for creating the international string.
+ * @return The international string, or {@code null} if the given map is null or does not contain values
+ * associated to keys starting with the given prefix.
+ * @throws IllegalArgumentException If a key starts by the given prefix and:
+ * <ul>
+ * <li>The key suffix is an illegal {@link Locale} code,</li>
+ * <li>or the value associated to that key is a not a {@link CharSequence}.</li>
+ * </ul>
+ *
+ * @see Locales#parseSuffix(String, String)
+ * @see DefaultInternationalString#DefaultInternationalString(Map)
+ *
+ * @since 0.4
+ */
+ public static InternationalString toInternationalString(Map<String,?> properties, final String prefix)
+ throws IllegalArgumentException
+ {
+ ArgumentChecks.ensureNonEmpty("prefix", prefix);
+ if (properties == null) {
+ return null;
+ }
+ /*
+ * If the given map is an instance of SortedMap using the natural ordering of keys,
+ * we can skip all keys that lexicographically precedes the given prefix.
+ */
+ boolean isSorted = false;
+ if (properties instanceof SortedMap<?,?>) {
+ final SortedMap<String,?> sorted = (SortedMap<String,?>) properties;
+ if (sorted.comparator() == null) { // We want natural ordering.
+ properties = sorted.tailMap(prefix);
+ isSorted = true;
+ }
+ }
+ /*
+ * Now iterates over the map entry and lazily create the InternationalString
+ * only when first needed. In most cases, we have 0 or 1 matching entry.
+ */
+ CharSequence i18n = null;
+ Locale firstLocale = null;
+ DefaultInternationalString dis = null;
+ final int length = prefix.length();
+ for (final Map.Entry<String,?> entry : properties.entrySet()) {
+ final String key = entry.getKey();
+ final Locale locale = Locales.parseSuffix(prefix, key);
+ if (locale == null) {
+ if (isSorted) {
+ /*
+ * If the map is sorted using natural ordering, we can stop as soon as we find a key which
+ * is lexicographically greater than prefix + '_'. We check 'startsWith' last since the other
+ * tests are cheaper and usually sufficient.
+ */
+ if (key.length() <= length || key.charAt(length) > '_' || !key.startsWith(prefix)) {
+ break;
+ }
+ }
+ } else {
+ final Object value = entry.getValue();
+ if (value != null) {
+ if (!(value instanceof CharSequence)) {
+ throw new IllegalArgumentException(Errors.format(
+ Errors.Keys.IllegalPropertyClass_2, key, value.getClass()));
+ }
+ if (i18n == null) {
+ i18n = (CharSequence) value;
+ firstLocale = locale;
+ } else {
+ if (dis == null) {
+ dis = new DefaultInternationalString();
+ dis.add(firstLocale, i18n);
+ i18n = dis;
+ }
+ dis.add(locale, (CharSequence) value);
+ }
+ }
+ }
+ }
+ return toInternationalString(i18n);
+ }
+
+ /**
* 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
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -74,6 +74,11 @@ public final class Errors extends Indexe
public static final int CanNotComputeDerivative = 44;
/**
+ * Can not connect to “{0}”.
+ */
+ public static final int CanNotConnectTo_1 = 114;
+
+ /**
* Can not convert from type ‘{0}’ to type ‘{1}’.
*/
public static final int CanNotConvertFromType_2 = 72;
@@ -149,7 +154,7 @@ public final class Errors extends Indexe
public static final int EmptyArgument_1 = 1;
/**
- * The dictionary shall contains at least one entry.
+ * The dictionary shall contain at least one entry.
*/
public static final int EmptyDictionary = 54;
@@ -241,7 +246,7 @@ public final class Errors extends Indexe
public static final int IllegalOrdinateRange_3 = 5;
/**
- * Property ‘{0}’ can be associated to an instance of ‘{1}’.
+ * Property ‘{0}’ does not accept instances of ‘{1}’.
*/
public static final int IllegalPropertyClass_2 = 62;
@@ -541,6 +546,11 @@ public final class Errors extends Indexe
public static final int UnknownCommand_1 = 102;
/**
+ * Unknown enumeration value: {0}.
+ */
+ public static final int UnknownEnumValue_1 = 115;
+
+ /**
* Format of “{0}” is not recognized.
*/
public static final int UnknownFormatFor_1 = 107;
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Fri Aug 30 21:00:40 2013
@@ -25,6 +25,7 @@
# can reorder the parameters as they want.
#
CanNotAddToExclusiveSet_2 = No element can be added to this set because properties \u2018{0}\u2019 and \u2018{1}\u2019 are mutually exclusive.
+CanNotConnectTo_1 = Can not connect to \u201c{0}\u201d.
CanNotConvertFromType_2 = Can not convert from type \u2018{0}\u2019 to type \u2018{1}\u2019.
CanNotConvertValue_2 = Can not convert value \u201c{0}\u201d to type \u2018{1}\u2019.
CanNotComputeDerivative = Can not compute the derivative.
@@ -41,7 +42,7 @@ DuplicatedOption_1 = Option
DuplicatedIdentifier_1 = Identifier \u201c{0}\u201d is duplicated.
ElementAlreadyPresent_1 = Element \u201c{0}\u201d is already present.
EmptyArgument_1 = Argument \u2018{0}\u2019 shall not be empty.
-EmptyDictionary = The dictionary shall contains at least one entry.
+EmptyDictionary = The dictionary shall contain at least one entry.
EmptyEnvelope2D = Envelope must be at least two-dimensional and non-empty.
EmptyProperty_1 = Property named \u201c{0}\u201d shall not be empty.
ExcessiveArgumentSize_3 = Argument \u2018{0}\u2019 shall not contain more than {1} elements. A number of {2} is excessive.
@@ -58,7 +59,7 @@ IllegalFormatPatternForClass_2 = The \u
IllegalLanguageCode_1 = The \u201c{0}\u201d language is not recognized.
IllegalMemberType_2 = Member \u201c{0}\u201d can not be associated to type \u201c{1}\u201d.
IllegalOrdinateRange_3 = The [{0} \u2026 {1}] range of ordinate values is not valid for the \u201c{2}\u201d axis.
-IllegalPropertyClass_2 = Property \u2018{0}\u2019 can be associated to an instance of \u2018{1}\u2019.
+IllegalPropertyClass_2 = Property \u2018{0}\u2019 does not accept instances of \u2018{1}\u2019.
IllegalRange_2 = Range [{0} \u2026 {1}] is not valid.
IllegalUnicodeCodePoint_2 = Value {1} for \u201c{0}\u201d is not a valid Unicode code point.
IncompatiblePropertyValue_1 = Property \u201c{0}\u201d has an incompatible value.
@@ -120,6 +121,7 @@ UnexpectedEndOfFile_1 = Unexpe
UnexpectedEndOfString_1 = More characters were expected at the end of \u201c{0}\u201d.
UnexpectedFileFormat_2 = File \u201c{1}\u201d seems to be encoded in an other format than {0}.
UnknownCommand_1 = Command \u201c{0}\u201d is not recognized.
+UnknownEnumValue_1 = Unknown enumeration value: {0}.
UnknownFormatFor_1 = Format of \u201c{0}\u201d is not recognized.
UnknownOption_1 = Option \u201c{0}\u201d is not recognized.
UnknownType_1 = Type \u2018{0}\u2019 is unknown in this context.
Modified: sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] (original)
+++ sis/trunk/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] Fri Aug 30 21:00:40 2013
@@ -15,6 +15,7 @@
# limitations under the License.
#
CanNotAddToExclusiveSet_2 = Aucun \u00e9l\u00e9ment ne peut \u00eatre ajout\u00e9 \u00e0 cet ensemble car les propri\u00e9t\u00e9s \u2018{0}\u2019 et \u2018{1}\u2019 sont mutuellement exclusives.
+CanNotConnectTo_1 = Ne peut pas se connecter \u00e0 \u201c{0}\u201d.
CanNotConvertFromType_2 = Ne peut pas convertir du type \u2018{0}\u2019 vers le type \u2018{1}\u2019.
CanNotConvertValue_2 = La valeur \u201c{0}\u201d ne peut pas \u00eatre convertie vers le type \u2018{1}\u2019.
CanNotComputeDerivative = La d\u00e9riv\u00e9 ne peut pas \u00eatre calcul\u00e9e.
@@ -48,7 +49,7 @@ IllegalFormatPatternForClass_2 = Le mod
IllegalLanguageCode_1 = Le code de langue \u201c{0}\u201d n\u2019est pas reconnu.
IllegalMemberType_2 = Le membre \u201c{0}\u201d ne peut pas \u00eatre associ\u00e9 au type \u201c{1}\u201d.
IllegalOrdinateRange_3 = La plage de valeurs de coordonn\u00e9es [{1} \u2026 {2}] n\u2019est pas valide pour l\u2019axe \u201c{0}\u201d.
-IllegalPropertyClass_2 = La propri\u00e9t\u00e9 \u2018{0}\u2019 ne peut pas \u00eatre associ\u00e9e \u00e0 une valeur de type \u2018{1}\u2019.
+IllegalPropertyClass_2 = La propri\u00e9t\u00e9 \u2018{0}\u2019 n\u2019accepte pas les valeurs de type \u2018{1}\u2019.
IllegalRange_2 = La plage [{0} \u2026 {1}] n\u2019est pas valide.
IllegalUnicodeCodePoint_2 = La valeur {1} de \u201c{0}\u201d n\u2019est pas un code Unicode valide.
IncompatiblePropertyValue_1 = La valeur de la propri\u00e9t\u00e9 \u201c{0}\u201d n\u2019est pas compatible.
@@ -109,6 +110,7 @@ UnexpectedEndOfFile_1 = Fin de
UnexpectedEndOfString_1 = D\u2019autres caract\u00e8res \u00e9taient attendus \u00e0 la fin du texte \u201c{0}\u201d.
UnexpectedFileFormat_2 = Le fichier \u201c{1}\u201d semble \u00eatre encod\u00e9 dans un autre format que {0}.
UnknownCommand_1 = La commande \u201c{0}\u201d n\u2019est pas reconnue.
+UnknownEnumValue_1 = Valeur d\u2019\u00e9num\u00e9ration inconnue: {0}.
UnknownFormatFor_1 = Le format de \u201c{0}\u201d n\u2019est pas reconnu.
UnknownOption_1 = L\u2019option \u201c{0}\u201d n\u2019est pas reconnue.
UnknownType_1 = Le type \u2018{0}\u2019 n\u2019est pas reconnu dans ce contexte.
Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/converter/FallbackConverterTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/converter/FallbackConverterTest.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/converter/FallbackConverterTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/internal/converter/FallbackConverterTest.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -60,7 +60,8 @@ public final strictfp class FallbackConv
final EnumSet<FunctionProperty> SURJECTIVE = EnumSet.of(FunctionProperty.SURJECTIVE);
final EnumSet<FunctionProperty> INVERTIBLE = EnumSet.of(FunctionProperty.SURJECTIVE, FunctionProperty.INVERTIBLE);
- ObjectConverter<String,? extends Object> c = new StringConverter.Short();
+ // The "extends Object" part is unnecessary according Java specification, but Eclipse compiler insists for it.
+ ObjectConverter<String, ? extends Object> c = new StringConverter.Short();
assertEquals(String.class, c.getSourceClass());
assertEquals(Short.class, c.getTargetClass());
assertEquals(INVERTIBLE, c.properties());
Modified: sis/trunk/core/sis-utility/src/test/java/org/apache/sis/util/iso/TypesTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-utility/src/test/java/org/apache/sis/util/iso/TypesTest.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/core/sis-utility/src/test/java/org/apache/sis/util/iso/TypesTest.java [UTF-8] (original)
+++ sis/trunk/core/sis-utility/src/test/java/org/apache/sis/util/iso/TypesTest.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -17,8 +17,11 @@
package org.apache.sis.util.iso;
import java.util.Set;
+import java.util.Map;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.HashMap;
+import java.util.TreeMap;
import java.util.Locale;
import org.opengis.util.InternationalString;
import org.opengis.metadata.citation.Address;
@@ -31,7 +34,7 @@ import org.opengis.referencing.cs.AxisDi
import org.apache.sis.test.TestCase;
import org.junit.Test;
-import static org.junit.Assert.*;
+import static org.opengis.test.Assert.*;
/**
@@ -39,11 +42,49 @@ import static org.junit.Assert.*;
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @since 0.3 (derived from geotk-2.1)
- * @version 0.3
+ * @version 0.4
* @module
*/
public final strictfp class TypesTest extends TestCase {
/**
+ * Tests the {@link Types#toInternationalString(Map, String)} method.
+ */
+ @Test
+ public void testToInternationalString() {
+ testToInternationalString(new HashMap<String,Object>());
+ testToInternationalString(new TreeMap<String,Object>());
+ }
+
+ /**
+ * Implementation of {@link #testToInternationalString()} using the given map implementation.
+ */
+ private static void testToInternationalString(final Map<String,Object> properties) {
+ assertNull(properties.put("name", "Some name"));
+ assertNull(properties.put("identifier", "Some identifier"));
+ assertNull(properties.put("code", "Some code"));
+ assertNull(properties.put("codeSpace", "Some code space"));
+ assertNull(properties.put("authority", "Some authority"));
+ assertNull(properties.put("version", "Some version"));
+ assertNull(properties.put("remarks", "Some remarks"));
+ assertNull(Types.toInternationalString(properties, "dummy"));
+
+ InternationalString i18n = Types.toInternationalString(properties, "remarks");
+ assertInstanceOf("Single locale", SimpleInternationalString.class, i18n);
+ assertEquals("Some remarks", i18n.toString());
+
+ assertNull(properties.put("remarks_fr", "Une remarque"));
+ i18n = Types.toInternationalString(properties, "remarks");
+ assertInstanceOf("Two locales", DefaultInternationalString.class, i18n);
+ assertEquals("Some remarks", i18n.toString(Locale.ROOT));
+ assertEquals("Une remarque", i18n.toString(Locale.FRENCH));
+
+ assertNotNull(properties.remove("remarks"));
+ i18n = Types.toInternationalString(properties, "remarks");
+ assertInstanceOf("Single locale", SimpleInternationalString.class, i18n);
+ assertEquals("Une remarque", i18n.toString());
+ }
+
+ /**
* Tests the {@link Types#getStandardName(Class)} method.
*/
@Test
Modified: sis/trunk/pom.xml
URL: http://svn.apache.org/viewvc/sis/trunk/pom.xml?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/pom.xml (original)
+++ sis/trunk/pom.xml Fri Aug 30 21:00:40 2013
@@ -733,6 +733,14 @@ Apache SIS is a free software, Java lang
</pluginRepository>
</pluginRepositories>
+ <repositories>
+ <!-- UCAR repository from which to download the NetCDF library. -->
+ <repository>
+ <id>UCAR</id>
+ <name>UCAR repository</name>
+ <url>https://artifacts.unidata.ucar.edu/content/repositories/unidata-releases</url>
+ </repository>
+ </repositories>
<!-- ==============================================================
Modified: sis/trunk/storage/sis-netcdf/pom.xml
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-netcdf/pom.xml?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/storage/sis-netcdf/pom.xml (original)
+++ sis/trunk/storage/sis-netcdf/pom.xml Fri Aug 30 21:00:40 2013
@@ -125,13 +125,4 @@ Bridge between NetCDF Climate and Foreca
</dependency>
</dependencies>
- <!-- UCAR repository from which to download the NetCDF library. -->
- <repositories>
- <repository>
- <id>UCAR</id>
- <name>UCAR repository</name>
- <url>https://artifacts.unidata.ucar.edu/content/repositories/unidata-releases</url>
- </repository>
- </repositories>
-
</project>
Modified: sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java [UTF-8] (original)
+++ sis/trunk/storage/sis-netcdf/src/main/java/org/apache/sis/storage/netcdf/NetcdfStoreProvider.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -16,6 +16,7 @@
*/
package org.apache.sis.storage.netcdf;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.lang.reflect.Method;
@@ -34,6 +35,7 @@ import org.apache.sis.storage.StorageCon
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.ProbeResult;
import org.apache.sis.util.logging.WarningListeners;
+import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.ThreadSafe;
import org.apache.sis.util.Version;
@@ -139,6 +141,9 @@ public class NetcdfStoreProvider extends
* The UCAR library is an optional dependency. If that library is present and the
* input is a String, then the following code may trigs a large amount of classes
* loading.
+ *
+ * Note that the UCAR library expects a String argument, not a File, because it
+ * has special cases for "file:", "http:", "nodods:" and "slurp:" protocols.
*/
if (!isSupported) {
final String path = storage.getStorageAs(String.class);
@@ -155,6 +160,16 @@ public class NetcdfStoreProvider extends
if (cause instanceof DataStoreException) throw (DataStoreException) cause;
if (cause instanceof RuntimeException) throw (RuntimeException) cause;
if (cause instanceof Error) throw (Error) cause;
+ if (cause instanceof FileNotFoundException) {
+ /*
+ * Happen if the String argument uses any protocol not recognized by the UCAR library,
+ * in which case UCAR tries to open it as a file even if it is not a file. For example
+ * we get this exception for "jar:file:/file.jar!/entry.nc".
+ */
+ Logging.recoverableException(
+ Logging.getLogger("org.apache.sis.storage"), netcdfFileClass, "canOpen", cause);
+ return ProbeResult.UNSUPPORTED_STORAGE;
+ }
throw new DataStoreException(e); // The cause may be IOException.
}
} else {
Modified: sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java [UTF-8] (original)
+++ sis/trunk/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/IOUtilities.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -112,7 +112,8 @@ public final class IOUtilities extends S
if (path instanceof URL) {
name = ((URL) path).getPath();
} else if (path instanceof URI) {
- name = ((URI) path).getPath();
+ final URI uri = (URI) path;
+ name = uri.isOpaque() ? uri.getSchemeSpecificPart() : uri.getPath();
} else if (path instanceof CharSequence) {
name = path.toString();
separator = File.separatorChar;
Modified: sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/IOUtilitiesTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/IOUtilitiesTest.java?rev=1519087&r1=1519086&r2=1519087&view=diff
==============================================================================
--- sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/IOUtilitiesTest.java [UTF-8] (original)
+++ sis/trunk/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/IOUtilitiesTest.java [UTF-8] Fri Aug 30 21:00:40 2013
@@ -35,7 +35,7 @@ import static org.junit.Assert.*;
* @author Martin Desruisseaux (Geomatys)
* @author Johann Sorel (Geomatys)
* @since 0.3 (derived from geotk-3.00)
- * @version 0.3
+ * @version 0.4
* @module
*/
public final strictfp class IOUtilitiesTest extends TestCase {
@@ -75,6 +75,26 @@ public final strictfp class IOUtilitiesT
}
/**
+ * Tests again {@link IOUtilities#filename(Object)} and {@link IOUtilities#extension(Object)}, but with a URI
+ * that point to a JAR entry. Such URI are opaque, in which case {@link URI#getPath()} returns {@code null}.
+ *
+ * @throws URISyntaxException Should never happen.
+ * @throws MalformedURLException Should never happen.
+ */
+ @Test
+ @DependsOnMethod({"testFilename", "testExtension"})
+ public void testWithOpaqueURI() throws URISyntaxException, MalformedURLException {
+ final URI uri = new URI("jar:file:/sis-storage-tests.jar!/org/apache/sis/Any.xml");
+ assertTrue(uri.isOpaque()); // This test would be useless if this condition is false.
+ assertEquals("Any.xml", IOUtilities.filename (uri));
+ assertEquals( "xml", IOUtilities.extension(uri));
+
+ final URL url = new URL("jar:file:/sis-storage-tests.jar!/org/apache/sis/Any.xml");
+ assertEquals("Any.xml", IOUtilities.filename (url));
+ assertEquals( "xml", IOUtilities.extension(url));
+ }
+
+ /**
* Tests {@link IOUtilities#toString(Object)}.
*
* @throws URISyntaxException Should never happen.