blob: 8061c269901233260438b7711dd8a5ed203ef65a [file] [log] [blame]
/*
* 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 java.util.Collections;
import org.opengis.test.Validators;
import org.opengis.referencing.ReferenceIdentifier;
import org.apache.sis.referencing.datum.AbstractDatum;
import org.apache.sis.internal.jaxb.referencing.Code;
import org.apache.sis.internal.jaxb.Context;
import org.apache.sis.test.DependsOnMethod;
import org.apache.sis.test.DependsOn;
import org.apache.sis.test.TestCase;
import org.junit.Test;
import static org.apache.sis.test.Assert.*;
import static org.apache.sis.test.TestUtilities.getSingleton;
import static org.apache.sis.metadata.iso.citation.Citations.EPSG;
/**
* Tests the {@link AbstractIdentifiedObject} class.
*
* @author Martin Desruisseaux (IRD, Geomatys)
* @version 0.7
* @since 0.4
* @module
*/
@DependsOn({
IdentifiedObjectsTest.class, NamedIdentifierTest.class,
org.apache.sis.internal.jaxb.referencing.CodeTest.class
})
public final strictfp class AbstractIdentifiedObjectTest extends TestCase {
/**
* 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 Map<String,Object> properties = new HashMap<>(8);
assertNull(properties.put("name", "GRS 1980"));
assertNull(properties.put("identifiers", identifiers.toArray(new ReferenceIdentifier[identifiers.size()])));
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 ReferenceIdentifier name = object.getName();
assertEquals("name", "GRS 1980", name.getCode());
assertEquals("codespace", "EPSG", name.getCodeSpace());
assertEquals("version", "8.3", name.getVersion());
assertEquals("aliases", "International 1979", getSingleton(object.getAlias()).toString());
assertEquals("names", name, getSingleton(object.getNames()));
assertEquals("identifiers", identifiers, object.getIdentifiers());
assertEquals("ID", gmlID, object.getID());
assertEquals("remarks", "Adopted by IUGG 1979 Canberra", object.getRemarks().toString(Locale.ENGLISH));
assertEquals("remarks_fr", "Adopté par IUGG 1979 Canberra", object.getRemarks().toString(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 Map<String,Object> properties = new HashMap<>(4);
assertNull(properties.put(AbstractIdentifiedObject.REMARKS_KEY, "Not a name."));
try {
new AbstractIdentifiedObject(properties);
fail("Should not allow unnamed object.");
} catch (IllegalArgumentException e) {
/*
* The message may be in any language, but shall
* contain at least the missing property name.
*/
final String message = e.getMessage();
assertTrue(message, message.contains("name"));
}
// Try again, with error messages forced to English.
assertNull(properties.put(AbstractIdentifiedObject.LOCALE_KEY, Locale.US));
try {
new AbstractIdentifiedObject(properties);
fail("Should not allow unnamed object.");
} catch (IllegalArgumentException e) {
assertEquals("Missing value for “name” property.", e.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 Set<ReferenceIdentifier> identifiers = Collections.emptySet();
final AbstractIdentifiedObject object = new AbstractIdentifiedObject(properties(identifiers));
final ReferenceIdentifier gmlId = validate(object, identifiers, "GRS1980");
assertNull("gmlId", 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
@DependsOnMethod("testWithoutIdentifier")
public void testWithSingleIdentifier() {
final ReferenceIdentifier identifier = new ImmutableIdentifier(null, "EPSG", "7019");
final Set<ReferenceIdentifier> identifiers = Collections.singleton(identifier);
final AbstractIdentifiedObject object = new AbstractIdentifiedObject(properties(identifiers));
final ReferenceIdentifier gmlId = validate(object, identifiers, "epsg-7019");
assertNotNull("gmlId", gmlId);
assertEquals ("gmlId.codespace", "EPSG", gmlId.getCodeSpace());
assertEquals ("gmlId.code", "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
@DependsOnMethod("testWithSingleIdentifier")
public void testWithManyIdentifiers() {
final Set<ReferenceIdentifier> identifiers = new LinkedHashSet<>(4);
assertTrue(identifiers.add(new NamedIdentifier(EPSG, "7019")));
assertTrue(identifiers.add(new NamedIdentifier(EPSG, "IgnoreMe")));
final AbstractIdentifiedObject object = new AbstractIdentifiedObject(properties(identifiers));
final ReferenceIdentifier gmlId = validate(object, identifiers, "epsg-7019");
assertNotNull("gmlId", gmlId);
assertEquals ("gmlId.codespace", "EPSG", gmlId.getCodeSpace());
assertEquals ("gmlId.code", "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
@DependsOnMethod("testWithManyIdentifiers")
public void testAsSubtype() {
final ReferenceIdentifier identifier = new NamedIdentifier(EPSG, "7019");
final Set<ReferenceIdentifier> identifiers = Collections.singleton(identifier);
final AbstractIdentifiedObject object = new AbstractDatum(properties(identifiers));
final ReferenceIdentifier gmlId = validate(object, identifiers, "epsg-datum-7019");
assertNotNull("gmlId", gmlId);
assertEquals ("gmlId.codespace", "EPSG", gmlId.getCodeSpace());
assertEquals ("gmlId.code", "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.
*
* @since 0.7
*/
@Test
@DependsOnMethod("testWithManyIdentifiers")
public void testIdentifierCollision() {
final Map<String,Object> properties = new HashMap<>(4);
assertNull(properties.put("name", "GRS 1980"));
assertNull(properties.put("identifiers", new NamedIdentifier(EPSG, "7019")));
final AbstractIdentifiedObject o1 = new AbstractIdentifiedObject(properties);
final AbstractIdentifiedObject o2 = new AbstractIdentifiedObject(properties);
final AbstractIdentifiedObject o3 = new AbstractIdentifiedObject(properties);
final AbstractIdentifiedObject o4 = new AbstractIdentifiedObject(properties);
final Context context = new Context(0, null, null, null, null, null, null, null, null);
try {
final String c1, c2, c3, c4;
assertEquals("o1", "epsg-7019", c1 = o1.getID());
assertEquals("o2", "GRS1980", c2 = o2.getID());
assertEquals("o3", "GRS1980-1", c3 = o3.getID());
assertEquals("o4", "GRS1980-2", c4 = o4.getID());
assertSame ("o1", c1, o1.getID()); // Verify that values are remembered.
assertSame ("o2", c2, o2.getID());
assertSame ("o3", c3, o3.getID());
assertSame ("o4", c4, o4.getID());
} finally {
context.finish();
}
}
/**
* Tests serialization.
*/
@Test
@DependsOnMethod("testWithoutIdentifier")
public void testSerialization() {
final Set<ReferenceIdentifier> identifiers = Collections.emptySet();
final AbstractIdentifiedObject object = new AbstractIdentifiedObject(properties(identifiers));
final AbstractIdentifiedObject actual = assertSerializedEquals(object);
assertNotSame(object, actual);
assertNull("gmlId", validate(actual, identifiers, "GRS1980"));
}
}