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; 033 034import java.util.Map; 035import java.util.List; 036import java.util.ArrayList; 037import java.util.Collections; 038import java.util.LinkedHashMap; 039import java.util.Objects; 040import java.io.Serializable; 041 042import org.opengis.util.Factory; 043import org.opengis.util.CodeList; 044import org.opengis.util.GenericName; 045import org.opengis.util.InternationalString; 046import org.opengis.geometry.DirectPosition; 047import org.opengis.referencing.IdentifiedObject; 048import org.opengis.referencing.cs.CSFactory; 049import org.opengis.referencing.cs.CSAuthorityFactory; 050import org.opengis.referencing.crs.CRSFactory; 051import org.opengis.referencing.crs.CRSAuthorityFactory; 052import org.opengis.referencing.datum.DatumFactory; 053import org.opengis.referencing.datum.DatumAuthorityFactory; 054import org.opengis.referencing.operation.Matrix; 055import org.opengis.referencing.operation.MathTransform; 056import org.opengis.referencing.operation.MathTransformFactory; 057import org.opengis.referencing.operation.CoordinateOperationFactory; 058import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory; 059 060 061/** 062 * Contains information about the test environment, like available factories and disabled tests. 063 * {@code Configuration} is used in two places: 064 * 065 * <ul> 066 * <li>Before each test is executed, {@link ImplementationDetails} can provide configuration information. 067 * For example an implementation can declare that it does not support the calculation of transform derivative.</li> 068 * <li>After each test is executed, {@link TestListener} can obtain the actual configuration used by the test. 069 * For example listeners can know which {@link Factory} instances were used.</li> 070 * </ul> 071 * 072 * This class provides {@link #get get}, {@link #put put} and {@link #remove remove} methods 073 * similar to those of the {@code java.util.Map} interface, with the addition of type-safety. 074 * The pre-defined keys are listed below: 075 * 076 * <table class="ogc"> 077 * <caption>Configuration properties</caption> 078 * <tr> 079 * <th>Supported features</th> 080 * <th>Factories</th> 081 * <th>Other</th> 082 * </tr> 083 * <tr><td valign="top"> 084 * {@link Key#isMultiLocaleSupported isMultiLocaleSupported}<br> 085 * {@link Key#isMixedNameSyntaxSupported isMixedNameSyntaxSupported}<br> 086 * {@link Key#isStandardNameSupported isStandardNameSupported}<br> 087 * {@link Key#isStandardAliasSupported isStandardAliasSupported}<br> 088 * {@link Key#isDependencyIdentificationSupported isDependencyIdentificationSupported}<br> 089 * {@link Key#isDoubleToDoubleSupported isDoubleToDoubleSupported}<br> 090 * {@link Key#isFloatToFloatSupported isFloatToFloatSupported}<br> 091 * {@link Key#isDoubleToFloatSupported isDoubleToFloatSupported}<br> 092 * {@link Key#isFloatToDoubleSupported isFloatToDoubleSupported}<br> 093 * {@link Key#isOverlappingArraySupported isOverlappingArraySupported}<br> 094 * {@link Key#isInverseTransformSupported isInverseTransformSupported}<br> 095 * {@link Key#isDerivativeSupported isDerivativeSupported}<br> 096 * {@link Key#isNonSquareMatrixSupported isNonSquareMatrixSupported}<br> 097 * {@link Key#isNonBidimensionalSpaceSupported isNonBidimensionalSpaceSupported}<br> 098 * {@link Key#isAxisSwappingSupported isAxisSwappingSupported}</td><td valign="top"> 099 * {@link Key#mtFactory mtFactory}<br> 100 * {@link Key#copFactory copFactory}<br> 101 * {@link Key#copAuthorityFactory copAuthorityFactory}<br> 102 * {@link Key#crsFactory crsFactory}<br> 103 * {@link Key#crsAuthorityFactory crsAuthorityFactory}<br> 104 * {@link Key#csFactory csFactory}<br> 105 * {@link Key#csAuthorityFactory csAuthorityFactory}<br> 106 * {@link Key#datumFactory datumFactory}<br> 107 * {@link Key#datumAuthorityFactory datumAuthorityFactory}<br> 108 * {@link Key#isFactoryPreservingUserValues isFactoryPreservingUserValues}</td><td valign="top"> 109 * {@link Key#validators validators}<br> 110 * {@link Key#isValidationEnabled isValidationEnabled}<br> 111 * {@link Key#isToleranceRelaxed isToleranceRelaxed} 112 * </td></tr></table> 113 * 114 * @see TestCase#configuration() 115 * @see ImplementationDetails#configuration(Factory[]) 116 * 117 * @author Martin Desruisseaux (Geomatys) 118 * @version 3.1 119 * @since 3.1 120 */ 121public class Configuration implements Serializable { 122 /** 123 * For cross-version compatibility. 124 */ 125 private static final long serialVersionUID = 4725836424438658750L; 126 127 /** 128 * The map were to store the configuration entries. 129 */ 130 private final Map<Key<?>,Object> properties; 131 132 /** 133 * An unmodifiable view of the {@link #properties} map. 134 * 135 * @see #map() 136 */ 137 private final Map<Key<?>,Object> unmodifiable; 138 139 /** 140 * Creates a new, initially empty, configuration map. 141 */ 142 public Configuration() { 143 properties = new LinkedHashMap<>(); 144 unmodifiable = Collections.unmodifiableMap(properties); 145 } 146 147 /** 148 * Creates a new configuration with the same mappings as the specified configuration. 149 * 150 * @param toCopy the configuration whose mappings are to be placed in this map. 151 * @throws NullPointerException if the specified configuration is null. 152 */ 153 public Configuration(final Configuration toCopy) { 154 properties = new LinkedHashMap<>(toCopy.properties); 155 unmodifiable = Collections.unmodifiableMap(properties); 156 } 157 158 /** 159 * Returns the value to which the specified key is mapped, or {@code null} 160 * if this map contains no mapping for the key. 161 * 162 * @param <T> the value type, which is determined by the key. 163 * @param key the key whose associated value is to be returned. 164 * @return the value to which the specified key is mapped, or {@code null} 165 * if this map contains no mapping for the key. 166 * @throws NullPointerException if the specified key is null. 167 */ 168 public <T> T get(final Key<T> key) { 169 return key.type.cast(properties.get(key)); 170 } 171 172 /** 173 * Removes the mapping for a key from this map if it is present. 174 * 175 * @param <T> the value type, which is determined by the key. 176 * @param key the key whose associated value is to be removed. 177 * @return the value which was previously mapped to the specified key, or {@code null}. 178 * @throws NullPointerException if the specified key is null. 179 */ 180 public <T> T remove(final Key<T> key) { 181 return key.type.cast(properties.remove(key)); 182 } 183 184 /** 185 * Associates the specified value with the specified key in this map. 186 * 187 * @param <T> the value type, which is determined by the key. 188 * @param key the key with which the specified value is to be associated. 189 * @param value the value to be associated with the specified key (can be {@code null}). 190 * @return the previous value associated with {@code key}, or {@code null} if there was no mapping for that key. 191 * @throws NullPointerException if the specified key is null. 192 */ 193 public <T> T put(final Key<T> key, final T value) { 194 return key.type.cast(properties.put(key, value)); 195 } 196 197 /** 198 * Declares that all given operations are unsupported. This is a convenience method 199 * invoking <code>{@linkplain #put(Key,Object) put}(key, Boolean.False)</code> for 200 * all operations given in argument. 201 * 202 * @param operations the operations to declare as unsupported. 203 * @throws NullPointerException if a specified key is null. 204 */ 205 @SafeVarargs 206 public final void unsupported(final Key<Boolean>... operations) { 207 for (final Key<Boolean> operation : operations) { 208 put(operation, Boolean.FALSE); 209 } 210 } 211 212 /** 213 * Returns all entries as an unmodifiable map. 214 * 215 * @return a map view over the entries in this {@code Configuration} object. 216 */ 217 @SuppressWarnings("ReturnOfCollectionOrArrayField") 218 public Map<Key<?>,Object> map() { 219 return unmodifiable; 220 } 221 222 /** 223 * Returns a hash code value for this configuration map. 224 */ 225 @Override 226 public int hashCode() { 227 return properties.hashCode() ^ (int) serialVersionUID; 228 } 229 230 /** 231 * Compares this configuration with the given object for equality. 232 * 233 * @param other the other object to compare with this configuration. 234 */ 235 @Override 236 public boolean equals(final Object other) { 237 if (other instanceof Configuration) { 238 return properties.equals(((Configuration) other).properties); 239 } 240 return false; 241 } 242 243 /** 244 * Returns a string representation of this configuration map. 245 */ 246 @Override 247 public String toString() { 248 return properties.toString(); 249 } 250 251 /** 252 * Type-safe keys that can be used in a {@link Configuration} map. 253 * This code list is extensible: users can create new instances by 254 * invoking the {@link #valueOf(String, Class)} static method. 255 * 256 * <p><b><u>Note on field names:</u></b><br> 257 * Every constants declared in this class have a name matching exactly the field names in 258 * {@link TestCase} subclasses. This is a departure from the usual <cite>"all upper-case 259 * letters"</cite> convention, but make the relationship with fields more obvious 260 * and the parsing of {@link java.util.Properties} files easier.</p> 261 * 262 * @param <T> the type of values associated with the key. 263 * 264 * @author Martin Desruisseaux (Geomatys) 265 * @version 3.1 266 * @since 3.1 267 */ 268 public static final class Key<T> extends CodeList<Key<?>> { 269 /** 270 * For cross-version compatibility. 271 */ 272 private static final long serialVersionUID = -5920183652024058448L; 273 274 /** 275 * The list of all keys created. Contains the key constants declared in this class, and 276 * any key that the user may have created. Must be declared before any key declaration. 277 */ 278 private static final List<Key<?>> VALUES = new ArrayList<>(32); 279 280 /* 281 * If new constants are added, please remember to update the Configuration class javadoc. 282 */ 283 284 /** 285 * Whether the {@link InternationalString} instances can support more than one {@link java.util.Locale}. 286 * If {@code false}, then the factory method may retain only one locale among the set of user-provided 287 * localized strings. 288 * 289 * @see org.opengis.test.util.NameTest#isMultiLocaleSupported 290 */ 291 public static final Key<Boolean> isMultiLocaleSupported = 292 new Key<>(Boolean.class, "isMultiLocaleSupported"); 293 294 /** 295 * Whether the {@link GenericName} instances can apply different syntax rules in different 296 * parts of their name. If {@code true}, then URI using different separators in different 297 * parts of their name (e.g. {@code ":"}, {@code "."}, {@code "/"} and {@code "#"} 298 * in {@code "http://www.opengis.net/gml/srs/epsg.xml#4326"}) are supported. 299 * If {@code false}, then only a single rule can be applied to the name as a whole 300 * (e.g. only the {@code ":"} separator is used in {@code "urn:ogc:def:crs:epsg:4326"}). 301 * 302 * @see org.opengis.test.util.NameTest#isMixedNameSyntaxSupported 303 */ 304 public static final Key<Boolean> isMixedNameSyntaxSupported = 305 new Key<>(Boolean.class, "isMixedNameSyntaxSupported"); 306 307 /** 308 * Whether the {@link IdentifiedObject} instances have {@linkplain IdentifiedObject#getName() 309 * names} matching the names declared in the EPSG database. 310 * 311 * @see org.opengis.test.referencing.gigs.AuthorityFactoryTestCase#isStandardNameSupported 312 */ 313 public static final Key<Boolean> isStandardNameSupported = 314 new Key<>(Boolean.class, "isStandardNameSupported"); 315 316 /** 317 * Whether the {@link IdentifiedObject} instances have at least the 318 * {@linkplain IdentifiedObject#getAlias() aliases} declared in the EPSG database. 319 * 320 * @see org.opengis.test.referencing.gigs.AuthorityFactoryTestCase#isStandardAliasSupported 321 */ 322 public static final Key<Boolean> isStandardAliasSupported = 323 new Key<>(Boolean.class, "isStandardAliasSupported"); 324 325 /** 326 * Whether the {@link IdentifiedObject} instances created indirectly by the factories 327 * are expected to have correct identification information. 328 * 329 * @see org.opengis.test.referencing.gigs.AuthorityFactoryTestCase#isDependencyIdentificationSupported 330 */ 331 public static final Key<Boolean> isDependencyIdentificationSupported = 332 new Key<>(Boolean.class, "isDependencyIdentificationSupported"); 333 334 /** 335 * Whether the authority factory supports creation of deprecated {@link IdentifiedObject} instances. 336 * 337 * @see org.opengis.test.referencing.gigs.AuthorityFactoryTestCase#isDeprecatedObjectCreationSupported 338 */ 339 public static final Key<Boolean> isDeprecatedObjectCreationSupported = 340 new Key<>(Boolean.class, "isDeprecatedObjectCreationSupported"); 341 342 /** 343 * Whether {@link MathTransform#transform(double[], int, double[], int, int)} is supported. 344 * Implementors can set the value for this key to {@code false} in order to test 345 * {@link MathTransform} instances which are not yet fully implemented. 346 * 347 * @see org.opengis.test.referencing.TransformTestCase#isDoubleToDoubleSupported 348 */ 349 public static final Key<Boolean> isDoubleToDoubleSupported = 350 new Key<>(Boolean.class, "isDoubleToDoubleSupported"); 351 352 /** 353 * Whether {@link MathTransform#transform(float[], int, float[], int, int)} is supported. 354 * Implementors can set the value for this key to {@code false} in order to test 355 * {@link MathTransform} instances which are not yet fully implemented. 356 * 357 * @see org.opengis.test.referencing.TransformTestCase#isFloatToFloatSupported 358 */ 359 public static final Key<Boolean> isFloatToFloatSupported = 360 new Key<>(Boolean.class, "isFloatToFloatSupported"); 361 362 /** 363 * Whether {@link MathTransform#transform(double[], int, float[], int, int)} is supported. 364 * Implementors can set the value for this key to {@code false} in order to test 365 * {@link MathTransform} instances which are not yet fully implemented. 366 * 367 * @see org.opengis.test.referencing.TransformTestCase#isDoubleToFloatSupported 368 */ 369 public static final Key<Boolean> isDoubleToFloatSupported = 370 new Key<>(Boolean.class, "isDoubleToFloatSupported"); 371 372 /** 373 * Whether {@link MathTransform#transform(float[], int, double[], int, int)} is supported. 374 * Implementors can set the value for this key to {@code false} in order to test 375 * {@link MathTransform} instances which are not yet fully implemented. 376 * 377 * @see org.opengis.test.referencing.TransformTestCase#isFloatToDoubleSupported 378 */ 379 public static final Key<Boolean> isFloatToDoubleSupported = 380 new Key<>(Boolean.class, "isFloatToDoubleSupported"); 381 382 /** 383 * Whether source and destination arrays can overlap in {@link MathTransform} operations. 384 * Overlapping occur when: 385 * 386 * <ul> 387 * <li>The invoked method is one of the following: 388 * <ul> 389 * <li>{@link MathTransform#transform(double[], int, double[], int, int)}</li> 390 * <li>{@link MathTransform#transform(float[], int, float[], int, int)}</li> 391 * </ul></li> 392 * <li>The {@code srcPts} and {@code dstPts} arguments are references to the same array.</li> 393 * <li>The {@code srcOff} and {@code dstOff} offsets are such that the source region of 394 * the array overlaps with the target region.</li> 395 * </ul> 396 * 397 * @see org.opengis.test.referencing.TransformTestCase#isOverlappingArraySupported 398 */ 399 public static final Key<Boolean> isOverlappingArraySupported = 400 new Key<>(Boolean.class, "isOverlappingArraySupported"); 401 402 /** 403 * Whether {@link MathTransform#inverse()} is supported. 404 * Implementors can set the value for this key to {@code false} in order to test 405 * {@link MathTransform} instances which are not yet fully implemented. 406 * 407 * @see org.opengis.test.referencing.TransformTestCase#isInverseTransformSupported 408 */ 409 public static final Key<Boolean> isInverseTransformSupported = 410 new Key<>(Boolean.class, "isInverseTransformSupported"); 411 412 /** 413 * Whether {@link MathTransform#derivative(DirectPosition)} is supported. 414 * Implementors can set the value for this key to {@code false} in order to test 415 * {@link MathTransform} instances which are not yet fully implemented. 416 * 417 * @see org.opengis.test.referencing.TransformTestCase#isDerivativeSupported 418 */ 419 public static final Key<Boolean> isDerivativeSupported = 420 new Key<>(Boolean.class, "isDerivativeSupported"); 421 422 /** 423 * Whether {@link MathTransformFactory#createAffineTransform(Matrix)} accepts non-square matrixes. 424 * 425 * @see org.opengis.test.referencing.AffineTransformTest#isNonSquareMatrixSupported 426 */ 427 public static final Key<Boolean> isNonSquareMatrixSupported = 428 new Key<>(Boolean.class, "isNonSquareMatrixSupported"); 429 430 /** 431 * Whether {@link MathTransformFactory} can create transforms between spaces that are 432 * not two-dimensional. If {@code true}, then the tested spaces may be one-dimensional 433 * (typically elevation or time), three-dimensional or four-dimensional. 434 * 435 * @see org.opengis.test.referencing.AffineTransformTest#isNonBidimensionalSpaceSupported 436 */ 437 public static final Key<Boolean> isNonBidimensionalSpaceSupported = 438 new Key<>(Boolean.class, "isNonBidimensionalSpaceSupported"); 439 440 /** 441 * Whether (<var>y</var>,<var>x</var>) axis order is supported. This axis swapping is not 442 * supported, then the tests that would normally expect (<var>y</var>,<var>x</var>) axis 443 * order or <cite>South Oriented</cite> CRS will rather use the (<var>x</var>,<var>y</var>) 444 * axis order and <cite>North Oriented</cite> CRS in their test. 445 * 446 * @see org.opengis.test.referencing.AuthorityFactoryTest#isAxisSwappingSupported 447 */ 448 public static final Key<Boolean> isAxisSwappingSupported = 449 new Key<>(Boolean.class, "isAxisSwappingSupported"); 450 451 /** 452 * Whether the test methods can invoke a <code>{@linkplain TestCase#validators validators}.validate(…)}</code> 453 * method. GeoAPI allows to disable the validation checks in some tests where strict conformance to a standard 454 * is relaxed. 455 * 456 * <div class="note"><b>Example:</b> 457 * ISO 19111 (the <cite>referencing by coordinates</cite> abstract model) specifies that the name of 458 * the latitude axis in a geographic CRS shall be <cite>"Geodetic latitude"</cite> while ISO 19162 459 * (a.k.a <cite>Well Known Text 2</cite>) specifies <cite>"Latitude"</cite>. Consequently the GeoAPI 460 * conformance module allows implementor to disable the check for ISO 19111 conformance if their WKT 461 * parser does not adapt the parsed CRS objects to the ISO 19111 axis naming.</div> 462 * 463 * @see org.opengis.test.wkt.CRSParserTest#isValidationEnabled 464 */ 465 public static final Key<Boolean> isValidationEnabled = 466 new Key<>(Boolean.class, "isValidationEnabled"); 467 468 /** 469 * Whether the tolerance threshold of a {@link org.opengis.test.referencing.TransformTestCase} 470 * has been relaxed. This information is determined after test execution. 471 */ 472 public static final Key<Boolean> isToleranceRelaxed = 473 new Key<>(Boolean.class, "isToleranceRelaxed"); 474 475 /** 476 * The provider of {@linkplain Units units} to use for tests. If this configuration hint 477 * is not specified, then the {@linkplain Units#getDefault() default instance} is used. 478 */ 479 public static final Key<Units> units = new Key<>(Units.class, "units"); 480 481 /** 482 * The {@linkplain MathTransformFactory Math Transform factory} instance used for a test. 483 * 484 * @see org.opengis.test.referencing.AffineTransformTest#mtFactory 485 * @see org.opengis.test.referencing.ParameterizedTransformTest#mtFactory 486 * @see org.opengis.test.referencing.PseudoEpsgFactory#mtFactory 487 */ 488 public static final Key<MathTransformFactory> mtFactory = 489 new Key<>(MathTransformFactory.class, "mtFactory"); 490 491 /** 492 * The {@linkplain CoordinateOperationFactory Coordinate Operation factory} instance used for a test. 493 * 494 * @see org.opengis.test.referencing.PseudoEpsgFactory#copFactory 495 * @see org.opengis.test.referencing.gigs.GIGS3005#copFactory 496 */ 497 public static final Key<CoordinateOperationFactory> copFactory = 498 new Key<>(CoordinateOperationFactory.class, "copFactory"); 499 500 /** 501 * The {@linkplain CoordinateOperationAuthorityFactory Coordinate Operation authority factory} 502 * instance used for a test. 503 * 504 * @see org.opengis.test.referencing.gigs.AuthorityFactoryTestCase 505 */ 506 public static final Key<CoordinateOperationAuthorityFactory> copAuthorityFactory = 507 new Key<>(CoordinateOperationAuthorityFactory.class, "copAuthorityFactory"); 508 509 /** 510 * The {@linkplain CRSFactory Coordinate Reference System factory} instance used for a test. 511 * 512 * @see org.opengis.test.referencing.ObjectFactoryTest#crsFactory 513 * @see org.opengis.test.referencing.PseudoEpsgFactory#crsFactory 514 * @see org.opengis.test.referencing.gigs.GIGS3004#crsFactory 515 */ 516 public static final Key<CRSFactory> crsFactory = 517 new Key<>(CRSFactory.class, "crsFactory"); 518 519 /** 520 * The {@linkplain CRSAuthorityFactory Coordinate Reference System authority factory} 521 * instance used for a test. 522 * 523 * @see org.opengis.test.referencing.AuthorityFactoryTest#crsAuthorityFactory 524 * @see org.opengis.test.referencing.gigs.AuthorityFactoryTestCase 525 */ 526 public static final Key<CRSAuthorityFactory> crsAuthorityFactory = 527 new Key<>(CRSAuthorityFactory.class, "crsAuthorityFactory"); 528 529 /** 530 * The {@linkplain CSFactory Coordinate System factory} instance used for a test. 531 * 532 * @see org.opengis.test.referencing.ObjectFactoryTest#csFactory 533 * @see org.opengis.test.referencing.PseudoEpsgFactory#csFactory 534 */ 535 public static final Key<CSFactory> csFactory = 536 new Key<>(CSFactory.class, "csFactory"); 537 538 /** 539 * The {@linkplain CSAuthorityFactory Coordinate System authority factory} instance used for a test. 540 * 541 * @see org.opengis.test.referencing.AuthorityFactoryTest#csAuthorityFactory 542 * @see org.opengis.test.referencing.gigs.AuthorityFactoryTestCase 543 */ 544 public static final Key<CSAuthorityFactory> csAuthorityFactory = 545 new Key<>(CSAuthorityFactory.class, "csAuthorityFactory"); 546 547 /** 548 * The {@linkplain DatumFactory Datum factory} instance used for a test. 549 * 550 * @see org.opengis.test.referencing.ObjectFactoryTest#datumFactory 551 * @see org.opengis.test.referencing.PseudoEpsgFactory#datumFactory 552 * @see org.opengis.test.referencing.gigs.GIGS3003#datumFactory 553 */ 554 public static final Key<DatumFactory> datumFactory = 555 new Key<>(DatumFactory.class, "datumFactory"); 556 557 /** 558 * The {@linkplain DatumAuthorityFactory Datum authority factory} instance used for a test. 559 * 560 * @see org.opengis.test.referencing.AuthorityFactoryTest#datumAuthorityFactory 561 * @see org.opengis.test.referencing.gigs.AuthorityFactoryTestCase 562 */ 563 public static final Key<DatumAuthorityFactory> datumAuthorityFactory = 564 new Key<>(DatumAuthorityFactory.class, "datumAuthorityFactory"); 565 566 /** 567 * Whether the objects created by the tested {@link org.opengis.referencing.ObjectFactory} use the 568 * specified values <i>as-is</i>. This flag should be set to {@code false} if the factory performs 569 * any of the following operations: 570 * 571 * <ul> 572 * <li>Convert numerical values from user-provided linear units to metres.</li> 573 * <li>Convert numerical values from user-provided angular units to degrees.</li> 574 * <li>Change ellipsoid second defining parameter 575 * (e.g. from <i>semi-major axis length</i> to an equivalent <i>inverse flattening factor</i>).</li> 576 * <li>Change map projection parameters 577 * (e.g. from <i>standard parallel</i> to an equivalent <i>scale factor</i>).</li> 578 * <li>Any other change that preserve numeric equivalence.</li> 579 * </ul> 580 * 581 * If the factory does not perform any of the above conversions, then this flag can be {@code true}. 582 * 583 * @see org.opengis.test.referencing.gigs.UserObjectFactoryTestCase#isFactoryPreservingUserValues 584 */ 585 public static final Key<Boolean> isFactoryPreservingUserValues = 586 new Key<>(Boolean.class, "isFactoryPreservingUserValues"); 587 588 /** 589 * The set of {@link Validator} instances to use for validating objects. 590 * If no value is provided for this key, then the system-wide 591 * {@linkplain Validators#DEFAULT default validators} are used. 592 * 593 * @see Validators#DEFAULT 594 */ 595 public static final Key<ValidatorContainer> validators = 596 new Key<>(ValidatorContainer.class, "validators"); 597 598 /** 599 * The type of values associated to this key. 600 */ 601 final Class<T> type; 602 603 /** 604 * Constructs a key with the given name. The new key is 605 * automatically added to the list returned by {@link #values}. 606 * 607 * @param type the type of values associated to the new key. 608 * @param name the key name. This name must not be in use by any other key. 609 */ 610 private Key(final Class<T> type, final String name) { 611 super(name, VALUES); 612 this.type = type; 613 } 614 615 /** 616 * Returns the key that matches the given name, or returns a new one if none match it. 617 * If no existing instance is found, then a new one is created for the given name and 618 * type. 619 * 620 * @param <T> the type of the key to fetch. 621 * @param type the type of the key to fetch. 622 * @param name the name of the key to fetch or to create. 623 * @return a key matching the given name. 624 * @throws NullPointerException if the given name or type is {@code null}. 625 * @throws ClassCastException if a key is found but the type is not assignable to the given type. 626 */ 627 @SuppressWarnings("unchecked") 628 public static <T> Key<? extends T> valueOf(final String name, final Class<T> type) { 629 Objects.requireNonNull(type, "type"); 630 final Key<?> key = valueOf(Key.class, (code) -> name.equals(code.name()), null); 631 if (key != null) { 632 if (!type.isAssignableFrom(key.type)) { 633 throw new ClassCastException(key.type.getName()); 634 } 635 return (Key) key; 636 } 637 return new Key<>(type, name); 638 } 639 640 /** 641 * Returns the list of {@code Key}s. 642 * 643 * @return the list of keys declared in the current JVM. 644 */ 645 public static Key<?>[] values() { 646 synchronized (VALUES) { 647 return VALUES.toArray(new Key<?>[VALUES.size()]); 648 } 649 } 650 651 /** 652 * Returns the list of codes of the same kind than this code list element. 653 * Invoking this method is equivalent to invoking {@link #values()}, except that 654 * this method can be invoked on an instance of the parent {@code CodeList} class. 655 * 656 * @return all code {@linkplain #values() values} for this code list. 657 */ 658 @Override 659 public Key<?>[] family() { 660 return values(); 661 } 662 663 /** 664 * Returns the type of values assigned to this key. 665 * 666 * @return the value type. 667 */ 668 public Class<T> valueType() { 669 return type; 670 } 671 } 672}