| /* |
| * 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.metadata.privy; |
| |
| import java.util.Locale; |
| import java.util.TimeZone; |
| import java.util.ServiceLoader; |
| import java.text.Format; |
| import org.opengis.geometry.Envelope; |
| import org.opengis.geometry.DirectPosition; |
| import org.opengis.parameter.ParameterDescriptor; |
| import org.opengis.referencing.IdentifiedObject; |
| import org.opengis.referencing.operation.CoordinateOperationFactory; |
| import org.opengis.referencing.operation.TransformException; |
| import org.opengis.util.FactoryException; |
| import org.apache.sis.metadata.iso.extent.DefaultExtent; |
| import org.apache.sis.metadata.iso.extent.DefaultVerticalExtent; |
| import org.apache.sis.metadata.iso.extent.DefaultTemporalExtent; |
| import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox; |
| import org.apache.sis.metadata.iso.extent.DefaultSpatialTemporalExtent; |
| import org.apache.sis.system.OptionalDependency; |
| import org.apache.sis.system.Modules; |
| |
| |
| /** |
| * Provides access to services defined in the {@code org.apache.sis.referencing} module. |
| * This class also opportunistically defines some methods and constants related |
| * to <q>referencing by coordinates</q> but needed by metadata. |
| * |
| * @author Martin Desruisseaux (Geomatys) |
| */ |
| public class ReferencingServices extends OptionalDependency { |
| /** |
| * The length of one nautical mile, which is {@value} metres. |
| */ |
| public static final double NAUTICAL_MILE = 1852; |
| |
| /** |
| * The GRS80 {@linkplain org.apache.sis.referencing.datum.DefaultEllipsoid#getAuthalicRadius() authalic radius}, |
| * which is {@value} metres. This is close to the WGS84 authalic radius, which is about 6371007.180918474 when |
| * computed with {@code double} precision. |
| */ |
| public static final double AUTHALIC_RADIUS = 6371007; |
| |
| /** |
| * The services, fetched when first needed. |
| * Guaranteed non-null after the search was done, even if the service implementation was not found. |
| * |
| * @see #getInstance() |
| */ |
| private static volatile ReferencingServices instance; |
| |
| /** |
| * For subclass only. This constructor registers this instance as a |
| * {@link org.apache.sis.system.SystemListener} in order to |
| * force a new {@code ReferencingServices} lookup if the module path changes. |
| */ |
| protected ReferencingServices() { |
| super(Modules.METADATA, Modules.REFERENCING); |
| } |
| |
| /** |
| * Invoked when the module path changed. Resets the {@link #instance} to {@code null} |
| * in order to force the next call to {@link #getInstance()} to fetch a new one, |
| * which may be different. |
| */ |
| @Override |
| protected final void classpathChanged() { |
| synchronized (ReferencingServices.class) { |
| instance = null; |
| } |
| } |
| |
| /** |
| * Returns the singleton instance. |
| * |
| * @return the singleton instance. |
| */ |
| @SuppressWarnings("DoubleCheckedLocking") |
| public static ReferencingServices getInstance() { |
| ReferencingServices c = instance; |
| if (c == null) { |
| synchronized (ReferencingServices.class) { |
| c = instance; |
| if (c == null) { |
| /* |
| * Double-checked locking: okay since Java 5 provided that the `instance` field is volatile. |
| * In the particular case of this class, the intent is to ensure that SystemListener.add(…) |
| * is invoked only once. |
| */ |
| c = getInstance(ReferencingServices.class, ServiceLoader.load(ReferencingServices.class), Modules.REFERENCING); |
| if (c == null) { |
| c = new ReferencingServices(); |
| } |
| instance = c; |
| } |
| } |
| } |
| return c; |
| } |
| |
| |
| |
| |
| /////////////////////////////////////////////////////////////////////////////////////// |
| //// //// |
| //// SERVICES FOR ISO 19115 METADATA //// |
| //// //// |
| /////////////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * Sets a geographic bounding box from the specified envelope. |
| * If the envelope contains a CRS which is not geographic, then the bounding box will be transformed |
| * to a geographic CRS (without datum shift if possible). Otherwise, the envelope is assumed already |
| * in a geographic CRS using (<var>longitude</var>, <var>latitude</var>) axis order. |
| * |
| * <p>If {@code findOpCaller} is non-null, then this method is invoked for computing a <em>hint</em> |
| * for choosing a coordinate operation between a pair of reference systems. It changes the behavior |
| * of this methods in two ways:</p> |
| * |
| * <ul> |
| * <li>Some failures will cause this method to return {@code null} instead of throwing an exception. |
| * Those exception will be logged on the assumption that {@code findOpCaller} is a public method |
| * of {@code Envelopes}.</li> |
| * <li>The bounding box may be conservatively expanded to the whole world.</li> |
| * </ul> |
| * |
| * @param envelope the source envelope. |
| * @param target the target bounding box, or {@code null} for creating it automatically. |
| * @param findOpCaller non-null for computing a hint rather than an exact bounding box. |
| * @return the bounding box, or {@code null} on failure (in hint mode) or if no horizontal component was found. |
| * @throws UnsupportedOperationException if the {@code org.apache.sis.referencing} module has not been found on the module path. |
| * @throws TransformException if the given envelope cannot be transformed. |
| */ |
| public DefaultGeographicBoundingBox setBounds(Envelope envelope, DefaultGeographicBoundingBox target, String findOpCaller) |
| throws TransformException |
| { |
| throw moduleNotFound(); |
| } |
| |
| /** |
| * Sets a vertical extent with the value inferred from the given envelope. |
| * Only the vertical coordinates are extracted; all other coordinates are ignored. |
| * |
| * @param envelope the source envelope. |
| * @param target the target vertical extent. |
| * @return whether the envelope contains a vertical component. |
| * @throws UnsupportedOperationException if the {@code org.apache.sis.referencing} module has not been found on the module path. |
| */ |
| public boolean setBounds(Envelope envelope, DefaultVerticalExtent target) { |
| throw moduleNotFound(); |
| } |
| |
| /** |
| * Sets a temporal extent with the value inferred from the given envelope. |
| * Only the temporal coordinates are extracted; all other coordinates are ignored. |
| * |
| * @param envelope the source envelope. |
| * @param target the target temporal extent. |
| * @return whether the envelope contains a temporal component. |
| * @throws UnsupportedOperationException if the {@code org.apache.sis.referencing} module has not been found on the module path. |
| */ |
| public boolean setBounds(Envelope envelope, DefaultTemporalExtent target) { |
| throw moduleNotFound(); |
| } |
| |
| /** |
| * Sets the geographic, vertical and temporal extents with the values inferred from the given envelope. |
| * If the given {@code target} has more geographic or vertical extents than needed (0 or 1), then the |
| * extraneous extents are removed. |
| * |
| * <p>Behavior regarding missing dimensions:</p> |
| * <ul> |
| * <li>If the given envelope has no horizontal component, then all geographic extents are removed |
| * from the given {@code target}. Non-geographic extents (e.g. descriptions and polygons) are |
| * left unchanged.</li> |
| * <li>If the given envelope has no vertical component, then the vertical extent is set to {@code null}.</li> |
| * <li>If the given envelope has no temporal component, then the temporal extent is set to {@code null}.</li> |
| * </ul> |
| * |
| * @param envelope the source envelope. |
| * @param target the target spatiotemporal extent. |
| * @return whether the envelope contains a spatial or temporal component. |
| * @throws TransformException if a coordinate transformation was required and failed. |
| * @throws UnsupportedOperationException if the {@code org.apache.sis.referencing} module has not been found on the module path. |
| */ |
| public boolean setBounds(Envelope envelope, DefaultSpatialTemporalExtent target) throws TransformException { |
| throw moduleNotFound(); |
| } |
| |
| /** |
| * Initializes a horizontal, vertical and temporal extent with the values inferred from the given envelope. |
| * |
| * @param envelope the source envelope. |
| * @param target the target extent. |
| * @return whether the envelope contains a spatial or temporal component. |
| * @throws TransformException if a coordinate transformation was required and failed. |
| * @throws UnsupportedOperationException if the {@code org.apache.sis.referencing} module has not been found on the module path. |
| */ |
| public boolean addElements(Envelope envelope, DefaultExtent target) throws TransformException { |
| throw moduleNotFound(); |
| } |
| |
| /** |
| * Creates a two-dimensional geographic position associated to the default geographic CRS. |
| * Axis order is (longitude, latitude). |
| * |
| * @param λ the longitude value. |
| * @param φ the latitude value. |
| * @return the direct position for the given geographic coordinate. |
| */ |
| public DirectPosition geographic(final double λ, final double φ) { |
| throw moduleNotFound(); |
| } |
| |
| /** |
| * Returns an identifier for the given object, giving precedence to EPSG identifier if available. |
| * The returned string should be of the form {@code "AUTHORITY:CODE"} if possible (no guarantees). |
| * |
| * @param object the object for which to get an identifier. |
| * @return an identifier for the given object, with preference given to EPSG codes. |
| * @throws FactoryException if an error occurred while searching for the EPSG code. |
| */ |
| public String getPreferredIdentifier(final IdentifiedObject object) throws FactoryException { |
| throw moduleNotFound(); |
| } |
| |
| |
| |
| |
| /////////////////////////////////////////////////////////////////////////////////////// |
| //// //// |
| //// OTHER REFERENCING SERVICES //// |
| //// //// |
| /////////////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * Returns a fully implemented parameter descriptor. |
| * |
| * @param <T> the type of values. |
| * @param parameter a partially implemented parameter descriptor, or {@code null}. |
| * @return a fully implemented parameter descriptor, or {@code null} if the given argument was null. |
| * @throws UnsupportedOperationException if the {@code org.apache.sis.referencing} module has not been found on the module path. |
| */ |
| public <T> ParameterDescriptor<T> toImplementation(ParameterDescriptor<T> parameter) { |
| throw moduleNotFound(); |
| } |
| |
| /** |
| * Creates a format for {@link DirectPosition} instances. |
| * |
| * @param locale the locale for the new {@code Format}, or {@code null} for {@code Locale.ROOT}. |
| * @param timezone the timezone, or {@code null} for UTC. |
| * @return a {@link org.apache.sis.geometry.CoordinateFormat}. |
| */ |
| public Format createCoordinateFormat(final Locale locale, final TimeZone timezone) { |
| throw moduleNotFound(); |
| } |
| |
| /** |
| * Returns the default coordinate operation factory. |
| * |
| * @return the coordinate operation factory to use. |
| */ |
| public CoordinateOperationFactory getCoordinateOperationFactory() { |
| throw moduleNotFound(); |
| } |
| |
| /** |
| * Returns information about the Apache SIS configuration to be reported in {@link org.apache.sis.setup.About}. |
| * This method is invoked only for aspects that depends on other modules than {@code org.apache.sis.util}. |
| * |
| * <p>Current keys are:</p> |
| * <ul> |
| * <li>{@code "EPSG"}: version of EPSG database.</li> |
| * </ul> |
| * |
| * @param key a key identifying the information to return. |
| * @param locale language to use if possible. |
| * @return the information, or {@code null} if none. |
| * |
| * @see org.apache.sis.util.privy.MetadataServices#getInformation(String, Locale) |
| */ |
| public String getInformation(String key, Locale locale) { |
| return null; |
| } |
| } |