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.Collection; 035import org.opengis.util.Factory; 036import org.opengis.util.FactoryException; 037import org.opengis.util.GenericName; 038import org.opengis.metadata.Identifier; 039import org.opengis.referencing.AuthorityFactory; 040import org.opengis.referencing.IdentifiedObject; 041import org.opengis.test.referencing.ReferencingTestCase; 042import org.opengis.test.Configuration; 043 044import static org.junit.Assert.*; 045 046 047/** 048 * Base class for tests of EPSG definitions (2000 series). 049 * The tests for this series are designed to verify the correctness of geodetic parameters that 050 * are delivered with the software. The comparison to be taken as truth is the EPSG Dataset. 051 * 052 * @param <T> the type of objects to test. 053 * 054 * @see org.opengis.test.referencing.AuthorityFactoryTest 055 * @see org.opengis.test.TestSuite 056 * 057 * @author Martin Desruisseaux (Geomatys) 058 * @version 3.1 059 * @since 3.1 060 */ 061public strictfp abstract class AuthorityFactoryTestCase<T> extends GIGSTestCase { 062 /** 063 * The value to give to the {@link #aliases} field for meaning "no alias". 064 */ 065 static final String[] NONE = new String[0]; 066 067 /** 068 * The EPSG code of the {@code T} instance to test. 069 * This field is set by all test methods before to create and to verify the {@code T} instance. 070 * 071 * <p>This code can be compared to the identifiers returned by {@link IdentifiedObject#getIdentifiers()}.</p> 072 */ 073 public int code; 074 075 /** 076 * The name of the {@code T} instance to test, as used in the EPSG dataset. 077 * This field is set by all test methods before to create and to verify the {@code T} instance. 078 * 079 * <p>This name will be compared to the value returned by {@link IdentifiedObject#getName()}, 080 * unless {@link #isStandardNameSupported} is {@code false}.</p> 081 */ 082 public String name; 083 084 /** 085 * The expected aliases of the {@code T} instance to test, or an empty array if none. 086 * This field is set by all test methods before to create and to verify the {@code T} instance. 087 * 088 * <p>Those aliases will be compared to the values returned by {@link IdentifiedObject#getAlias()}, 089 * unless {@link #isStandardAliasSupported} is {@code false}.</p> 090 */ 091 public String[] aliases; 092 093 /** 094 * {@code true} if the tested factories support {@linkplain IdentifiedObject#getName() name}. 095 * If {@code true} (the default), then the test methods will ensure that the identified objects 096 * created by the factories declare the same name than the GIGS tests. 097 * If {@code false}, then the names are ignored. 098 */ 099 protected boolean isStandardNameSupported; 100 101 /** 102 * {@code true} if the tested factories support {@linkplain IdentifiedObject#getAlias() aliases}. 103 * If {@code true} (the default), then the test methods will ensure that the identified objects 104 * created by the factories declare at least all the aliases enumerated in the GIGS tests - additional aliases, 105 * if any, are ignored. If {@code false}, then the aliases are ignored. 106 */ 107 protected boolean isStandardAliasSupported; 108 109 /** 110 * {@code true} if the {@link IdentifiedObject} instances created indirectly by the factories 111 * are expected to have correct identification information. 112 * 113 * <div class="note"><b>Example:</b> 114 * when testing a {@link org.opengis.referencing.crs.CoordinateReferenceSystem} (CRS) object, 115 * the CRS authority code will be verified unconditionally but the authority codes of associated objects 116 * ({@link org.opengis.referencing.datum.GeodeticDatum} or {@link org.opengis.referencing.cs.CoordinateSystem}) 117 * will be verified only if this flag is {@code true}.</div> 118 */ 119 protected boolean isDependencyIdentificationSupported; 120 121 /** 122 * {@code true} if the factory support creation of deprecated objects. 123 */ 124 protected boolean isDeprecatedObjectCreationSupported; 125 126 /** 127 * {@code true} if the tested object is particularly important to E&P industry. 128 * This field is set at the beginning of test methods. 129 */ 130 boolean important; 131 132 /** 133 * Creates a new test which will use the given factories to execute. 134 * 135 * @param factories the factories to be used by the test. Those factories passed verbatim to the 136 * {@linkplain ReferencingTestCase#ReferencingTestCase(Factory[]) super-class constructor}. 137 */ 138 protected AuthorityFactoryTestCase(final AuthorityFactory... factories) { 139 super(factories); 140 @SuppressWarnings("unchecked") 141 final boolean[] isEnabled = getEnabledFlags( 142 Configuration.Key.isStandardNameSupported, 143 Configuration.Key.isStandardAliasSupported, 144 Configuration.Key.isDependencyIdentificationSupported, 145 Configuration.Key.isDeprecatedObjectCreationSupported); 146 isStandardNameSupported = isEnabled[0]; 147 isStandardAliasSupported = isEnabled[1]; 148 isDependencyIdentificationSupported = isEnabled[2]; 149 isDeprecatedObjectCreationSupported = isEnabled[3]; 150 } 151 152 /** 153 * Returns information about the configuration of the test which has been run. 154 * This method returns a map containing: 155 * 156 * <ul> 157 * <li>All the following values associated to the {@link org.opengis.test.Configuration.Key} of the same name: 158 * <ul> 159 * <li>{@link #isStandardNameSupported}</li> 160 * <li>{@link #isStandardAliasSupported}</li> 161 * <li>{@link #isDependencyIdentificationSupported}</li> 162 * <li>The factories used by the test (provided by subclasses)</li> 163 * </ul> 164 * </li> 165 * </ul> 166 * 167 * @return the configuration of the test being run. 168 */ 169 @Override 170 public Configuration configuration() { 171 final Configuration op = super.configuration(); 172 assertNull(op.put(Configuration.Key.isStandardNameSupported, isStandardNameSupported)); 173 assertNull(op.put(Configuration.Key.isStandardAliasSupported, isStandardAliasSupported)); 174 assertNull(op.put(Configuration.Key.isDependencyIdentificationSupported, isDependencyIdentificationSupported)); 175 return op; 176 } 177 178 /** 179 * Returns the instance to be tested. When this method is invoked for the first time, it creates the instance 180 * to test by invoking a {@code createXXX(String)} method from the user-specified {@link AuthorityFactory} 181 * with the current {@link #code} value in argument. The created object is then cached and returned in 182 * subsequent invocations of this method. 183 * 184 * <p>Usually, each test method creates exactly one object. But a few (relatively rare) tests may create 185 * more than one object. In such case, the instance returned by this method may vary.</p> 186 * 187 * @return the instance to test. 188 * @throws FactoryException if an error occurred while creating the identified object. 189 */ 190 public abstract T getIdentifiedObject() throws FactoryException; 191 192 /** 193 * Returns a name of the given object that can be compared against the expected name. 194 * The default implementation returns {@code object.getName().getCode()} or {@code null} 195 * if the given object, its name or its code is null. 196 * 197 * <p>Subclasses can override this method when testing an {@link AuthorityFactory} implementation 198 * which is known to use slightly different name than the one used in the EPSG database, or if the 199 * implementation stores the EPSG name as an {@linkplain IdentifiedObject#getAlias() alias} instead 200 * than as the {@linkplain IdentifiedObject#getName() primary name}.</p> 201 * 202 * <div class="note"><b>Example:</b> if an implementation replaces all spaces by underscores, 203 * then a subclass testing that implementation could override this method as below: 204 * 205 * <pre> @Override 206 * protected String getVerifiableName(IdentifiedObject object) { 207 * return super.getVerifiableName().replace(' ', '_'); 208 * }</pre></div> 209 * 210 * Note that if the object names are too different for being compared, then subclasses can also 211 * disable name comparisons by setting {@link #isStandardNameSupported} to {@code false}. 212 * 213 * @param object the object from which to get a name than can be verified against the expected name. 214 * @return the name of the given object, eventually modified in order to match the expected name. 215 * 216 * @see #isStandardNameSupported 217 * @see #isStandardAliasSupported 218 */ 219 protected String getVerifiableName(final IdentifiedObject object) { 220 return getName(object); 221 } 222 223 /** 224 * Compares the given generic names with the given set of expected aliases. 225 * This method verifies that the given collection contains at least the expected aliases. 226 * However the collection may contain additional aliases, which will be ignored. 227 * 228 * @param message the prefix of the message to show in case of failure. 229 * @param expected the expected aliases. 230 * @param aliases the actual aliases. 231 */ 232 static void assertContainsAll(final String message, final String[] expected, 233 final Collection<GenericName> aliases) 234 { 235 assertNotNull(message, aliases); 236next: for (final String search : expected) { 237 for (final GenericName alias : aliases) { 238 final String tip = alias.tip().toString(); 239 if (search.equalsIgnoreCase(tip)) { 240 continue next; 241 } 242 } 243 fail(message + ": alias not found: " + search); 244 } 245 } 246 247 /** 248 * Ensures that the given collection contains at least one identifier having the given 249 * codespace (ignoring case) and the given code value. 250 * 251 * @param message the message to show in case of failure. 252 * @param codespace the code space of identifiers to search. 253 * @param expected the expected identifier code. 254 * @param identifiers the actual identifiers. 255 */ 256 static void assertContainsCode(final String message, final String codespace, final int expected, 257 final Collection<? extends Identifier> identifiers) 258 { 259 assertNotNull(message, identifiers); 260 int found = 0; 261 for (final Identifier id : identifiers) { 262 if (codespace.equalsIgnoreCase(id.getCodeSpace().trim())) { 263 found++; 264 try { 265 assertEquals(message, expected, Integer.parseInt(id.getCode())); 266 } catch (NumberFormatException e) { 267 fail(message + ".getCode(): expected " + expected + 268 " but got a non-numerical value: " + e); 269 } 270 } 271 } 272 assertEquals(message + ": occurrence of " + codespace + ':' + expected, 1, found); 273 } 274}