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.DatumAuthorityFactory;
041import org.opengis.referencing.NoSuchAuthorityCodeException;
042import org.opengis.referencing.datum.PrimeMeridian;
043import org.opengis.test.Configuration;
044import org.opengis.test.FactoryFilter;
045
046import org.junit.Test;
047import org.junit.runner.RunWith;
048import org.junit.runners.Parameterized;
049
050import static org.junit.Assume.*;
051import static org.junit.Assert.*;
052
053
054/**
055 * Verifies reference prime meridians bundled with the geoscience software.
056 *
057 * <table class="gigs" summary="Test description"><tr>
058 *   <th>Test method:</th>
059 *   <td>Compare prime meridian definitions included in the software against the EPSG Dataset.</td>
060 * </tr><tr>
061 *   <th>Test data:</th>
062 *   <td><a href="doc-files/GIGS_2003_libPrimeMeridian.csv">{@code GIGS_2003_libPrimeMeridian.csv}</a>
063 *       and EPSG Dataset.</td>
064 * </tr><tr>
065 *   <th>Tested API:</th>
066 *   <td>{@link DatumAuthorityFactory#createPrimeMeridian(String)}.</td>
067 * </tr><tr>
068 *   <th>Expected result:</th>
069 *   <td>Prime meridian definitions bundled with the software should have the same name and Greenwich Longitude
070 *       as in the EPSG Dataset. Equivalent alternative units are acceptable but should be reported.
071 *       The values of the Greenwich Longitude should be correct to at least 7 decimal places (of degrees or grads).
072 *       Meridians missing from the software or at variance with those in the EPSG Dataset should be reported.</td>
073 * </tr></table>
074 *
075 *
076 * <div class="note"><b>Usage example:</b>
077 * in order to specify their factories and run the tests in a JUnit framework, implementors can
078 * define a subclass in their own test suite as in the example below:
079 *
080 * <blockquote><pre>import org.junit.runner.RunWith;
081 *import org.junit.runners.JUnit4;
082 *import org.opengis.test.referencing.gigs.GIGS2003;
083 *
084 *&#64;RunWith(JUnit4.class)
085 *public class MyTest extends GIGS2003 {
086 *    public MyTest() {
087 *        super(new MyDatumAuthorityFactory());
088 *    }
089 *}</pre></blockquote>
090 * </div>
091 *
092 * @author  GIGS (IOGP)
093 * @author  Martin Desruisseaux (Geomatys)
094 * @author  Alexis Manin (Geomatys)
095 * @version 3.1
096 * @since   3.1
097 */
098@RunWith(Parameterized.class)
099public strictfp class GIGS2003 extends AuthorityFactoryTestCase<PrimeMeridian> {
100    /**
101     * The expected Greenwich longitude in decimal degrees.
102     */
103    public double greenwichLongitude;
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 #datumAuthorityFactory
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 DatumAuthorityFactory datumAuthorityFactory;
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 GIGS2003} constructor.
127     */
128    @Parameterized.Parameters
129    @SuppressWarnings("unchecked")
130    public static List<Factory[]> factories() {
131        return factories(FactoryFilter.ByAuthority.EPSG, DatumAuthorityFactory.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 GIGS2003(final DatumAuthorityFactory datumFactory) {
141        super(datumFactory);
142        datumAuthorityFactory = 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 #isStandardNameSupported}</li>
153     *       <li>{@link #isStandardAliasSupported}</li>
154     *       <li>{@link #isDependencyIdentificationSupported}</li>
155     *       <li>{@link #datumAuthorityFactory}</li>
156     *     </ul>
157     *   </li>
158     * </ul>
159     *
160     * @return the configuration of the test being run.
161     */
162    @Override
163    public Configuration configuration() {
164        final Configuration op = super.configuration();
165        assertNull(op.put(Configuration.Key.datumAuthorityFactory, datumAuthorityFactory));
166        return op;
167    }
168
169    /**
170     * Returns the prime meridian instance to be tested. When this method is invoked for the first time, it creates the
171     * prime meridian to test by invoking the {@link DatumAuthorityFactory#createPrimeMeridian(String)} method with the
172     * current {@link #code} value in argument. The created object is then cached and returned in all subsequent
173     * invocations of this method.
174     *
175     * @return the prime meridian instance to test.
176     * @throws FactoryException if an error occurred while creating the prime meridian instance.
177     */
178    @Override
179    public PrimeMeridian getIdentifiedObject() throws FactoryException {
180        if (primeMeridian == null) {
181            assumeNotNull(datumAuthorityFactory);
182            try {
183                primeMeridian = datumAuthorityFactory.createPrimeMeridian(String.valueOf(code));
184            } catch (NoSuchAuthorityCodeException e) {
185                unsupportedCode(PrimeMeridian.class, code);
186                throw e;
187            }
188        }
189        return primeMeridian;
190    }
191
192    /**
193     * Verifies the properties of the prime meridian given by {@link #getIdentifiedObject()}.
194     */
195    private void verifyPrimeMeridian() throws FactoryException {
196        final PrimeMeridian pm = getIdentifiedObject();
197        assertNotNull("PrimeMeridian", pm);
198        validators.validate(pm);
199
200        // Prime meridian identifiers.
201        assertContainsCode("PrimeMeridian.getIdentifiers()", "EPSG", code, pm.getIdentifiers());
202
203        // Prime meridian name.
204        if (isStandardNameSupported) {
205            configurationTip = Configuration.Key.isStandardNameSupported;
206            assertEquals("PrimeMeridian.getName()", name, getVerifiableName(pm));
207            configurationTip = null;
208        }
209
210        // Prime meridian alias.
211        if (isStandardAliasSupported) {
212            configurationTip = Configuration.Key.isStandardAliasSupported;
213            assertContainsAll("PrimeMeridian.getAlias()", aliases, pm.getAlias());
214            configurationTip = null;
215        }
216        /*
217         * Before to compare the Greenwich longitude, convert the expected angular value from decimal degrees
218         * to the units actually used by the implementation. We do the conversion that way rather than the
219         * opposite way in order to have a more appropriate error message in case of failure.
220         */
221        final Unit<Angle> unit = pm.getAngularUnit();
222        double longitude = greenwichLongitude;
223        final Unit<Angle> degree = units.degree();
224        if (unit != null && !unit.equals(degree)) {
225            longitude = degree.getConverterTo(unit).convert(longitude);
226        }
227        assertEquals("PrimeMeridian.getGreenwichLongitude()", longitude,
228                pm.getGreenwichLongitude(), ANGULAR_TOLERANCE);
229    }
230
231    /**
232     * Tests “Greenwich” prime meridian creation from the factory.
233     *
234     * <ul>
235     *   <li>EPSG prime meridian code: <b>8901</b></li>
236     *   <li>EPSG prime meridian name: <b>Greenwich</b></li>
237     *   <li>Greenwich longitude: <b>0°</b></li>
238     *   <li>Particularly important to E&amp;P industry.</li>
239     * </ul>
240     *
241     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
242     *
243     * @see GIGS3003#testGreenwich()
244     */
245    @Test
246    public void testGreenwich() throws FactoryException {
247        important          = true;
248        code               = 8901;
249        name               = "Greenwich";
250        aliases            = NONE;
251        greenwichLongitude = 0.0;
252        verifyPrimeMeridian();
253    }
254
255    /**
256     * Tests “Ferro” prime meridian creation from the factory.
257     *
258     * <ul>
259     *   <li>EPSG prime meridian code: <b>8909</b></li>
260     *   <li>EPSG prime meridian name: <b>Ferro</b></li>
261     *   <li>Greenwich longitude: <b>-17°40′</b></li>
262     *   <li>Particularly important to E&amp;P industry.</li>
263     * </ul>
264     *
265     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
266     */
267    @Test
268    public void testFerro() throws FactoryException {
269        important          = true;
270        code               = 8909;
271        name               = "Ferro";
272        aliases            = NONE;
273        greenwichLongitude = -17.666666666666668;
274        verifyPrimeMeridian();
275    }
276
277    /**
278     * Tests “Jakarta” prime meridian creation from the factory.
279     *
280     * <ul>
281     *   <li>EPSG prime meridian code: <b>8908</b></li>
282     *   <li>EPSG prime meridian name: <b>Jakarta</b></li>
283     *   <li>Greenwich longitude: <b>106°48′27.79″</b></li>
284     *   <li>Particularly important to E&amp;P industry.</li>
285     * </ul>
286     *
287     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
288     *
289     * @see GIGS3003#testJakarta()
290     */
291    @Test
292    public void testJakarta() throws FactoryException {
293        important          = true;
294        code               = 8908;
295        name               = "Jakarta";
296        aliases            = NONE;
297        greenwichLongitude = 106.80771944444444;
298        verifyPrimeMeridian();
299    }
300
301    /**
302     * Tests “Paris” prime meridian creation from the factory.
303     *
304     * <ul>
305     *   <li>EPSG prime meridian code: <b>8903</b></li>
306     *   <li>EPSG prime meridian name: <b>Paris</b></li>
307     *   <li>Greenwich longitude: <b>2.5969213</b></li>
308     *   <li>Specific usage / Remarks: <b>Equivalent to 2°20'14.025\".</b></li>
309     *   <li>Particularly important to E&amp;P industry.</li>
310     * </ul>
311     *
312     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
313     *
314     * @see GIGS3003#testParis()
315     */
316    @Test
317    public void testParis() throws FactoryException {
318        important          = true;
319        code               = 8903;
320        name               = "Paris";
321        aliases            = NONE;
322        greenwichLongitude = 2.33722917;
323        verifyPrimeMeridian();
324    }
325
326    /**
327     * Tests “Athens” prime meridian creation from the factory.
328     *
329     * <ul>
330     *   <li>EPSG prime meridian code: <b>8912</b></li>
331     *   <li>EPSG prime meridian name: <b>Athens</b></li>
332     *   <li>Greenwich longitude: <b>23°42′58.815″</b></li>
333     * </ul>
334     *
335     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
336     */
337    @Test
338    public void testAthens() throws FactoryException {
339        code               = 8912;
340        name               = "Athens";
341        aliases            = NONE;
342        greenwichLongitude = 23.7163375;
343        verifyPrimeMeridian();
344    }
345
346    /**
347     * Tests “Bern” prime meridian creation from the factory.
348     *
349     * <ul>
350     *   <li>EPSG prime meridian code: <b>8907</b></li>
351     *   <li>EPSG prime meridian name: <b>Bern</b></li>
352     *   <li>Greenwich longitude: <b>7°26′22.5″</b></li>
353     * </ul>
354     *
355     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
356     */
357    @Test
358    public void testBern() throws FactoryException {
359        code               = 8907;
360        name               = "Bern";
361        aliases            = NONE;
362        greenwichLongitude = 7.439583333333333;
363        verifyPrimeMeridian();
364    }
365
366    /**
367     * Tests “Bogota” prime meridian creation from the factory.
368     *
369     * <ul>
370     *   <li>EPSG prime meridian code: <b>8904</b></li>
371     *   <li>EPSG prime meridian name: <b>Bogota</b></li>
372     *   <li>Greenwich longitude: <b>-74°04′51.3″</b></li>
373     * </ul>
374     *
375     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
376     *
377     * @see GIGS3003#testBogota()
378     */
379    @Test
380    public void testBogota() throws FactoryException {
381        code               = 8904;
382        name               = "Bogota";
383        aliases            = NONE;
384        greenwichLongitude = -74.08091666666667;
385        verifyPrimeMeridian();
386    }
387
388    /**
389     * Tests “Brussels” prime meridian creation from the factory.
390     *
391     * <ul>
392     *   <li>EPSG prime meridian code: <b>8910</b></li>
393     *   <li>EPSG prime meridian name: <b>Brussels</b></li>
394     *   <li>Greenwich longitude: <b>4°22′04.71″</b></li>
395     * </ul>
396     *
397     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
398     */
399    @Test
400    public void testBrussels() throws FactoryException {
401        code               = 8910;
402        name               = "Brussels";
403        aliases            = NONE;
404        greenwichLongitude = 4.367975;
405        verifyPrimeMeridian();
406    }
407
408    /**
409     * Tests “Lisbon” prime meridian creation from the factory.
410     *
411     * <ul>
412     *   <li>EPSG prime meridian code: <b>8902</b></li>
413     *   <li>EPSG prime meridian name: <b>Lisbon</b></li>
414     *   <li>Greenwich longitude: <b>-9°07′54.862″</b></li>
415     * </ul>
416     *
417     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
418     */
419    @Test
420    public void testLisbon() throws FactoryException {
421        code               = 8902;
422        name               = "Lisbon";
423        aliases            = NONE;
424        greenwichLongitude = -9.13190611111111;
425        verifyPrimeMeridian();
426    }
427
428    /**
429     * Tests “Madrid” prime meridian creation from the factory.
430     *
431     * <ul>
432     *   <li>EPSG prime meridian code: <b>8905</b></li>
433     *   <li>EPSG prime meridian name: <b>Madrid</b></li>
434     *   <li>Greenwich longitude: <b>-3°41′16.58″</b></li>
435     * </ul>
436     *
437     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
438     */
439    @Test
440    public void testMadrid() throws FactoryException {
441        code               = 8905;
442        name               = "Madrid";
443        aliases            = NONE;
444        greenwichLongitude = -3.687938888888889;
445        verifyPrimeMeridian();
446    }
447
448    /**
449     * Tests “Oslo” prime meridian creation from the factory.
450     *
451     * <ul>
452     *   <li>EPSG prime meridian code: <b>8913</b></li>
453     *   <li>EPSG prime meridian name: <b>Oslo</b></li>
454     *   <li>Alias(es) given by EPSG: <b>Kristiania</b></li>
455     *   <li>Greenwich longitude: <b>10°43′22.5″</b></li>
456     * </ul>
457     *
458     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
459     */
460    @Test
461    public void testOslo() throws FactoryException {
462        code               = 8913;
463        name               = "Oslo";
464        aliases            = new String[] {"Kristiania"};
465        greenwichLongitude = 10.722916666666666;
466        verifyPrimeMeridian();
467    }
468
469    /**
470     * Tests “Paris RGS” prime meridian creation from the factory.
471     *
472     * <ul>
473     *   <li>EPSG prime meridian code: <b>8914</b></li>
474     *   <li>EPSG prime meridian name: <b>Paris RGS</b></li>
475     *   <li>Greenwich longitude: <b>2°20′13.95″</b></li>
476     * </ul>
477     *
478     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
479     */
480    @Test
481    public void testParisRGS() throws FactoryException {
482        code               = 8914;
483        name               = "Paris RGS";
484        aliases            = NONE;
485        greenwichLongitude = 2.3372083333333333;
486        verifyPrimeMeridian();
487    }
488
489    /**
490     * Tests “Rome” prime meridian creation from the factory.
491     *
492     * <ul>
493     *   <li>EPSG prime meridian code: <b>8906</b></li>
494     *   <li>EPSG prime meridian name: <b>Rome</b></li>
495     *   <li>Greenwich longitude: <b>12°27′08.4″</b></li>
496     * </ul>
497     *
498     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
499     */
500    @Test
501    public void testRome() throws FactoryException {
502        code               = 8906;
503        name               = "Rome";
504        aliases            = NONE;
505        greenwichLongitude = 12.452333333333334;
506        verifyPrimeMeridian();
507    }
508
509    /**
510     * Tests “Stockholm” prime meridian creation from the factory.
511     *
512     * <ul>
513     *   <li>EPSG prime meridian code: <b>8911</b></li>
514     *   <li>EPSG prime meridian name: <b>Stockholm</b></li>
515     *   <li>Greenwich longitude: <b>18°03′29.8″</b></li>
516     * </ul>
517     *
518     * @throws FactoryException if an error occurred while creating the prime meridian from the EPSG code.
519     */
520    @Test
521    public void testStockholm() throws FactoryException {
522        code               = 8911;
523        name               = "Stockholm";
524        aliases            = NONE;
525        greenwichLongitude = 18.05827777777778;
526        verifyPrimeMeridian();
527    }
528}