All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.geotoolkit.naming.DefaultNameFactory Maven / Gradle / Ivy

Go to download

Implementations of metadata derived from ISO 19115. This module provides both an implementation of the metadata interfaces defined in GeoAPI, and a framework for handling those metadata through Java reflection.

There is a newer version: 3.20-geoapi-3.0
Show newest version
/*
 *    Geotoolkit.org - An Open Source Java GIS Toolkit
 *    http://www.geotoolkit.org
 *
 *    (C) 2004-2011, Open Source Geospatial Foundation (OSGeo)
 *    (C) 2009-2011, Geomatys
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation;
 *    version 2.1 of the License.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 */
package org.geotoolkit.naming;

import java.util.Map;
import java.util.List;
import java.util.Arrays;
import java.util.Locale;
import java.util.ArrayList;
import java.util.Collection;
import net.jcip.annotations.ThreadSafe;

import org.opengis.util.TypeName;
import org.opengis.util.NameSpace;
import org.opengis.util.LocalName;
import org.opengis.util.MemberName;
import org.opengis.util.GenericName;
import org.opengis.util.NameFactory;
import org.opengis.util.InternationalString;
import org.opengis.metadata.Identifier;

import org.geotoolkit.factory.Factory;
import org.geotoolkit.resources.Errors;
import org.geotoolkit.util.NullArgumentException;
import org.geotoolkit.util.SimpleInternationalString;
import org.geotoolkit.util.DefaultInternationalString;
import static org.geotoolkit.util.ArgumentChecks.ensureNonNull;
import static org.geotoolkit.naming.DefaultNameSpace.DEFAULT_SEPARATOR_STRING;


/**
 * A factory for {@link AbstractName} objects.
 *
 * @author Martin Desruisseaux (Geomatys)
 * @version 3.17
 *
 * @see org.geotoolkit.factory.FactoryFinder#getNameFactory
 *
 * @since 2.1
 * @module
 */
@ThreadSafe
public class DefaultNameFactory extends Factory implements NameFactory {
    /**
     * Creates a new factory. Users should not invoke this constructor directly.
     * Use {@link org.geotoolkit.factory.FactoryFinder#getNameFactory} instead.
     */
    public DefaultNameFactory() {
    }

    /**
     * Creates an international string from a set of strings in different locales.
     */
    @Override
    public InternationalString createInternationalString(final Map strings) {
        ensureNonNull("strings", strings);
        switch (strings.size()) {
            case 0:  throw new IllegalArgumentException(Errors.format(Errors.Keys.EMPTY_DICTIONARY));
            case 1:  return new SimpleInternationalString(strings.values().iterator().next());
            default: return new DefaultInternationalString(strings);
        }
    }

    /**
     * Returns the value for the given key in the given properties map, or {@code null} if none.
     */
    private static String getString(final Map properties, final String key) {
        if (properties != null) {
            final Object value = properties.get(key);
            if (value != null) {
                return value.toString();
            }
        }
        return null;
    }

    /**
     * Creates a namespace having the given name. Despite the "create" name, this method tries
     * to returns an existing instance when possible.
     *
     * @param name
     *          The name of the namespace to be returned. This argument can be created using
     *          {@linkplain #createGenericName createGenericName}(null, parsedNames).
     * @param properties
     *          An optional map of properties to be assigned to the namespace. Recognized entries
     *          are:
     * 
     *   
     *     
     *     
     *   
     *   
     *     
     *     
     *   
     *   
     *     
     *     
     *   
     * 
Property namePurpose
 {@code "separator"}  The separator to insert between {@linkplain GenericName#getParsedNames * parsed names} in that namespace. For HTTP namespace, it is {@code "."}. For URN namespace, * it is typically {@code ":"}.
 {@code "separator.head"}  The separator to insert between the namespace and the * {@linkplain GenericName#head head}. For HTTP namespace, it is {@code "://"}. * For URN namespace, it is typically {@code ":"}. If this entry is omitted, then * the default is the same value than the {@code "separator"} entry.
* * @return A namespace having the given name and separator. * * @since 3.01 */ @Override public NameSpace createNameSpace(final GenericName name, final Map properties) { ensureNonNull("name", name); String separator = getString(properties, "separator"); if (separator == null) { separator = DefaultNameSpace.DEFAULT_SEPARATOR_STRING; } String headSeparator = getString(properties, "separator.head"); if (headSeparator == null) { headSeparator = separator; } final boolean isEmpty = (separator.isEmpty()); if (isEmpty || headSeparator.isEmpty()) { throw new IllegalArgumentException(Errors.format( Errors.Keys.ILLEGAL_ARGUMENT_$1, isEmpty ? "separator" : "separator.head")); } return DefaultNameSpace.forName(name, headSeparator, separator); } /** * Creates a namespace having the given name and using the * {@linkplain DefaultNameSpace#DEFAULT_SEPARATOR default separator}. * * @param name The name of the namespace to be returned. This argument can be created using * {@linkplain #createGenericName createGenericName}(null, parsedNames). * @return A namespace having the given name and separator. * * @since 3.00 */ public NameSpace createNameSpace(final GenericName name) { return createNameSpace(name, null); } /** * Creates a member name from the given character sequence and attribute type. * The default implementation returns a new {@linkplain DefaultMemberName} instance. * * @param scope The {@linkplain GenericName#scope scope} of the type * name to be created, or {@code null} for a global namespace. * @param name The type name as a string or an international string. * @param attributeType The type of the data associated with the record member. * @return The type name for the given character sequence. * @throws NullArgumentException If the {@code name} or {@code attributeType} argument is null. * * @since 3.17 */ public MemberName createMemberName(final NameSpace scope, final CharSequence name, final TypeName attributeType) { return new DefaultMemberName(scope, name, attributeType); } /** * Creates a type name from the given character sequence. The default implementation * returns a new {@linkplain DefaultTypeName} instance. * * @param scope The {@linkplain GenericName#scope scope} of the type * name to be created, or {@code null} for a global namespace. * @param name The type name as a string or an international string. * @return The type name for the given character sequence. * @throws NullArgumentException If the {@code name} argument is null. * * @since 3.04 */ @Override public TypeName createTypeName(final NameSpace scope, final CharSequence name) { return new DefaultTypeName(scope, name); } /** * Creates a local name from the given character sequence. The default implementation * returns a new {@linkplain DefaultLocalName} instance. * * @param scope The {@linkplain GenericName#scope scope} of the local * name to be created, or {@code null} for a global namespace. * @param name The local name as a string or an international string. * @return The local name for the given character sequence. * @throws NullArgumentException If the {@code name} argument is null. * * @since 3.00 */ @Override public LocalName createLocalName(final NameSpace scope, final CharSequence name) { if (scope instanceof DefaultNameSpace) { // Following may return a cached instance. return ((DefaultNameSpace) scope).local(name, null); } return new DefaultLocalName(scope, name); } /** * Creates a local or scoped name from an array of parsed names. The default implementation * returns an instance of {@link DefaultLocalName} if the length of the {@code parsedNames} * 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 {@linkplain String strings} or * {@linkplain InternationalString international strings}. This array must * contains at least one element. * @return The generic name for the given parsed names. * @throws NullArgumentException If the given array is empty. * * @since 3.00 */ @Override public GenericName createGenericName(final NameSpace scope, final CharSequence... parsedNames) { ensureNonNull("parsedNames", parsedNames); switch (parsedNames.length) { default: return new DefaultScopedName(scope, Arrays.asList(parsedNames)); case 1: return createLocalName(scope, parsedNames[0]); // User may override. case 0: throw new IllegalArgumentException(Errors.format(Errors.Keys.EMPTY_ARRAY)); } } /** * Constructs a generic name from a qualified name. This method splits the given name around a * separator inferred from the given scope, or the {@linkplain DefaultNameSpace#DEFAULT_SEPARATOR * default separator} if the given scope is null. * * @param scope The {@linkplain AbstractName#scope scope} of the generic name to * be created, or {@code null} for a global namespace. * @param name The qualified name, as a sequence of names separated by a scope-dependent * separator. * @return A name parsed from the given string. */ @Override public GenericName parseGenericName(final NameSpace scope, final CharSequence name) { final String separator; if (scope instanceof DefaultNameSpace) { separator = ((DefaultNameSpace) scope).separator; } else { separator = DEFAULT_SEPARATOR_STRING; } final int s = separator.length(); final List names = new ArrayList(); int lower = 0; final String string = name.toString(); while (true) { final int upper = string.indexOf(separator, lower); if (upper >= 0) { names.add(string.substring(lower, upper)); lower = upper + s; } else { names.add(string.substring(lower)); break; } } if (names.size() == 1) { // Preserves the InternationalString (current implementation of // the parsing code above has lost the internationalization). return createLocalName(scope, name); } return createGenericName(scope, names.toArray(new String[names.size()])); } /** * Creates a generic name from the given value. The value may be an instance of * {@link GenericName}, {@link Identifier} or {@link CharSequence}. If the given * object is not recognized, then this method returns {@code null}. * * @param value The object to convert. * @return The converted object, or {@code null} if {@code value} is not convertible. */ private GenericName createFromObject(final Object value) { ensureNonNull("value", value); if (value instanceof GenericName) { return (GenericName) value; } if (value instanceof Identifier) { return parseGenericName(null, ((Identifier) value).getCode()); } if (value instanceof CharSequence) { return parseGenericName(null, (CharSequence) value); } return null; } /** * Converts the given value to an array of generic names. If the given value is an instance of * {@link GenericName}, {@link String} or any other type enumerated below, then it is converted * and returned in an array of length 1. If the given value is an array or a collection, then an * array of same length is returned where each element has been converted. Allowed types or * element types are: *

*

    *
  • {@link GenericName}, to be casted and returned as-is.
  • *
  • {@link CharSequence} (usually a {@link String} or an {@link InternationalString}), to * be parsed as a generic name using the {@linkplain DefaultNameSpace#DEFAULT_SEPARATOR * default separator}.
  • *
  • {@link Identifier}, its {@linkplain Identifier#getCode code} to be parsed as a generic * name using the {@linkplain DefaultNameSpace#DEFAULT_SEPARATOR default separator}.
  • *
* * @param value The object to cast into an array of generic names. * @return The generic names. May be a direct reference to {@code value}. * @throws NullArgumentException if {@code value} is null. * @throws ClassCastException if {@code value} can't be casted. */ public GenericName[] toArray(Object value) throws ClassCastException { GenericName name = createFromObject(value); if (name != null) { return new GenericName[] { name }; } /* * Above code checked for a singleton. Now check for a collection or an array. * The "jump" loop is just a trick for jumping to the throw clause in case of * failure. */ jump: while (true) { final Object[] values; if (value instanceof Collection) { values = ((Collection) value).toArray(); } else if (value instanceof Object[]) { values = (Object[]) value; } else { break jump; } if (values instanceof GenericName[]) { return (GenericName[]) values; } final GenericName[] names = new GenericName[values.length]; for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy