blob: 669a1cc66892cadfc7508bb9cc3e6d09eeebc8e2 [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.xml.bind.referencing;
import java.util.List;
import java.util.Map;
import java.util.IdentityHashMap;
import jakarta.xml.bind.JAXBException;
import org.opengis.metadata.Identifier;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.ParameterDescriptorGroup;
import org.opengis.parameter.GeneralParameterDescriptor;
import org.apache.sis.parameter.DefaultParameterDescriptor;
import org.apache.sis.parameter.DefaultParameterDescriptorGroup;
import org.apache.sis.parameter.ParameterBuilder;
import org.apache.sis.referencing.operation.provider.Mercator1SP;
import org.apache.sis.util.privy.UnmodifiableArrayList;
import org.apache.sis.measure.Units;
import org.apache.sis.xml.Namespaces;
import static org.apache.sis.metadata.iso.citation.Citations.EPSG;
import static org.apache.sis.xml.bind.referencing.CC_GeneralOperationParameter.DEFAULT_OCCURRENCE;
// Test dependencies
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import org.apache.sis.xml.test.TestCase;
/**
* Tests {@link CC_OperationParameterGroup} static methods.
* Also opportunistically tests {@link CC_OperationMethod} because we use the same data.
*
* @author Martin Desruisseaux (Geomatys)
*
* @see <a href="http://issues.apache.org/jira/browse/SIS-290">SIS-290</a>
*/
public final class CC_OperationParameterGroupTest extends TestCase {
/**
* Creates a new test case.
*/
public CC_OperationParameterGroupTest() {
}
/**
* The remark to associate to the "Latitude of natural origin" parameter.
* Should be different than the comment stored in {@link Mercator1SP} in
* order to test parameter merges.
*/
private static final String REMARK = "Always zero for this projection.";
/**
* Creates a parameter descriptor group as unmarshalled by JAXB, without {@code valueClass}.
*
* @throws JAXBException if this method failed to create test data.
*/
private DefaultParameterDescriptorGroup unmarshal() throws JAXBException {
return unmarshal(DefaultParameterDescriptorGroup.class,
"<gml:OperationParameterGroup xmlns:gml=\"" + Namespaces.GML + "\">\n" +
" <gml:name>Mercator (1SP)</gml:name>\n" +
" <gml:parameter>\n" +
" <gml:OperationParameter gml:id=\"epsg-parameter-8801\">\n" +
" <gml:identifier codeSpace=\"IOGP\">urn:ogc:def:parameter:EPSG::8801</gml:identifier>\n" +
" <gml:name codeSpace=\"EPSG\">Latitude of natural origin</gml:name>\n" +
" <gml:remarks>" + REMARK + "</gml:remarks>\n" +
" </gml:OperationParameter>\n" +
" </gml:parameter>\n" +
" <gml:parameter>\n" +
" <gml:OperationParameter gml:id=\"epsg-parameter-8802\">\n" +
" <gml:identifier codeSpace=\"IOGP\">urn:ogc:def:parameter:EPSG::8802</gml:identifier>\n" +
" <gml:name codeSpace=\"EPSG\">Longitude of natural origin</gml:name>\n" +
" </gml:OperationParameter>\n" +
" </gml:parameter>\n" +
// There is more parameters in a Mercator projection, but 2 is enough for this test.
"</gml:OperationParameterGroup>");
}
/**
* Creates the parameter descriptors equivalent to the result of {@link #unmarshal()}
* but with value class, units and default values.
*
* @param remarks Remarks to associate to the latitude parameter, or {@code null} if none.
*/
private static ParameterDescriptor<?>[] create(final String remarks) {
final ParameterBuilder builder = new ParameterBuilder();
builder.setCodeSpace(EPSG, "EPSG").setRequired(true);
return new ParameterDescriptor<?>[] {
builder.addIdentifier("8801").addName("Latitude of natural origin") .setRemarks(remarks).create(0, Units.DEGREE),
builder.addIdentifier("8802").addName("Longitude of natural origin").create(0, Units.DEGREE),
};
}
/**
* Tests the substitution of unmarshalled descriptors by more complete descriptors.
* No merging should be done in this test.
*
* @throws JAXBException if this method failed to create test data.
*/
@Test
public void testSubtitution() throws JAXBException {
final ParameterDescriptor<?>[] expected = create(REMARK);
final List<GeneralParameterDescriptor> fromXML = unmarshal().descriptors();
final List<GeneralParameterDescriptor> fromValues = UnmodifiableArrayList.wrap(expected);
final Map<GeneralParameterDescriptor,GeneralParameterDescriptor> replacements = new IdentityHashMap<>(4);
final var merged = CC_OperationParameterGroup.merge(fromXML,
fromValues.toArray(GeneralParameterDescriptor[]::new), replacements);
assertTrue(replacements.isEmpty());
assertEquals(2, merged.length);
assertNotSame(expected, merged);
assertArrayEquals(expected, merged);
for (int i=0; i<merged.length; i++) {
assertSame(expected[i], merged[i]); // Not just equals, but actually same instance.
}
}
/**
* Tests the merge of unmarshalled descriptors with more complete descriptors.
* This operation is expected to create new descriptor instances as a result of the merges.
*
* @throws JAXBException if this method failed to create test data.
*/
@Test
public void testMerge() throws JAXBException {
final ParameterDescriptorGroup fromXML = unmarshal();
final ParameterDescriptor<?>[] fromValues = create(null);
final Map<GeneralParameterDescriptor,GeneralParameterDescriptor> replacements = new IdentityHashMap<>(4);
final GeneralParameterDescriptor[] merged = CC_OperationParameterGroup.merge(fromXML.descriptors(), fromValues.clone(), replacements);
assertNotSame(fromValues, merged);
/*
* "Longitude of natural origin" parameter should be the same.
*/
assertEquals(2, merged.length);
assertSame(fromValues[1], merged[1], "Longitude of natural origin");
/*
* "Latitude of natural origin" should be a new parameter, because we merged the remarks from the
* 'fromXML' descriptor with value class, unit and default value from the 'fromValue' descriptor.
*/
final GeneralParameterDescriptor incomplete = fromXML.descriptors().get(0);
final DefaultParameterDescriptor<?> fromValue = (DefaultParameterDescriptor<?>) fromValues[0];
final DefaultParameterDescriptor<?> complete = (DefaultParameterDescriptor<?>) merged[0];
assertNotSame(incomplete, complete, "Latitude of natural origin");
assertNotSame(fromValue, complete, "Latitude of natural origin");
assertSame (fromValue .getName(), complete.getName());
assertEquals (incomplete.getRemarks(), complete.getRemarks());
assertEquals (Double.class, complete.getValueClass());
assertSame (fromValue.getValueDomain(), complete.getValueDomain());
/*
* All references to 'fromValue' will need to be replaced by references to 'complete'.
*/
assertEquals(Map.of(fromValue, complete), replacements);
}
/**
* Tests {@link CC_OperationMethod#group(Identifier, GeneralParameterDescriptor[])}.
*
* @throws JAXBException if this method failed to create test data.
*/
@Test
public void testGroup() throws JAXBException {
// From XML
ParameterDescriptorGroup group = unmarshal();
List<GeneralParameterDescriptor> descriptors = group.descriptors();
// Merge with the parameters defined in Mercator1SP class
group = CC_OperationMethod.group(group.getName(), descriptors.toArray(GeneralParameterDescriptor[]::new));
descriptors = group.descriptors();
assertSame(group.getName(), group.getName());
assertEquals(2, descriptors.size());
verifyMethodParameter(Mercator1SP.LATITUDE_OF_ORIGIN, REMARK, (ParameterDescriptor<?>) descriptors.get(0));
verifyMethodParameter(Mercator1SP.LONGITUDE_OF_ORIGIN, null, (ParameterDescriptor<?>) descriptors.get(1));
}
/**
* Verifies the properties of an operation method parameter.
*
* @param expected a parameter descriptor containing the expected properties (except remarks).
* @param actual the parameter descriptor to verify.
*/
public static void verifyMethodParameter(final ParameterDescriptor<?> expected,
final ParameterDescriptor<?> actual)
{
assertEquals(expected.getName(), actual.getName());
assertEquals(expected.getDescription(), actual.getDescription());
assertEquals(expected.getValueClass(), actual.getValueClass());
assertEquals(expected.getValidValues(), actual.getValidValues());
assertEquals(expected.getUnit(), actual.getUnit());
assertEquals(DEFAULT_OCCURRENCE, actual.getMinimumOccurs());
assertEquals(DEFAULT_OCCURRENCE, actual.getMaximumOccurs());
}
/**
* Same verification as {@link #verifyMethodParameter(ParameterDescriptor, ParameterDescriptor)}, but stricter.
*
* @param expected a parameter descriptor containing the expected properties (except remarks).
* @param remarks the expected remarks, or {@code null} for fetching this information from {@code expected}.
* @param actual the parameter descriptor to verify.
*/
private static void verifyMethodParameter(final ParameterDescriptor<?> expected,
final String remarks, final ParameterDescriptor<?> actual)
{
verifyMethodParameter(expected, actual);
assertSame(expected.getName(), actual.getName());
assertSame(expected.getMinimumValue(), actual.getMinimumValue());
assertSame(expected.getMaximumValue(), actual.getMaximumValue());
assertSame(expected.getDefaultValue(), actual.getDefaultValue());
if (remarks != null) {
assertEquals(remarks, actual.getRemarks().toString());
} else {
assertEquals(expected.getRemarks(), actual.getRemarks());
}
}
}