blob: e7b78d4ff880736c42cd2e977e9169a8899309df [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.test;
import java.util.Locale;
import java.io.IOException;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import org.opengis.util.InternationalString;
import org.opengis.metadata.citation.Citation;
import org.opengis.metadata.lineage.Source;
import org.opengis.metadata.maintenance.Scope;
import org.opengis.metadata.maintenance.ScopeCode;
import org.opengis.metadata.content.FeatureTypeInfo;
import org.opengis.metadata.content.FeatureCatalogueDescription;
import org.apache.sis.xml.Namespaces;
import org.apache.sis.test.xml.DocumentComparator;
import org.apache.sis.internal.xml.LegacyNamespaces;
import org.apache.sis.internal.util.CollectionsExt;
import static org.apache.sis.test.TestUtilities.getSingleton;
// Branch-specific imports
import org.opengis.metadata.citation.Responsibility;
/**
* Assertion methods used by the {@code sis-metadata} module in addition of the ones inherited
* from other modules and libraries.
*
* @author Martin Desruisseaux (Geomatys)
* @version 1.0
* @since 0.4
* @module
*/
public strictfp class MetadataAssert extends Assert {
/**
* For subclass constructor only.
*/
protected MetadataAssert() {
}
/**
* Asserts that the English title of the given citation is equals to the expected string.
*
* @param message the message to report in case of test failure.
* @param expected the expected English title.
* @param citation the citation to test.
*
* @since 0.6
*
* @see #assertAnyTitleEquals(String, String, Citation)
*/
public static void assertTitleEquals(final String message, final String expected, final Citation citation) {
assertNotNull(message, citation);
final InternationalString title = citation.getTitle();
assertNotNull(message, title);
assertEquals(message, expected, title.toString(Locale.US));
}
/**
* Asserts that the given citation has only one responsible party,
* and its English name is equals to the expected string.
*
* @param message the message to report in case of test failure.
* @param expected the expected English responsibly party name.
* @param citation the citation to test.
*
* @since 0.8
*/
public static void assertPartyNameEquals(final String message, final String expected, final Citation citation) {
assertNotNull(message, citation);
final Responsibility r = getSingleton(citation.getCitedResponsibleParties());
final InternationalString name = getSingleton(r.getParties()).getName();
assertNotNull(message, name);
assertEquals(message, expected, name.toString(Locale.US));
}
/**
* Verifies that the given {@code ContentInfo} describes the given feature.
* This method expects that the given catalog contains exactly one feature info.
*
* @param name expected feature type name (possibly null).
* @param count expected feature instance count (possibly null).
* @param catalog the content info to validate.
*
* @since 1.0
*/
public static void assertContentInfoEquals(final String name, final Integer count, final FeatureCatalogueDescription catalog) {
final FeatureTypeInfo info = getSingleton(catalog.getFeatureTypeInfo());
assertEquals("metadata.contentInfo.featureType", name, String.valueOf(info.getFeatureTypeName()));
assertEquals("metadata.contentInfo.featureInstanceCount", count, info.getFeatureInstanceCount());
}
/**
* Verifies that the source contains the given feature type. This method expects that the given source contains
* exactly one scope description and that the hierarchical level is {@link ScopeCode#FEATURE_TYPE}.
*
* @param name expected source identifier.
* @param features expected names of feature type.
* @param source the source to validate.
*
* @since 1.0
*/
public static void assertFeatureSourceEquals(final String name, final String[] features, final Source source) {
assertEquals("metadata.lineage.source.sourceCitation.title", name, String.valueOf(source.getSourceCitation().getTitle()));
final Scope scope = source.getScope();
assertNotNull("metadata.lineage.source.scope", scope);
assertEquals("metadata.lineage.source.scope.level", ScopeCode.FEATURE_TYPE, scope.getLevel());
final CharSequence[] actual = CollectionsExt.toArray(getSingleton(scope.getLevelDescription()).getFeatures(), CharSequence.class);
for (int i=0; i<actual.length; i++) {
actual[i] = actual[i].toString();
}
assertArrayEquals("metadata.lineage.source.scope.levelDescription.feature", features, actual);
}
/**
* Parses two XML trees as DOM documents, and compares the nodes.
* The inputs given to this method can be any of the following types:
*
* <ul>
* <li>{@link org.w3c.dom.Node}: used directly without further processing.</li>
* <li>{@link java.io.File}, {@link java.net.URL} or {@link java.net.URI}: the
* stream is opened and parsed as a XML document.</li>
* <li>{@link String}: The string content is parsed directly as a XML document.</li>
* </ul>
*
* The comparison will ignore comments and the optional attributes given in arguments.
*
* <h4>Ignored attributes substitution</h4>
* For convenience, this method replaces some well known prefixes in the {@code ignoredAttributes}
* array by their full namespace URLs. For example this method replaces{@code "xsi:schemaLocation"}
* by {@code "http://www.w3.org/2001/XMLSchema-instance:schemaLocation"}.
* If such substitution is not desired, consider using {@link DocumentComparator} directly instead.
*
* <p>The current substitution map is as below (may be expanded in any future SIS version):</p>
*
* <table class="sis">
* <caption>Predefined prefix mapping</caption>
* <tr><th>Prefix</th> <th>URL</th></tr>
* <tr><td>xmlns</td> <td>{@code "http://www.w3.org/2000/xmlns"}</td></tr>
* <tr><td>xlink</td> <td>{@value Namespaces#XLINK}</td></tr>
* <tr><td>xsi</td> <td>{@value Namespaces#XSI}</td></tr>
* <tr><td>gml</td> <td>{@value Namespaces#GML}</td></tr>
* <tr><td>gco</td> <td>{@value Namespaces#GCO}</td></tr>
* <tr><td>gmd</td> <td>{@value LegacyNamespaces#GMD}</td></tr>
* <tr><td>gmx</td> <td>{@value LegacyNamespaces#GMX}</td></tr>
* <tr><td>gmi</td> <td>{@value LegacyNamespaces#GMI}</td></tr>
* </table>
*
* <p>For example in order to ignore the namespace, type and schema location declaration,
* the following strings can be given to the {@code ignoredAttributes} argument:</p>
*
* {@preformat text
* "xmlns:*", "xsi:schemaLocation", "xsi:type"
* }
*
* @param expected the expected XML document.
* @param actual the XML document to compare.
* @param ignoredAttributes the fully-qualified names of attributes to ignore
* (typically {@code "xmlns:*"} and {@code "xsi:schemaLocation"}).
*
* @see DocumentComparator
*/
public static void assertXmlEquals(final Object expected, final Object actual, final String... ignoredAttributes) {
assertXmlEquals(expected, actual, TestCase.STRICT, null, ignoredAttributes);
}
/**
* Parses two XML trees as DOM documents, and compares the nodes with the given tolerance
* threshold for numerical values. The inputs given to this method can be any of the types
* documented {@linkplain #assertXmlEquals(Object, Object, String[]) above}. This method
* will ignore comments and the optional attributes given in arguments as documented in the
* above method.
*
* @param expected the expected XML document.
* @param actual the XML document to compare.
* @param tolerance the tolerance threshold for comparison of numerical values.
* @param ignoredNodes the fully-qualified names of the nodes to ignore, or {@code null} if none.
* @param ignoredAttributes the fully-qualified names of attributes to ignore
* (typically {@code "xmlns:*"} and {@code "xsi:schemaLocation"}).
*
* @see DocumentComparator
*/
public static void assertXmlEquals(final Object expected, final Object actual,
final double tolerance, final String[] ignoredNodes, final String[] ignoredAttributes)
{
final DocumentComparator comparator;
try {
comparator = new DocumentComparator(expected, actual);
} catch (IOException | ParserConfigurationException | SAXException e) {
/*
* We don't throw directly those exceptions since failing to parse the XML file can
* be considered as part of test failures and the JUnit exception for such failures
* is AssertionError. Having no checked exception in "assert" methods allow us to
* declare the checked exceptions only for the library code being tested.
*/
throw new AssertionError(e);
}
comparator.tolerance = tolerance;
comparator.ignoreComments = true;
if (ignoredNodes != null) {
for (final String node : ignoredNodes) {
comparator.ignoredNodes.add(DocumentComparator.substitutePrefix(node));
}
}
if (ignoredAttributes != null) {
for (final String attribute : ignoredAttributes) {
comparator.ignoredAttributes.add(DocumentComparator.substitutePrefix(attribute));
}
}
comparator.compare();
}
}