Package org.apache.sis.internal.metadata

Source Code of org.apache.sis.internal.metadata.ReferencingUtilities

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.sis.internal.metadata;

import java.util.Collection;
import javax.measure.unit.Unit;
import org.opengis.annotation.UML;
import org.opengis.annotation.Specification;
import org.opengis.parameter.*;
import org.opengis.referencing.*;
import org.opengis.referencing.cs.*;
import org.opengis.referencing.crs.*;
import org.opengis.referencing.datum.*;
import org.opengis.referencing.operation.*;
import org.apache.sis.util.Static;


/**
* A set of static methods working on GeoAPI referencing objects.
* Some of those methods may be useful, but not really rigorous.
* This is why they do not appear in the public packages.
*
* <p><strong>Do not rely on this API!</strong> It may change in incompatible way in any future release.</p>
*
* @author  Martin Desruisseaux (IRD, Geomatys)
* @since   0.4 (derived from geotk-2.0)
* @version 0.4
* @module
*/
public final class ReferencingUtilities extends Static {
    /**
     * Subtypes of {@link IdentifiedObject} for which a URN type is defined.
     * For each interface at index <var>i</var>, the URN type is {@code URN_TYPES[i]}.
     *
     * <p>For performance reasons, most frequently used types should be first.</p>
     */
    private static final Class<?>[] TYPES = {
        CoordinateReferenceSystem.class,
        Datum.class,
        Ellipsoid.class,
        PrimeMeridian.class,
        CoordinateSystem.class,
        CoordinateSystemAxis.class,
        CoordinateOperation.class,
        OperationMethod.class,
        ParameterDescriptor.class,
        ReferenceSystem.class
    };

    /**
     * The URN types for instances of {@link #TYPES}.
     * See {@link org.apache.sis.internal.util.DefinitionURI} javadoc for a list of URN types.
     */
    private static final String[] URN_TYPES = {
        "crs",
        "datum",
        "ellipsoid",
        "meridian",
        "cs",
        "axis",
        "coordinateOperation",
        "method",
        "parameter",
        "referenceSystem"
    };

    /**
     * Do not allow instantiation of this class.
     */
    private ReferencingUtilities() {
    }

    /**
     * Returns {@code true} if codes in the given code space are often represented using the URN syntax.
     * Current implementation conservatively returns {@code true} only for {@code "EPSG"}.
     * The list of accepted code spaces may be expanded in any future SIS version.
     *
     * @param  codeSpace The code space (can be {@code null}).
     * @return {@code true} if the given code space is known to use the URN syntax.
     */
    public static boolean usesURN(final String codeSpace) {
        return (codeSpace != null) && codeSpace.equalsIgnoreCase("EPSG");
    }

    /**
     * Returns the URN type for the given class, or {@code null} if unknown.
     * See {@link org.apache.sis.internal.util.DefinitionURI} javadoc for a list of URN types.
     *
     * @param  type The class for which to get the URN type.
     * @return The URN type, or {@code null} if unknown.
     *
     * @see org.apache.sis.internal.util.DefinitionURI
     */
    public static String toURNType(final Class<?> type) {
        for (int i=0; i<TYPES.length; i++) {
            if (TYPES[i].isAssignableFrom(type)) {
                return URN_TYPES[i];
            }
        }
        return null;
    }

    /**
     * Returns the WKT type of the given interface.
     *
     * For {@link CoordinateSystem} base type, the returned value shall be one of
     * {@code affine}, {@code Cartesian}, {@code cylindrical}, {@code ellipsoidal}, {@code linear},
     * {@code parametric}, {@code polar}, {@code spherical}, {@code temporal} or {@code vertical}.
     *
     * @param  base The abstract base interface.
     * @param  type The interface or classes for which to get the WKT type.
     * @return The WKT type for the given class or interface, or {@code null} if none.
     */
    public static String toWKTType(final Class<?> base, final Class<?> type) {
        if (type != base) {
            final UML uml = type.getAnnotation(UML.class);
            if (uml != null && uml.specification() == Specification.ISO_19111) {
                String name = uml.identifier();
                final int length = name.length() - 5; // Length without "CS_" and "CS".
                if (length >= 1 && name.startsWith("CS_") && name.endsWith("CS")) {
                    final StringBuilder buffer = new StringBuilder(length).append(name, 3, 3 + length);
                    if (!name.regionMatches(3, "Cartesian", 0, 9)) {
                        buffer.setCharAt(0, Character.toLowerCase(buffer.charAt(0)));
                    }
                    name = buffer.toString();
                    if (name.equals("time")) {
                        name = "temporal";
                    }
                    return name;
                }
            }
            for (final Class<?> c : type.getInterfaces()) {
                if (base.isAssignableFrom(c)) {
                    final String name = toWKTType(base, c);
                    if (name != null) {
                        return name;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Returns the unit used for all axes in the given coordinate system.
     * If not all axes use the same unit, then this method returns {@code null}.
     *
     * <p>This method is used either when the coordinate system is expected to contain exactly one axis,
     * or for operations that support only one units for all axes, for example Well Know Text version 1
     * (WKT 1) formatting.</p>
     *
     * @param cs The coordinate system for which to get the unit, or {@code null}.
     * @return The unit for all axis in the given coordinate system, or {@code null}.
     */
    public static Unit<?> getUnit(final CoordinateSystem cs) {
        Unit<?> unit = null;
        if (cs != null) {
            for (int i=cs.getDimension(); --i>=0;) {
                final CoordinateSystemAxis axis = cs.getAxis(i);
                if (axis != null) { // Paranoiac check.
                    final Unit<?> candidate = axis.getUnit();
                    if (candidate != null) {
                        if (unit == null) {
                            unit = candidate;
                        } else if (!unit.equals(candidate)) {
                            return null;
                        }
                    }
                }
            }
        }
        return unit;
    }

    /**
     * Copies all {@link SingleCRS} components from the given source to the given collection.
     * For each {@link CompoundCRS} element found in the iteration, this method replaces the
     * {@code CompoundCRS} by its {@linkplain CompoundCRS#getComponents() components}, which
     * may themselves have other {@code CompoundCRS}. Those replacements are performed recursively
     * until we obtain a flat view of CRS components.
     *
     * @param  source The collection of single or compound CRS.
     * @param  addTo  Where to add the single CRS in order to obtain a flat view of {@code source}.
     * @return {@code true} if this method found only single CRS in {@code source}, in which case {@code addTo}
     *         got the same content (assuming that {@code addTo} was empty prior this method call).
     * @throws ClassCastException if a CRS is neither a {@link SingleCRS} or a {@link CompoundCRS}.
     *
     * @see org.apache.sis.referencing.CRS#getSingleComponents(CoordinateReferenceSystem)
     */
    public static boolean getSingleComponents(final Iterable<? extends CoordinateReferenceSystem> source,
            final Collection<? super SingleCRS> addTo) throws ClassCastException
    {
        boolean sameContent = true;
        for (final CoordinateReferenceSystem candidate : source) {
            if (candidate instanceof CompoundCRS) {
                getSingleComponents(((CompoundCRS) candidate).getComponents(), addTo);
                sameContent = false;
            } else {
                // Intentional CassCastException here if the candidate is not a SingleCRS.
                addTo.add((SingleCRS) candidate);
            }
        }
        return sameContent;
    }
}
TOP

Related Classes of org.apache.sis.internal.metadata.ReferencingUtilities

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.