001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    This file is hereby placed into the Public Domain.
004 *    This means anyone is free to do whatever they wish with this file.
005 */
006package org.opengis.example;
007
008import java.util.Map;
009import java.awt.geom.RectangularShape;
010import org.opengis.util.NameFactory;
011import org.opengis.util.GenericName;
012import org.opengis.metadata.Identifier;
013import org.opengis.metadata.citation.Citation;
014import org.opengis.metadata.extent.GeographicBoundingBox;
015import org.opengis.geometry.DirectPosition;
016import org.opengis.geometry.Envelope;
017import org.opengis.referencing.operation.MathTransform;
018import org.opengis.referencing.operation.MathTransformFactory;
019import org.opengis.referencing.crs.CoordinateReferenceSystem;
020import org.opengis.referencing.crs.CRSAuthorityFactory;
021import org.opengis.referencing.cs.CoordinateSystemAxis;
022import org.opengis.referencing.cs.AxisDirection;
023import org.opengis.referencing.cs.RangeMeaning;
024import org.opengis.coordinate.MismatchedDimensionException;
025import org.opengis.coordinate.MismatchedCoordinateMetadataException;
026import org.opengis.annotation.UML;
027import org.opengis.annotation.Specification;
028import org.opengis.example.util.SimpleNameFactory;
029import org.opengis.example.geometry.SimpleEnvelope;
030import org.opengis.example.geometry.SimpleDirectPosition;
031import org.opengis.example.metadata.MetadataProxyFactory;
032import org.opengis.example.metadata.SimpleCitation;
033import org.opengis.example.metadata.SimpleIdentifier;
034import org.opengis.example.metadata.SimpleGeographicBoundingBox;
035import org.opengis.example.referencing.SimpleAuthorityFactory;
036import org.opengis.example.referencing.SimpleTransformFactory;
037import org.opengis.example.referencing.SimpleAxis;
038
039
040/**
041 * Provides simple factories backed by the example implementations.
042 * This class is provided only for illustrative purposes with simple implementations.
043 * <strong>This class is not for use in production.</strong>
044 * For real applications, use a library implementing GeoAPI or providing GeoAPI wrappers.
045 *
046 * @see Specification#ISO_19115
047 * @see Specification#ISO_19103
048 */
049public final class SimpleFactories {
050    /**
051     * Do not allow instantiation of this class.
052     */
053    private SimpleFactories() {
054    }
055
056    /**
057     * Creates a new citation having the given title.
058     * This citation can be used for defining the authority of a set of identifiers.
059     *
060     * @param  title  the citation title.
061     * @return a citation with the given title.
062     */
063    public static Citation createCitation(String title) {
064        return new SimpleCitation(title);
065    }
066
067    /**
068     * Creates a new identifier of the given authority and code.
069     *
070     * @param  authority  the authority, or {@code null} if none.
071     * @param  code       the identifier code.
072     * @return identifier of the given code and (optionally) authority.
073     */
074    public static Identifier createIdentifier(Citation authority, String code) {
075        return new SimpleIdentifier(authority, code);
076    }
077
078    /**
079     * Creates a new direct position of the given dimension.
080     * The Coordinate Reference System is left unspecified.
081     * All coordinate values are initialized to zero.
082     *
083     * @param  dimension  the dimension.
084     * @return a new direct position of the given number of dimensions.
085     */
086    public static DirectPosition createPosition(final int dimension) {
087        return new SimpleDirectPosition(dimension);
088    }
089
090    /**
091     * Creates a new direct position associated to the given coordinate reference system.
092     * The {@linkplain DirectPosition#getDimension() dimension} of the new direct position
093     * is the dimension of the given CRS. All coordinate values are initialized to zero.
094     *
095     * @param crs  the coordinate reference system to associate to the new direct position.
096     * @return a new direct position associated to the given <abbr>CRS</abbr>.
097     */
098    public static DirectPosition createPosition(CoordinateReferenceSystem crs) {
099        return new SimpleDirectPosition(crs);
100    }
101
102    /**
103     * Creates a new envelope defined by two direct positions.
104     * The CRS of the envelope will be the CRS of the given direct positions, which shall be the equal.
105     * The coordinates of the given direct positions are copied.
106     *
107     * <p>This simple implementation does not support envelopes crossing the anti-meridian.
108     * Therefore, lower coordinate values shall not be greater than corresponding upper coordinate values.</p>
109     *
110     * @param  lowerCorner  the limits in the direction of decreasing coordinate values for each dimension.
111     * @param  upperCorner  the limits in the direction of increasing coordinate values for each dimension.
112     * @return the envelope defined by the given corners.
113     * @throws MismatchedCoordinateMetadataException if the CRS of the two position are not equal.
114     * @throws MismatchedDimensionException if the two positions do not have the same dimension.
115     * @throws IllegalArgumentException if an coordinate value in the lower corner is greater than
116     *         the corresponding coordinate value in the upper corner.
117     */
118    public static Envelope createEnvelope(DirectPosition lowerCorner, DirectPosition upperCorner) {
119        return new SimpleEnvelope(lowerCorner, upperCorner);
120    }
121
122    /**
123     * Creates a geographic bounding box from the specified rectangular area.
124     * The coordinate values are assumed in WGS84 <abbr>CRS</abbr>.
125     *
126     * @param bounds  the rectangle to use for the geographic bounding box.
127     * @return a geographic bounding box with the coordinates of the given rectangle.
128     * @throws IllegalArgumentException if (<var>west bound</var> &gt; <var>east bound</var>)
129     *         or (<var>south bound</var> &gt; <var>north bound</var>).
130     *         Note that {@linkplain Double#NaN NaN} values are allowed.
131     */
132    public static GeographicBoundingBox createGeographicBoundingBox(RectangularShape bounds) {
133        return new SimpleGeographicBoundingBox(bounds);
134    }
135
136    /**
137     * Creates a new implementation of the given metadata interface which will contains the values in the given map.
138     * The metadata values are specified by a {@link Map} of attributes in which keys are {@linkplain UML#identifier()
139     * UML identifiers}, and values must be assignable to the return value of the corresponding GeoAPI methods.
140     *
141     * <p><b>Example:</b> create an {@code Individual} instance:</p>
142     *
143     * {@snippet lang="java" :
144     * var attributes = new HashMap<String,Object>();
145     * attributes.put("name", getNameFactory().createInternationalString("Aristotle"));
146     * Individual party = createMetadataView(Individual.class, attributes);
147     * }
148     *
149     * The returned metadata is <i>live</i>, i.e. any change to the given map of attributes
150     * will be immediately reflected in the values returned by the metadata object.
151     *
152     * @param  <T>         the compile-time type of the {@code type} argument.
153     * @param  type        the metadata interface for which to get an instance.
154     * @param  attributes  the attribute values to give to the metadata instance.
155     * @return a metadata object which will fetch the values in the given map.
156     * @throws IllegalArgumentException if the given type is not an interface
157     *         from the GeoAPI metadata package.
158     */
159    public <T> T createMetadataView(Class<T> type, Map<String,?> attributes) {
160        return MetadataProxyFactory.INSTANCE.create(type, attributes);
161    }
162
163    /**
164     * Creates a new axis for the given authority, name and abbreviation.
165     * This is a simplified constructor which infers {@linkplain AxisDirection axis direction}
166     * and units from the abbreviation using the following table.
167     *
168     * <blockquote><table class="ogc">
169     * <caption>Axis properties inferred from the abbreviation</caption>
170     * <tr><th>Symbol</th>   <th>Common name</th>    <th>Axis direction</th> <th>Unit</th>  <th>Range</th></tr>
171     * <tr><td>λ</td> <td>geodetic longitude</td>    <td>east</td>           <td>degree</td><td>±90°  ({@link RangeMeaning#EXACT})</td></tr>
172     * <tr><td>φ</td> <td>geodetic latitude</td>     <td>north</td>          <td>degree</td><td>±180° ({@link RangeMeaning#WRAPAROUND})</td></tr>
173     * <tr><td>h</td> <td>ellipsoidal height</td>    <td>up</td>             <td>metre</td> <td></td></tr>
174     * <tr><td>H</td> <td>gravity-related height</td><td>up</td>             <td>metre</td> <td></td></tr>
175     * <tr><td>d</td> <td>depth</td>                 <td>down</td>           <td>metre</td> <td></td></tr>
176     * <tr><td>r</td> <td>geocentric radius</td>     <td>up</td>             <td>metre</td> <td>[0…∞]</td></tr>
177     * <tr><td>Ω</td> <td>spherical longitude</td>   <td>east</td>           <td>degree</td><td>±90°  ({@link RangeMeaning#EXACT})</td></tr>
178     * <tr><td>Θ</td> <td>spherical latitude</td>    <td>north</td>          <td>degree</td><td>±180° ({@link RangeMeaning#WRAPAROUND})</td></tr>
179     * <tr><td>X</td> <td>geocentric X</td>          <td>geocentric X</td>   <td>metre</td> <td></td></tr>
180     * <tr><td>Y</td> <td>geocentric Y</td>          <td>geocentric Y</td>   <td>metre</td> <td></td></tr>
181     * <tr><td>Z</td> <td>geocentric Z</td>          <td>geocentric Z</td>   <td>metre</td> <td></td></tr>
182     * <tr><td>E</td> <td>easting</td>               <td>east</td>           <td>metre</td> <td></td></tr>
183     * <tr><td>W</td> <td>westing</td>               <td>west</td>           <td>metre</td> <td></td></tr>
184     * <tr><td>N</td> <td>northing</td>              <td>north</td>          <td>metre</td> <td></td></tr>
185     * <tr><td>S</td> <td>southing</td>              <td>south</td>          <td>metre</td> <td></td></tr>
186     * <tr><td>t</td> <td>time</td>                  <td>future</td>         <td>second</td><td></td></tr>
187     * <tr><td>i</td> <td>column</td>                <td>column positive</td><td>unity</td> <td></td></tr>
188     * <tr><td>j</td> <td>row</td>                   <td>row positive</td>   <td>unity</td> <td></td></tr>
189     * </table></blockquote>
190     *
191     * @param  authority     organization responsible for definition of the name, or {@code null}.
192     * @param  name          the name of the new axis.
193     * @param  abbreviation  the abbreviation used for this coordinate system axes.
194     * @return a coordinate system axis of the given name and abbreviation.
195     * @throws IllegalArgumentException if the abbreviation is not recognized.
196     */
197    public static CoordinateSystemAxis createAxis(Citation authority, String name, char abbreviation) {
198        return new SimpleAxis(authority, name, abbreviation);
199    }
200
201    /**
202     * Returns a factory for creating {@code GenericName} instances.
203     * This factory provides methods for constructing
204     * {@link org.opengis.util.InternationalString},
205     * {@link org.opengis.util.GenericName},
206     * {@link org.opengis.util.LocalName},
207     * {@link org.opengis.util.ScopedName},
208     * {@link org.opengis.util.TypeName} and
209     * {@link org.opengis.util.MemberName}.
210     *
211     * @return a factory for creating instances of {@link GenericName}.
212     */
213    public static NameFactory getNameFactory() {
214        return SimpleNameFactory.provider();
215    }
216
217    /**
218     * Returns a factory for creating {@code CoordinateReferenceSystem} instances.
219     * The simple factory provided as an example defines only the following codes:
220     *
221     * <blockquote><table class="ogc">
222     * <caption>CRS codes defined by "GeoAPI example" pseudo-authority</caption>
223     * <tr><th>Code</th>        <th>Type</th>       <th>Name</th></tr>
224     * <tr><td>4326</td>        <td>Geographic</td> <td>WGS 84</td></tr>
225     * <tr><td>4047</td>        <td>Geographic</td> <td>GRS 1980 Authalic Sphere</td></tr>
226     * <tr><td>5714</td>        <td>Vertical</td>   <td>Mean Sea Level (MSL) height</td></tr>
227     * <tr><td>JulianDate</td>  <td>Temporal</td>   <td>Julian Date</td></tr>
228     * </table></blockquote>
229     *
230     * @return a factory for creating a few {@code CoordinateReferenceSystem} instances.
231     */
232    public static CRSAuthorityFactory getCRSAuthorityFactory() {
233        return SimpleAuthorityFactory.provider();
234    }
235
236    /**
237     * Returns a factory for creating {@code MathTransformFactory} instances.
238     * The simple factory provided as an example can create only linear transforms.
239     *
240     * @return a factory for creating linear instances of {@link MathTransform}.
241     */
242    public static MathTransformFactory getMathTransformFactory() {
243        return SimpleTransformFactory.provider();
244    }
245}