001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    http://www.geoapi.org
004 *
005 *    Copyright (C) 2011-2019 Open Geospatial Consortium, Inc.
006 *    All Rights Reserved. http://www.opengeospatial.org/ogc/legal
007 *
008 *    Permission to use, copy, and modify this software and its documentation, with
009 *    or without modification, for any purpose and without fee or royalty is hereby
010 *    granted, provided that you include the following on ALL copies of the software
011 *    and documentation or portions thereof, including modifications, that you make:
012 *
013 *    1. The full text of this NOTICE in a location viewable to users of the
014 *       redistributed or derivative work.
015 *    2. Notice of any changes or modifications to the OGC files, including the
016 *       date changes were made.
017 *
018 *    THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE
019 *    NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
020 *    TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
021 *    THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
022 *    PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
023 *
024 *    COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
025 *    CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
026 *
027 *    The name and trademarks of copyright holders may NOT be used in advertising or
028 *    publicity pertaining to the software without specific, written prior permission.
029 *    Title to copyright in this software and any associated documentation will at all
030 *    times remain with copyright holders.
031 */
032package org.opengis.test.referencing.gigs;
033
034import java.util.List;
035import javax.measure.Unit;
036import javax.measure.quantity.Angle;
037
038import org.opengis.util.Factory;
039import org.opengis.util.FactoryException;
040import org.opengis.referencing.datum.PrimeMeridian;
041import org.opengis.referencing.datum.DatumFactory;
042import org.opengis.test.Configuration;
043
044import org.junit.Test;
045import org.junit.runner.RunWith;
046import org.junit.runners.Parameterized;
047
048import static org.junit.Assume.*;
049import static org.junit.Assert.*;
050
051
052/**
053 * Verifies that the software allows correct definition of a user-defined prime meridian.
054 *
055 * <table class="gigs" summary="Test description"><tr>
056 *   <th>Test method:</th>
057 *   <td>Create user-defined prime meridian for each of several different prime meridians.</td>
058 * </tr><tr>
059 *   <th>Test data:</th>
060 *   <td><a href="doc-files/GIGS_3003_userPrimeMeridian.csv">{@code GIGS_3003_userPrimeMeridian.csv}</a>.</td>
061 * </tr><tr>
062 *   <th>Tested API:</th>
063 *   <td>{@link DatumFactory#createPrimeMeridian(Map, double, Unit)}.</td>
064 * </tr><tr>
065 *   <th>Expected result:</th>
066 *   <td>The software should accept the test data. The properties of the created objects will
067 *       be compared with the properties given to the factory method.</td>
068 * </tr></table>
069 *
070 *
071 * <div class="note"><b>Usage example:</b>
072 * in order to specify their factories and run the tests in a JUnit framework, implementors can
073 * define a subclass in their own test suite as in the example below:
074 *
075 * <blockquote><pre>import org.junit.runner.RunWith;
076 *import org.junit.runners.JUnit4;
077 *import org.opengis.test.referencing.gigs.GIGS3003;
078 *
079 *&#64;RunWith(JUnit4.class)
080 *public class MyTest extends GIGS3003 {
081 *    public MyTest() {
082 *        super(new MyDatumFactory());
083 *    }
084 *}</pre></blockquote>
085 * </div>
086 *
087 * @author  GIGS (IOGP)
088 * @author  Martin Desruisseaux (Geomatys)
089 * @author  Alexis Manin (Geomatys)
090 * @version 3.1
091 * @since   3.1
092 */
093@RunWith(Parameterized.class)
094public strictfp class GIGS3003 extends UserObjectFactoryTestCase<PrimeMeridian> {
095    /**
096     * The prime meridian Greenwich longitude, in unit of {@link #angularUnit}.
097     */
098    public double greenwichLongitude;
099
100    /**
101     * The unit of measurement of {@link #greenwichLongitude}.
102     */
103    public Unit<Angle> angularUnit;
104
105    /**
106     * The prime meridian created by the factory,
107     * or {@code null} if not yet created or if the prime meridian creation failed.
108     *
109     * @see #datumFactory
110     */
111    private PrimeMeridian primeMeridian;
112
113    /**
114     * Factory to use for building {@link PrimeMeridian} instances, or {@code null} if none.
115     * This is the factory used by the {@link #getIdentifiedObject()} method.
116     */
117    protected final DatumFactory datumFactory;
118
119    /**
120     * Returns a default set of factories to use for running the tests. Those factories are given
121     * in arguments to the constructor when this test class is instantiated directly by JUnit (for
122     * example as a {@linkplain org.junit.runners.Suite.SuiteClasses suite} element), instead than
123     * subclassed by the implementor. The factories are fetched as documented in the
124     * {@link #factories(Class[])} javadoc.
125     *
126     * @return the default set of arguments to be given to the {@code GIGS3003} constructor.
127     */
128    @Parameterized.Parameters
129    @SuppressWarnings("unchecked")
130    public static List<Factory[]> factories() {
131        return factories(DatumFactory.class);
132    }
133
134    /**
135     * Creates a new test using the given factory. If a given factory is {@code null},
136     * then the tests which depend on it will be skipped.
137     *
138     * @param datumFactory  factory for creating {@link PrimeMeridian} instances.
139     */
140    public GIGS3003(final DatumFactory datumFactory) {
141        super(datumFactory);
142        this.datumFactory = datumFactory;
143    }
144
145    /**
146     * Returns information about the configuration of the test which has been run.
147     * This method returns a map containing:
148     *
149     * <ul>
150     *   <li>All the following values associated to the {@link org.opengis.test.Configuration.Key} of the same name:
151     *     <ul>
152     *       <li>{@link #isFactoryPreservingUserValues}</li>
153     *       <li>{@linkplain #datumFactory}</li>
154     *     </ul>
155     *   </li>
156     * </ul>
157     *
158     * @return the configuration of the test being run.
159     */
160    @Override
161    public Configuration configuration() {
162        final Configuration op = super.configuration();
163        assertNull(op.put(Configuration.Key.datumFactory, datumFactory));
164        return op;
165    }
166
167    /**
168     * Sets the prime meridian instance to verify. This method is invoked only by other test classes
169     * which need to verify the prime meridian contained in a geodetic datum instead than the prime
170     * meridian immediately after creation.
171     */
172    final void setIdentifiedObject(final PrimeMeridian instance) {
173        primeMeridian = instance;
174    }
175
176    /**
177     * Returns the prime meridian instance to be tested. When this method is invoked for the first time,
178     * it creates the prime meridian to test by invoking the corresponding method from {@link DatumFactory}
179     * with the current {@link #properties properties} map in argument.
180     * The created object is then cached and returned in all subsequent invocations of this method.
181     *
182     * @return the prime meridian instance to test.
183     * @throws FactoryException if an error occurred while creating the prime meridian instance.
184     */
185    @Override
186    public PrimeMeridian getIdentifiedObject() throws FactoryException {
187        if (primeMeridian == null) {
188            assumeNotNull(datumFactory);
189            primeMeridian = datumFactory.createPrimeMeridian(properties, greenwichLongitude, angularUnit);
190        }
191        return primeMeridian;
192    }
193
194    /**
195     * Verifies the properties of the prime meridian given by {@link #getIdentifiedObject()}.
196     */
197    final void verifyPrimeMeridian() throws FactoryException {
198        if (skipTests) {
199            return;
200        }
201        final String name = getName();
202        final String code = getCode();
203        final PrimeMeridian primeMeridian = getIdentifiedObject();
204        assertNotNull("PrimeMeridian", primeMeridian);
205        validators.validate(primeMeridian);
206
207        verifyPrimeMeridian(primeMeridian, name, greenwichLongitude, angularUnit);
208        verifyIdentification(primeMeridian, name, code);
209        if (isFactoryPreservingUserValues) {
210            configurationTip = Configuration.Key.isFactoryPreservingUserValues;
211            assertEquals("PrimeMeridian.getAngularUnit()",        angularUnit,        primeMeridian.getAngularUnit());
212            assertEquals("PrimeMeridian.getGreenwichLongitude()", greenwichLongitude, primeMeridian.getGreenwichLongitude(), ANGULAR_TOLERANCE);
213            configurationTip = null;
214        }
215    }
216
217    /**
218     * Tests “GIGS PM A” prime meridian creation from the factory.
219     *
220     * <ul>
221     *   <li>GIGS prime meridian code: <b>68901</b></li>
222     *   <li>GIGS prime meridian name: <b>GIGS PM A</b></li>
223     *   <li>EPSG equivalence: <b>8901 – Greenwich</b></li>
224     *   <li>Greenwich longitude: <b>0°</b></li>
225     * </ul>
226     *
227     * @throws FactoryException if an error occurred while creating the prime meridian from the properties.
228     *
229     * @see GIGS2003#testGreenwich()
230     */
231    @Test
232    public void testGreenwich() throws FactoryException {
233        setCodeAndName(68901, "GIGS PM A");
234        greenwichLongitude = 0.0;
235        angularUnit        = units.degree();
236        verifyPrimeMeridian();
237    }
238
239    /**
240     * Tests “GIGS PM D” prime meridian creation from the factory.
241     *
242     * <ul>
243     *   <li>GIGS prime meridian code: <b>68908</b></li>
244     *   <li>GIGS prime meridian name: <b>GIGS PM D</b></li>
245     *   <li>EPSG equivalence: <b>8908 – Jakarta</b></li>
246     *   <li>Greenwich longitude: <b>106°48'27.79° (106.80771944444444°)</b></li>
247     * </ul>
248     *
249     * @throws FactoryException if an error occurred while creating the prime meridian from the properties.
250     *
251     * @see GIGS2003#testJakarta()
252     */
253    @Test
254    public void testJakarta() throws FactoryException {
255        setCodeAndName(68908, "GIGS PM D");
256        greenwichLongitude = 106.80771944444444;
257        angularUnit        = units.degree();
258        verifyPrimeMeridian();
259    }
260
261    /**
262     * Tests “GIGS PM H” prime meridian creation from the factory.
263     *
264     * <ul>
265     *   <li>GIGS prime meridian code: <b>68903</b></li>
266     *   <li>GIGS prime meridian name: <b>GIGS PM H</b></li>
267     *   <li>EPSG equivalence: <b>8903 – Paris</b></li>
268     *   <li>Greenwich longitude: <b>2.5969213 grad (2.33722917°)</b></li>
269     *   <li>Specific usage / Remarks: <b>Equivalent to 2°20'14.025.</b></li>
270     * </ul>
271     *
272     * @throws FactoryException if an error occurred while creating the prime meridian from the properties.
273     *
274     * @see GIGS2003#testParis()
275     */
276    @Test
277    public void testParis() throws FactoryException {
278        setCodeAndName(68903, "GIGS PM H");
279        greenwichLongitude = 2.5969213;
280        angularUnit        = units.grad();
281        verifyPrimeMeridian();
282    }
283
284    /**
285     * Tests “GIGS PM I” prime meridian creation from the factory.
286     *
287     * <ul>
288     *   <li>GIGS prime meridian code: <b>68904</b></li>
289     *   <li>GIGS prime meridian name: <b>GIGS PM I</b></li>
290     *   <li>EPSG equivalence: <b>8904 – Bogota</b></li>
291     *   <li>Greenwich longitude: <b>-74°04'51.3° (74.08091666666667°)</b></li>
292     * </ul>
293     *
294     * @throws FactoryException if an error occurred while creating the prime meridian from the properties.
295     *
296     * @see GIGS2003#testBogota()
297     */
298    @Test
299    public void testBogota() throws FactoryException {
300        setCodeAndName(68904, "GIGS PM I");
301        greenwichLongitude = 74.08091666666667;
302        angularUnit        = units.degree();
303        verifyPrimeMeridian();
304    }
305}