| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.sis.referencing; |
| |
| import java.util.Set; |
| import java.util.Map; |
| import java.util.HashMap; |
| import java.util.LinkedHashSet; |
| import java.util.Locale; |
| import org.apache.sis.referencing.datum.AbstractDatum; |
| import org.apache.sis.xml.bind.Context; |
| import org.apache.sis.xml.bind.referencing.Code; |
| import static org.apache.sis.metadata.iso.citation.Citations.EPSG; |
| |
| // Test dependencies |
| import org.junit.jupiter.api.Test; |
| import org.junit.jupiter.api.function.Executable; |
| import static org.junit.jupiter.api.Assertions.*; |
| import org.opengis.test.Validators; |
| import org.apache.sis.test.TestCase; |
| import static org.apache.sis.test.Assertions.assertMessageContains; |
| import static org.apache.sis.test.Assertions.assertSerializedEquals; |
| import static org.apache.sis.test.TestUtilities.getSingleton; |
| import static org.apache.sis.referencing.Assertions.assertRemarksEquals; |
| |
| // Specific to the main and geoapi-3.1 branches: |
| import org.opengis.referencing.ReferenceIdentifier; |
| |
| |
| /** |
| * Tests the {@link AbstractIdentifiedObject} class. |
| * |
| * @author Martin Desruisseaux (IRD, Geomatys) |
| */ |
| public final class AbstractIdentifiedObjectTest extends TestCase { |
| /** |
| * Creates a new test case. |
| */ |
| public AbstractIdentifiedObjectTest() { |
| } |
| |
| /** |
| * Creates a map of properties to be given to the {@link AbstractIdentifiedObject} constructor. |
| * The values in the map are consistent with the values expected by the {@link #validate} method. |
| * |
| * @param identifiers the value for the {@code "identifiers"} property. |
| */ |
| private static Map<String,Object> properties(final Set<ReferenceIdentifier> identifiers) { |
| final var properties = new HashMap<String,Object>(8); |
| assertNull(properties.put("name", "GRS 1980")); |
| assertNull(properties.put("identifiers", identifiers.toArray(ReferenceIdentifier[]::new))); |
| assertNull(properties.put("codespace", "EPSG")); |
| assertNull(properties.put("version", "8.3")); |
| assertNull(properties.put("alias", "International 1979")); |
| assertNull(properties.put("remarks", "Adopted by IUGG 1979 Canberra")); |
| assertNull(properties.put("remarks_fr", "Adopté par IUGG 1979 Canberra")); |
| return properties; |
| } |
| |
| /** |
| * Validates the given object created by the test methods. |
| * |
| * @param object the object to validate. |
| * @param identifiers the expected value of {@link AbstractIdentifiedObject#getIdentifiers()}. |
| * @param gmlID the expected value of {@link AbstractIdentifiedObject#getID()}. |
| * @return the value of {@link AbstractIdentifiedObject#getIdentifier()}. |
| */ |
| private static ReferenceIdentifier validate(final AbstractIdentifiedObject object, |
| final Set<ReferenceIdentifier> identifiers, final String gmlID) |
| { |
| Validators.validate(object); |
| final var name = object.getName(); |
| assertEquals("GRS 1980", name.getCode(), "name"); |
| assertEquals("EPSG", name.getCodeSpace(), "codespace"); |
| assertEquals("8.3", name.getVersion(), "version"); |
| assertEquals("International 1979", getSingleton(object.getAlias()).toString(), "aliases"); |
| assertEquals(name, getSingleton(object.getNames()), "names"); |
| assertEquals(identifiers, object.getIdentifiers(), "identifiers"); |
| assertEquals(gmlID, object.getID(), "ID"); |
| assertRemarksEquals("Adopted by IUGG 1979 Canberra", object, Locale.ENGLISH); |
| assertRemarksEquals("Adopté par IUGG 1979 Canberra", object, Locale.FRENCH); |
| final Code code = object.getIdentifier(); |
| return (code != null) ? code.getIdentifier() : null; |
| } |
| |
| /** |
| * Tests the {@link AbstractIdentifiedObject#AbstractIdentifiedObject(Map)} constructor without name. |
| * This is invalid and should throw an exception. |
| */ |
| @Test |
| @SuppressWarnings("ResultOfObjectAllocationIgnored") |
| public void testMissingName() { |
| final var properties = new HashMap<String,Object>(4); |
| assertNull(properties.put(AbstractIdentifiedObject.REMARKS_KEY, "Not a name.")); |
| final Executable test = () -> new AbstractIdentifiedObject(properties); |
| /* |
| * The message may be in any language, but shall |
| * contain at least the missing property name. |
| */ |
| IllegalArgumentException exception; |
| exception = assertThrows(IllegalArgumentException.class, test, "Should not allow unnamed object."); |
| assertMessageContains(exception, "name"); |
| |
| // Try again, with error messages forced to English. |
| assertNull(properties.put(AbstractIdentifiedObject.LOCALE_KEY, Locale.US)); |
| exception = assertThrows(IllegalArgumentException.class, test, "Should not allow unnamed object."); |
| assertEquals("Missing value for “name” property.", exception.getMessage()); |
| |
| // "code" with String value is accepted as well. |
| assertNull(properties.put("code", "Test")); |
| assertEquals("Test", new AbstractIdentifiedObject(properties).getName().getCode()); |
| } |
| |
| /** |
| * Tests the {@link AbstractIdentifiedObject#AbstractIdentifiedObject(Map)} constructor without identifier. |
| * This method compares the property values against the expected values. |
| */ |
| @Test |
| public void testWithoutIdentifier() { |
| final var identifiers = Set.<ReferenceIdentifier>of(); |
| final var object = new AbstractIdentifiedObject(properties(identifiers)); |
| final var gmlId = validate(object, identifiers, "GRS1980"); |
| assertNull(gmlId); |
| } |
| |
| /** |
| * Tests the {@link AbstractIdentifiedObject#AbstractIdentifiedObject(Map)} constructor |
| * with only one identifier. The methods of interest for this test are: |
| * |
| * <ul> |
| * <li>{@link AbstractIdentifiedObject#getIdentifiers()}</li> |
| * <li>{@link AbstractIdentifiedObject#getIdentifier()}</li> |
| * <li>{@link AbstractIdentifiedObject#getID()}</li> |
| * </ul> |
| */ |
| @Test |
| public void testWithSingleIdentifier() { |
| final var identifier = new ImmutableIdentifier(null, "EPSG", "7019"); |
| final var identifiers = Set.<ReferenceIdentifier>of(identifier); |
| final var object = new AbstractIdentifiedObject(properties(identifiers)); |
| final var gmlId = validate(object, identifiers, "epsg-7019"); |
| assertNotNull( gmlId); |
| assertEquals ("EPSG", gmlId.getCodeSpace()); |
| assertEquals ("7019", gmlId.getCode()); |
| } |
| |
| /** |
| * Tests the {@link AbstractIdentifiedObject#AbstractIdentifiedObject(Map)} constructor |
| * with more than one identifier. This method also tries a different identifier implementation |
| * than the one used by {@link #testWithSingleIdentifier()}. |
| */ |
| @Test |
| public void testWithManyIdentifiers() { |
| final var identifiers = new LinkedHashSet<ReferenceIdentifier>(4); |
| assertTrue(identifiers.add(new NamedIdentifier(EPSG, "7019"))); |
| assertTrue(identifiers.add(new NamedIdentifier(EPSG, "IgnoreMe"))); |
| final var object = new AbstractIdentifiedObject(properties(identifiers)); |
| final var gmlId = validate(object, identifiers, "epsg-7019"); |
| assertNotNull( gmlId); |
| assertEquals ("EPSG", gmlId.getCodeSpace()); |
| assertEquals ("7019", gmlId.getCode()); |
| } |
| |
| /** |
| * Tests {@link AbstractIdentifiedObject#getIdentifier()} with a sub-type of {@code AbstractIdentifiedObject}. |
| * The use of a subtype will allow {@code getIdentifier()} to build a URN and {@code getId()} to know what to |
| * insert between {@code "epsg-"} and the code. |
| */ |
| @Test |
| public void testAsSubtype() { |
| final var identifier = new NamedIdentifier(EPSG, "7019"); |
| final var identifiers = Set.<ReferenceIdentifier>of(identifier); |
| final var object = new AbstractDatum(properties(identifiers)); |
| final var gmlId = validate(object, identifiers, "epsg-datum-7019"); |
| assertNotNull( gmlId); |
| assertEquals ("EPSG", gmlId.getCodeSpace()); |
| assertEquals ("7019", gmlId.getCode()); |
| } |
| |
| /** |
| * Tests two {@code AbstractIdentifiedObject} declaring the same identifier in the same XML document. |
| * The {@code getID()} method should detect the collision and select different identifier. |
| */ |
| @Test |
| public void testIdentifierCollision() { |
| final var properties = new HashMap<String,Object>(4); |
| assertNull(properties.put("name", "GRS 1980")); |
| assertNull(properties.put("identifiers", new NamedIdentifier(EPSG, "7019"))); |
| final var o1 = new AbstractIdentifiedObject(properties); |
| final var o2 = new AbstractIdentifiedObject(properties); |
| final var o3 = new AbstractIdentifiedObject(properties); |
| final var o4 = new AbstractIdentifiedObject(properties); |
| final var context = new Context(0, null, null, null, null, null, null, null, null, null, null); |
| try { |
| final String c1, c2, c3, c4; |
| assertEquals("epsg-7019", c1 = o1.getID()); |
| assertEquals("GRS1980", c2 = o2.getID()); |
| assertEquals("GRS1980-1", c3 = o3.getID()); |
| assertEquals("GRS1980-2", c4 = o4.getID()); |
| assertSame (c1, o1.getID()); // Verify that values are remembered. |
| assertSame (c2, o2.getID()); |
| assertSame (c3, o3.getID()); |
| assertSame (c4, o4.getID()); |
| } finally { |
| context.finish(); |
| } |
| } |
| |
| /** |
| * Tests serialization. |
| */ |
| @Test |
| public void testSerialization() { |
| final var identifiers = Set.<ReferenceIdentifier>of(); |
| final var object = new AbstractIdentifiedObject(properties(identifiers)); |
| final var actual = assertSerializedEquals(object); |
| assertNotSame(object, actual); |
| assertNull(validate(actual, identifiers, "GRS1980"), "gmlId"); |
| } |
| } |