/* * Geotoolkit.org - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2010-2012, Open Source Geospatial Foundation (OSGeo) * (C) 2010-2012, 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.internal.referencing; import java.util.Map; import java.util.HashMap; import java.util.Objects; import org.opengis.referencing.crs.SingleCRS; import org.opengis.referencing.datum.GeodeticDatum; import org.opengis.metadata.Identifier; import org.apache.sis.metadata.iso.ImmutableIdentifier; import static org.opengis.referencing.IdentifiedObject.NAME_KEY; /** * Identifier for a 3D CRS built from a 2D horizontal component and a 1D vertical component. This * identifier is created by {@link org.geotoolkit.referencing.factory.ReferencingFactoryContainer} * in order to allow the {@link org.geotoolkit.referencing.operation.AuthorityBackedFactory} class * to find the original 2D component of a monolithic (not a compound) 3D CRS. * <p> * This class is a hack. It exists for the following reasons: * <p> * <ul> * <li>We can not just rebuilt a new 2D CRS from a 3D one, because the EPSG code would be lost. * We need the EPSG code of the 2D component for {@code AuthorityBackedFactory} work.</li> * <li>We can not let the 3D (horizontal + ellipsoidal height) CRS as a {@code ComponentCRS} * because the {@code DefaultCoordinateOperationFactory} processing chain needs to pass * those 3D CRS as monolithic objects. This is because some transformation steps need to * process the three dimensions together; the ellipsoidal height shall never be separated * from the geographical coordinates.</li> * </ul> * <p> * This hack should not be visible in public API, and may change in incompatible way in any future * version. * * @author Martin Desruisseaux (Geomatys) * @version 3.16 * * @see org.geotoolkit.referencing.operation.AuthorityBackedFactory#getHorizontalCRS * * @since 3.16 * @module */ public final class Identifier3D extends ImmutableIdentifier { /** * For cross-version compatibility. */ private static final long serialVersionUID = -1799606724741505296L; /** * The horizontal component of the 3D CRS identified by this object. * It must be a CRS backed by a geodetic datum. */ public final SingleCRS horizontalCRS; /** * Creates a new identifier with the same values than the given identifier, * and store the given horizontal component for information purpose. * * @param identifier The identifier to copy. * @param horizontalCRS The horizontal component of the 3D CRS. */ private Identifier3D(final Identifier identifier, final SingleCRS horizontalCRS) { super(identifier); this.horizontalCRS = horizontalCRS; assert horizontalCRS.getDatum() instanceof GeodeticDatum : horizontalCRS; } /** * Overridden for consistency with {@link #equals(Object)}. */ @Override public int hashCode() { return super.hashCode() + 31 * horizontalCRS.hashCode(); } /** * Compares this object with the given one for equality. This method needs to take * the horizontal CRS in account, because CRS using this identifier may be stored * in {@link org.geotoolkit.util.collection.WeakHashSet}. */ @Override public boolean equals(final Object object) { if (super.equals(object)) { final Identifier3D other = (Identifier3D) object; return Objects.equals(horizontalCRS, other.horizontalCRS); } return false; } /** * Given the properties of a CRS, replaces the value of the {@code "name"} key by an * {@code Identifier3D} instance declaring the given horizontal CRS. * * @param properties The properties of a CRS. * @param horizontalCRS The horizontal component of the 3D CRS. * @return The properties with the given horizontal CRS injected in the name identifier. */ public static Map<String,?> addHorizontalCRS(Map<String,?> properties, final SingleCRS horizontalCRS) { final Map<String,Object> copy = new HashMap<>(properties); final Identifier id = (Identifier) copy.get(NAME_KEY); copy.put(NAME_KEY, new Identifier3D(id, horizontalCRS)); return copy; } }