diff --git a/pom.xml b/pom.xml index e8dd6837..8c263722 100644 --- a/pom.xml +++ b/pom.xml @@ -3,13 +3,12 @@ org.opengis.cite ets-common - 9 + 13 4.0.0 - org.opengis.cite ets-ogcapi-features10 - 1.8-SNAPSHOT + 1.5-SNAPSHOT jar OGC API-Features 1.0 Conformance Test Suite @@ -50,15 +49,15 @@ ogcapi-features-1.0 1.0 - 5.4.1 + 6.0-SNAPSHOT false http://localhost:8081/teamengine ogctest ogctest - https://ri.ldproxy.net/daraa - 383 - 15 - 3 + https://demo.ldproxy.net/daraa + 401 + 0 + 0 @@ -69,7 +68,6 @@ org.locationtech.jts jts-core - 1.18.1 org.locationtech.proj4j @@ -81,24 +79,13 @@ jts-io-common 1.18.1 - - com.sun.jersey - jersey-client - - - com.sun.jersey - jersey-core - 1.19.4 - io.rest-assured rest-assured - 4.5.1 com.reprezen.kaizen openapi-parser - 4.0.4 junit @@ -123,62 +110,35 @@ com.beust jcommander - 1.81 - - - javax.ws.rs - jsr311-api - 1.1.1 org.hamcrest hamcrest-core - 1.3 org.testng testng - 6.9.10 - - - xml-apis - xml-apis - 1.4.01 commons-validator commons-validator - 1.7 org.apache.commons commons-lang3 - 3.4 + + + org.glassfish.jersey.inject + jersey-hk2 + + + org.glassfish.jersey.connectors + jersey-apache-connector - - maven-javadoc-plugin - 2.10.4 - - 8 - true - package - - http://testng.org/javadocs/ - - - - - attach-javadocs - - jar - - - - maven-assembly-plugin @@ -202,59 +162,6 @@ - - maven-surefire-plugin - - - maven-compiler-plugin - - - maven-jar-plugin - - - maven-release-plugin - 2.5.3 - - true - @{project.version} - release - - - - org.apache.maven.plugins - maven-site-plugin - 3.7.1 - - - site-package - prepare-package - - jar - - - - - - org.asciidoctor - asciidoctor-maven-plugin - 1.5.7.1 - - - - false - - - - org.codehaus.mojo - buildnumber-maven-plugin - - - maven-scm-publish-plugin - 1.1 - - gh-pages - - @@ -302,34 +209,6 @@ - - maven-dependency-plugin - 3.0.0 - - - - org.opengis.cite.teamengine - teamengine-web - ${docker.teamengine.version} - war - - - org.opengis.cite.teamengine - teamengine-web - ${docker.teamengine.version} - common-libs - zip - - - org.opengis.cite.teamengine - teamengine-console - ${docker.teamengine.version} - base - zip - - - - com.smartbear.soapui soapui-maven-plugin @@ -461,32 +340,6 @@ - - release - - - - maven-gpg-plugin - 1.6 - - - sign-artifacts - verify - - sign - - - - --pinentry-mode - loopback - - - - - - - - diff --git a/src/assembly/aio.xml b/src/assembly/aio.xml index 637399b5..34c320c1 100644 --- a/src/assembly/aio.xml +++ b/src/assembly/aio.xml @@ -12,9 +12,6 @@ true true runtime - - com.sun.jersey:jersey-server - diff --git a/src/assembly/deps.xml b/src/assembly/deps.xml index e27e7945..21a3b3b4 100644 --- a/src/assembly/deps.xml +++ b/src/assembly/deps.xml @@ -11,9 +11,6 @@ false - - com.sun.jersey:jersey-client - / false runtime @@ -22,10 +19,11 @@ org.opengis.cite.teamengine:teamengine-spi - com.sun.jersey:jersey-client com.beust:jcommander - com.sun.jersey:jersey-core - javax.ws.rs:jsr311-api + *:jersey-client + *:jersey-server + *:jersey-hk2 + jakarta.ws.rs:jakarta.ws.rs-api org.testng:testng / diff --git a/src/docker/Dockerfile b/src/docker/Dockerfile index 4f6306c7..baf5a932 100644 --- a/src/docker/Dockerfile +++ b/src/docker/Dockerfile @@ -1,4 +1,5 @@ -FROM tomcat:7.0-jre8 as builder +FROM tomcat:10-jre17 +RUN apt update && apt install -y unzip # add TEAM engine webapp ADD maven/dependency/teamengine-web-*.war /root/ diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/CommandLineArguments.java b/src/main/java/org/opengis/cite/ogcapifeatures10/CommandLineArguments.java index ec910a15..cbab675c 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/CommandLineArguments.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/CommandLineArguments.java @@ -7,9 +7,8 @@ import java.util.List; /** - * Declares supported command line arguments that are parsed using the - * JCommander library. All arguments are optional. The default values are as - * follows: + * Declares supported command line arguments that are parsed using the JCommander library. + * All arguments are optional. The default values are as follows: *
    *
  • XML properties file: ${user.home}/test-run-props.xml
  • *
  • outputDir: ${user.home}
  • @@ -27,42 +26,74 @@ */ public class CommandLineArguments { - @Parameter(description = "Properties file") - private List xmlProps; + @Parameter(description = "Properties file") + private List xmlProps; - @Parameter(names = {"-o", "--outputDir"}, description = "Output directory") - private String outputDir; + @Parameter(names = { "-o", "--outputDir" }, description = "Output directory") + private String outputDir; - @Parameter(names = {"-d", "--deleteSubjectOnFinish"}, description = "Delete file containing representation of test subject when finished") - private boolean deleteSubjectOnFinish = false; - - @Parameter(names = {"-h", "--generateHtmlReport"}, arity = 1, description = "Enable HTML report generation") - private boolean generateHtmlReport = false; + @Parameter(names = { "-d", "--deleteSubjectOnFinish" }, + description = "Delete file containing representation of test subject when finished") + private boolean deleteSubjectOnFinish = false; - public CommandLineArguments() { - this.xmlProps = new ArrayList<>(); - } + @Parameter(names = { "-h", "--generateHtmlReport" }, arity = 1, description = "Enable HTML report generation") + private boolean generateHtmlReport = false; - public File getPropertiesFile() { - File fileRef; - if (xmlProps.isEmpty()) { - fileRef = new File(System.getProperty("user.home"), "test-run-props.xml"); - } else { - String propsFile = xmlProps.get(0); - fileRef = (propsFile.startsWith("file:")) ? new File(URI.create(propsFile)) : new File(propsFile); - } - return fileRef; - } + /** + *

    + * Constructor for CommandLineArguments. + *

    + */ + public CommandLineArguments() { + this.xmlProps = new ArrayList<>(); + } - public String getOutputDir() { - return (null != outputDir) ? outputDir : System.getProperty("user.home"); - } + /** + *

    + * getPropertiesFile. + *

    + * @return a {@link java.io.File} object + */ + public File getPropertiesFile() { + File fileRef; + if (xmlProps.isEmpty()) { + fileRef = new File(System.getProperty("user.home"), "test-run-props.xml"); + } + else { + String propsFile = xmlProps.get(0); + fileRef = (propsFile.startsWith("file:")) ? new File(URI.create(propsFile)) : new File(propsFile); + } + return fileRef; + } - public boolean doDeleteSubjectOnFinish() { - return deleteSubjectOnFinish; - } + /** + *

    + * Getter for the field outputDir. + *

    + * @return a {@link java.lang.String} object + */ + public String getOutputDir() { + return (null != outputDir) ? outputDir : System.getProperty("user.home"); + } + + /** + *

    + * doDeleteSubjectOnFinish. + *

    + * @return a boolean + */ + public boolean doDeleteSubjectOnFinish() { + return deleteSubjectOnFinish; + } + + /** + *

    + * isGenerateHtmlReport. + *

    + * @return a boolean + */ + public boolean isGenerateHtmlReport() { + return generateHtmlReport; + } - public boolean isGenerateHtmlReport() { - return generateHtmlReport; - } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/ErrorMessage.java b/src/main/java/org/opengis/cite/ogcapifeatures10/ErrorMessage.java index e7bf7ada..99fdecfd 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/ErrorMessage.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/ErrorMessage.java @@ -4,46 +4,39 @@ import java.util.ResourceBundle; /** - * Utility class for retrieving and formatting localized error messages that - * describe failed assertions. + * Utility class for retrieving and formatting localized error messages that describe + * failed assertions. */ public class ErrorMessage { - private static final String BASE_NAME = - "org.opengis.cite.ogcapifeatures10.MessageBundle"; - private static ResourceBundle msgResources = - ResourceBundle.getBundle(BASE_NAME); + private static final String BASE_NAME = "org.opengis.cite.ogcapifeatures10.MessageBundle"; - /** - * Produces a formatted error message using the supplied substitution - * arguments and the current locale. The arguments should reflect the order - * of the placeholders in the message template. - * - * @param msgKey - * The key identifying the message template; it should be a - * member of {@code ErrorMessageKeys}. - * @param args - * An array of arguments to be formatted and substituted in the - * content of the message. - * @return A String containing the message content. If no message is found - * for the given key, a {@link java.util.MissingResourceException} - * is thrown. - */ - public static String format(String msgKey, Object... args) { - return MessageFormat.format(msgResources.getString(msgKey), args); - } + private static ResourceBundle msgResources = ResourceBundle.getBundle(BASE_NAME); + + /** + * Produces a formatted error message using the supplied substitution arguments and + * the current locale. The arguments should reflect the order of the placeholders in + * the message template. + * @param msgKey The key identifying the message template; it should be a member of + * {@code ErrorMessageKeys}. + * @param args An array of arguments to be formatted and substituted in the content of + * the message. + * @return A String containing the message content. If no message is found for the + * given key, a {@link java.util.MissingResourceException} is thrown. + */ + public static String format(String msgKey, Object... args) { + return MessageFormat.format(msgResources.getString(msgKey), args); + } + + /** + * Retrieves a simple message according to the current locale. + * @param msgKey The key identifying the message; it should be a member of + * {@code ErrorMessageKeys}. + * @return A String containing the message content. If no message is found for the + * given key, a {@link java.util.MissingResourceException} is thrown. + */ + public static String get(String msgKey) { + return msgResources.getString(msgKey); + } - /** - * Retrieves a simple message according to the current locale. - * - * @param msgKey - * The key identifying the message; it should be a member of - * {@code ErrorMessageKeys}. - * @return A String containing the message content. If no message is found - * for the given key, a {@link java.util.MissingResourceException} - * is thrown. - */ - public static String get(String msgKey) { - return msgResources.getString(msgKey); - } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/ErrorMessageKeys.java b/src/main/java/org/opengis/cite/ogcapifeatures10/ErrorMessageKeys.java index dc901c7f..378c3f94 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/ErrorMessageKeys.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/ErrorMessageKeys.java @@ -1,22 +1,44 @@ package org.opengis.cite.ogcapifeatures10; /** - * Defines keys used to access localized messages for assertion errors. The - * messages are stored in Properties files that are encoded in ISO-8859-1 - * (Latin-1). For some languages the {@code native2ascii} tool must be used to - * process the files and produce escaped Unicode characters. + * Defines keys used to access localized messages for assertion errors. The messages are + * stored in Properties files that are encoded in ISO-8859-1 (Latin-1). For some languages + * the {@code native2ascii} tool must be used to process the files and produce escaped + * Unicode characters. */ public class ErrorMessageKeys { - public static final String NOT_SCHEMA_VALID = "NotSchemaValid"; - public static final String EMPTY_STRING = "EmptyString"; - public static final String XPATH_RESULT = "XPathResult"; - public static final String NAMESPACE_NAME = "NamespaceName"; - public static final String LOCAL_NAME = "LocalName"; - public static final String XML_ERROR = "XMLError"; - public static final String XPATH_ERROR = "XPathError"; - public static final String MISSING_INFOSET_ITEM = "MissingInfosetItem"; - public static final String UNEXPECTED_STATUS = "UnexpectedStatus"; - public static final String UNEXPECTED_MEDIA_TYPE = "UnexpectedMediaType"; - public static final String MISSING_ENTITY = "MissingEntity"; + /** Constant NOT_SCHEMA_VALID="NotSchemaValid" */ + public static final String NOT_SCHEMA_VALID = "NotSchemaValid"; + + /** Constant EMPTY_STRING="EmptyString" */ + public static final String EMPTY_STRING = "EmptyString"; + + /** Constant XPATH_RESULT="XPathResult" */ + public static final String XPATH_RESULT = "XPathResult"; + + /** Constant NAMESPACE_NAME="NamespaceName" */ + public static final String NAMESPACE_NAME = "NamespaceName"; + + /** Constant LOCAL_NAME="LocalName" */ + public static final String LOCAL_NAME = "LocalName"; + + /** Constant XML_ERROR="XMLError" */ + public static final String XML_ERROR = "XMLError"; + + /** Constant XPATH_ERROR="XPathError" */ + public static final String XPATH_ERROR = "XPathError"; + + /** Constant MISSING_INFOSET_ITEM="MissingInfosetItem" */ + public static final String MISSING_INFOSET_ITEM = "MissingInfosetItem"; + + /** Constant UNEXPECTED_STATUS="UnexpectedStatus" */ + public static final String UNEXPECTED_STATUS = "UnexpectedStatus"; + + /** Constant UNEXPECTED_MEDIA_TYPE="UnexpectedMediaType" */ + public static final String UNEXPECTED_MEDIA_TYPE = "UnexpectedMediaType"; + + /** Constant MISSING_ENTITY="MissingEntity" */ + public static final String MISSING_ENTITY = "MissingEntity"; + } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/EtsAssert.java b/src/main/java/org/opengis/cite/ogcapifeatures10/EtsAssert.java index 516271f1..0ae87b26 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/EtsAssert.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/EtsAssert.java @@ -16,171 +16,166 @@ */ public class EtsAssert { - private static Envelope CRS84_BBOX = new Envelope( -180, 180, -90, 90 ); + private static Envelope CRS84_BBOX = new Envelope(-180, 180, -90, 90); - /** - * @param valueToAssert - * the boolean to assert to be true - * @param failureMsg - * the message to throw in case of a failure, should not be null - */ - public static void assertTrue( boolean valueToAssert, String failureMsg ) { - if ( !valueToAssert ) - throw new AssertionError( failureMsg ); - } + /** + *

    + * assertTrue. + *

    + * @param valueToAssert the boolean to assert to be true + * @param failureMsg the message to throw in case of a failure, should not be + * null + */ + public static void assertTrue(boolean valueToAssert, String failureMsg) { + if (!valueToAssert) + throw new AssertionError(failureMsg); + } - /** - * @param valueToAssert - * the boolean to assert to be false - * @param failureMsg - * the message to throw in case of a failure, should not be null - */ - public static void assertFalse( boolean valueToAssert, String failureMsg ) { - if ( valueToAssert ) - throw new AssertionError( failureMsg ); - } + /** + *

    + * assertFalse. + *

    + * @param valueToAssert the boolean to assert to be false + * @param failureMsg the message to throw in case of a failure, should not be + * null + */ + public static void assertFalse(boolean valueToAssert, String failureMsg) { + if (valueToAssert) + throw new AssertionError(failureMsg); + } - /** - *
    -     *  1. For http-URIs (starting with http:) validate that the string conforms to the syntax specified  
    -     *     by RFC 7230, section 2.7.1. 
    -     *  2. For https-URIs (starting with https:) validate that the string conforms to the syntax specified 
    -     *     by RFC 7230, section 2.7.2. 
    -     *  3. For URNs (starting with urn:) validate that the string conforms to the syntax specified 
    -     *     by RFC 8141, section 2. 
    -     *  4. For OGC URNs (starting with urn:ogc:def:crs:) and OGC http-URIs (starting with http://www.opengis.net/def/crs/) 
    -     *     validate that the string conforms to the syntax specified by OGC Name Type Specification - definitions - part 1 – basic name.
    -     * 
    - * - * @param coordinateSystem - * the coordinate system to assert as valid identifier (see above). If null an - * AssertionError is thrown. - * @param failureMsg - * the message to throw in case of a failure, should not be null - */ - public static void assertValidCrsIdentifier( CoordinateSystem coordinateSystem, String failureMsg ) { - if ( coordinateSystem == null ) - throw new AssertionError( failureMsg ); - if ( !coordinateSystem.isValid() ) - throw new AssertionError( failureMsg ); - } + /** + *
    +	 *  1. For http-URIs (starting with http:) validate that the string conforms to the syntax specified
    +	 *     by RFC 7230, section 2.7.1.
    +	 *  2. For https-URIs (starting with https:) validate that the string conforms to the syntax specified
    +	 *     by RFC 7230, section 2.7.2.
    +	 *  3. For URNs (starting with urn:) validate that the string conforms to the syntax specified
    +	 *     by RFC 8141, section 2.
    +	 *  4. For OGC URNs (starting with urn:ogc:def:crs:) and OGC http-URIs (starting with http://www.opengis.net/def/crs/)
    +	 *     validate that the string conforms to the syntax specified by OGC Name Type Specification - definitions - part 1 – basic name.
    +	 * 
    + * @param coordinateSystem the coordinate system to assert as valid identifier (see + * above). If null an AssertionError is thrown. + * @param failureMsg the message to throw in case of a failure, should not be + * null + */ + public static void assertValidCrsIdentifier(CoordinateSystem coordinateSystem, String failureMsg) { + if (coordinateSystem == null) + throw new AssertionError(failureMsg); + if (!coordinateSystem.isValid()) + throw new AssertionError(failureMsg); + } - /** - * Assert that one of the default CRS - * - *
    -     *   * http://www.opengis.net/def/crs/OGC/1.3/CRS84 (for coordinates without height)
    -     *   * http://www.opengis.net/def/crs/OGC/0/CRS84h (for coordinates with height)
    -     * 
    - * - * is in the list of passed crs. - * - * @param valueToAssert - * list of CRS which should contain the default crs, never null - * @param failureMsg - * the message to throw in case of a failure, should not be null - * @return the default CRS - */ - public static CoordinateSystem assertDefaultCrs( List valueToAssert, String failureMsg ) { - if ( valueToAssert.contains( OgcApiFeatures10.DEFAULT_CRS_CODE ) ) - return DEFAULT_CRS; - if ( valueToAssert.contains( OgcApiFeatures10.DEFAULT_CRS_WITH_HEIGHT_CODE ) ) - return DEFAULT_CRS_WITH_HEIGHT; - throw new AssertionError( failureMsg ); - } + /** + * Assert that one of the default CRS + * + *
    +	 *   * http://www.opengis.net/def/crs/OGC/1.3/CRS84 (for coordinates without height)
    +	 *   * http://www.opengis.net/def/crs/OGC/0/CRS84h (for coordinates with height)
    +	 * 
    + * + * is in the list of passed crs. + * @param valueToAssert list of CRS which should contain the default crs, never + * null + * @param failureMsg the message to throw in case of a failure, should not be + * null + * @return the default CRS + */ + public static CoordinateSystem assertDefaultCrs(List valueToAssert, String failureMsg) { + if (valueToAssert.contains(OgcApiFeatures10.DEFAULT_CRS_CODE)) + return DEFAULT_CRS; + if (valueToAssert.contains(OgcApiFeatures10.DEFAULT_CRS_WITH_HEIGHT_CODE)) + return DEFAULT_CRS_WITH_HEIGHT; + throw new AssertionError(failureMsg); + } - /** - * Assert that the first is one of the default CRS - * - *
    -     *   * http://www.opengis.net/def/crs/OGC/1.3/CRS84 (for coordinates without height)
    -     *   * http://www.opengis.net/def/crs/OGC/0/CRS84h (for coordinates with height)
    -     * 
    - * - * @param valueToAssert - * list of CRS which should contain the default crs, never null - * @param failureMsg - * the message to throw in case of a failure, should not be null - */ - public static void assertDefaultCrsAtFirst( List valueToAssert, String failureMsg ) { - if ( !valueToAssert.isEmpty() ) { - String firstCrs = valueToAssert.get( 0 ); - if ( OgcApiFeatures10.DEFAULT_CRS_CODE.equals( firstCrs ) ) - return; - if ( OgcApiFeatures10.DEFAULT_CRS_WITH_HEIGHT_CODE.equals( firstCrs ) ) - return; - } - throw new AssertionError( failureMsg ); - } + /** + * Assert that the first is one of the default CRS + * + *
    +	 *   * http://www.opengis.net/def/crs/OGC/1.3/CRS84 (for coordinates without height)
    +	 *   * http://www.opengis.net/def/crs/OGC/0/CRS84h (for coordinates with height)
    +	 * 
    + * @param valueToAssert list of CRS which should contain the default crs, never + * null + * @param failureMsg the message to throw in case of a failure, should not be + * null + */ + public static void assertDefaultCrsAtFirst(List valueToAssert, String failureMsg) { + if (!valueToAssert.isEmpty()) { + String firstCrs = valueToAssert.get(0); + if (OgcApiFeatures10.DEFAULT_CRS_CODE.equals(firstCrs)) + return; + if (OgcApiFeatures10.DEFAULT_CRS_WITH_HEIGHT_CODE.equals(firstCrs)) + return; + } + throw new AssertionError(failureMsg); + } - /** - * Assert that the passed string is one of the the default CRS - * - *
    -     *   * http://www.opengis.net/def/crs/OGC/1.3/CRS84 (for coordinates without height)
    -     *   * http://www.opengis.net/def/crs/OGC/0/CRS84h (for coordinates with height)
    -     * 
    - * - * @param crsHeaderValue - * CRS which should be the default crs, never null - * @param failureMsg - * the message to throw in case of a failure, should not be null - */ - public static void assertDefaultCrs( String crsHeaderValue, String failureMsg ) { - if ( !crsHeaderValue.matches( "<" + OgcApiFeatures10.DEFAULT_CRS_CODE + ">" ) - && !crsHeaderValue.matches( "<" + OgcApiFeatures10.DEFAULT_CRS_WITH_HEIGHT_CODE + ">" ) ) { - throw new AssertionError( failureMsg ); - } - } + /** + * Assert that the passed string is one of the the default CRS + * + *
    +	 *   * http://www.opengis.net/def/crs/OGC/1.3/CRS84 (for coordinates without height)
    +	 *   * http://www.opengis.net/def/crs/OGC/0/CRS84h (for coordinates with height)
    +	 * 
    + * @param crsHeaderValue CRS which should be the default crs, never null + * @param failureMsg the message to throw in case of a failure, should not be + * null + */ + public static void assertDefaultCrs(String crsHeaderValue, String failureMsg) { + if (!crsHeaderValue.matches("<" + OgcApiFeatures10.DEFAULT_CRS_CODE + ">") + && !crsHeaderValue.matches("<" + OgcApiFeatures10.DEFAULT_CRS_WITH_HEIGHT_CODE + ">")) { + throw new AssertionError(failureMsg); + } + } - /** - * @param crsHeaderValue - * the value from the header, never null - * @param expectedCrs - * th expected value, never null - * @param failureMsg - * the message to throw in case of a failure, should not be null - */ - public static void assertCrsHeader( String crsHeaderValue, CoordinateSystem expectedCrs, String failureMsg ) { - if ( !crsHeaderValue.matches( expectedCrs.getAsHeaderValue() ) ) { - throw new AssertionError( failureMsg ); - } - } + /** + *

    + * assertCrsHeader. + *

    + * @param crsHeaderValue the value from the header, never null + * @param expectedCrs th expected value, never null + * @param failureMsg the message to throw in case of a failure, should not be + * null + */ + public static void assertCrsHeader(String crsHeaderValue, CoordinateSystem expectedCrs, String failureMsg) { + if (!crsHeaderValue.matches(expectedCrs.getAsHeaderValue())) { + throw new AssertionError(failureMsg); + } + } - /** - * Assert that one of the default CRS - * - *
    -     *   * http://www.opengis.net/def/crs/OGC/1.3/CRS84 (for coordinates without height)
    -     *   * http://www.opengis.net/def/crs/OGC/0/CRS84h (for coordinates with height)
    -     * 
    - * - * @param crsHeaderValue - * the value from the header, never null - * @param failureMsg - * the message to throw in case of a failure, should not be null - */ - public static void assertDefaultCrsHeader( String crsHeaderValue, String failureMsg ) { - if ( !crsHeaderValue.matches( "<" + OgcApiFeatures10.DEFAULT_CRS_CODE + ">" ) - && !crsHeaderValue.matches( "<" + OgcApiFeatures10.DEFAULT_CRS_WITH_HEIGHT_CODE + ">" ) ) { - throw new AssertionError( failureMsg ); - } - } + /** + * Assert that one of the default CRS + * + *
    +	 *   * http://www.opengis.net/def/crs/OGC/1.3/CRS84 (for coordinates without height)
    +	 *   * http://www.opengis.net/def/crs/OGC/0/CRS84h (for coordinates with height)
    +	 * 
    + * @param crsHeaderValue the value from the header, never null + * @param failureMsg the message to throw in case of a failure, should not be + * null + */ + public static void assertDefaultCrsHeader(String crsHeaderValue, String failureMsg) { + if (!crsHeaderValue.matches("<" + OgcApiFeatures10.DEFAULT_CRS_CODE + ">") + && !crsHeaderValue.matches("<" + OgcApiFeatures10.DEFAULT_CRS_WITH_HEIGHT_CODE + ">")) { + throw new AssertionError(failureMsg); + } + } - /** - * Assert that the passed geometry is in the valid area of CRS84. - * - * @param geometry - * to check, may be null - * @param failureMsg - * the message to throw in case of a failure, should not be null - */ - public static void assertInCrs84( Geometry geometry, String failureMsg ) { - if ( geometry == null ) - return; - if ( !CRS84_BBOX.contains( geometry.getEnvelopeInternal() ) ) { - throw new AssertionError( failureMsg ); - } - } + /** + * Assert that the passed geometry is in the valid area of CRS84. + * @param geometry to check, may be null + * @param failureMsg the message to throw in case of a failure, should not be + * null + */ + public static void assertInCrs84(Geometry geometry, String failureMsg) { + if (geometry == null) + return; + if (!CRS84_BBOX.contains(geometry.getEnvelopeInternal())) { + throw new AssertionError(failureMsg); + } + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/Namespaces.java b/src/main/java/org/opengis/cite/ogcapifeatures10/Namespaces.java index d4096ca0..37fa85b3 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/Namespaces.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/Namespaces.java @@ -4,28 +4,30 @@ /** * XML namespace names. - * - * @see Namespaces in XML 1.0 * + * @see Namespaces in XML 1.0 */ public class Namespaces { - private Namespaces() { - } - - /** SOAP 1.2 message envelopes. */ - public static final String SOAP_ENV = "http://www.w3.org/2003/05/soap-envelope"; - /** W3C XLink */ - public static final String XLINK = "http://www.w3.org/1999/xlink"; - /** OGC 06-121r3 (OWS 1.1) */ - public static final String OWS = "http://www.opengis.net/ows/1.1"; - /** ISO 19136 (GML 3.2) */ - public static final String GML = "http://www.opengis.net/gml/3.2"; - /** W3C XML Schema namespace */ - public static final URI XSD = URI - .create("http://www.w3.org/2001/XMLSchema"); - /** Schematron (ISO 19757-3) namespace */ - public static final URI SCH = URI - .create("http://purl.oclc.org/dsdl/schematron"); + private Namespaces() { + } + + /** SOAP 1.2 message envelopes. */ + public static final String SOAP_ENV = "http://www.w3.org/2003/05/soap-envelope"; + + /** W3C XLink */ + public static final String XLINK = "http://www.w3.org/1999/xlink"; + + /** OGC 06-121r3 (OWS 1.1) */ + public static final String OWS = "http://www.opengis.net/ows/1.1"; + + /** ISO 19136 (GML 3.2) */ + public static final String GML = "http://www.opengis.net/gml/3.2"; + + /** W3C XML Schema namespace */ + public static final URI XSD = URI.create("http://www.w3.org/2001/XMLSchema"); + + /** Schematron (ISO 19757-3) namespace */ + public static final URI SCH = URI.create("http://purl.oclc.org/dsdl/schematron"); } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/OgcApiFeatures10.java b/src/main/java/org/opengis/cite/ogcapifeatures10/OgcApiFeatures10.java index 5135e47d..fbb3b07e 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/OgcApiFeatures10.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/OgcApiFeatures10.java @@ -9,34 +9,56 @@ */ public class OgcApiFeatures10 { - private OgcApiFeatures10() { - } + private OgcApiFeatures10() { + } - public static final String OPEN_API_MIME_TYPE = "application/vnd.oai.openapi+json;version=3.0"; + /** + * Constant + * OPEN_API_MIME_TYPE="application/vnd.oai.openapi+json;versio"{trunked} + */ + public static final String OPEN_API_MIME_TYPE = "application/vnd.oai.openapi+json;version=3.0"; - public static final String GEOJSON_MIME_TYPE = "application/geo+json"; + /** Constant GEOJSON_MIME_TYPE="application/geo+json" */ + public static final String GEOJSON_MIME_TYPE = "application/geo+json"; - /** Conformance class: CRS **/ + /** Conformance class: CRS **/ - public static final String DEFAULT_CRS_CODE = "http://www.opengis.net/def/crs/OGC/1.3/CRS84"; + public static final String DEFAULT_CRS_CODE = "http://www.opengis.net/def/crs/OGC/1.3/CRS84"; - public static final String DEFAULT_CRS_WITH_HEIGHT_CODE = "http://www.opengis.net/def/crs/OGC/0/CRS84h"; + /** + * Constant + * DEFAULT_CRS_WITH_HEIGHT_CODE="http://www.opengis.net/def/crs/OGC/0/CR"{trunked} + */ + public static final String DEFAULT_CRS_WITH_HEIGHT_CODE = "http://www.opengis.net/def/crs/OGC/0/CRS84h"; - public static final CoordinateSystem DEFAULT_CRS = new CoordinateSystem( DEFAULT_CRS_CODE ); + /** Constant DEFAULT_CRS */ + public static final CoordinateSystem DEFAULT_CRS = new CoordinateSystem(DEFAULT_CRS_CODE); - public static final CoordinateSystem DEFAULT_CRS_WITH_HEIGHT = new CoordinateSystem( DEFAULT_CRS_WITH_HEIGHT_CODE ); + /** Constant DEFAULT_CRS_WITH_HEIGHT */ + public static final CoordinateSystem DEFAULT_CRS_WITH_HEIGHT = new CoordinateSystem(DEFAULT_CRS_WITH_HEIGHT_CODE); - public static final String UNSUPPORTED_CRS = "http://www.opengis.net/def/crs/0/unsupported"; + /** + * Constant + * UNSUPPORTED_CRS="http://www.opengis.net/def/crs/0/unsupp"{trunked} + */ + public static final String UNSUPPORTED_CRS = "http://www.opengis.net/def/crs/0/unsupported"; - public static final String CRS_PARAMETER = "crs"; + /** Constant CRS_PARAMETER="crs" */ + public static final String CRS_PARAMETER = "crs"; - public static final int PAGING_LIMIT = 3; + /** Constant PAGING_LIMIT=3 */ + public static final int PAGING_LIMIT = 3; - public static final int COLLECTIONS_LIMIT = 20; + /** Constant COLLECTIONS_LIMIT=20 */ + public static final int COLLECTIONS_LIMIT = 20; - public static final int CRS_LIMIT = 20; + /** Constant CRS_LIMIT=20 */ + public static final int CRS_LIMIT = 20; + + /** Constant FEATURES_LIMIT=100 */ + public static final int FEATURES_LIMIT = 100; + + /** Constant NUMBERMATCHED_LIMIT=10000 */ + public static final int NUMBERMATCHED_LIMIT = 10000; - public static final int FEATURES_LIMIT = 100; - - public static final int NUMBERMATCHED_LIMIT = 10000; } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/ReusableEntityFilter.java b/src/main/java/org/opengis/cite/ogcapifeatures10/ReusableEntityFilter.java deleted file mode 100644 index daa33b14..00000000 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/ReusableEntityFilter.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.opengis.cite.ogcapifeatures10; - -import com.sun.jersey.api.client.ClientHandlerException; -import com.sun.jersey.api.client.ClientRequest; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.filter.ClientFilter; - -/** - * Buffers the (response) entity so it can be read multiple times. - * - *

    WARNING: The entity InputStream must be reset after each - * read attempt.

    - */ -public class ReusableEntityFilter extends ClientFilter { - - @Override - public ClientResponse handle(ClientRequest req) throws ClientHandlerException { - // leave request entity--it can usually be read multiple times - ClientResponse rsp = getNext().handle(req); - if (rsp.hasEntity()) { - rsp.bufferEntity(); - } - return rsp; - } - -} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/TestNGController.java b/src/main/java/org/opengis/cite/ogcapifeatures10/TestNGController.java index 2d5969c1..62287ae3 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/TestNGController.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/TestNGController.java @@ -30,155 +30,155 @@ */ public class TestNGController implements TestSuiteController { - private TestRunExecutor executor; - private Properties etsProperties = new Properties(); - - /** - * A convenience method for running the test suite using a command-line - * interface. The default values of the test run arguments are as follows: - *
      - *
    • XML properties file: ${user.home}/test-run-props.xml
    • - *
    • outputDir: ${user.home}
    • - *
    • deleteSubjectOnFinish: false
    • - *
    • generateHtmlReport: false
    • - *
    - *

    - * Synopsis - *

    - * - *
    -     * ets-*-aio.jar [-o|--outputDir $TMPDIR] [-d|--deleteSubjectOnFinish] [-h|--generateHtmlReport] [test-run-props.xml]
    -     * 
    - * - * @param args - * Test run arguments (optional). The first argument must refer - * to an XML properties file containing the expected set of test - * run arguments. If no argument is supplied, the file located at - * ${user.home}/test-run-props.xml will be used. - * @throws Exception - * If the test run cannot be executed (usually due to - * unsatisfied pre-conditions). - */ - public static void main(String[] args) throws Exception { - CommandLineArguments testRunArgs = new CommandLineArguments(); - JCommander cmd = new JCommander(testRunArgs); - try { - cmd.parse(args); - } catch (ParameterException px) { - System.out.println(px.getMessage()); - cmd.usage(); - } - if (testRunArgs.doDeleteSubjectOnFinish()) { - System.setProperty("deleteSubjectOnFinish", "true"); - } - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db = dbf.newDocumentBuilder(); - File xmlArgs = testRunArgs.getPropertiesFile(); - Document testRunProps = db.parse(xmlArgs); - TestNGController controller = new TestNGController(testRunArgs.getOutputDir(), testRunArgs.isGenerateHtmlReport()); - Source testResults = controller.doTestRun(testRunProps); - System.out.println("Test results: " + testResults.getSystemId()); - } - - /** - * Default constructor uses the location given by the "java.io.tmpdir" - * system property as the root output directory. - */ - public TestNGController() { - this(System.getProperty("java.io.tmpdir"), false); - } - - /** - * Construct a controller that writes results to the given output directory. - * - * @param outputDir - * The location of the directory in which test results will be - * written (a file system path or a 'file' URI). It will be - * created if it does not exist. - */ - public TestNGController(String outputDir) { - this(outputDir, false); - } - - /** - * Construct a controller that writes results to the given output directory. - * - * @param outputDir - * The location of the directory in which test results will be - * written (a file system path or a 'file' URI). It will be - * created if it does not exist. - * @param generateHtmlReport - * Enable HTML report generation. - */ - public TestNGController(String outputDir, boolean generateHtmlReport) { - InputStream is = getClass().getResourceAsStream("ets.properties"); - try { - this.etsProperties.load(is); - } catch (IOException ex) { - TestSuiteLogger.log(Level.WARNING, "Unable to load ets.properties. " + ex.getMessage()); - } - URL tngSuite = TestNGController.class.getResource("testng.xml"); - File resultsDir; - if (null == outputDir || outputDir.isEmpty()) { - resultsDir = new File(System.getProperty("user.home")); - } else if (outputDir.startsWith("file:")) { - resultsDir = new File(URI.create(outputDir)); - } else { - resultsDir = new File(outputDir); - } - TestSuiteLogger.log(Level.CONFIG, "Using TestNG config: " + tngSuite); - TestSuiteLogger.log(Level.CONFIG, "Using outputDirPath: " + resultsDir.getAbsolutePath()); - // NOTE: setting third argument to 'true' enables the default listeners - this.executor = new TestNGExecutor(tngSuite.toString(), resultsDir.getAbsolutePath(), generateHtmlReport); - } - - @Override - public String getCode() { - return etsProperties.getProperty("ets-code"); - } - - @Override - public String getVersion() { - return etsProperties.getProperty("ets-version"); - } - - @Override - public String getTitle() { - return etsProperties.getProperty("ets-title"); - } - - @Override - public Source doTestRun(Document testRunArgs) throws Exception { - validateTestRunArgs(testRunArgs); - return executor.execute(testRunArgs); - } - - /** - * Validates the test run arguments. The test run is aborted if any of these - * checks fail. - * - * @param testRunArgs - * A DOM Document containing a set of XML properties (key-value - * pairs). - * @throws IllegalArgumentException - * If any arguments are missing or invalid for some reason. - */ - void validateTestRunArgs(Document testRunArgs) { - if (null == testRunArgs || !testRunArgs.getDocumentElement().getNodeName().equals("properties")) { - throw new IllegalArgumentException("Input is not an XML properties document."); - } - NodeList entries = testRunArgs.getDocumentElement().getElementsByTagName("entry"); - if (entries.getLength() == 0) { - throw new IllegalArgumentException("No test run arguments found."); - } - Map args = new HashMap(); - for (int i = 0; i < entries.getLength(); i++) { - Element entry = (Element) entries.item(i); - args.put(entry.getAttribute("key"), entry.getTextContent()); - } - if (!args.containsKey(TestRunArg.IUT.toString())) { - throw new IllegalArgumentException( - String.format("Missing argument: '%s' must be present.", TestRunArg.IUT)); - } - } + private TestRunExecutor executor; + + private Properties etsProperties = new Properties(); + + /** + * A convenience method for running the test suite using a command-line interface. The + * default values of the test run arguments are as follows: + *
      + *
    • XML properties file: ${user.home}/test-run-props.xml
    • + *
    • outputDir: ${user.home}
    • + *
    • deleteSubjectOnFinish: false
    • + *
    • generateHtmlReport: false
    • + *
    + *

    + * Synopsis + *

    + * + *
    +	 * ets-*-aio.jar [-o|--outputDir $TMPDIR] [-d|--deleteSubjectOnFinish] [-h|--generateHtmlReport] [test-run-props.xml]
    +	 * 
    + * @param args Test run arguments (optional). The first argument must refer to an XML + * properties file containing the expected set of test run arguments. If no argument + * is supplied, the file located at ${user.home}/test-run-props.xml will be used. + * @throws java.lang.Exception If the test run cannot be executed (usually due to + * unsatisfied pre-conditions). + */ + public static void main(String[] args) throws Exception { + CommandLineArguments testRunArgs = new CommandLineArguments(); + JCommander cmd = new JCommander(testRunArgs); + try { + cmd.parse(args); + } + catch (ParameterException px) { + System.out.println(px.getMessage()); + cmd.usage(); + } + if (testRunArgs.doDeleteSubjectOnFinish()) { + System.setProperty("deleteSubjectOnFinish", "true"); + } + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + File xmlArgs = testRunArgs.getPropertiesFile(); + Document testRunProps = db.parse(xmlArgs); + TestNGController controller = new TestNGController(testRunArgs.getOutputDir(), + testRunArgs.isGenerateHtmlReport()); + Source testResults = controller.doTestRun(testRunProps); + System.out.println("Test results: " + testResults.getSystemId()); + } + + /** + * Default constructor uses the location given by the "java.io.tmpdir" system property + * as the root output directory. + */ + public TestNGController() { + this(System.getProperty("java.io.tmpdir"), false); + } + + /** + * Construct a controller that writes results to the given output directory. + * @param outputDir The location of the directory in which test results will be + * written (a file system path or a 'file' URI). It will be created if it does not + * exist. + */ + public TestNGController(String outputDir) { + this(outputDir, false); + } + + /** + * Construct a controller that writes results to the given output directory. + * @param outputDir The location of the directory in which test results will be + * written (a file system path or a 'file' URI). It will be created if it does not + * exist. + * @param generateHtmlReport Enable HTML report generation. + */ + public TestNGController(String outputDir, boolean generateHtmlReport) { + InputStream is = getClass().getResourceAsStream("ets.properties"); + try { + this.etsProperties.load(is); + } + catch (IOException ex) { + TestSuiteLogger.log(Level.WARNING, "Unable to load ets.properties. " + ex.getMessage()); + } + URL tngSuite = TestNGController.class.getResource("testng.xml"); + File resultsDir; + if (null == outputDir || outputDir.isEmpty()) { + resultsDir = new File(System.getProperty("user.home")); + } + else if (outputDir.startsWith("file:")) { + resultsDir = new File(URI.create(outputDir)); + } + else { + resultsDir = new File(outputDir); + } + TestSuiteLogger.log(Level.CONFIG, "Using TestNG config: " + tngSuite); + TestSuiteLogger.log(Level.CONFIG, "Using outputDirPath: " + resultsDir.getAbsolutePath()); + // NOTE: setting third argument to 'true' enables the default listeners + this.executor = new TestNGExecutor(tngSuite.toString(), resultsDir.getAbsolutePath(), generateHtmlReport); + } + + /** {@inheritDoc} */ + @Override + public String getCode() { + return etsProperties.getProperty("ets-code"); + } + + /** {@inheritDoc} */ + @Override + public String getVersion() { + return etsProperties.getProperty("ets-version"); + } + + /** {@inheritDoc} */ + @Override + public String getTitle() { + return etsProperties.getProperty("ets-title"); + } + + /** {@inheritDoc} */ + @Override + public Source doTestRun(Document testRunArgs) throws Exception { + validateTestRunArgs(testRunArgs); + return executor.execute(testRunArgs); + } + + /** + * Validates the test run arguments. The test run is aborted if any of these checks + * fail. + * @param testRunArgs A DOM Document containing a set of XML properties (key-value + * pairs). + * @throws IllegalArgumentException If any arguments are missing or invalid for some + * reason. + */ + void validateTestRunArgs(Document testRunArgs) { + if (null == testRunArgs || !testRunArgs.getDocumentElement().getNodeName().equals("properties")) { + throw new IllegalArgumentException("Input is not an XML properties document."); + } + NodeList entries = testRunArgs.getDocumentElement().getElementsByTagName("entry"); + if (entries.getLength() == 0) { + throw new IllegalArgumentException("No test run arguments found."); + } + Map args = new HashMap(); + for (int i = 0; i < entries.getLength(); i++) { + Element entry = (Element) entries.item(i); + args.put(entry.getAttribute("key"), entry.getTextContent()); + } + if (!args.containsKey(TestRunArg.IUT.toString())) { + throw new IllegalArgumentException( + String.format("Missing argument: '%s' must be present.", TestRunArg.IUT)); + } + } + } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/TestRunArg.java b/src/main/java/org/opengis/cite/ogcapifeatures10/TestRunArg.java index 5b6bf5b1..923b3256 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/TestRunArg.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/TestRunArg.java @@ -5,18 +5,22 @@ */ public enum TestRunArg { - /** - * An absolute URI that refers to a representation of the test subject or metadata about it. - */ - IUT, + /** + * An absolute URI that refers to a representation of the test subject or metadata + * about it. + */ + IUT, - /** - * The number of collections to test (a value less or equal to 0 means all collections). - */ - NOOFCOLLECTIONS; + /** + * The number of collections to test (a value less or equal to 0 means all + * collections). + */ + NOOFCOLLECTIONS; + + /** {@inheritDoc} */ + @Override + public String toString() { + return name().toLowerCase(); + } - @Override - public String toString() { - return name().toLowerCase(); - } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/CommonDataFixture.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/CommonDataFixture.java index 826b1e6b..4be2287f 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/CommonDataFixture.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/CommonDataFixture.java @@ -14,68 +14,119 @@ import org.testng.annotations.BeforeClass; /** + *

    + * CommonDataFixture class. + *

    + * * @author Lyn Goltz */ public class CommonDataFixture extends CommonFixture { - private static final int DEFAULT_NUMBER_OF_COLLECTIONS = 3; - - private OpenApi3 apiModel; - - private List requirementClasses; - - protected int noOfCollections = DEFAULT_NUMBER_OF_COLLECTIONS; - - @BeforeClass - public void requirementClasses( ITestContext testContext ) { - this.requirementClasses = (List) testContext.getSuite().getAttribute( REQUIREMENTCLASSES.getName() ); - } - - @BeforeClass - public void noOfCollections( ITestContext testContext ) { - Object noOfCollections = testContext.getSuite().getAttribute( NO_OF_COLLECTIONS.getName() ); - if ( noOfCollections != null ) { - this.noOfCollections = (Integer) noOfCollections; - } - } - - @BeforeClass - public void retrieveApiModel( ITestContext testContext ) { - this.apiModel = (OpenApi3) testContext.getSuite().getAttribute( API_MODEL.getName() ); - } - - public OpenApi3 getApiModel() { - if ( apiModel == null ) - throw new SkipException( "ApiModel is not available." ); - return apiModel; - } - - protected List createListOfMediaTypesToSupportForOtherResources( Map linkToSelf ) { - if ( this.requirementClasses == null ) - throw new SkipException( "No requirement classes described in resource /conformance available" ); - List mediaTypesToSupport = new ArrayList<>(); - for ( RequirementClass requirementClass : this.requirementClasses ) - if ( requirementClass.hasMediaTypeForOtherResources() ) - mediaTypesToSupport.add( requirementClass.getMediaTypeOtherResources() ); - if ( linkToSelf != null ) - mediaTypesToSupport.remove( linkToSelf.get( "type" ) ); - return mediaTypesToSupport; - } - - protected List createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures() { - if ( this.requirementClasses == null ) - throw new SkipException( "No requirement classes described in resource /conformance available" ); - List mediaTypesToSupport = new ArrayList<>(); - for ( RequirementClass requirementClass : this.requirementClasses ) - if ( requirementClass.hasMediaTypeForFeaturesAndCollections() ) - mediaTypesToSupport.add( requirementClass.getMediaTypeFeaturesAndCollections() ); - return mediaTypesToSupport; - } - - protected List createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures( Map linkToSelf ) { - List mediaTypesToSupport = createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures(); - if ( linkToSelf != null ) - mediaTypesToSupport.remove( linkToSelf.get( "type" ) ); - return mediaTypesToSupport; - } + private static final int DEFAULT_NUMBER_OF_COLLECTIONS = 3; + + private OpenApi3 apiModel; + + private List requirementClasses; + + protected int noOfCollections = DEFAULT_NUMBER_OF_COLLECTIONS; + + /** + *

    + * requirementClasses. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @BeforeClass + public void requirementClasses(ITestContext testContext) { + this.requirementClasses = (List) testContext.getSuite() + .getAttribute(REQUIREMENTCLASSES.getName()); + } + + /** + *

    + * noOfCollections. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @BeforeClass + public void noOfCollections(ITestContext testContext) { + Object noOfCollections = testContext.getSuite().getAttribute(NO_OF_COLLECTIONS.getName()); + if (noOfCollections != null) { + this.noOfCollections = (Integer) noOfCollections; + } + } + + /** + *

    + * retrieveApiModel. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @BeforeClass + public void retrieveApiModel(ITestContext testContext) { + this.apiModel = (OpenApi3) testContext.getSuite().getAttribute(API_MODEL.getName()); + } + + /** + *

    + * Getter for the field apiModel. + *

    + * @return a {@link com.reprezen.kaizen.oasparser.model3.OpenApi3} object + */ + public OpenApi3 getApiModel() { + if (apiModel == null) + throw new SkipException("ApiModel is not available."); + return apiModel; + } + + /** + *

    + * createListOfMediaTypesToSupportForOtherResources. + *

    + * @param linkToSelf a {@link java.util.Map} object + * @return a {@link java.util.List} object + */ + protected List createListOfMediaTypesToSupportForOtherResources(Map linkToSelf) { + if (this.requirementClasses == null) + throw new SkipException("No requirement classes described in resource /conformance available"); + List mediaTypesToSupport = new ArrayList<>(); + for (RequirementClass requirementClass : this.requirementClasses) + if (requirementClass.hasMediaTypeForOtherResources()) + mediaTypesToSupport.add(requirementClass.getMediaTypeOtherResources()); + if (linkToSelf != null) + mediaTypesToSupport.remove(linkToSelf.get("type")); + return mediaTypesToSupport; + } + + /** + *

    + * createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures. + *

    + * @return a {@link java.util.List} object + */ + protected List createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures() { + if (this.requirementClasses == null) + throw new SkipException("No requirement classes described in resource /conformance available"); + List mediaTypesToSupport = new ArrayList<>(); + for (RequirementClass requirementClass : this.requirementClasses) + if (requirementClass.hasMediaTypeForFeaturesAndCollections()) + mediaTypesToSupport.add(requirementClass.getMediaTypeFeaturesAndCollections()); + return mediaTypesToSupport; + } + + /** + *

    + * createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures. + *

    + * @param linkToSelf a {@link java.util.Map} object + * @return a {@link java.util.List} object + */ + protected List createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures( + Map linkToSelf) { + List mediaTypesToSupport = createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures(); + if (linkToSelf != null) + mediaTypesToSupport.remove(linkToSelf.get("type")); + return mediaTypesToSupport; + } + } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/CommonFixture.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/CommonFixture.java index 5161b960..23d199a3 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/CommonFixture.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/CommonFixture.java @@ -22,84 +22,108 @@ import io.restassured.specification.RequestSpecification; /** - * A supporting base class that sets up a common test fixture. These configuration methods are invoked before those - * defined in a subclass. + * A supporting base class that sets up a common test fixture. These configuration methods + * are invoked before those defined in a subclass. */ public class CommonFixture { - private ByteArrayOutputStream requestOutputStream = new ByteArrayOutputStream(); - - private ByteArrayOutputStream responseOutputStream = new ByteArrayOutputStream(); - - protected RequestLoggingFilter requestLoggingFilter; - - protected ResponseLoggingFilter responseLoggingFilter; - - protected URI rootUri; - - /** - * Initializes the common test fixture with a client component for interacting with HTTP endpoints. - * - * @param testContext - * The test context that contains all the information for a test run, including suite attributes. - */ - @BeforeClass - public void initCommonFixture( ITestContext testContext ) { - initLogging(); - rootUri = (URI) testContext.getSuite().getAttribute( SuiteAttribute.IUT.getName() ); - } - - @BeforeMethod - public void clearMessages() { - initLogging(); - } - - public String getRequest() { - return requestOutputStream.toString(); - } - - public String getResponse() { - return responseOutputStream.toString(); - } - - protected RequestSpecification init() { - JsonConfig jsonConfig = JsonConfig.jsonConfig().numberReturnType(NumberReturnType.DOUBLE); - RestAssuredConfig config = RestAssuredConfig.newConfig().jsonConfig(jsonConfig) ; - return given().filters( new RequestLimitFilter(), requestLoggingFilter, responseLoggingFilter ).log().all().with().config(config); - } - - /** - * Obtains the (XML) response entity as a DOM Document. This convenience method wraps a static method call to - * facilitate unit testing (Mockito workaround). - * - * @param response - * A representation of an HTTP response message. - * @param targetURI - * The target URI from which the entity was retrieved (may be null). - * @return A Document representing the entity. - * - * @see ClientUtils#getResponseEntityAsDocument public Document getResponseEntityAsDocument( ClientResponse - * response, String targetURI ) { return ClientUtils.getResponseEntityAsDocument( response, targetURI ); } - */ - - /** - * Builds an HTTP request message that uses the GET method. This convenience method wraps a static method call to - * facilitate unit testing (Mockito workaround). - * - * @return A ClientRequest object. - * - * @see ClientUtils#buildGetRequest public ClientRequest buildGetRequest( URI endpoint, Map - * qryParams, MediaType... mediaTypes ) { return ClientUtils.buildGetRequest( endpoint, qryParams, mediaTypes - * ); } - */ - - private void initLogging() { - this.requestOutputStream = new ByteArrayOutputStream(); - this.responseOutputStream = new ByteArrayOutputStream(); - PrintStream requestPrintStream = new PrintStream( requestOutputStream, true ); - PrintStream responsePrintStream = new PrintStream( responseOutputStream, true ); - requestLoggingFilter = new RequestLoggingFilter( requestPrintStream ); - responseLoggingFilter = new ResponseLoggingFilter( responsePrintStream ); - } - -} \ No newline at end of file + private ByteArrayOutputStream requestOutputStream = new ByteArrayOutputStream(); + + private ByteArrayOutputStream responseOutputStream = new ByteArrayOutputStream(); + + protected RequestLoggingFilter requestLoggingFilter; + + protected ResponseLoggingFilter responseLoggingFilter; + + protected URI rootUri; + + /** + * Initializes the common test fixture with a client component for interacting with + * HTTP endpoints. + * @param testContext The test context that contains all the information for a test + * run, including suite attributes. + */ + @BeforeClass + public void initCommonFixture(ITestContext testContext) { + initLogging(); + rootUri = (URI) testContext.getSuite().getAttribute(SuiteAttribute.IUT.getName()); + } + + /** + *

    + * clearMessages. + *

    + */ + @BeforeMethod + public void clearMessages() { + initLogging(); + } + + /** + *

    + * getRequest. + *

    + * @return a {@link java.lang.String} object + */ + public String getRequest() { + return requestOutputStream.toString(); + } + + /** + *

    + * getResponse. + *

    + * @return a {@link java.lang.String} object + */ + public String getResponse() { + return responseOutputStream.toString(); + } + + /** + *

    + * init. + *

    + * @return a {@link io.restassured.specification.RequestSpecification} object + */ + protected RequestSpecification init() { + JsonConfig jsonConfig = JsonConfig.jsonConfig().numberReturnType(NumberReturnType.DOUBLE); + RestAssuredConfig config = RestAssuredConfig.newConfig().jsonConfig(jsonConfig); + return given().filters(new RequestLimitFilter(), requestLoggingFilter, responseLoggingFilter) + .log() + .all() + .with() + .config(config); + } + + /** + * Obtains the (XML) response entity as a DOM Document. This convenience method wraps + * a static method call to facilitate unit testing (Mockito workaround). + * @param response A representation of an HTTP response message. + * @param targetURI The target URI from which the entity was retrieved (may be null). + * @return A Document representing the entity. + * + * @see ClientUtils#getResponseEntityAsDocument public Document + * getResponseEntityAsDocument( ClientResponse response, String targetURI ) { return + * ClientUtils.getResponseEntityAsDocument( response, targetURI ); } + */ + + /** + * Builds an HTTP request message that uses the GET method. This convenience method + * wraps a static method call to facilitate unit testing (Mockito workaround). + * @return A ClientRequest object. + * + * @see ClientUtils#buildGetRequest public ClientRequest buildGetRequest( URI + * endpoint, Map qryParams, MediaType... mediaTypes ) { return + * ClientUtils.buildGetRequest( endpoint, qryParams, mediaTypes ); } + */ + + private void initLogging() { + this.requestOutputStream = new ByteArrayOutputStream(); + this.responseOutputStream = new ByteArrayOutputStream(); + PrintStream requestPrintStream = new PrintStream(requestOutputStream, true); + PrintStream responsePrintStream = new PrintStream(responseOutputStream, true); + requestLoggingFilter = new RequestLoggingFilter(requestPrintStream); + responseLoggingFilter = new ResponseLoggingFilter(responsePrintStream); + } + +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/RequirementClass.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/RequirementClass.java index ef063943..746fe089 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/RequirementClass.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/RequirementClass.java @@ -8,81 +8,97 @@ */ public enum RequirementClass { - CORE( "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core" ), - - HTML( "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/html", "text/html", "text/html" ), - - GEOJSON( "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson", "application/geo+json", "application/json" ), - - GMLSF0( "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/gmlsf0", - "application/gml+xml;version=3.2;profile=http://www.opengis.net/def/profile/ogc/2.0/gml-sf0", - "application/xml" ), - - GMLSF2( "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/gmlsf2", - "application/gml+xml;version=3.2;profile=http://www.opengis.net/def/profile/ogc/2.0/gml-sf2", - "application/xml" ), - - OPENAPI30( "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30" ), - - CRS( "http://www.opengis.net/spec/ogcapi-features-2/1.0/conf/crs" ); - - private final String conformanceClass; - - private final String mediaTypeFeaturesAndCollections; - - private final String mediaTypeOtherResources; - - RequirementClass( String conformanceClass ) { - this( conformanceClass, null, null ); - } - - RequirementClass( String conformanceClass, String mediaTypeFeaturesAndCollections, String mediaTypeOtherResources ) { - this.conformanceClass = conformanceClass; - this.mediaTypeFeaturesAndCollections = mediaTypeFeaturesAndCollections; - this.mediaTypeOtherResources = mediaTypeOtherResources; - } - - /** - * @return true if the RequirementClass has a media type for features and collections, - * true otherwise - */ - public boolean hasMediaTypeForFeaturesAndCollections() { - return mediaTypeFeaturesAndCollections != null; - } - - /** - * @return media type for features and collections, null if not available - */ - public String getMediaTypeFeaturesAndCollections() { - return mediaTypeFeaturesAndCollections; - } - - /** - * @return true if the RequirementClass has a media type for other resources, - * true otherwise - */ - public boolean hasMediaTypeForOtherResources() { - return mediaTypeOtherResources != null; - } - - /** - * @return media type of other resources, null if not available - */ - public String getMediaTypeOtherResources() { - return mediaTypeOtherResources; - } - - /** - * @param conformanceClass - * the conformance class of the RequirementClass to return. - * @return the RequirementClass with the passed conformance class, null if RequirementClass exists - */ - public static RequirementClass byConformanceClass( String conformanceClass ) { - for ( RequirementClass requirementClass : values() ) { - if ( requirementClass.conformanceClass.equals( conformanceClass ) ) - return requirementClass; - } - return null; - } - -} \ No newline at end of file + CORE("http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core"), + + HTML("http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/html", "text/html", "text/html"), + + GEOJSON("http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson", "application/geo+json", + "application/json"), + + GMLSF0("http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/gmlsf0", + "application/gml+xml;version=3.2;profile=http://www.opengis.net/def/profile/ogc/2.0/gml-sf0", + "application/xml"), + + GMLSF2("http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/gmlsf2", + "application/gml+xml;version=3.2;profile=http://www.opengis.net/def/profile/ogc/2.0/gml-sf2", + "application/xml"), + + OPENAPI30("http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/oas30"), + + CRS("http://www.opengis.net/spec/ogcapi-features-2/1.0/conf/crs"); + + private final String conformanceClass; + + private final String mediaTypeFeaturesAndCollections; + + private final String mediaTypeOtherResources; + + RequirementClass(String conformanceClass) { + this(conformanceClass, null, null); + } + + RequirementClass(String conformanceClass, String mediaTypeFeaturesAndCollections, String mediaTypeOtherResources) { + this.conformanceClass = conformanceClass; + this.mediaTypeFeaturesAndCollections = mediaTypeFeaturesAndCollections; + this.mediaTypeOtherResources = mediaTypeOtherResources; + } + + /** + *

    + * hasMediaTypeForFeaturesAndCollections. + *

    + * @return true if the RequirementClass has a media type for features and + * collections, true otherwise + */ + public boolean hasMediaTypeForFeaturesAndCollections() { + return mediaTypeFeaturesAndCollections != null; + } + + /** + *

    + * Getter for the field mediaTypeFeaturesAndCollections. + *

    + * @return media type for features and collections, null if not available + */ + public String getMediaTypeFeaturesAndCollections() { + return mediaTypeFeaturesAndCollections; + } + + /** + *

    + * hasMediaTypeForOtherResources. + *

    + * @return true if the RequirementClass has a media type for other + * resources, true otherwise + */ + public boolean hasMediaTypeForOtherResources() { + return mediaTypeOtherResources != null; + } + + /** + *

    + * Getter for the field mediaTypeOtherResources. + *

    + * @return media type of other resources, null if not available + */ + public String getMediaTypeOtherResources() { + return mediaTypeOtherResources; + } + + /** + *

    + * byConformanceClass. + *

    + * @param conformanceClass the conformance class of the RequirementClass to return. + * @return the RequirementClass with the passed conformance class, null + * if RequirementClass exists + */ + public static RequirementClass byConformanceClass(String conformanceClass) { + for (RequirementClass requirementClass : values()) { + if (requirementClass.conformanceClass.equals(conformanceClass)) + return requirementClass; + } + return null; + } + +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/SuiteAttribute.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/SuiteAttribute.java index a6f36957..d738ae49 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/SuiteAttribute.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/SuiteAttribute.java @@ -6,95 +6,115 @@ import java.util.Map; import com.reprezen.kaizen.oasparser.model3.OpenApi3; -import com.sun.jersey.api.client.Client; + +import jakarta.ws.rs.client.Client; /** - * An enumerated type defining ISuite attributes that may be set to constitute a shared test fixture. + * An enumerated type defining ISuite attributes that may be set to constitute a shared + * test fixture. */ @SuppressWarnings("rawtypes") public enum SuiteAttribute { - /** - * A client component for interacting with HTTP endpoints. - */ - CLIENT( "httpClient", Client.class ), - - /** - * The root URL. - */ - IUT( "instanceUnderTest", URI.class ), - - /** - * A File containing the test subject or a description of it. - */ - TEST_SUBJ_FILE( "testSubjectFile", File.class ), - - /** - * The number of collections to test. - */ - NO_OF_COLLECTIONS( "noOfCollections", Integer.class ), - - /** - * Parsed OpenApi3 document resource /api; Added during execution. - */ - API_MODEL( "apiModel", OpenApi3.class ), - - /** - * Requirement classes parsed from /conformance; Added during execution. - */ - REQUIREMENTCLASSES( "requirementclasses", List.class ), - - /** - * Response of resource /collections; Added during execution. - */ - COLLECTIONS_RESPONSE( "collectionsResponse", Map.class ), - - /** - * Parsed collections from resource /collections; Added during execution. - */ - COLLECTIONS( "collections", List.class ), - - /** - * collectionId mapped to response of resource /collection/{collectionId}; Added during execution. - */ - COLLECTION_BY_ID( "collectionById", Map.class ), - - /** - * collectionId mapped to parsed CRSs of resource /collection/{collectionId}; Added during execution. - */ - COLLECTION_CRS_BY_ID( "collectionCrsById", Map.class ), - - /** - * collectionId mapped to parsed default CRS of resource /collection/{collectionId}; Added during execution. - */ - COLLECTION_DEFAULT_CRS_BY_ID( "collectionDefaultCrsById", Map.class ), - - /** - * Collection names assigned to a feature id parsed from resource /collections/{name}/items; Added during execution. - */ - FEATUREIDS( "featureIds", Map.class ); - - private final Class attrType; - - private final String attrName; - - SuiteAttribute( String attrName, Class attrType ) { - this.attrName = attrName; - this.attrType = attrType; - } - - public Class getType() { - return attrType; - } - - public String getName() { - return attrName; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder( attrName ); - sb.append( '(' ).append( attrType.getName() ).append( ')' ); - return sb.toString(); - } + /** + * A client component for interacting with HTTP endpoints. + */ + CLIENT("httpClient", Client.class), + + /** + * The root URL. + */ + IUT("instanceUnderTest", URI.class), + + /** + * A File containing the test subject or a description of it. + */ + TEST_SUBJ_FILE("testSubjectFile", File.class), + + /** + * The number of collections to test. + */ + NO_OF_COLLECTIONS("noOfCollections", Integer.class), + + /** + * Parsed OpenApi3 document resource /api; Added during execution. + */ + API_MODEL("apiModel", OpenApi3.class), + + /** + * Requirement classes parsed from /conformance; Added during execution. + */ + REQUIREMENTCLASSES("requirementclasses", List.class), + + /** + * Response of resource /collections; Added during execution. + */ + COLLECTIONS_RESPONSE("collectionsResponse", Map.class), + + /** + * Parsed collections from resource /collections; Added during execution. + */ + COLLECTIONS("collections", List.class), + + /** + * collectionId mapped to response of resource /collection/{collectionId}; Added + * during execution. + */ + COLLECTION_BY_ID("collectionById", Map.class), + + /** + * collectionId mapped to parsed CRSs of resource /collection/{collectionId}; Added + * during execution. + */ + COLLECTION_CRS_BY_ID("collectionCrsById", Map.class), + + /** + * collectionId mapped to parsed default CRS of resource /collection/{collectionId}; + * Added during execution. + */ + COLLECTION_DEFAULT_CRS_BY_ID("collectionDefaultCrsById", Map.class), + + /** + * Collection names assigned to a feature id parsed from resource + * /collections/{name}/items; Added during execution. + */ + FEATUREIDS("featureIds", Map.class); + + private final Class attrType; + + private final String attrName; + + SuiteAttribute(String attrName, Class attrType) { + this.attrName = attrName; + this.attrType = attrType; + } + + /** + *

    + * getType. + *

    + * @return a {@link java.lang.Class} object + */ + public Class getType() { + return attrType; + } + + /** + *

    + * getName. + *

    + * @return a {@link java.lang.String} object + */ + public String getName() { + return attrName; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(attrName); + sb.append('(').append(attrType.getName()).append(')'); + return sb.toString(); + } + } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/SuitePreconditions.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/SuitePreconditions.java index f8ab6d06..8da2ff30 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/SuitePreconditions.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/SuitePreconditions.java @@ -4,36 +4,38 @@ import java.util.logging.Logger; import org.testng.ITestContext; +import org.testng.Reporter; import org.testng.annotations.BeforeSuite; /** - * Checks that various preconditions are satisfied before the test suite is run. - * If any of these (BeforeSuite) methods fail, all tests will be skipped. + * Checks that various preconditions are satisfied before the test suite is run. If any of + * these (BeforeSuite) methods fail, all tests will be skipped. */ public class SuitePreconditions { - private static final Logger LOGR = Logger.getLogger(SuitePreconditions.class.getName()); + private static final Logger LOGR = Logger.getLogger(SuitePreconditions.class.getName()); + + /** + * Verifies that the referenced test subject exists and has the expected type. + */ + @BeforeSuite + @SuppressWarnings("rawtypes") + public void verifyTestSubject() { + // ITestcontext was removed from the BeforeSuite annotation, see here: + // https://github.com/testng-team/testng/issues/3032 + ITestContext testContext = Reporter.getCurrentTestResult().getTestContext(); + SuiteAttribute testFileAttr = SuiteAttribute.TEST_SUBJ_FILE; + Object sutObj = testContext.getSuite().getAttribute(testFileAttr.getName()); + Class expectedType = testFileAttr.getType(); + if (null != sutObj && expectedType.isInstance(sutObj)) { + // TODO: Verify test subject + } + else { + String msg = String.format("Value of test suite attribute '%s' is missing or is not an instance of %s", + testFileAttr.getName(), expectedType.getName()); + LOGR.log(Level.SEVERE, msg); + throw new AssertionError(msg); + } + } - /** - * Verifies that the referenced test subject exists and has the expected - * type. - * - * @param testContext - * Information about the (pending) test run. - */ - @BeforeSuite - @SuppressWarnings("rawtypes") - public void verifyTestSubject(ITestContext testContext) { - SuiteAttribute testFileAttr = SuiteAttribute.TEST_SUBJ_FILE; - Object sutObj = testContext.getSuite().getAttribute(testFileAttr.getName()); - Class expectedType = testFileAttr.getType(); - if (null != sutObj && expectedType.isInstance(sutObj)) { - // TODO: Verify test subject - } else { - String msg = String.format("Value of test suite attribute '%s' is missing or is not an instance of %s", - testFileAttr.getName(), expectedType.getName()); - LOGR.log(Level.SEVERE, msg); - throw new AssertionError(msg); - } - } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/apidefinition/ApiDefinition.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/apidefinition/ApiDefinition.java index 10c37fa1..371796fa 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/apidefinition/ApiDefinition.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/apidefinition/ApiDefinition.java @@ -30,100 +30,103 @@ */ public class ApiDefinition extends CommonFixture { - private String response; - - private String apiUrl; - - @BeforeClass(dependsOnMethods = "initCommonFixture") - public void retrieveApiUrl() { - Response request = init().baseUri( rootUri.toString() ).accept( JSON ).when().request( GET ); - JsonPath jsonPath = request.jsonPath(); - - this.apiUrl = parseApiUrl( jsonPath ); - } - - /** - *
    -     * Abstract Test 5: /ats/core/api-definition-op
    -     * Test Purpose: Validate that the API Definition document can be retrieved from the expected location.
    -     * Requirement: /req/core/api-definition-op
    -     *
    -     * Test Method
    -     *
    -     *  1. Construct a path for each API Definition link on the landing page
    -     *  2. Issue a HTTP GET request on each path
    -     *  3. Validate that a document was returned with a status code 200
    -     *  4. Validate the contents of the returned document using test /ats/core/api-definition-success.
    -     * 
    - */ - @Test(description = "Implements A.2.3. API Definition Path {root}/api (link), Abstract Test 5 (Requirement /req/core/api-definition-op)", groups = "apidefinition", dependsOnGroups = "landingpage") - public void openapiDocumentRetrieval() { - if ( apiUrl == null || apiUrl.isEmpty() ) - throw new AssertionError( "Path to the API Definition could not be constructed from the landing page" ); - Response request = init().baseUri( apiUrl ).accept( OPEN_API_MIME_TYPE ).when().request( GET ); - request.then().statusCode( 200 ); - response = request.asString(); - } - - /** - *
    -     * Abstract Test 6: /ats/core/api-definition-success
    -     * Test Purpose: Validate that the API Definition complies with the required structure and contents.
    -     * Requirement: /req/core/api-definition-success
    -     *
    -     * Test Method: Validate the API Definition document against an appropriate schema document.
    -     * 
    - * - * @param testContext - * never null - * @throws MalformedURLException - * if the apiUrl is malformed - */ - @Test(description = "Implements A.2.3. API Definition Path {root}/api (link), Abstract Test 6 (Requirement /req/core/api-definition-success)", groups = "apidefinition", dependsOnMethods = "openapiDocumentRetrieval") - public void apiDefinitionValidation( ITestContext testContext ) - throws MalformedURLException { - OpenApi3Parser parser = new OpenApi3Parser(); - - OpenApi3 apiModel = parser.parse( response, new URL( apiUrl ), true ); - assertTrue( apiModel.isValid(), createValidationMsg( apiModel ) ); - - testContext.getSuite().setAttribute( API_MODEL.getName(), apiModel ); - } - - private String parseApiUrl( JsonPath jsonPath ) { - for ( Object link : parseAsListOfMaps( "links", jsonPath ) ) { - Map linkMap = (Map) link; - Object rel = linkMap.get( "rel" ); - Object type = linkMap.get( "type" ); - if ("service-desc".equals(rel) && OPEN_API_MIME_TYPE.equals(type.toString().replace(" ", ""))) { - String url = (String) linkMap.get("href"); - if (!url.startsWith("http")) { - String path = url; - if (null != rootUri.getScheme() && !rootUri.getScheme().isEmpty()) - url = rootUri.getScheme() + ":"; - if (null != rootUri.getAuthority() && !rootUri.getAuthority().isEmpty()) - url = url + "//" + rootUri.getAuthority(); - url = url + path; - if (null != rootUri.getQuery() && !rootUri.getQuery().isEmpty()) - url = url + "?" + rootUri.getQuery(); - if (null != rootUri.getFragment() && !rootUri.getFragment().isEmpty()) - url = url + "#" + rootUri.getFragment(); - } - return url; - } - } - return null; - } - - private String createValidationMsg( OpenApi3 model ) { - StringBuilder sb = new StringBuilder(); - sb.append( "API definition document is not valid. Found following validation items:" ); - if ( !model.isValid() ) { - for ( ValidationResults.ValidationItem item : model.getValidationItems() ) { - sb.append( " - " ).append( item.getSeverity() ).append( ": " ).append( item.toString() ).append("\n"); - } - } - return sb.toString(); - } + private String response; + + private String apiUrl; + + /** + *

    + * retrieveApiUrl. + *

    + */ + @BeforeClass(dependsOnMethods = "initCommonFixture") + public void retrieveApiUrl() { + Response request = init().baseUri(rootUri.toString()).accept(JSON).when().request(GET); + JsonPath jsonPath = request.jsonPath(); + + this.apiUrl = parseApiUrl(jsonPath); + } + + /** + *
    +	 * Abstract Test 5: /ats/core/api-definition-op
    +	 * Test Purpose: Validate that the API Definition document can be retrieved from the expected location.
    +	 * Requirement: /req/core/api-definition-op
    +	 *
    +	 * Test Method
    +	 *
    +	 *  1. Construct a path for each API Definition link on the landing page
    +	 *  2. Issue a HTTP GET request on each path
    +	 *  3. Validate that a document was returned with a status code 200
    +	 *  4. Validate the contents of the returned document using test /ats/core/api-definition-success.
    +	 * 
    + */ + @Test(description = "Implements A.2.3. API Definition Path {root}/api (link), Abstract Test 5 (Requirement /req/core/api-definition-op)", + groups = "apidefinition", dependsOnGroups = "landingpage") + public void openapiDocumentRetrieval() { + if (apiUrl == null || apiUrl.isEmpty()) + throw new AssertionError("Path to the API Definition could not be constructed from the landing page"); + Response request = init().baseUri(apiUrl).accept(OPEN_API_MIME_TYPE).when().request(GET); + request.then().statusCode(200); + response = request.asString(); + } + + /** + *
    +	 * Abstract Test 6: /ats/core/api-definition-success
    +	 * Test Purpose: Validate that the API Definition complies with the required structure and contents.
    +	 * Requirement: /req/core/api-definition-success
    +	 *
    +	 * Test Method: Validate the API Definition document against an appropriate schema document.
    +	 * 
    + * @param testContext never null + * @throws java.net.MalformedURLException if the apiUrl is malformed + */ + @Test(description = "Implements A.2.3. API Definition Path {root}/api (link), Abstract Test 6 (Requirement /req/core/api-definition-success)", + groups = "apidefinition", dependsOnMethods = "openapiDocumentRetrieval") + public void apiDefinitionValidation(ITestContext testContext) throws MalformedURLException { + OpenApi3Parser parser = new OpenApi3Parser(); + + OpenApi3 apiModel = parser.parse(response, new URL(apiUrl), true); + assertTrue(apiModel.isValid(), createValidationMsg(apiModel)); + + testContext.getSuite().setAttribute(API_MODEL.getName(), apiModel); + } + + private String parseApiUrl(JsonPath jsonPath) { + for (Object link : parseAsListOfMaps("links", jsonPath)) { + Map linkMap = (Map) link; + Object rel = linkMap.get("rel"); + Object type = linkMap.get("type"); + if ("service-desc".equals(rel) && OPEN_API_MIME_TYPE.equals(type.toString().replace(" ", ""))) { + String url = (String) linkMap.get("href"); + if (!url.startsWith("http")) { + String path = url; + if (null != rootUri.getScheme() && !rootUri.getScheme().isEmpty()) + url = rootUri.getScheme() + ":"; + if (null != rootUri.getAuthority() && !rootUri.getAuthority().isEmpty()) + url = url + "//" + rootUri.getAuthority(); + url = url + path; + if (null != rootUri.getQuery() && !rootUri.getQuery().isEmpty()) + url = url + "?" + rootUri.getQuery(); + if (null != rootUri.getFragment() && !rootUri.getFragment().isEmpty()) + url = url + "#" + rootUri.getFragment(); + } + return url; + } + } + return null; + } + + private String createValidationMsg(OpenApi3 model) { + StringBuilder sb = new StringBuilder(); + sb.append("API definition document is not valid. Found following validation items:"); + if (!model.isValid()) { + for (ValidationResults.ValidationItem item : model.getValidationItems()) { + sb.append(" - ").append(item.getSeverity()).append(": ").append(item.toString()).append("\n"); + } + } + return sb.toString(); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/AbstractFeatures.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/AbstractFeatures.java index 1aa94df3..0a7bdfbd 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/AbstractFeatures.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/AbstractFeatures.java @@ -52,397 +52,418 @@ import io.restassured.response.Response; /** + *

    + * AbstractFeatures class. + *

    + * * @author Lyn Goltz */ public class AbstractFeatures extends CommonDataFixture { - protected final Map collectionIdAndResponse = new HashMap<>(); - - protected List> collections; - - protected URI iut; - - @DataProvider(name = "collectionPaths") - public Iterator collectionPaths( ITestContext testContext ) { - List testPointsForCollections = retrieveTestPointsForCollections( getApiModel(), iut, - noOfCollections ); - List collectionsData = new ArrayList<>(); - for ( TestPoint testPointForCollections : testPointsForCollections ) { - collectionsData.add( new Object[] { testPointForCollections } ); - } - return collectionsData.iterator(); - } - - @BeforeClass - public void retrieveRequiredInformationFromTestContext( ITestContext testContext ) { - this.iut = (URI) testContext.getSuite().getAttribute( IUT.getName() ); - this.collections = (List>) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTIONS.getName() ); - } - - /** - * Abstract Test 22, Test Method 1 - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   1. Validate that the type property is present and has a value of FeatureCollection
    -     * 
    - * - * @param collection - * the collection under test, never null - */ - public void validateTypeProperty( CollectionResponseKey collection ) { - ResponseData response = collectionIdAndResponse.get( collection ); - if ( response == null ) - throw new SkipException( "Could not find a response for collection with id " + collection.id ); - - JsonPath jsonPath = response.jsonPath(); - String type = jsonPath.get( "type" ); - assertNotNull( type, "type property is missing" ); - assertEquals( type, "FeatureCollection", "Expected type property value of FeatureCollection but was " + type ); - } - - /** - * Abstract Test 22, Test Method 2 - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   2. Validate the features property is present and that it is populated with an array of feature items.
    -     * 
    - * - * @param collection - * the collection under test, never null - */ - void validateFeaturesProperty( CollectionResponseKey collection ) { - ResponseData response = collectionIdAndResponse.get( collection ); - if ( response == null ) - throw new SkipException( "Could not find a response for collection with id " + collection.id ); - - JsonPath jsonPath = response.jsonPath(); - List type = jsonPath.get( "features" ); - assertNotNull( type, "features property is missing:" ); - } - - /** - * Abstract Test 22, Test Method 4 (Abstract Test 23) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   4. If the links property is present, validate that all entries comply with /ats/core/fc-links
    -     * 
    - * - *
    -     * Abstract Test 23: /ats/core/fc-links
    -     * Test Purpose: Validate that the required links are included in the Collections document.
    -     * Requirement: /req/core/fc-links, /req/core/fc-rel-type
    -     *
    -     * Test Method:
    -     * Verify that the response document includes:
    -     *   1. a link to this response document (relation: self),
    -     *   2. a link to the response document in every other media type supported by the server (relation: alternate).
    -     *
    -     * Verify that all links include the rel and type link parameters.
    -     * 
    - * - * @param collection - * the collection under test, never null - */ - void validateLinks( CollectionResponseKey collection ) { - ResponseData response = collectionIdAndResponse.get( collection ); - if ( response == null ) - throw new SkipException( "Could not find a response for collection with id " + collection.id ); - - JsonPath jsonPath = response.jsonPath(); - List> links = jsonPath.getList( "links" ); - - // 1. a link to this response document (relation: self) - Map linkToSelf = findLinkByRel( links, "self" ); - assertNotNull( linkToSelf, "Feature Collection Metadata document must include a link for itself" ); - - // 2. a link to the response document in every other media type supported by the server (relation: alternate) - // Dev: Supported media type are identified by the compliance classes for this server - List mediaTypesToSupport = createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures( linkToSelf ); - List> alternateLinks = findLinksWithSupportedMediaTypeByRel( links, mediaTypesToSupport, - "alternate" ); - List typesWithoutLink = findUnsupportedTypes( alternateLinks, mediaTypesToSupport ); - assertTrue( typesWithoutLink.isEmpty(), - "Feature Collection Metadata document must include links for alternate encodings. Missing links for types " - + typesWithoutLink ); - - // Validate that each "self"/"alternate" link includes a rel and type parameter. - Set rels = new HashSet<>(); - rels.add("self"); - rels.add("alternate"); - List linksWithoutRelOrType = findLinksWithoutRelOrType( links, rels ); - assertTrue( linksWithoutRelOrType.isEmpty(), - "Links for alternate encodings must include a rel and type parameter. Missing for links " - + linksWithoutRelOrType ); - } - - /** - * Abstract Test 22, Test Method 5 (Abstract Test 24) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   5. If the timeStamp property is present, validate that it complies with /ats/core/fc-timeStamp
    -     * 
    - * - *
    -     * Abstract Test 24: /ats/core/fc-timeStamp
    -     * Test Purpose: Validate the timeStamp parameter returned with a Features response
    -     * Requirement: /req/core/fc-timeStamp
    -     *
    -     * Test Method: Validate that the timeStamp value is set to the time when the response was generated.
    -     * 
    - * - * @param collection - * the collection under test, never null - */ - public void validateTimeStamp( CollectionResponseKey collection ) { - ResponseData response = collectionIdAndResponse.get( collection ); - if ( response == null ) - throw new SkipException( "Could not find a response for collection with id " + collection.id ); - - JsonPath jsonPath = response.jsonPath(); - - assertTimeStamp( collection.id, jsonPath, response.timeStampBeforeResponse, response.timeStampAfterResponse, - true ); - } - - /** - * Abstract Test 22, Test Method 6 (Abstract Test 25) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   6. If the numberMatched property is present, validate that it complies with /ats/core/fc-numberMatched
    -     * 
    - * - *
    -     * Abstract Test 25: /ats/core/fc-numberMatched
    -     * Test Purpose: Validate the numberMatched parameter returned with a Features response
    -     * Requirement: /req/core/fc-numberMatched
    -     *
    -     * Test Method: Validate that the value of the numberMatched parameter is identical to the number of features in the feature collections that match the selection parameters like bbox, datetime or additional filter parameters.
    -     * 
    - * - * @param collection - * the collection under test, never null - * - * @throws URISyntaxException - * if the creation of a uri fails - */ - void validateNumberMatched( CollectionResponseKey collection ) - throws URISyntaxException { - ResponseData response = collectionIdAndResponse.get( collection ); - if ( response == null ) - throw new SkipException( "Could not find a response for collection with id " + collection.id ); - - JsonPath jsonPath = response.jsonPath(); - - assertNumberMatched( getApiModel(), iut, collection.id, jsonPath, true ); - } - - /** - * Abstract Test 22, Test Method 7 (Abstract Test 26) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   7. If the numberReturned property is present, validate that it complies with /ats/core/fc-numberReturned
    -     * 
    - * - *
    -     * Abstract Test 26: /ats/core/fc-numberReturned
    -     * Test Purpose: Validate the numberReturned parameter returned with a Features response
    -     * Requirement: /req/core/fc-numberReturned
    -     *
    -     * Test Method: Validate that the numberReturned value is identical to the number of features in the response.
    -     * 
    - * - * @param collection - * the collection under test, never null - */ - void validateNumberReturned( CollectionResponseKey collection ) { - ResponseData response = collectionIdAndResponse.get( collection ); - if ( response == null ) - throw new SkipException( "Could not find a response for collection with id " + collection.id ); - - JsonPath jsonPath = response.jsonPath(); - - assertNumberReturned( collection.id, jsonPath, true ); - } - - /** - * Abstract Test 2, Test Method 1 - * - *
    -     * Abstract Test 2: /ats/core/crs84
    -     * Test Purpose: Validate that all spatial geometries provided through the API are in the CRS84 spatial reference system unless otherwise requested by the client.
    -     * Requirement: /req/core/crs84
    -     *
    -     * Test Method
    -     *  1. Do not specify a coordinate reference system in any request. All spatial data should be in the CRS84 reference system.
    -     *  2. Validate retrieved spatial data using the CRS84 reference system.
    -     * 
    - * @throws ParseException - * if the geometry could not be parsed - * - * @param collection - * the collection under test, never null - */ - void validateGeometriesInCrs84( CollectionResponseKey collection ) - throws ParseException { - ResponseData response = collectionIdAndResponse.get( collection ); - if ( response == null ) - throw new SkipException( "Could not find a response for collection with id " + collection.id ); - - JsonPath jsonPath = response.jsonPath(); - List> features = jsonPath.getList( "features" ); - int count = 0; - for ( Map feature : features ) { - if(count >= OgcApiFeatures10.FEATURES_LIMIT) { - break; - } - Object featureIdOrNull = feature.get( "id" ); - if(featureIdOrNull == null) { - featureIdOrNull = "N/A"; - } - String featureId = featureIdOrNull.toString(); - Geometry geometry = null; - try { - geometry = JsonUtils.parseFeatureGeometry( feature, DEFAULT_CRS ); - } catch (Exception e) { - // do nothing - } - if(geometry == null) { - //features without geometry should be returned, so this is fine - continue; - } - assertInCrs84( geometry, - String.format( "Geometry of feature with id {} in collection with id {} is outside the valid area of the ", - featureId, collection.id ) ); - count++; - } - } - - void validateGeometriesInBBox(CollectionResponseKey collection, BBox bbox) - throws ParseException { - ResponseData response = collectionIdAndResponse.get(collection); - if (response == null) - throw new SkipException("Could not find a response for collection with id " + collection.id); - - JsonPath jsonPath = response.jsonPath(); - List> features = jsonPath.getList("features"); - - if (features.isEmpty()) { - throw new SkipException("No features were returned for collection."); - } - Coordinate min1 = new Coordinate(bbox.getMinX(), bbox.getMinY()); - Coordinate min2 = new Coordinate(bbox.getMinX(), bbox.getMaxY()); - Coordinate max1 = new Coordinate(bbox.getMaxX(), bbox.getMinY()); - Coordinate max2 = new Coordinate(bbox.getMaxX(), bbox.getMaxY()); - Polygon bboxPolygon = null; - //see https://github.com/opengeospatial/ets-ogcapi-features10/issues/247 - //special case to cover bounding boxes that cross the date line - if(bbox.getMinX() == 177.0d) { - bboxPolygon = new GeometryFactory().createPolygon(new Coordinate [] {min1, max1, new Coordinate(-180d, 65d), new Coordinate(180d, 65d), max2, min2, min1}); - } else { - bboxPolygon = new GeometryFactory().createPolygon(new Coordinate [] {min1, max1, max2, min2, min1}); - } - int count = 0; - for (Map feature : features) { - if(count >= OgcApiFeatures10.FEATURES_LIMIT) { - break; - } - Geometry geometry = null; - try { - geometry = JsonUtils.parseFeatureGeometry( feature, DEFAULT_CRS ); - } catch (Exception e) { - // do nothing - } - if(geometry == null) { - //features without geometry should be returned, so this is fine - continue; - } - boolean insideBBox = RectangleIntersects.intersects(bboxPolygon, geometry); - assertTrue(insideBBox, String.format("Geometry '%s' outside bounding box: '%s'.", geometry.toString(), bbox.toString())); - count++; - } - - } - - protected boolean isRequired( Parameter param ) { - return param.getRequired() != null && param.getRequired(); - } - - protected Boolean isExplode( Parameter param ) { - return param.getExplode() != null && param.getExplode(); - } - - protected class ResponseData { - - private final Response response; - - protected final ZonedDateTime timeStampBeforeResponse; - - protected final ZonedDateTime timeStampAfterResponse; - - public ResponseData( Response response, ZonedDateTime timeStampBeforeResponse, - ZonedDateTime timeStampAfterResponse ) { - this.response = response; - this.timeStampBeforeResponse = timeStampBeforeResponse; - this.timeStampAfterResponse = timeStampAfterResponse; - } - - public JsonPath jsonPath() { - return response.jsonPath(); - } - } - - protected class CollectionResponseKey { - - private final String id; - - protected CollectionResponseKey( String id ) { - this.id = id; - } - - @Override - public boolean equals( Object o ) { - if ( this == o ) - return true; - if ( o == null || getClass() != o.getClass() ) - return false; - CollectionResponseKey that = (CollectionResponseKey) o; - return Objects.equals( id, that.id ); - } - - @Override - public int hashCode() { - return Objects.hash( id ); - } - } - + protected final Map collectionIdAndResponse = new HashMap<>(); + + protected List> collections; + + protected URI iut; + + /** + *

    + * collectionPaths. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionPaths") + public Iterator collectionPaths(ITestContext testContext) { + List testPointsForCollections = retrieveTestPointsForCollections(getApiModel(), iut, + noOfCollections); + List collectionsData = new ArrayList<>(); + for (TestPoint testPointForCollections : testPointsForCollections) { + collectionsData.add(new Object[] { testPointForCollections }); + } + return collectionsData.iterator(); + } + + /** + *

    + * retrieveRequiredInformationFromTestContext. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @BeforeClass + public void retrieveRequiredInformationFromTestContext(ITestContext testContext) { + this.iut = (URI) testContext.getSuite().getAttribute(IUT.getName()); + this.collections = (List>) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTIONS.getName()); + } + + /** + * Abstract Test 22, Test Method 1 + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   1. Validate that the type property is present and has a value of FeatureCollection
    +	 * 
    + * @param collection the collection under test, never null + */ + public void validateTypeProperty(CollectionResponseKey collection) { + ResponseData response = collectionIdAndResponse.get(collection); + if (response == null) + throw new SkipException("Could not find a response for collection with id " + collection.id); + + JsonPath jsonPath = response.jsonPath(); + String type = jsonPath.get("type"); + assertNotNull(type, "type property is missing"); + assertEquals(type, "FeatureCollection", "Expected type property value of FeatureCollection but was " + type); + } + + /** + * Abstract Test 22, Test Method 2 + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   2. Validate the features property is present and that it is populated with an array of feature items.
    +	 * 
    + * @param collection the collection under test, never null + */ + void validateFeaturesProperty(CollectionResponseKey collection) { + ResponseData response = collectionIdAndResponse.get(collection); + if (response == null) + throw new SkipException("Could not find a response for collection with id " + collection.id); + + JsonPath jsonPath = response.jsonPath(); + List type = jsonPath.get("features"); + assertNotNull(type, "features property is missing:"); + } + + /** + * Abstract Test 22, Test Method 4 (Abstract Test 23) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   4. If the links property is present, validate that all entries comply with /ats/core/fc-links
    +	 * 
    + * + *
    +	 * Abstract Test 23: /ats/core/fc-links
    +	 * Test Purpose: Validate that the required links are included in the Collections document.
    +	 * Requirement: /req/core/fc-links, /req/core/fc-rel-type
    +	 *
    +	 * Test Method:
    +	 * Verify that the response document includes:
    +	 *   1. a link to this response document (relation: self),
    +	 *   2. a link to the response document in every other media type supported by the server (relation: alternate).
    +	 *
    +	 * Verify that all links include the rel and type link parameters.
    +	 * 
    + * @param collection the collection under test, never null + */ + void validateLinks(CollectionResponseKey collection) { + ResponseData response = collectionIdAndResponse.get(collection); + if (response == null) + throw new SkipException("Could not find a response for collection with id " + collection.id); + + JsonPath jsonPath = response.jsonPath(); + List> links = jsonPath.getList("links"); + + // 1. a link to this response document (relation: self) + Map linkToSelf = findLinkByRel(links, "self"); + assertNotNull(linkToSelf, "Feature Collection Metadata document must include a link for itself"); + + // 2. a link to the response document in every other media type supported by the + // server (relation: alternate) + // Dev: Supported media type are identified by the compliance classes for this + // server + List mediaTypesToSupport = createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures(linkToSelf); + List> alternateLinks = findLinksWithSupportedMediaTypeByRel(links, mediaTypesToSupport, + "alternate"); + List typesWithoutLink = findUnsupportedTypes(alternateLinks, mediaTypesToSupport); + assertTrue(typesWithoutLink.isEmpty(), + "Feature Collection Metadata document must include links for alternate encodings. Missing links for types " + + typesWithoutLink); + + // Validate that each "self"/"alternate" link includes a rel and type parameter. + Set rels = new HashSet<>(); + rels.add("self"); + rels.add("alternate"); + List linksWithoutRelOrType = findLinksWithoutRelOrType(links, rels); + assertTrue(linksWithoutRelOrType.isEmpty(), + "Links for alternate encodings must include a rel and type parameter. Missing for links " + + linksWithoutRelOrType); + } + + /** + * Abstract Test 22, Test Method 5 (Abstract Test 24) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   5. If the timeStamp property is present, validate that it complies with /ats/core/fc-timeStamp
    +	 * 
    + * + *
    +	 * Abstract Test 24: /ats/core/fc-timeStamp
    +	 * Test Purpose: Validate the timeStamp parameter returned with a Features response
    +	 * Requirement: /req/core/fc-timeStamp
    +	 *
    +	 * Test Method: Validate that the timeStamp value is set to the time when the response was generated.
    +	 * 
    + * @param collection the collection under test, never null + */ + public void validateTimeStamp(CollectionResponseKey collection) { + ResponseData response = collectionIdAndResponse.get(collection); + if (response == null) + throw new SkipException("Could not find a response for collection with id " + collection.id); + + JsonPath jsonPath = response.jsonPath(); + + assertTimeStamp(collection.id, jsonPath, response.timeStampBeforeResponse, response.timeStampAfterResponse, + true); + } + + /** + * Abstract Test 22, Test Method 6 (Abstract Test 25) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   6. If the numberMatched property is present, validate that it complies with /ats/core/fc-numberMatched
    +	 * 
    + * + *
    +	 * Abstract Test 25: /ats/core/fc-numberMatched
    +	 * Test Purpose: Validate the numberMatched parameter returned with a Features response
    +	 * Requirement: /req/core/fc-numberMatched
    +	 *
    +	 * Test Method: Validate that the value of the numberMatched parameter is identical to the number of features in the feature collections that match the selection parameters like bbox, datetime or additional filter parameters.
    +	 * 
    + * @param collection the collection under test, never null + * @throws URISyntaxException if the creation of a uri fails + */ + void validateNumberMatched(CollectionResponseKey collection) throws URISyntaxException { + ResponseData response = collectionIdAndResponse.get(collection); + if (response == null) + throw new SkipException("Could not find a response for collection with id " + collection.id); + + JsonPath jsonPath = response.jsonPath(); + + assertNumberMatched(getApiModel(), iut, collection.id, jsonPath, true); + } + + /** + * Abstract Test 22, Test Method 7 (Abstract Test 26) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   7. If the numberReturned property is present, validate that it complies with /ats/core/fc-numberReturned
    +	 * 
    + * + *
    +	 * Abstract Test 26: /ats/core/fc-numberReturned
    +	 * Test Purpose: Validate the numberReturned parameter returned with a Features response
    +	 * Requirement: /req/core/fc-numberReturned
    +	 *
    +	 * Test Method: Validate that the numberReturned value is identical to the number of features in the response.
    +	 * 
    + * @param collection the collection under test, never null + */ + void validateNumberReturned(CollectionResponseKey collection) { + ResponseData response = collectionIdAndResponse.get(collection); + if (response == null) + throw new SkipException("Could not find a response for collection with id " + collection.id); + + JsonPath jsonPath = response.jsonPath(); + + assertNumberReturned(collection.id, jsonPath, true); + } + + /** + * Abstract Test 2, Test Method 1 + * + *
    +	 * Abstract Test 2: /ats/core/crs84
    +	 * Test Purpose: Validate that all spatial geometries provided through the API are in the CRS84 spatial reference system unless otherwise requested by the client.
    +	 * Requirement: /req/core/crs84
    +	 *
    +	 * Test Method
    +	 *  1. Do not specify a coordinate reference system in any request. All spatial data should be in the CRS84 reference system.
    +	 *  2. Validate retrieved spatial data using the CRS84 reference system.
    +	 * 
    + * @throws ParseException if the geometry could not be parsed + * @param collection the collection under test, never null + */ + void validateGeometriesInCrs84(CollectionResponseKey collection) throws ParseException { + ResponseData response = collectionIdAndResponse.get(collection); + if (response == null) + throw new SkipException("Could not find a response for collection with id " + collection.id); + + JsonPath jsonPath = response.jsonPath(); + List> features = jsonPath.getList("features"); + int count = 0; + for (Map feature : features) { + if (count >= OgcApiFeatures10.FEATURES_LIMIT) { + break; + } + Object featureIdOrNull = feature.get("id"); + if (featureIdOrNull == null) { + featureIdOrNull = "N/A"; + } + String featureId = featureIdOrNull.toString(); + Geometry geometry = null; + try { + geometry = JsonUtils.parseFeatureGeometry(feature, DEFAULT_CRS); + } + catch (Exception e) { + // do nothing + } + if (geometry == null) { + // features without geometry should be returned, so this is fine + continue; + } + assertInCrs84(geometry, String.format( + "Geometry of feature with id {} in collection with id {} is outside the valid area of the ", + featureId, collection.id)); + count++; + } + } + + void validateGeometriesInBBox(CollectionResponseKey collection, BBox bbox) throws ParseException { + ResponseData response = collectionIdAndResponse.get(collection); + if (response == null) + throw new SkipException("Could not find a response for collection with id " + collection.id); + + JsonPath jsonPath = response.jsonPath(); + List> features = jsonPath.getList("features"); + + if (features.isEmpty()) { + throw new SkipException("No features were returned for collection."); + } + Coordinate min1 = new Coordinate(bbox.getMinX(), bbox.getMinY()); + Coordinate min2 = new Coordinate(bbox.getMinX(), bbox.getMaxY()); + Coordinate max1 = new Coordinate(bbox.getMaxX(), bbox.getMinY()); + Coordinate max2 = new Coordinate(bbox.getMaxX(), bbox.getMaxY()); + Polygon bboxPolygon = null; + // see https://github.com/opengeospatial/ets-ogcapi-features10/issues/247 + // special case to cover bounding boxes that cross the date line + if (bbox.getMinX() == 177.0d) { + bboxPolygon = new GeometryFactory().createPolygon(new Coordinate[] { min1, max1, new Coordinate(-180d, 65d), + new Coordinate(180d, 65d), max2, min2, min1 }); + } + else { + bboxPolygon = new GeometryFactory().createPolygon(new Coordinate[] { min1, max1, max2, min2, min1 }); + } + int count = 0; + for (Map feature : features) { + if (count >= OgcApiFeatures10.FEATURES_LIMIT) { + break; + } + Geometry geometry = null; + try { + geometry = JsonUtils.parseFeatureGeometry(feature, DEFAULT_CRS); + } + catch (Exception e) { + // do nothing + } + if (geometry == null) { + // features without geometry should be returned, so this is fine + continue; + } + boolean insideBBox = RectangleIntersects.intersects(bboxPolygon, geometry); + assertTrue(insideBBox, + String.format("Geometry '%s' outside bounding box: '%s'.", geometry.toString(), bbox.toString())); + count++; + } + + } + + /** + *

    + * isRequired. + *

    + * @param param a {@link com.reprezen.kaizen.oasparser.model3.Parameter} object + * @return a boolean + */ + protected boolean isRequired(Parameter param) { + return param.getRequired() != null && param.getRequired(); + } + + /** + *

    + * isExplode. + *

    + * @param param a {@link com.reprezen.kaizen.oasparser.model3.Parameter} object + * @return a {@link java.lang.Boolean} object + */ + protected Boolean isExplode(Parameter param) { + return param.getExplode() != null && param.getExplode(); + } + + protected class ResponseData { + + private final Response response; + + protected final ZonedDateTime timeStampBeforeResponse; + + protected final ZonedDateTime timeStampAfterResponse; + + public ResponseData(Response response, ZonedDateTime timeStampBeforeResponse, + ZonedDateTime timeStampAfterResponse) { + this.response = response; + this.timeStampBeforeResponse = timeStampBeforeResponse; + this.timeStampAfterResponse = timeStampAfterResponse; + } + + public JsonPath jsonPath() { + return response.jsonPath(); + } + + } + + protected class CollectionResponseKey { + + private final String id; + + protected CollectionResponseKey(String id) { + this.id = id; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + CollectionResponseKey that = (CollectionResponseKey) o; + return Objects.equals(id, that.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } + + } + } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/Feature.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/Feature.java index c1acdf8a..9ab29258 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/Feature.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/Feature.java @@ -38,156 +38,174 @@ */ public class Feature extends CommonDataFixture { - public static final String DUMMY_COLLECTION_ID = "dUmmYColLection"; - - private List> collections; - - private final Map collectionNameAndResponse = new HashMap<>(); - - @DataProvider(name = "collectionFeatureId") - public Iterator collectionFeatureId( ITestContext testContext ) { - Map collectionNameToFeatureId = (Map) testContext.getSuite().getAttribute( SuiteAttribute.FEATUREIDS.getName() ); - List collectionsData = new ArrayList<>(); - for ( Map collection : collections ) { - String collectionId = (String) collection.get( "id" ); - String featureId = null; - if ( collectionNameToFeatureId != null ) { - featureId = collectionNameToFeatureId.get( collectionId ); - } - if(featureId != null) { - collectionsData.add( new Object[] { collection, featureId } ); - } - } - - //https://github.com/opengeospatial/ets-ogcapi-features10/issues/215 - //Add dummy collection ID if no feature IDs were found. - //Throw assertionError in feature tests, if dummy ID is found. - if(collectionsData.isEmpty()) { - Map dummyCollection = new HashMap(); - dummyCollection.put("id", DUMMY_COLLECTION_ID); - collectionsData.add( new Object[] { dummyCollection, null } ); - } - - return collectionsData.iterator(); - } - - @BeforeClass - public void retrieveRequiredInformationFromTestContext( ITestContext testContext ) { - this.collections = (List>) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTIONS.getName() ); - } - - /** - *
    -     * Abstract Test 27: /ats/core/f-op
    -     * Test Purpose: Validate that a feature can be retrieved from the expected location.
    -     * Requirement: /req/core/f-op
    -     *
    -     * Test Method
    -     *  1. For a sufficiently large subset of all features in a feature collection (path /collections/{collectionId}), issue an HTTP GET request to the URL /collections/{collectionId}/items/{featureId} where {collectionId} is the id property for the collection and {featureId} is the id property of the feature.
    -     *  2. Validate that a feature was returned with a status code 200
    -     *  3. Validate the contents of the returned feature using test /ats/core/f-success.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param featureId - * the featureId to request, may be null (test will be skipped) - */ - @Test(description = "Implements A.2.8. Feature, Abstract Test 27 (Requirement /req/core/f-op)", dataProvider = "collectionFeatureId", dependsOnGroups = "featuresBase", alwaysRun = true) - public void featureOperation( Map collection, String featureId ) { - String collectionId = (String) collection.get( "id" ); - //https://github.com/opengeospatial/ets-ogcapi-features10/issues/215 - if ( collectionId == DUMMY_COLLECTION_ID ) { - throw new AssertionError( "No feature Ids found in tested collections." ); - } - if ( featureId == null ) - throw new SkipException( "No featureId available for collection '" + collectionId + "'" ); - - String getFeatureUrlWithFeatureId = JsonUtils.findFeatureUrlForGeoJson( rootUri, collection, featureId ); - if ( getFeatureUrlWithFeatureId == null ) - throw new SkipException( "Could not find url for collection with name " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); - - Response response = init().baseUri( getFeatureUrlWithFeatureId ).accept( GEOJSON_MIME_TYPE ).when().request( GET ); - response.then().statusCode( 200 ); - - collectionNameAndResponse.put( collectionId, response ); - } - - /** - *
    -     * Abstract Test 28: /ats/core/f-success
    -     * Test Purpose: Validate that the Feature complies with the required structure and contents.
    -     * Requirement: /req/core/f-success
    -     *
    -     * Test Method
    -     *  1. Validate that the Feature includes all required link properties using /ats/core/f-links
    -     *  2. Validate the Feature for all supported media types using the resources and tests identified in Schema and Tests for Features
    -     * 
    - * - *
    -     * Abstract Test 29: /ats/core/f-links
    -     * Test Purpose: Validate that the required links are included in a Feature.
    -     * Requirement: /req/core/f-links
    -     *
    -     * Test Method:
    -     * Verify that the returned Feature includes:
    -     *  1. a link to this response document (relation: self),
    -     *  2. a link to the response document in every other media type supported by the server (relation: alternate).
    -     *  3. a link to the feature collection that contains this feature (relation: collection).
    -     * Verify that all links include the rel and type link parameters.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param featureId - * the featureId to request, may be null (test will be skipped) - */ - @Test(description = "Implements A.2.8. Feature, Abstract Test 28 + 29 (Requirements /req/core/f-success, /req/core/f-links)", dataProvider = "collectionFeatureId", dependsOnMethods = "featureOperation", alwaysRun = true) - public void validateFeatureResponse( Map collection, String featureId ) { - String collectionId = (String) collection.get( "id" ); - //https://github.com/opengeospatial/ets-ogcapi-features10/issues/215 - if ( collectionId == DUMMY_COLLECTION_ID ) { - throw new AssertionError( "No feature Ids found in tested collections." ); - } - Response response = collectionNameAndResponse.get( collectionId ); - if ( response == null ) - throw new SkipException( "Could not find a response for collection with id " + collectionId ); - - JsonPath jsonPath = response.jsonPath(); - List> links = parseAsListOfMaps( "links", jsonPath ); - - // 1. a link to this response document (relation: self), - Map linkToSelf = findLinkByRel( links, "self" ); - assertNotNull( linkToSelf, "Feature Response must include a link for itself" ); - // Verify that all links include the rel and type link parameters. - assertTrue( linkIncludesRelAndType( linkToSelf ), "Link to itself must include a rel and type parameter" ); - - // 2. a link to the response document in every other media type supported by the server (relation: alternate). - // Dev: Supported media type are identified by the compliance classes for this server - List mediaTypesToSupport = createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures( linkToSelf ); - List> alternateLinks = findLinksWithSupportedMediaTypeByRel( links, mediaTypesToSupport, - "alternate" ); - List typesWithoutLink = findUnsupportedTypes( alternateLinks, mediaTypesToSupport ); - assertTrue( typesWithoutLink.isEmpty(), - "Feature Response must include links for alternate encodings. Missing links for types " - + typesWithoutLink ); - - // 3. a link to the feature collection that contains this feature (relation: collection). - Map linkToCollection = findLinkByRel( links, "collection" ); - assertNotNull( linkToCollection, "Feature Response must include a link for the feature collection" ); - assertTrue( linkIncludesRelAndType( linkToCollection ), - "Link to feature collection must include a rel and type parameter" ); - - // Verify that all "self"/"alternate"/"collection" links include the rel and type link parameters. - Set rels = new HashSet(); - rels.add( "self" ); - rels.add( "alternate" ); - rels.add( "collection" ); - List linksWithoutRelOrType = findLinksWithoutRelOrType( links, rels ); - assertTrue( linksWithoutRelOrType.isEmpty(), - "Links with link relation types 'self', 'alternate' and 'collection' in Get Feature Operation Response must include a rel and type parameter. Missing for links " - + linksWithoutRelOrType ); - } - -} \ No newline at end of file + /** Constant DUMMY_COLLECTION_ID="dUmmYColLection" */ + public static final String DUMMY_COLLECTION_ID = "dUmmYColLection"; + + private List> collections; + + private final Map collectionNameAndResponse = new HashMap<>(); + + /** + *

    + * collectionFeatureId. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionFeatureId") + public Iterator collectionFeatureId(ITestContext testContext) { + Map collectionNameToFeatureId = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.FEATUREIDS.getName()); + List collectionsData = new ArrayList<>(); + for (Map collection : collections) { + String collectionId = (String) collection.get("id"); + String featureId = null; + if (collectionNameToFeatureId != null) { + featureId = collectionNameToFeatureId.get(collectionId); + } + if (featureId != null) { + collectionsData.add(new Object[] { collection, featureId }); + } + } + + // https://github.com/opengeospatial/ets-ogcapi-features10/issues/215 + // Add dummy collection ID if no feature IDs were found. + // Throw assertionError in feature tests, if dummy ID is found. + if (collectionsData.isEmpty()) { + Map dummyCollection = new HashMap(); + dummyCollection.put("id", DUMMY_COLLECTION_ID); + collectionsData.add(new Object[] { dummyCollection, null }); + } + + return collectionsData.iterator(); + } + + /** + *

    + * retrieveRequiredInformationFromTestContext. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @BeforeClass + public void retrieveRequiredInformationFromTestContext(ITestContext testContext) { + this.collections = (List>) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTIONS.getName()); + } + + /** + *
    +	 * Abstract Test 27: /ats/core/f-op
    +	 * Test Purpose: Validate that a feature can be retrieved from the expected location.
    +	 * Requirement: /req/core/f-op
    +	 *
    +	 * Test Method
    +	 *  1. For a sufficiently large subset of all features in a feature collection (path /collections/{collectionId}), issue an HTTP GET request to the URL /collections/{collectionId}/items/{featureId} where {collectionId} is the id property for the collection and {featureId} is the id property of the feature.
    +	 *  2. Validate that a feature was returned with a status code 200
    +	 *  3. Validate the contents of the returned feature using test /ats/core/f-success.
    +	 * 
    + * @param collection the collection under test, never null + * @param featureId the featureId to request, may be null (test will be + * skipped) + */ + @Test(description = "Implements A.2.8. Feature, Abstract Test 27 (Requirement /req/core/f-op)", + dataProvider = "collectionFeatureId", dependsOnGroups = "featuresBase", alwaysRun = true) + public void featureOperation(Map collection, String featureId) { + String collectionId = (String) collection.get("id"); + // https://github.com/opengeospatial/ets-ogcapi-features10/issues/215 + if (collectionId == DUMMY_COLLECTION_ID) { + throw new AssertionError("No feature Ids found in tested collections."); + } + if (featureId == null) + throw new SkipException("No featureId available for collection '" + collectionId + "'"); + + String getFeatureUrlWithFeatureId = JsonUtils.findFeatureUrlForGeoJson(rootUri, collection, featureId); + if (getFeatureUrlWithFeatureId == null) + throw new SkipException("Could not find url for collection with name " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); + + Response response = init().baseUri(getFeatureUrlWithFeatureId).accept(GEOJSON_MIME_TYPE).when().request(GET); + response.then().statusCode(200); + + collectionNameAndResponse.put(collectionId, response); + } + + /** + *
    +	 * Abstract Test 28: /ats/core/f-success
    +	 * Test Purpose: Validate that the Feature complies with the required structure and contents.
    +	 * Requirement: /req/core/f-success
    +	 *
    +	 * Test Method
    +	 *  1. Validate that the Feature includes all required link properties using /ats/core/f-links
    +	 *  2. Validate the Feature for all supported media types using the resources and tests identified in Schema and Tests for Features
    +	 * 
    + * + *
    +	 * Abstract Test 29: /ats/core/f-links
    +	 * Test Purpose: Validate that the required links are included in a Feature.
    +	 * Requirement: /req/core/f-links
    +	 *
    +	 * Test Method:
    +	 * Verify that the returned Feature includes:
    +	 *  1. a link to this response document (relation: self),
    +	 *  2. a link to the response document in every other media type supported by the server (relation: alternate).
    +	 *  3. a link to the feature collection that contains this feature (relation: collection).
    +	 * Verify that all links include the rel and type link parameters.
    +	 * 
    + * @param collection the collection under test, never null + * @param featureId the featureId to request, may be null (test will be + * skipped) + */ + @Test(description = "Implements A.2.8. Feature, Abstract Test 28 + 29 (Requirements /req/core/f-success, /req/core/f-links)", + dataProvider = "collectionFeatureId", dependsOnMethods = "featureOperation", alwaysRun = true) + public void validateFeatureResponse(Map collection, String featureId) { + String collectionId = (String) collection.get("id"); + // https://github.com/opengeospatial/ets-ogcapi-features10/issues/215 + if (collectionId == DUMMY_COLLECTION_ID) { + throw new AssertionError("No feature Ids found in tested collections."); + } + Response response = collectionNameAndResponse.get(collectionId); + if (response == null) + throw new SkipException("Could not find a response for collection with id " + collectionId); + + JsonPath jsonPath = response.jsonPath(); + List> links = parseAsListOfMaps("links", jsonPath); + + // 1. a link to this response document (relation: self), + Map linkToSelf = findLinkByRel(links, "self"); + assertNotNull(linkToSelf, "Feature Response must include a link for itself"); + // Verify that all links include the rel and type link parameters. + assertTrue(linkIncludesRelAndType(linkToSelf), "Link to itself must include a rel and type parameter"); + + // 2. a link to the response document in every other media type supported by the + // server (relation: alternate). + // Dev: Supported media type are identified by the compliance classes for this + // server + List mediaTypesToSupport = createListOfMediaTypesToSupportForFeatureCollectionsAndFeatures(linkToSelf); + List> alternateLinks = findLinksWithSupportedMediaTypeByRel(links, mediaTypesToSupport, + "alternate"); + List typesWithoutLink = findUnsupportedTypes(alternateLinks, mediaTypesToSupport); + assertTrue(typesWithoutLink.isEmpty(), + "Feature Response must include links for alternate encodings. Missing links for types " + + typesWithoutLink); + + // 3. a link to the feature collection that contains this feature (relation: + // collection). + Map linkToCollection = findLinkByRel(links, "collection"); + assertNotNull(linkToCollection, "Feature Response must include a link for the feature collection"); + assertTrue(linkIncludesRelAndType(linkToCollection), + "Link to feature collection must include a rel and type parameter"); + + // Verify that all "self"/"alternate"/"collection" links include the rel and type + // link parameters. + Set rels = new HashSet(); + rels.add("self"); + rels.add("alternate"); + rels.add("collection"); + List linksWithoutRelOrType = findLinksWithoutRelOrType(links, rels); + assertTrue(linksWithoutRelOrType.isEmpty(), + "Links with link relation types 'self', 'alternate' and 'collection' in Get Feature Operation Response must include a rel and type parameter. Missing for links " + + linksWithoutRelOrType); + } + +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollection.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollection.java index 937edaa9..362bb984 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollection.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollection.java @@ -35,104 +35,117 @@ */ public class FeatureCollection extends CommonDataFixture { - private Map collectionIdAndResponse = new HashMap<>(); - - @DataProvider(name = "collections") - public Object[][] collections( ITestContext testContext ) { - List> testPointAndCollections = (List>) testContext.getSuite().getAttribute( COLLECTIONS.getName() ); - int length = testPointAndCollections.size(); - Object[][] objects = new Object[length][]; - int i = 0; - for ( Map collection : testPointAndCollections ) - objects[i++] = new Object[] { collection }; - return objects; - } - - @AfterClass - public void storeCollectionInTestContext( ITestContext testContext ) { - Map collectionsResponses = new HashMap<>(); - for ( Map.Entry collectionIdAndResponseEntry : collectionIdAndResponse.entrySet() ) { - if ( collectionIdAndResponseEntry.getValue() != null ) { - JsonPath jsonPath = collectionIdAndResponseEntry.getValue().jsonPath(); - collectionsResponses.put( collectionIdAndResponseEntry.getKey(), jsonPath ); - } - } - testContext.getSuite().setAttribute( SuiteAttribute.COLLECTION_BY_ID.getName(), collectionsResponses ); - } - - /** - *
    -     * Abstract Test 11: /ats/core/sfc-md-op
    -     * Test Purpose: Validate that the Collection content can be retrieved from the expected location.
    -     * Requirement: /req/core/sfc-md-op
    -     *
    -     * Test Method: For every Feature Collection described in the Collections content, issue an HTTP GET request to the URL /collections/{collectionId} where {collectionId} is the id property for the collection. Validate that a Collection was returned with a status code 200. Validate the contents of the returned document using test /ats/core/sfc-md-success.
    -     * 
    - * - * @param testContext - * never null - * @param collection - * the collection to test, never null - */ - @Test(description = "Implements A.2.6. Feature Collection {root}/collections/{collectionId}, Abstract Test 11 (Requirement /req/core/sfc-md-op)", groups = "collection", dataProvider = "collections", dependsOnGroups = { "collections" }) - public void validateFeatureCollectionMetadataOperation( ITestContext testContext, Map collection ) { - String collectionId = (String) collection.get( "id" ); - assertNotNull( collectionId, "Id of the collection is not available" ); - URI iut = (URI) testContext.getSuite().getAttribute( IUT.getName() ); - List testPointsForNamedCollection = retrieveTestPointsForCollectionMetadata( getApiModel(), iut, - collectionId ); - if ( testPointsForNamedCollection.isEmpty() ) - throw new SkipException( "Could not find collection with id " + collectionId + " in the OpenAPI document" ); - - TestPoint testPoint = testPointsForNamedCollection.get( 0 ); - String testPointUri = new UriBuilder( testPoint ).collectionName( collectionId ).buildUrl(); - Response response = init().baseUri( testPointUri ).accept( JSON ).when().request( GET ); - response.then().statusCode( 200 ); - - collectionIdAndResponse.put( collectionId, response ); - } - - /** - *
    -     * Abstract Test 12: /ats/core/sfc-md-success
    -     * Test Purpose: Validate that the Collection content complies with the required structure and contents.
    -     * Requirement: /req/core/sfc-md-success
    -     *
    -     * Test Method: Verify that the content of the response is consistent with the content for this Feature Collection in the /collections response. That is, the values for id, title, description and extent are identical.
    -     * 
    - * - * @param collection - * the collection to test, never null - */ - @Test(description = "Implements A.2.6. Feature Collection {root}/collections/{collectionId}, Abstract Test 12 (Requirement /req/core/sfc-md-success)", groups = "collection", dataProvider = "collections", dependsOnMethods = "validateFeatureCollectionMetadataOperation", alwaysRun = true) - public void validateFeatureCollectionMetadataResponse( Map collection ) { - String collectionId = (String) collection.get( "id" ); - assertNotNull( collectionId, "Id of the collection is not available" ); - Response response = collectionIdAndResponse.get( collectionId ); - if ( response == null ) - throw new SkipException( "Could not find a response for collection with id " + collectionId ); - - JsonPath jsonPath = response.jsonPath(JsonPathConfig.jsonPathConfig().numberReturnType(NumberReturnType.DOUBLE)); - - assertEqualStringContent( collection, jsonPath, "id" ); - assertEqualStringContent( collection, jsonPath, "title" ); - assertEqualStringContent( collection, jsonPath, "description" ); - assertExtent( collection, jsonPath ); - - } - - private void assertEqualStringContent( Map collection, JsonPath jsonPath, String property ) { - String idFromCollections = (String) collection.get( property ); - String idFromCollection = jsonPath.get( property ); - assertEquals( idFromCollection, idFromCollections, - property + " from collection is not equal to the collections " + property ); - } - - private void assertExtent( Map collection, JsonPath jsonPath ) { - Map idFromCollections = (Map) collection.get( "extent" ); - Map idFromCollection = jsonPath.getMap( "extent" ); - assertEquals( idFromCollection, idFromCollections, - " extent from collection is not equal to the collections extent" ); - } - -} \ No newline at end of file + private Map collectionIdAndResponse = new HashMap<>(); + + /** + *

    + * collections. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return an array of {@link java.lang.Object} objects + */ + @DataProvider(name = "collections") + public Object[][] collections(ITestContext testContext) { + List> testPointAndCollections = (List>) testContext.getSuite() + .getAttribute(COLLECTIONS.getName()); + int length = testPointAndCollections.size(); + Object[][] objects = new Object[length][]; + int i = 0; + for (Map collection : testPointAndCollections) + objects[i++] = new Object[] { collection }; + return objects; + } + + /** + *

    + * storeCollectionInTestContext. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @AfterClass + public void storeCollectionInTestContext(ITestContext testContext) { + Map collectionsResponses = new HashMap<>(); + for (Map.Entry collectionIdAndResponseEntry : collectionIdAndResponse.entrySet()) { + if (collectionIdAndResponseEntry.getValue() != null) { + JsonPath jsonPath = collectionIdAndResponseEntry.getValue().jsonPath(); + collectionsResponses.put(collectionIdAndResponseEntry.getKey(), jsonPath); + } + } + testContext.getSuite().setAttribute(SuiteAttribute.COLLECTION_BY_ID.getName(), collectionsResponses); + } + + /** + *
    +	 * Abstract Test 11: /ats/core/sfc-md-op
    +	 * Test Purpose: Validate that the Collection content can be retrieved from the expected location.
    +	 * Requirement: /req/core/sfc-md-op
    +	 *
    +	 * Test Method: For every Feature Collection described in the Collections content, issue an HTTP GET request to the URL /collections/{collectionId} where {collectionId} is the id property for the collection. Validate that a Collection was returned with a status code 200. Validate the contents of the returned document using test /ats/core/sfc-md-success.
    +	 * 
    + * @param testContext never null + * @param collection the collection to test, never null + */ + @Test(description = "Implements A.2.6. Feature Collection {root}/collections/{collectionId}, Abstract Test 11 (Requirement /req/core/sfc-md-op)", + groups = "collection", dataProvider = "collections", dependsOnGroups = { "collections" }) + public void validateFeatureCollectionMetadataOperation(ITestContext testContext, Map collection) { + String collectionId = (String) collection.get("id"); + assertNotNull(collectionId, "Id of the collection is not available"); + URI iut = (URI) testContext.getSuite().getAttribute(IUT.getName()); + List testPointsForNamedCollection = retrieveTestPointsForCollectionMetadata(getApiModel(), iut, + collectionId); + if (testPointsForNamedCollection.isEmpty()) + throw new SkipException("Could not find collection with id " + collectionId + " in the OpenAPI document"); + + TestPoint testPoint = testPointsForNamedCollection.get(0); + String testPointUri = new UriBuilder(testPoint).collectionName(collectionId).buildUrl(); + Response response = init().baseUri(testPointUri).accept(JSON).when().request(GET); + response.then().statusCode(200); + + collectionIdAndResponse.put(collectionId, response); + } + + /** + *
    +	 * Abstract Test 12: /ats/core/sfc-md-success
    +	 * Test Purpose: Validate that the Collection content complies with the required structure and contents.
    +	 * Requirement: /req/core/sfc-md-success
    +	 *
    +	 * Test Method: Verify that the content of the response is consistent with the content for this Feature Collection in the /collections response. That is, the values for id, title, description and extent are identical.
    +	 * 
    + * @param collection the collection to test, never null + */ + @Test(description = "Implements A.2.6. Feature Collection {root}/collections/{collectionId}, Abstract Test 12 (Requirement /req/core/sfc-md-success)", + groups = "collection", dataProvider = "collections", + dependsOnMethods = "validateFeatureCollectionMetadataOperation", alwaysRun = true) + public void validateFeatureCollectionMetadataResponse(Map collection) { + String collectionId = (String) collection.get("id"); + assertNotNull(collectionId, "Id of the collection is not available"); + Response response = collectionIdAndResponse.get(collectionId); + if (response == null) + throw new SkipException("Could not find a response for collection with id " + collectionId); + + JsonPath jsonPath = response + .jsonPath(JsonPathConfig.jsonPathConfig().numberReturnType(NumberReturnType.DOUBLE)); + + assertEqualStringContent(collection, jsonPath, "id"); + assertEqualStringContent(collection, jsonPath, "title"); + assertEqualStringContent(collection, jsonPath, "description"); + assertExtent(collection, jsonPath); + + } + + private void assertEqualStringContent(Map collection, JsonPath jsonPath, String property) { + String idFromCollections = (String) collection.get(property); + String idFromCollection = jsonPath.get(property); + assertEquals(idFromCollection, idFromCollections, + property + " from collection is not equal to the collections " + property); + } + + private void assertExtent(Map collection, JsonPath jsonPath) { + Map idFromCollections = (Map) collection.get("extent"); + Map idFromCollection = jsonPath.getMap("extent"); + assertEquals(idFromCollection, idFromCollections, + " extent from collection is not equal to the collections extent"); + } + +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollections.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollections.java index 1d4b2e09..37cdfc4f 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollections.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollections.java @@ -49,235 +49,257 @@ */ public class FeatureCollections extends CommonDataFixture { - private final Map testPointAndResponses = new HashMap<>(); + private final Map testPointAndResponses = new HashMap<>(); - private final Map>> testPointAndCollections = new HashMap<>(); + private final Map>> testPointAndCollections = new HashMap<>(); - private Object[][] testPointsData; + private Object[][] testPointsData; - @DataProvider(name = "collectionsUris") - public Object[][] collectionsUris( ITestContext testContext ) { - if ( this.testPointsData == null ) { - URI iut = (URI) testContext.getSuite().getAttribute( IUT.getName() ); - List testPoints = retrieveTestPointsForCollectionsMetadata( getApiModel(), iut ); - this.testPointsData = new Object[testPoints.size()][]; - int i = 0; - for ( TestPoint testPoint : testPoints ) { - this.testPointsData[i++] = new Object[] { testPoint }; - } - } - return testPointsData; - } + /** + *

    + * collectionsUris. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return an array of {@link java.lang.Object} objects + */ + @DataProvider(name = "collectionsUris") + public Object[][] collectionsUris(ITestContext testContext) { + if (this.testPointsData == null) { + URI iut = (URI) testContext.getSuite().getAttribute(IUT.getName()); + List testPoints = retrieveTestPointsForCollectionsMetadata(getApiModel(), iut); + this.testPointsData = new Object[testPoints.size()][]; + int i = 0; + for (TestPoint testPoint : testPoints) { + this.testPointsData[i++] = new Object[] { testPoint }; + } + } + return testPointsData; + } - @AfterClass - public void storeCollectionsInTestContext( ITestContext testContext ) { - List> collections = new ArrayList<>(); - for ( List> testPointAndCollection : testPointAndCollections.values() ) { - collections.addAll( testPointAndCollection ); - } - testContext.getSuite().setAttribute( SuiteAttribute.COLLECTIONS.getName(), collections ); - } + /** + *

    + * storeCollectionsInTestContext. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @AfterClass + public void storeCollectionsInTestContext(ITestContext testContext) { + List> collections = new ArrayList<>(); + for (List> testPointAndCollection : testPointAndCollections.values()) { + collections.addAll(testPointAndCollection); + } + testContext.getSuite().setAttribute(SuiteAttribute.COLLECTIONS.getName(), collections); + } - @AfterClass - public void storeCollectionsResponseInTestContext( ITestContext testContext ) { - Map collectionsResponses = new HashMap<>(); - for ( Map.Entry testPointAndResponse : testPointAndResponses.entrySet() ) { - if ( testPointAndResponse.getValue() != null ) { - JsonPath jsonPath = testPointAndResponse.getValue().jsonPath(); - collectionsResponses.put( testPointAndResponse.getKey(), jsonPath ); - } - } - testContext.getSuite().setAttribute( SuiteAttribute.COLLECTIONS_RESPONSE.getName(), collectionsResponses ); - } - - /** - *
    -     * Abstract Test 9: /ats/core/fc-md-op
    -     * Test Purpose:  Validate that information about the Collections can be retrieved from the expected location.
    -     * Requirement: /req/core/fc-md-op
    -     *
    -     * Test Method
    -     *  1. Issue an HTTP GET request to the URL {root}/collections
    -     *  2. Validate that a document was returned with a status code 200
    -     *  3. Validate the contents of the returned document using test /ats/core/fc-md-success.
    -     * 
    - * - * @param testPoint - * the test point to test, never null - */ - @Test(description = "Implements A.2.5. Feature Collections {root}/collections, Abstract Test 9 (Requirement /req/core/fc-md-op)", groups = "collections", dataProvider = "collectionsUris", dependsOnGroups = { "apidefinition", - "conformance" }) - public void validateFeatureCollectionsMetadataOperation( TestPoint testPoint ) { - String testPointUri = new UriBuilder( testPoint ).buildUrl(); - Response response = init().baseUri( testPointUri ).accept( JSON ).when().request( GET ); - response.then().statusCode( 200 ); - this.testPointAndResponses.put( testPoint, response ); - } + /** + *

    + * storeCollectionsResponseInTestContext. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @AfterClass + public void storeCollectionsResponseInTestContext(ITestContext testContext) { + Map collectionsResponses = new HashMap<>(); + for (Map.Entry testPointAndResponse : testPointAndResponses.entrySet()) { + if (testPointAndResponse.getValue() != null) { + JsonPath jsonPath = testPointAndResponse.getValue().jsonPath(); + collectionsResponses.put(testPointAndResponse.getKey(), jsonPath); + } + } + testContext.getSuite().setAttribute(SuiteAttribute.COLLECTIONS_RESPONSE.getName(), collectionsResponses); + } - /** - * Abstract Test 10, Test Method 1 - * - *
    -     * Abstract Test 10: /ats/core/fc-md-success
    -     * Test Purpose: Validate that the Collections content complies with the required structure and contents.
    -     * Requirement: /req/core/fc-md-success, /req/core/crs84
    -     *
    -     * Test Method
    -     *  1. Validate that all response documents comply with /ats/core/fc-md-links
    -     * 
    - * - * @param testPoint - * the test point to test, never null - */ - @Test(description = "A.2.5. Feature Collections {root}/collections, Abstract Test 10, Test Method 1 (Requirement /req/core/fc-md-success, /req/core/crs84)", groups = "collections", dataProvider = "collectionsUris", dependsOnMethods = "validateFeatureCollectionsMetadataOperation", alwaysRun = true) - public void validateFeatureCollectionsMetadataOperationResponse_Links( TestPoint testPoint ) { - Response response = testPointAndResponses.get( testPoint ); - if ( response == null ) - throw new SkipException( "Could not find a response for test point " + testPoint ); + /** + *
    +	 * Abstract Test 9: /ats/core/fc-md-op
    +	 * Test Purpose:  Validate that information about the Collections can be retrieved from the expected location.
    +	 * Requirement: /req/core/fc-md-op
    +	 *
    +	 * Test Method
    +	 *  1. Issue an HTTP GET request to the URL {root}/collections
    +	 *  2. Validate that a document was returned with a status code 200
    +	 *  3. Validate the contents of the returned document using test /ats/core/fc-md-success.
    +	 * 
    + * @param testPoint the test point to test, never null + */ + @Test(description = "Implements A.2.5. Feature Collections {root}/collections, Abstract Test 9 (Requirement /req/core/fc-md-op)", + groups = "collections", dataProvider = "collectionsUris", + dependsOnGroups = { "apidefinition", "conformance" }) + public void validateFeatureCollectionsMetadataOperation(TestPoint testPoint) { + String testPointUri = new UriBuilder(testPoint).buildUrl(); + Response response = init().baseUri(testPointUri).accept(JSON).when().request(GET); + response.then().statusCode(200); + this.testPointAndResponses.put(testPoint, response); + } - JsonPath jsonPath = response.jsonPath(); - List> links = parseAsListOfMaps( "links", jsonPath ); + /** + * Abstract Test 10, Test Method 1 + * + *
    +	 * Abstract Test 10: /ats/core/fc-md-success
    +	 * Test Purpose: Validate that the Collections content complies with the required structure and contents.
    +	 * Requirement: /req/core/fc-md-success, /req/core/crs84
    +	 *
    +	 * Test Method
    +	 *  1. Validate that all response documents comply with /ats/core/fc-md-links
    +	 * 
    + * @param testPoint the test point to test, never null + */ + @Test(description = "A.2.5. Feature Collections {root}/collections, Abstract Test 10, Test Method 1 (Requirement /req/core/fc-md-success, /req/core/crs84)", + groups = "collections", dataProvider = "collectionsUris", + dependsOnMethods = "validateFeatureCollectionsMetadataOperation", alwaysRun = true) + public void validateFeatureCollectionsMetadataOperationResponse_Links(TestPoint testPoint) { + Response response = testPointAndResponses.get(testPoint); + if (response == null) + throw new SkipException("Could not find a response for test point " + testPoint); - // Requirement 13 A (1): a link to this response document (relation: self) - Map linkToSelf = findLinkByRel( links, "self" ); - assertNotNull( linkToSelf, "Feature Collections Metadata document must include a link for itself" ); - // Requirement 13B: All links SHALL include the rel and type link parameters. - assertTrue( linkIncludesRelAndType( linkToSelf ), "Link to itself must include a rel and type parameter" ); + JsonPath jsonPath = response.jsonPath(); + List> links = parseAsListOfMaps("links", jsonPath); - // Requirement 13 A (2): a link to the response document in every other media type supported by the server - // (relation: alternate) - // Dev: Supported media type are identified by the compliance classes for this server - List mediaTypesToSupport = createListOfMediaTypesToSupportForOtherResources( linkToSelf ); - List> alternateLinks = findLinksWithSupportedMediaTypeByRel( links, mediaTypesToSupport, - "alternate" ); - List typesWithoutLink = findUnsupportedTypes( alternateLinks, mediaTypesToSupport ); - assertTrue( typesWithoutLink.isEmpty(), - "Feature Collections Metadata document must include links for alternate encodings. Missing links for types " - + typesWithoutLink ); + // Requirement 13 A (1): a link to this response document (relation: self) + Map linkToSelf = findLinkByRel(links, "self"); + assertNotNull(linkToSelf, "Feature Collections Metadata document must include a link for itself"); + // Requirement 13B: All links SHALL include the rel and type link parameters. + assertTrue(linkIncludesRelAndType(linkToSelf), "Link to itself must include a rel and type parameter"); - // Requirement 13 B: All "self"/"alternate" links SHALL include the rel and type link parameters. - Set rels = new HashSet<>(); - rels.add("self"); - rels.add("alternate"); - List linksWithoutRelOrType = findLinksWithoutRelOrType( alternateLinks, rels ); - assertTrue( linksWithoutRelOrType.isEmpty(), - "Links for alternate encodings must include a rel and type parameter. Missing for links " - + linksWithoutRelOrType ); - } + // Requirement 13 A (2): a link to the response document in every other media type + // supported by the server + // (relation: alternate) + // Dev: Supported media type are identified by the compliance classes for this + // server + List mediaTypesToSupport = createListOfMediaTypesToSupportForOtherResources(linkToSelf); + List> alternateLinks = findLinksWithSupportedMediaTypeByRel(links, mediaTypesToSupport, + "alternate"); + List typesWithoutLink = findUnsupportedTypes(alternateLinks, mediaTypesToSupport); + assertTrue(typesWithoutLink.isEmpty(), + "Feature Collections Metadata document must include links for alternate encodings. Missing links for types " + + typesWithoutLink); - /** - * Abstract Test 10, Test Method 2 - * - *
    -     * Abstract Test 10: /ats/core/fc-md-success
    -     * Test Purpose: Validate that the Collections content complies with the required structure and contents.
    -     * Requirement: /req/core/fc-md-success, /req/core/crs84
    -     *
    -     * Test Method
    -     *  2. Validate that all response documents comply with /ats/core/fc-md-items
    -     * 
    - * - * @param testPoint - * the test point to test, never null - */ - @Test(description = "A.2.5. Feature Collections {root}/collections, Abstract Test 10, Test Method 2 (Requirement /req/core/fc-md-success, /req/core/crs84)", groups = "collections", dataProvider = "collectionsUris", dependsOnMethods = "validateFeatureCollectionsMetadataOperation", alwaysRun = true) - public void validateFeatureCollectionsMetadataOperationResponse_Items( TestPoint testPoint ) { - Response response = testPointAndResponses.get( testPoint ); - if ( response == null ) - throw new SkipException( "Could not find a response for test point " + testPoint ); - JsonPathConfig config = JsonPathConfig.jsonPathConfig().numberReturnType(NumberReturnType.DOUBLE); - JsonPath jsonPath = response.jsonPath(config); - List collections = jsonPath.getList( "collections" ); + // Requirement 13 B: All "self"/"alternate" links SHALL include the rel and type + // link parameters. + Set rels = new HashSet<>(); + rels.add("self"); + rels.add("alternate"); + List linksWithoutRelOrType = findLinksWithoutRelOrType(alternateLinks, rels); + assertTrue(linksWithoutRelOrType.isEmpty(), + "Links for alternate encodings must include a rel and type parameter. Missing for links " + + linksWithoutRelOrType); + } - // Test method cannot be verified as the provided collections are not known. + /** + * Abstract Test 10, Test Method 2 + * + *
    +	 * Abstract Test 10: /ats/core/fc-md-success
    +	 * Test Purpose: Validate that the Collections content complies with the required structure and contents.
    +	 * Requirement: /req/core/fc-md-success, /req/core/crs84
    +	 *
    +	 * Test Method
    +	 *  2. Validate that all response documents comply with /ats/core/fc-md-items
    +	 * 
    + * @param testPoint the test point to test, never null + */ + @Test(description = "A.2.5. Feature Collections {root}/collections, Abstract Test 10, Test Method 2 (Requirement /req/core/fc-md-success, /req/core/crs84)", + groups = "collections", dataProvider = "collectionsUris", + dependsOnMethods = "validateFeatureCollectionsMetadataOperation", alwaysRun = true) + public void validateFeatureCollectionsMetadataOperationResponse_Items(TestPoint testPoint) { + Response response = testPointAndResponses.get(testPoint); + if (response == null) + throw new SkipException("Could not find a response for test point " + testPoint); + JsonPathConfig config = JsonPathConfig.jsonPathConfig().numberReturnType(NumberReturnType.DOUBLE); + JsonPath jsonPath = response.jsonPath(config); + List collections = jsonPath.getList("collections"); - this.testPointAndCollections.put( testPoint, createCollectionsMap( collections ) ); - } + // Test method cannot be verified as the provided collections are not known. - /** - * Abstract Test 10, Test Method 3 - * - *
    -     * Abstract Test 10: /ats/core/fc-md-success
    -     * Test Purpose: Validate that the Collections content complies with the required structure and contents.
    -     * Requirement: /req/core/fc-md-success, /req/core/crs84
    -     *
    -     * Test Method
    -     *  3. In case the response includes a "crs" property, validate that the first value is either "http://www.opengis.net/def/crs/OGC/1.3/CRS84" or "http://www.opengis.net/def/crs/OGC/0/CRS84h"
    -     * 
    - * - * @param testPoint - * the test point to test, never null - */ - @Test(description = "A.2.5. Feature Collections {root}/collections, Abstract Test 10, Test Method 3 (Requirement /req/core/fc-md-success, /req/core/crs84)", groups = "collections", dataProvider = "collectionsUris", dependsOnMethods = "validateFeatureCollectionsMetadataOperation", alwaysRun = true) - public void validateFeatureCollectionsMetadataOperationResponse_CrsProperty( TestPoint testPoint ) { - Response response = testPointAndResponses.get( testPoint ); - if ( response == null ) - throw new SkipException( "Could not find a response for test point " + testPoint ); - JsonPath jsonPath = response.jsonPath(); - if ( jsonPath.get( "crs" ) != null ) { - List crs = JsonUtils.parseAsList( "crs", jsonPath ); - assertDefaultCrsAtFirst( crs, - String.format( "Feature Collections Metadata document does not specify one of the default CRS '%s' or '%s' as first value.", - DEFAULT_CRS_CODE, DEFAULT_CRS_WITH_HEIGHT_CODE ) ); - } - } + this.testPointAndCollections.put(testPoint, createCollectionsMap(collections)); + } - /** - * Abstract Test 10, Test Method 4 - * - *
    -     * Abstract Test 10: /ats/core/fc-md-success
    -     * Test Purpose: Validate that the Collections content complies with the required structure and contents.
    -     * Requirement: /req/core/fc-md-success, /req/core/crs84
    -     *
    -     * Test Method
    -     *  4. Validate the collections content for all supported media types using the resources and tests identified in Schema and Tests for Collections content
    -     * 
    - * - * @param testPoint - * the test point to test, never null - */ - @Test(description = "A.2.5. Feature Collections {root}/collections, Abstract Test 10, Test Method 4 (Requirement /req/core/fc-md-success, /req/core/crs84)", groups = "collections", dataProvider = "collectionsUris", dependsOnMethods = "validateFeatureCollectionsMetadataOperation", alwaysRun = true) - public void validateFeatureCollectionsMetadataOperationResponse_Content( TestPoint testPoint ) { - Response response = testPointAndResponses.get( testPoint ); - if ( response == null ) - throw new SkipException( "Could not find a response for test point " + testPoint ); + /** + * Abstract Test 10, Test Method 3 + * + *
    +	 * Abstract Test 10: /ats/core/fc-md-success
    +	 * Test Purpose: Validate that the Collections content complies with the required structure and contents.
    +	 * Requirement: /req/core/fc-md-success, /req/core/crs84
    +	 *
    +	 * Test Method
    +	 *  3. In case the response includes a "crs" property, validate that the first value is either "http://www.opengis.net/def/crs/OGC/1.3/CRS84" or "http://www.opengis.net/def/crs/OGC/0/CRS84h"
    +	 * 
    + * @param testPoint the test point to test, never null + */ + @Test(description = "A.2.5. Feature Collections {root}/collections, Abstract Test 10, Test Method 3 (Requirement /req/core/fc-md-success, /req/core/crs84)", + groups = "collections", dataProvider = "collectionsUris", + dependsOnMethods = "validateFeatureCollectionsMetadataOperation", alwaysRun = true) + public void validateFeatureCollectionsMetadataOperationResponse_CrsProperty(TestPoint testPoint) { + Response response = testPointAndResponses.get(testPoint); + if (response == null) + throw new SkipException("Could not find a response for test point " + testPoint); + JsonPath jsonPath = response.jsonPath(); + if (jsonPath.get("crs") != null) { + List crs = JsonUtils.parseAsList("crs", jsonPath); + assertDefaultCrsAtFirst(crs, String.format( + "Feature Collections Metadata document does not specify one of the default CRS '%s' or '%s' as first value.", + DEFAULT_CRS_CODE, DEFAULT_CRS_WITH_HEIGHT_CODE)); + } + } - JsonPath jsonPath = response.jsonPath(); - List> links = parseAsListOfMaps( "links", jsonPath ); - boolean linksAreAvailable = links != null && !links.isEmpty(); - assertTrue( linksAreAvailable, "Feature Collections Metadata document does not contain links." ); + /** + * Abstract Test 10, Test Method 4 + * + *
    +	 * Abstract Test 10: /ats/core/fc-md-success
    +	 * Test Purpose: Validate that the Collections content complies with the required structure and contents.
    +	 * Requirement: /req/core/fc-md-success, /req/core/crs84
    +	 *
    +	 * Test Method
    +	 *  4. Validate the collections content for all supported media types using the resources and tests identified in Schema and Tests for Collections content
    +	 * 
    + * @param testPoint the test point to test, never null + */ + @Test(description = "A.2.5. Feature Collections {root}/collections, Abstract Test 10, Test Method 4 (Requirement /req/core/fc-md-success, /req/core/crs84)", + groups = "collections", dataProvider = "collectionsUris", + dependsOnMethods = "validateFeatureCollectionsMetadataOperation", alwaysRun = true) + public void validateFeatureCollectionsMetadataOperationResponse_Content(TestPoint testPoint) { + Response response = testPointAndResponses.get(testPoint); + if (response == null) + throw new SkipException("Could not find a response for test point " + testPoint); - List> collections = parseAsListOfMaps( "collections", jsonPath ); - boolean collectionsAreAvailable = collections != null && !collections.isEmpty(); - assertTrue( collectionsAreAvailable, "Feature Collections Metadata document does not contain collections." ); - } + JsonPath jsonPath = response.jsonPath(); + List> links = parseAsListOfMaps("links", jsonPath); + boolean linksAreAvailable = links != null && !links.isEmpty(); + assertTrue(linksAreAvailable, "Feature Collections Metadata document does not contain links."); - private List> createCollectionsMap( List collections ) { - List> collectionsMap = new ArrayList<>(); - for (Object collectionObj : collections) { - Map collection = (Map) collectionObj; - if (null != collection.get("id")) { - String itemType = (String) collection.get("itemType"); - if (StringUtils.isEmpty(itemType) || itemType.equalsIgnoreCase("feature")) { - List links = (List) collection.get("links"); - for (Object linkObj : links) { - Map link = (Map) linkObj; - if (link.get("rel").equals("items")) { - collectionsMap.add(collection); - break; - } - } - } - if (noOfCollections > 0 && collectionsMap.size() >= noOfCollections) { - return collectionsMap; - } else if (collectionsMap.size() >= OgcApiFeatures10.COLLECTIONS_LIMIT) { - return collectionsMap.subList( 0, OgcApiFeatures10.COLLECTIONS_LIMIT ); - } - } - } - return collectionsMap; - } + List> collections = parseAsListOfMaps("collections", jsonPath); + boolean collectionsAreAvailable = collections != null && !collections.isEmpty(); + assertTrue(collectionsAreAvailable, "Feature Collections Metadata document does not contain collections."); + } -} \ No newline at end of file + private List> createCollectionsMap(List collections) { + List> collectionsMap = new ArrayList<>(); + for (Object collectionObj : collections) { + Map collection = (Map) collectionObj; + if (null != collection.get("id")) { + String itemType = (String) collection.get("itemType"); + if (StringUtils.isEmpty(itemType) || itemType.equalsIgnoreCase("feature")) { + List links = (List) collection.get("links"); + for (Object linkObj : links) { + Map link = (Map) linkObj; + if (link.get("rel").equals("items")) { + collectionsMap.add(collection); + break; + } + } + } + if (noOfCollections > 0 && collectionsMap.size() >= noOfCollections) { + return collectionsMap; + } + else if (collectionsMap.size() >= OgcApiFeatures10.COLLECTIONS_LIMIT) { + return collectionsMap.subList(0, OgcApiFeatures10.COLLECTIONS_LIMIT); + } + } + } + return collectionsMap; + } + +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/Features.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/Features.java index 07476b33..e20f6d1d 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/Features.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/Features.java @@ -24,263 +24,258 @@ /** * A.2.7. Features {root}/collections/{collectionId}/items - * + * * @author Lyn Goltz */ public class Features extends AbstractFeatures { - @DataProvider(name = "collectionItemUris") - public Iterator collectionItemUris( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - for ( Map collection : collections ) { - collectionsData.add( new Object[] { collection } ); - } - return collectionsData.iterator(); - } + /** + *

    + * collectionItemUris. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionItemUris") + public Iterator collectionItemUris(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + for (Map collection : collections) { + collectionsData.add(new Object[] { collection }); + } + return collectionsData.iterator(); + } - /** - *
    -     * Abstract Test 13: /ats/core/fc-op
    -     * Test Purpose: Validate that features can be identified and extracted from a Collection using query parameters.
    -     * Requirement: /req/core/fc-op
    -     *
    -     * Test Method
    -     *   1. For every feature collection identified in Collections, issue an HTTP GET request to the URL /collections/{collectionId}/items where {collectionId} is the id property for a Collection described in the Collections content.
    -     *   2. Validate that a document was returned with a status code 200.
    -     *   3. Validate the contents of the returned document using test /ats/core/fc-response.
    -     * 
    - * - * @param testContext - * used to fill the FEATUREIDS, never null - * @param collection - * the collection under test, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 13 (Requirement /req/core/fc-op)", groups = "featuresBase", dataProvider = "collectionItemUris", dependsOnGroups = "collections", alwaysRun = true) - public void validateFeaturesOperation( ITestContext testContext, Map collection ) { - String collectionId = (String) collection.get( "id" ); + /** + *
    +	 * Abstract Test 13: /ats/core/fc-op
    +	 * Test Purpose: Validate that features can be identified and extracted from a Collection using query parameters.
    +	 * Requirement: /req/core/fc-op
    +	 *
    +	 * Test Method
    +	 *   1. For every feature collection identified in Collections, issue an HTTP GET request to the URL /collections/{collectionId}/items where {collectionId} is the id property for a Collection described in the Collections content.
    +	 *   2. Validate that a document was returned with a status code 200.
    +	 *   3. Validate the contents of the returned document using test /ats/core/fc-response.
    +	 * 
    + * @param testContext used to fill the FEATUREIDS, never null + * @param collection the collection under test, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 13 (Requirement /req/core/fc-op)", + groups = "featuresBase", dataProvider = "collectionItemUris", dependsOnGroups = "collections", + alwaysRun = true) + public void validateFeaturesOperation(ITestContext testContext, Map collection) { + String collectionId = (String) collection.get("id"); - String featuresUrl = findFeaturesUrlForGeoJson( rootUri, collection ); - if ( featuresUrl == null ) - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); + String featuresUrl = findFeaturesUrlForGeoJson(rootUri, collection); + if (featuresUrl == null) + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); - ZonedDateTime timeStampBeforeResponse = ZonedDateTime.now(); - Response response = init().baseUri( featuresUrl ).accept( GEOJSON_MIME_TYPE ).when().request( GET ); - response.then().statusCode( 200 ); - ZonedDateTime timeStampAfterResponse = ZonedDateTime.now(); - ResponseData responseData = new ResponseData( response, timeStampBeforeResponse, timeStampAfterResponse ); - collectionIdAndResponse.put( asKey( collectionId ), responseData ); + ZonedDateTime timeStampBeforeResponse = ZonedDateTime.now(); + Response response = init().baseUri(featuresUrl).accept(GEOJSON_MIME_TYPE).when().request(GET); + response.then().statusCode(200); + ZonedDateTime timeStampAfterResponse = ZonedDateTime.now(); + ResponseData responseData = new ResponseData(response, timeStampBeforeResponse, timeStampAfterResponse); + collectionIdAndResponse.put(asKey(collectionId), responseData); - addFeatureIdToTestContext( testContext, collectionId, response ); - } + addFeatureIdToTestContext(testContext, collectionId, response); + } - /** - * Abstract Test 2, Test Method 1 - * - *
    -     * Abstract Test 2: /ats/core/crs84
    -     * Test Purpose: Validate that all spatial geometries provided through the API are in the CRS84 spatial reference system unless otherwise requested by the client.
    -     * Requirement: /req/core/crs84
    -     *
    -     * Test Method
    -     *  1. Do not specify a coordinate reference system in any request. All spatial data should be in the CRS84 reference system.
    -     *  2. Validate retrieved spatial data using the CRS84 reference system.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @throws ParseException - * if the geometry could not be parsed - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 2, Test Method 2 (Requirement /req/core/crs84)", dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) - public void validateFeaturesResponse_GeometryInCRS84( Map collection ) - throws ParseException { - String collectionId = (String) collection.get( "id" ); - validateGeometriesInCrs84( asKey( collectionId ) ); - } + /** + * Abstract Test 2, Test Method 1 + * + *
    +	 * Abstract Test 2: /ats/core/crs84
    +	 * Test Purpose: Validate that all spatial geometries provided through the API are in the CRS84 spatial reference system unless otherwise requested by the client.
    +	 * Requirement: /req/core/crs84
    +	 *
    +	 * Test Method
    +	 *  1. Do not specify a coordinate reference system in any request. All spatial data should be in the CRS84 reference system.
    +	 *  2. Validate retrieved spatial data using the CRS84 reference system.
    +	 * 
    + * @param collection the collection under test, never null + * @throws org.locationtech.jts.io.ParseException if the geometry could not be parsed + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 2, Test Method 2 (Requirement /req/core/crs84)", + dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) + public void validateFeaturesResponse_GeometryInCRS84(Map collection) throws ParseException { + String collectionId = (String) collection.get("id"); + validateGeometriesInCrs84(asKey(collectionId)); + } - /** - * Abstract Test 22, Test Method 1 - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   1. Validate that the type property is present and has a value of FeatureCollection
    -     * 
    - * - * @param collection - * the collection under test, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 22, Test Method 1 (Requirement /req/core/fc-response)", dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) - public void validateFeaturesResponse_TypeProperty( Map collection ) { - String collectionId = (String) collection.get( "id" ); - validateTypeProperty( asKey( collectionId ) ); - } + /** + * Abstract Test 22, Test Method 1 + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   1. Validate that the type property is present and has a value of FeatureCollection
    +	 * 
    + * @param collection the collection under test, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 22, Test Method 1 (Requirement /req/core/fc-response)", + dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) + public void validateFeaturesResponse_TypeProperty(Map collection) { + String collectionId = (String) collection.get("id"); + validateTypeProperty(asKey(collectionId)); + } - /** - * Abstract Test 22, Test Method 2 - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   2. Validate the features property is present and that it is populated with an array of feature items.
    -     * 
    - * - * @param collection - * the collection under test, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 22, Test Method 2 (Requirement /req/core/fc-response)", dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) - public void validateFeaturesResponse_FeaturesProperty( Map collection ) { - String collectionId = (String) collection.get( "id" ); - validateFeaturesProperty( asKey( collectionId ) ); - } + /** + * Abstract Test 22, Test Method 2 + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   2. Validate the features property is present and that it is populated with an array of feature items.
    +	 * 
    + * @param collection the collection under test, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 22, Test Method 2 (Requirement /req/core/fc-response)", + dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) + public void validateFeaturesResponse_FeaturesProperty(Map collection) { + String collectionId = (String) collection.get("id"); + validateFeaturesProperty(asKey(collectionId)); + } - /** - * Abstract Test 22, Test Method 4 (Abstract Test 23) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   4. If the links property is present, validate that all entries comply with /ats/core/fc-links
    -     * 
    - * - *
    -     * Abstract Test 23: /ats/core/fc-links
    -     * Test Purpose: Validate that the required links are included in the Collections document.
    -     * Requirement: /req/core/fc-links, /req/core/fc-rel-type
    -     *
    -     * Test Method:
    -     * Verify that the response document includes:
    -     *   1. a link to this response document (relation: self),
    -     *   2. a link to the response document in every other media type supported by the server (relation: alternate).
    -     *
    -     * Verify that all links include the rel and type link parameters.
    -     * 
    - * - * @param collection - * the collection under test, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 22, Test Method 4 (Requirement /req/core/fc-response) - Abstract Test 23 (Requirement /req/core/fc-links, /req/core/fc-rel-type)", dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) - public void validateFeaturesResponse_Links( Map collection ) { - String collectionId = (String) collection.get( "id" ); - validateLinks( asKey( collectionId ) ); - } + /** + * Abstract Test 22, Test Method 4 (Abstract Test 23) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   4. If the links property is present, validate that all entries comply with /ats/core/fc-links
    +	 * 
    + * + *
    +	 * Abstract Test 23: /ats/core/fc-links
    +	 * Test Purpose: Validate that the required links are included in the Collections document.
    +	 * Requirement: /req/core/fc-links, /req/core/fc-rel-type
    +	 *
    +	 * Test Method:
    +	 * Verify that the response document includes:
    +	 *   1. a link to this response document (relation: self),
    +	 *   2. a link to the response document in every other media type supported by the server (relation: alternate).
    +	 *
    +	 * Verify that all links include the rel and type link parameters.
    +	 * 
    + * @param collection the collection under test, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 22, Test Method 4 (Requirement /req/core/fc-response) - Abstract Test 23 (Requirement /req/core/fc-links, /req/core/fc-rel-type)", + dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) + public void validateFeaturesResponse_Links(Map collection) { + String collectionId = (String) collection.get("id"); + validateLinks(asKey(collectionId)); + } - /** - * Abstract Test 22, Test Method 5 (Abstract Test 24) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   5. If the timeStamp property is present, validate that it complies with /ats/core/fc-timeStamp
    -     * 
    - * - *
    -     * Abstract Test 24: /ats/core/fc-timeStamp
    -     * Test Purpose: Validate the timeStamp parameter returned with a Features response
    -     * Requirement: /req/core/fc-timeStamp
    -     *
    -     * Test Method: Validate that the timeStamp value is set to the time when the response was generated.
    -     * 
    - * - * @param collection - * the collection under test, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 22, Test Method 5 (Requirement /req/core/fc-response) - Abstract Test 24 (Requirement /req/core/fc-timeStamp)", dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) - public void validateFeaturesResponse_TimeStamp( Map collection ) { - String collectionId = (String) collection.get( "id" ); - validateTimeStamp( asKey( collectionId ) ); - } + /** + * Abstract Test 22, Test Method 5 (Abstract Test 24) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   5. If the timeStamp property is present, validate that it complies with /ats/core/fc-timeStamp
    +	 * 
    + * + *
    +	 * Abstract Test 24: /ats/core/fc-timeStamp
    +	 * Test Purpose: Validate the timeStamp parameter returned with a Features response
    +	 * Requirement: /req/core/fc-timeStamp
    +	 *
    +	 * Test Method: Validate that the timeStamp value is set to the time when the response was generated.
    +	 * 
    + * @param collection the collection under test, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 22, Test Method 5 (Requirement /req/core/fc-response) - Abstract Test 24 (Requirement /req/core/fc-timeStamp)", + dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) + public void validateFeaturesResponse_TimeStamp(Map collection) { + String collectionId = (String) collection.get("id"); + validateTimeStamp(asKey(collectionId)); + } - /** - * Abstract Test 22, Test Method 6 (Abstract Test 25) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   6. If the numberMatched property is present, validate that it complies with /ats/core/fc-numberMatched
    -     * 
    - * - *
    -     * Abstract Test 25: /ats/core/fc-numberMatched
    -     * Test Purpose: Validate the numberMatched parameter returned with a Features response
    -     * Requirement: /req/core/fc-numberMatched
    -     *
    -     * Test Method: Validate that the value of the numberMatched parameter is identical to the number of features in the feature collections that match the selection parameters like bbox, datetime or additional filter parameters.
    -     * 
    - * - * @param collection - * the collection under test, never null - * - * @throws URISyntaxException - * if the creation of a uri fails - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 22, Test Method 6 (Requirement /req/core/fc-response) - Abstract Test 25 (Requirement /req/core/fc-numberMatched)", dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) - public void validateFeaturesResponse_NumberMatched( Map collection ) - throws URISyntaxException { - String collectionId = (String) collection.get( "id" ); - validateNumberMatched( asKey( collectionId ) ); - } + /** + * Abstract Test 22, Test Method 6 (Abstract Test 25) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   6. If the numberMatched property is present, validate that it complies with /ats/core/fc-numberMatched
    +	 * 
    + * + *
    +	 * Abstract Test 25: /ats/core/fc-numberMatched
    +	 * Test Purpose: Validate the numberMatched parameter returned with a Features response
    +	 * Requirement: /req/core/fc-numberMatched
    +	 *
    +	 * Test Method: Validate that the value of the numberMatched parameter is identical to the number of features in the feature collections that match the selection parameters like bbox, datetime or additional filter parameters.
    +	 * 
    + * @param collection the collection under test, never null + * @throws java.net.URISyntaxException if the creation of a uri fails + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 22, Test Method 6 (Requirement /req/core/fc-response) - Abstract Test 25 (Requirement /req/core/fc-numberMatched)", + dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) + public void validateFeaturesResponse_NumberMatched(Map collection) throws URISyntaxException { + String collectionId = (String) collection.get("id"); + validateNumberMatched(asKey(collectionId)); + } - /** - * Abstract Test 22, Test Method 7 (Abstract Test 26) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   7. If the numberReturned property is present, validate that it complies with /ats/core/fc-numberReturned
    -     * 
    - * - *
    -     * Abstract Test 26: /ats/core/fc-numberReturned
    -     * Test Purpose: Validate the numberReturned parameter returned with a Features response
    -     * Requirement: /req/core/fc-numberReturned
    -     *
    -     * Test Method: Validate that the numberReturned value is identical to the number of features in the response.
    -     * 
    - * - * @param collection - * the collection under test, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 22, Test Method 7 (Requirement /req/core/fc-response) - Abstract Test 26 (Requirement /req/core/fc-numberReturned)", dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) - public void validateFeaturesResponse_NumberReturned( Map collection ) { - String collectionId = (String) collection.get( "id" ); - validateNumberReturned( asKey( collectionId ) ); - } + /** + * Abstract Test 22, Test Method 7 (Abstract Test 26) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   7. If the numberReturned property is present, validate that it complies with /ats/core/fc-numberReturned
    +	 * 
    + * + *
    +	 * Abstract Test 26: /ats/core/fc-numberReturned
    +	 * Test Purpose: Validate the numberReturned parameter returned with a Features response
    +	 * Requirement: /req/core/fc-numberReturned
    +	 *
    +	 * Test Method: Validate that the numberReturned value is identical to the number of features in the response.
    +	 * 
    + * @param collection the collection under test, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Abstract Test 22, Test Method 7 (Requirement /req/core/fc-response) - Abstract Test 26 (Requirement /req/core/fc-numberReturned)", + dataProvider = "collectionItemUris", dependsOnMethods = "validateFeaturesOperation", alwaysRun = true) + public void validateFeaturesResponse_NumberReturned(Map collection) { + String collectionId = (String) collection.get("id"); + validateNumberReturned(asKey(collectionId)); + } - private void addFeatureIdToTestContext( ITestContext testContext, String collectionName, Response response ) { - if ( response == null ) - return; - Map collectionNameAndFeatureId = (Map) testContext.getSuite().getAttribute( SuiteAttribute.FEATUREIDS.getName() ); - if ( collectionNameAndFeatureId == null ) { - collectionNameAndFeatureId = new HashMap<>(); - testContext.getSuite().setAttribute( SuiteAttribute.FEATUREIDS.getName(), collectionNameAndFeatureId ); - } - String featureId = parseFeatureId( response.jsonPath() ); - if ( featureId != null ) - collectionNameAndFeatureId.put( collectionName, featureId ); - } + private void addFeatureIdToTestContext(ITestContext testContext, String collectionName, Response response) { + if (response == null) + return; + Map collectionNameAndFeatureId = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.FEATUREIDS.getName()); + if (collectionNameAndFeatureId == null) { + collectionNameAndFeatureId = new HashMap<>(); + testContext.getSuite().setAttribute(SuiteAttribute.FEATUREIDS.getName(), collectionNameAndFeatureId); + } + String featureId = parseFeatureId(response.jsonPath()); + if (featureId != null) + collectionNameAndFeatureId.put(collectionName, featureId); + } - private CollectionResponseKey asKey( String collectionId ) { - return new CollectionResponseKey( collectionId ); - } + private CollectionResponseKey asKey(String collectionId) { + return new CollectionResponseKey(collectionId); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesAssertions.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesAssertions.java index 0b310784..f1afa42a 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesAssertions.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesAssertions.java @@ -26,90 +26,92 @@ import io.restassured.path.json.JsonPath; /** + *

    + * FeaturesAssertions class. + *

    + * * @author Lyn Goltz */ public class FeaturesAssertions { - static void assertIntegerGreaterOrEqualsZero( Object value, String propertyName ) { - if ( value instanceof Number ) - assertIntegerGreaterOrEqualsZero( ( (Number) value ).intValue(), propertyName ); - else if ( value instanceof String ) - try { - int valueAsInt = Integer.parseInt( (String) value ); - assertIntegerGreaterOrEqualsZero( valueAsInt, propertyName ); - } catch ( NumberFormatException e ) { - String msg = "Expected property '%s' to be an integer, but was '%s'"; - throw new AssertionError( String.format( msg, propertyName, value ) ); - } - } - - static void assertIntegerGreaterOrEqualsZero( int value, String propertyName ) { - String msg = "Expected property '%s' to be an integer greater than or equals 0, but was '%s'"; - assertTrue( value >= 0, String.format( msg, propertyName, value ) ); - } - - static void assertTimeStamp( String collectionName, JsonPath jsonPath, ZonedDateTime timeStampBeforeResponse, - ZonedDateTime timeStampAfterResponse, boolean skipIfNoTimeStamp ) { - String timeStamp = jsonPath.getString( "timeStamp" ); - if ( timeStamp == null ) - if ( skipIfNoTimeStamp ) - throw new SkipException( "No server response timeStamp set for collection items request ( '" + collectionName + "')." ); - else - return; - - ZonedDateTime date = parseAsDate( timeStamp ); - assertNotNull(date, "Not valid timestamp."); - } - - static void assertNumberReturned( String collectionName, JsonPath jsonPath, boolean skipIfNoNumberReturned ) { - if ( !hasProperty( "numberReturned", jsonPath ) ) - if ( skipIfNoNumberReturned ) - throw new SkipException( "Property numberReturned is not set in collection items '" + collectionName - + "'" ); - else - return; - - int numberReturned = jsonPath.getInt( "numberReturned" ); - int numberOfFeatures = parseAsList( "features", jsonPath ).size(); - assertEquals( numberReturned, numberOfFeatures, - "Value of numberReturned (" + numberReturned - + ") does not match the number of features in the response (" - + numberOfFeatures + ")" ); - } - - static void assertNumberMatched( OpenApi3 apiModel, URI iut, String collectionName, JsonPath jsonPath, - boolean skipIfNoNumberMatched ) - throws URISyntaxException { - if ( !hasProperty( "numberMatched", jsonPath ) ) - if ( skipIfNoNumberMatched ) - throw new SkipException( "Property numberMatched is not set in collection items '" + collectionName - + "'" ); - else - return; - - int maximumLimit = -1; - - List testPoints = retrieveTestPointsForCollection( apiModel, iut, collectionName ); - if ( !testPoints.isEmpty() ) { - TestPoint testPoint = testPoints.get( 0 ); - Parameter limitParameter = OpenApiUtils.retrieveParameterByName( testPoint.getPath(), apiModel, "limit" ); - if ( limitParameter != null && limitParameter.getSchema() != null ) { - Number maximumLimitNumber = limitParameter.getSchema().getMaximum(); - if(maximumLimitNumber != null) { - maximumLimit = maximumLimitNumber.intValue(); - } - } - } - int numberMatched = jsonPath.getInt( "numberMatched" ); - if (numberMatched > OgcApiFeatures10.NUMBERMATCHED_LIMIT) { - throw new SkipException( - String.format("Number of matched features too large to check, was %d, test suite limit is %d.", - numberMatched, OgcApiFeatures10.NUMBERMATCHED_LIMIT)); - } - int numberOfAllReturnedFeatures = collectNumberOfAllReturnedFeatures( jsonPath, maximumLimit ); - assertEquals( numberMatched, numberOfAllReturnedFeatures, - "Value of numberReturned (" + numberMatched + ") does not match the number of features in all responses (" - + numberOfAllReturnedFeatures + ")" ); - } + static void assertIntegerGreaterOrEqualsZero(Object value, String propertyName) { + if (value instanceof Number) + assertIntegerGreaterOrEqualsZero(((Number) value).intValue(), propertyName); + else if (value instanceof String) + try { + int valueAsInt = Integer.parseInt((String) value); + assertIntegerGreaterOrEqualsZero(valueAsInt, propertyName); + } + catch (NumberFormatException e) { + String msg = "Expected property '%s' to be an integer, but was '%s'"; + throw new AssertionError(String.format(msg, propertyName, value)); + } + } + + static void assertIntegerGreaterOrEqualsZero(int value, String propertyName) { + String msg = "Expected property '%s' to be an integer greater than or equals 0, but was '%s'"; + assertTrue(value >= 0, String.format(msg, propertyName, value)); + } + + static void assertTimeStamp(String collectionName, JsonPath jsonPath, ZonedDateTime timeStampBeforeResponse, + ZonedDateTime timeStampAfterResponse, boolean skipIfNoTimeStamp) { + String timeStamp = jsonPath.getString("timeStamp"); + if (timeStamp == null) + if (skipIfNoTimeStamp) + throw new SkipException( + "No server response timeStamp set for collection items request ( '" + collectionName + "')."); + else + return; + + ZonedDateTime date = parseAsDate(timeStamp); + assertNotNull(date, "Not valid timestamp."); + } + + static void assertNumberReturned(String collectionName, JsonPath jsonPath, boolean skipIfNoNumberReturned) { + if (!hasProperty("numberReturned", jsonPath)) + if (skipIfNoNumberReturned) + throw new SkipException( + "Property numberReturned is not set in collection items '" + collectionName + "'"); + else + return; + + int numberReturned = jsonPath.getInt("numberReturned"); + int numberOfFeatures = parseAsList("features", jsonPath).size(); + assertEquals(numberReturned, numberOfFeatures, "Value of numberReturned (" + numberReturned + + ") does not match the number of features in the response (" + numberOfFeatures + ")"); + } + + static void assertNumberMatched(OpenApi3 apiModel, URI iut, String collectionName, JsonPath jsonPath, + boolean skipIfNoNumberMatched) throws URISyntaxException { + if (!hasProperty("numberMatched", jsonPath)) + if (skipIfNoNumberMatched) + throw new SkipException( + "Property numberMatched is not set in collection items '" + collectionName + "'"); + else + return; + + int maximumLimit = -1; + + List testPoints = retrieveTestPointsForCollection(apiModel, iut, collectionName); + if (!testPoints.isEmpty()) { + TestPoint testPoint = testPoints.get(0); + Parameter limitParameter = OpenApiUtils.retrieveParameterByName(testPoint.getPath(), apiModel, "limit"); + if (limitParameter != null && limitParameter.getSchema() != null) { + Number maximumLimitNumber = limitParameter.getSchema().getMaximum(); + if (maximumLimitNumber != null) { + maximumLimit = maximumLimitNumber.intValue(); + } + } + } + int numberMatched = jsonPath.getInt("numberMatched"); + if (numberMatched > OgcApiFeatures10.NUMBERMATCHED_LIMIT) { + throw new SkipException( + String.format("Number of matched features too large to check, was %d, test suite limit is %d.", + numberMatched, OgcApiFeatures10.NUMBERMATCHED_LIMIT)); + } + int numberOfAllReturnedFeatures = collectNumberOfAllReturnedFeatures(jsonPath, maximumLimit); + assertEquals(numberMatched, numberOfAllReturnedFeatures, "Value of numberReturned (" + numberMatched + + ") does not match the number of features in all responses (" + numberOfAllReturnedFeatures + ")"); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesBBox.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesBBox.java index e0c9d9d5..2986fb8c 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesBBox.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesBBox.java @@ -39,398 +39,396 @@ /** * A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox - * + * * @author Lyn Goltz */ public class FeaturesBBox extends AbstractFeatures { - @DataProvider(name = "collectionItemUrisWithBboxes") - public Iterator collectionItemUrisWithBboxes( ITestContext testContext ) { - List collectionsWithBboxes = new ArrayList<>(); - for ( Map collection : collections ) { - BBox extent = parseSpatialExtent( collection ); - if ( extent != null ) { - collectionsWithBboxes.add( new Object[] { collection, extent } ); - // These should include test cases which cross the - // meridian, - collectionsWithBboxes.add( new Object[] { collection, new BBox( -1.5, 50.0, 1.5, 53.0 ) } ); - // equator, - collectionsWithBboxes.add( new Object[] { collection, new BBox( -80.0, -5.0, -70.0, 5.0 ) } ); - // 180 longitude, - collectionsWithBboxes.add( new Object[] { collection, new BBox( 177.0, 65.0, -177.0, 70.0 ) } ); - // and polar regions. - collectionsWithBboxes.add( new Object[] { collection, new BBox( -180.0, 85.0, 180.0, 90.0 ) } ); - collectionsWithBboxes.add( new Object[] { collection, new BBox( -180.0, -90.0, 180.0, -85.0 ) } ); - } - } - return collectionsWithBboxes.iterator(); - } - - /** - *
    -     * Abstract Test 14: /ats/core/fc-bbox-definition
    -     * Test Purpose: Validate that the bounding box query parameters are constructed correctly.
    -     * Requirement: /req/core/fc-bbox-definition
    -     *
    -     * Test Method: Verify that the bbox query parameter complies with the following definition (using an OpenAPI Specification 3.0 fragment):
    -     *
    -     * name: bbox
    -     * in: query
    -     * required: false
    -     * schema:
    -     *   type: array
    -     *   minItems: 4
    -     *   maxItems: 6
    -     *   items:
    -     *     type: number
    -     * style: form
    -     * explode: false
    -     *
    -     * Use a bounding box with four numbers in all requests:
    -     *  * Lower left corner, WGS 84 longitude
    -     *  * Lower left corner, WGS 84 latitude
    -     *  * Upper right corner, WGS 84 longitude
    -     *  * Upper right corner, WGS 84 latitude
    -     * 
    - * - * @param testPoint - * the testPoint under test, never null - */ - @Test(description = "A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 14: (Requirement /req/core/fc-bbox-definition)", dataProvider = "collectionPaths", dependsOnGroups = "featuresBase", alwaysRun = true) - public void boundingBoxParameterDefinition( TestPoint testPoint ) { - Parameter bbox = retrieveParameterByName( testPoint.getPath(), getApiModel(), "bbox" ); - - assertNotNull( bbox, "Required bbox parameter for collections path '" + testPoint.getPath() - + "' in OpenAPI document is missing" ); - - String msg = "Expected property '%s' with value '%s' for collections path '" + testPoint.getPath() - + "' but was '%s'."; - - assertEquals( bbox.getName(), "bbox", String.format( msg, "name", "bbox", bbox.getName() ) ); - assertEquals( bbox.getIn(), "query", String.format( msg, "in", "query", bbox.getIn() ) ); - assertFalse( isRequired( bbox ), String.format( msg, "required", "false", bbox.getRequired() ) ); - assertEquals( bbox.getStyle(), "form", String.format( msg, "style", "form", bbox.getStyle() ) ); - assertFalse( isExplode( bbox ), String.format( msg, "explode", "false", bbox.getExplode() ) ); - - Schema schema = bbox.getSchema(); - assertNotNull( schema, "Expected schema for bbox parameter for collections path '" + testPoint.getPath() ); - assertEquals( schema.getType(), "array", String.format( msg, "schema -> type", "array", schema.getType() ) ); - - assertNotNull( schema.getMinItems(), String.format( msg, "schema -> minItems", "null", schema.getMinItems() ) ); - assertEquals( schema.getMinItems().intValue(), 4, - String.format( msg, "schema -> minItems", "4", schema.getMinItems() ) ); - - assertNotNull( schema.getMaxItems(), String.format( msg, "schema -> maxItems", "null", schema.getMaxItems() ) ); - assertEquals( schema.getMaxItems().intValue(), 6, - String.format( msg, "schema -> maxItems", "6", schema.getMaxItems() ) ); - - String itemsType = schema.getItemsSchema().getType(); - assertEquals( itemsType, "number", String.format( msg, "schema -> items -> type", "number", itemsType ) ); - } - - /** - *
    -     * Abstract Test 13: /ats/core/fc-op
    -     * Test Purpose: Validate that features can be identified and extracted from a Collection using query parameters.
    -     * Requirement: /req/core/fc-op
    -     *
    -     * Test Method
    -     *   1. For every feature collection identified in Collections, issue an HTTP GET request to the URL /collections/{collectionId}/items where {collectionId} is the id property for a Collection described in the Collections content.
    -     *   2. Validate that a document was returned with a status code 200.
    -     *   3. Validate the contents of the returned document using test /ats/core/fc-response.
    -     *
    -     * Repeat these tests using the following parameter tests:
    -     * Bounding Box:
    -     *   * Parameter /ats/core/fc-bbox-definition
    -     *   * Response /ats/core/fc-bbox-response
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param bbox - * bbox parameter to request, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 13: (Requirement /req/core/fc-op)", dataProvider = "collectionItemUrisWithBboxes", dependsOnGroups = "featuresBase", alwaysRun = true) - public void validateFeaturesWithBoundingBoxOperation( Map collection, BBox bbox ) { - String collectionId = (String) collection.get( "id" ); - - String getFeaturesUrl = findFeaturesUrlForGeoJson( rootUri, collection ); - if ( getFeaturesUrl.isEmpty() ) - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); - ZonedDateTime timeStampBeforeResponse = ZonedDateTime.now(); - Response response = init().baseUri( getFeaturesUrl ).accept( GEOJSON_MIME_TYPE ).param( "bbox", - bbox.asQueryParameter() ).when().request( GET ); - response.then().statusCode( 200 ); - ZonedDateTime timeStampAfterResponse = ZonedDateTime.now(); - ResponseData responseData = new ResponseData( response, timeStampBeforeResponse, timeStampAfterResponse ); - collectionIdAndResponse.put( asKey( collectionId, bbox ), responseData ); - } - - /** - *
    -     * Abstract Test 15: /ats/core/fc-bbox-response
    -     * Test Purpose: Validate that the bounding box query parameters are processed correctly.
    -     * Requirement: /req/core/fc-bbox-response
    -     *
    -     * Test Method
    -     *   1. Verify that only features that have a spatial geometry that intersects the bounding box are returned as part of the result set.
    -     *   2. Verify that the bbox parameter matched all features in the collection that were not associated with a spatial geometry (this is only applicable for datasets that include features without a spatial geometry).
    -     *   3.  Verify that the coordinate reference system of the geometries is WGS 84 longitude/latitude ("http://www.opengis.net/def/crs/OGC/1.3/CRS84" or "http://www.opengis.net/def/crs/OGC/0/CRS84h") since no parameter bbox-crs was specified in the request.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param bbox - * bbox parameter to request, never null - * @throws ParseException - * If the JSON cannot be parsed - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 15: (Requirement /req/core/fc-bbox-response)", dataProvider = "collectionItemUrisWithBboxes", dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) - public void validateFeaturesWithBoundingBoxResponse( Map collection, BBox bbox ) throws ParseException { - - String collectionId = (String) collection.get( "id" ); - // Test Method 1 - validateGeometriesInBBox( asKey( collectionId, bbox ), bbox ); - - // Test Method 3 - validateGeometriesInCrs84( asKey( collectionId, bbox ) ); - } - - /** - * Abstract Test 2, Test Method 1 - * - *
    -     * Abstract Test 2: /ats/core/crs84
    -     * Test Purpose: Validate that all spatial geometries provided through the API are in the CRS84 spatial reference system unless otherwise requested by the client.
    -     * Requirement: /req/core/crs84
    -     *
    -     * Test Method
    -     *  1. Do not specify a coordinate reference system in any request. All spatial data should be in the CRS84 reference system.
    -     *  2. Validate retrieved spatial data using the CRS84 reference system.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param bbox - * bbox parameter to request, never null - * @throws ParseException - * if the geometry could not be parsed - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 2, Test Method 2 (Requirement /req/core/crs84)", dataProvider = "collectionItemUrisWithBboxes", dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) - public void validateFeaturesResponse_GeometryInCRS84( Map collection, BBox bbox ) - throws ParseException { - String collectionId = (String) collection.get( "id" ); - validateGeometriesInCrs84( asKey( collectionId, bbox ) ); - } - - /** - * Abstract Test 22, Test Method 1 - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   1. Validate that the type property is present and has a value of FeatureCollection
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param bbox - * bbox parameter to request, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 22, Test Method 1 (Requirement /req/core/fc-response)", dataProvider = "collectionItemUrisWithBboxes", dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) - public void validateFeaturesWithBoundingBoxResponse_TypeProperty( Map collection, BBox bbox ) { - String collectionId = (String) collection.get( "id" ); - validateTypeProperty( asKey( collectionId, bbox ) ); - } - - /** - * Abstract Test 22, Test Method 2 - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   2. Validate the features property is present and that it is populated with an array of feature items.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param bbox - * bbox parameter to request, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 22, Test Method 2 (Requirement /req/core/fc-response)", dataProvider = "collectionItemUrisWithBboxes", dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) - public void validateFeaturesWithBoundingBoxResponse_FeaturesProperty( Map collection, BBox bbox ) { - String collectionId = (String) collection.get( "id" ); - validateFeaturesProperty( asKey( collectionId, bbox ) ); - } - - /** - * Abstract Test 22, Test Method 4 (Abstract Test 23) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   4. If the links property is present, validate that all entries comply with /ats/core/fc-links
    -     * 
    - * - *
    -     * Abstract Test 23: /ats/core/fc-links
    -     * Test Purpose: Validate that the required links are included in the Collections document.
    -     * Requirement: /req/core/fc-links, /req/core/fc-rel-type
    -     *
    -     * Test Method:
    -     * Verify that the response document includes:
    -     *   1. a link to this response document (relation: self),
    -     *   2. a link to the response document in every other media type supported by the server (relation: alternate).
    -     *
    -     * Verify that all links include the rel and type link parameters.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param bbox - * bbox parameter to request, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 22, Test Method 4 (Requirement /req/core/fc-response) - Abstract Test 23 (Requirement /req/core/fc-links, /req/core/fc-rel-type)", dataProvider = "collectionItemUrisWithBboxes", dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) - public void validateFeaturesWithBoundingBoxResponse_Links( Map collection, BBox bbox ) { - String collectionId = (String) collection.get( "id" ); - validateLinks( asKey( collectionId, bbox ) ); - } - - /** - * Abstract Test 22, Test Method 5 (Abstract Test 24) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   5. If the timeStamp property is present, validate that it complies with /ats/core/fc-timeStamp
    -     * 
    - * - *
    -     * Abstract Test 24: /ats/core/fc-timeStamp
    -     * Test Purpose: Validate the timeStamp parameter returned with a Features response
    -     * Requirement: /req/core/fc-timeStamp
    -     *
    -     * Test Method: Validate that the timeStamp value is set to the time when the response was generated.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param bbox - * bbox parameter to request, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 22, Test Method 5 (Requirement /req/core/fc-response) - Abstract Test 24 (Requirement /req/core/fc-timeStamp)", dataProvider = "collectionItemUrisWithBboxes", dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) - public void validateFeaturesWithBoundingBoxResponse_TimeStamp( Map collection, BBox bbox ) { - String collectionId = (String) collection.get( "id" ); - validateTimeStamp( asKey( collectionId, bbox ) ); - } - - /** - * Abstract Test 22, Test Method 6 (Abstract Test 25) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   6. If the numberMatched property is present, validate that it complies with /ats/core/fc-numberMatched
    -     * 
    - * - *
    -     * Abstract Test 25: /ats/core/fc-numberMatched
    -     * Test Purpose: Validate the numberMatched parameter returned with a Features response
    -     * Requirement: /req/core/fc-numberMatched
    -     *
    -     * Test Method: Validate that the value of the numberMatched parameter is identical to the number of features in the feature collections that match the selection parameters like bbox, datetime or additional filter parameters.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param bbox - * bbox parameter to request, never null - * - * @throws URISyntaxException - * if the creation of a uri fails - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 22, Test Method 6 (Requirement /req/core/fc-response) - Abstract Test 25 (Requirement /req/core/fc-numberMatched)", dataProvider = "collectionItemUrisWithBboxes", dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) - public void validateFeaturesWithBoundingBoxResponse_NumberMatched( Map collection, BBox bbox ) - throws URISyntaxException { - String collectionId = (String) collection.get( "id" ); - validateNumberMatched( asKey( collectionId, bbox ) ); - } - - /** - * Abstract Test 22, Test Method 7 (Abstract Test 26) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   7. If the numberReturned property is present, validate that it complies with /ats/core/fc-numberReturned
    -     * 
    - * - *
    -     * Abstract Test 26: /ats/core/fc-numberReturned
    -     * Test Purpose: Validate the numberReturned parameter returned with a Features response
    -     * Requirement: /req/core/fc-numberReturned
    -     *
    -     * Test Method: Validate that the numberReturned value is identical to the number of features in the response.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param bbox - * bbox parameter to request, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 22, Test Method 7 (Requirement /req/core/fc-response) - Abstract Test 26 (Requirement /req/core/fc-numberReturned)", dataProvider = "collectionItemUrisWithBboxes", dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) - public void validateFeaturesResponse_NumberReturned( Map collection, BBox bbox ) { - String collectionId = (String) collection.get( "id" ); - validateNumberReturned( asKey( collectionId, bbox ) ); - } - - private CollectionIdWithBboxKey asKey( String collectionId, BBox bBox ) { - return new CollectionIdWithBboxKey( collectionId, bBox ); - } - - private class CollectionIdWithBboxKey extends CollectionResponseKey { - - BBox bbox; - - public CollectionIdWithBboxKey( String collectionId, BBox bbox ) { - super( collectionId ); - this.bbox = bbox; - } - - @Override - public boolean equals( Object o ) { - if ( this == o ) - return true; - if ( o == null || getClass() != o.getClass() ) - return false; - if ( !super.equals( o ) ) - return false; - CollectionIdWithBboxKey that = (CollectionIdWithBboxKey) o; - return Objects.equals( bbox, that.bbox ); - } - - @Override - public int hashCode() { - return Objects.hash( super.hashCode(), bbox ); - } - } + /** + *

    + * collectionItemUrisWithBboxes. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionItemUrisWithBboxes") + public Iterator collectionItemUrisWithBboxes(ITestContext testContext) { + List collectionsWithBboxes = new ArrayList<>(); + for (Map collection : collections) { + BBox extent = parseSpatialExtent(collection); + if (extent != null) { + collectionsWithBboxes.add(new Object[] { collection, extent }); + // These should include test cases which cross the + // meridian, + collectionsWithBboxes.add(new Object[] { collection, new BBox(-1.5, 50.0, 1.5, 53.0) }); + // equator, + collectionsWithBboxes.add(new Object[] { collection, new BBox(-80.0, -5.0, -70.0, 5.0) }); + // 180 longitude, + collectionsWithBboxes.add(new Object[] { collection, new BBox(177.0, 65.0, -177.0, 70.0) }); + // and polar regions. + collectionsWithBboxes.add(new Object[] { collection, new BBox(-180.0, 85.0, 180.0, 90.0) }); + collectionsWithBboxes.add(new Object[] { collection, new BBox(-180.0, -90.0, 180.0, -85.0) }); + } + } + return collectionsWithBboxes.iterator(); + } + + /** + *
    +	 * Abstract Test 14: /ats/core/fc-bbox-definition
    +	 * Test Purpose: Validate that the bounding box query parameters are constructed correctly.
    +	 * Requirement: /req/core/fc-bbox-definition
    +	 *
    +	 * Test Method: Verify that the bbox query parameter complies with the following definition (using an OpenAPI Specification 3.0 fragment):
    +	 *
    +	 * name: bbox
    +	 * in: query
    +	 * required: false
    +	 * schema:
    +	 *   type: array
    +	 *   minItems: 4
    +	 *   maxItems: 6
    +	 *   items:
    +	 *     type: number
    +	 * style: form
    +	 * explode: false
    +	 *
    +	 * Use a bounding box with four numbers in all requests:
    +	 *  * Lower left corner, WGS 84 longitude
    +	 *  * Lower left corner, WGS 84 latitude
    +	 *  * Upper right corner, WGS 84 longitude
    +	 *  * Upper right corner, WGS 84 latitude
    +	 * 
    + * @param testPoint the testPoint under test, never null + */ + @Test(description = "A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 14: (Requirement /req/core/fc-bbox-definition)", + dataProvider = "collectionPaths", dependsOnGroups = "featuresBase", alwaysRun = true) + public void boundingBoxParameterDefinition(TestPoint testPoint) { + Parameter bbox = retrieveParameterByName(testPoint.getPath(), getApiModel(), "bbox"); + + assertNotNull(bbox, "Required bbox parameter for collections path '" + testPoint.getPath() + + "' in OpenAPI document is missing"); + + String msg = "Expected property '%s' with value '%s' for collections path '" + testPoint.getPath() + + "' but was '%s'."; + + assertEquals(bbox.getName(), "bbox", String.format(msg, "name", "bbox", bbox.getName())); + assertEquals(bbox.getIn(), "query", String.format(msg, "in", "query", bbox.getIn())); + assertFalse(isRequired(bbox), String.format(msg, "required", "false", bbox.getRequired())); + assertEquals(bbox.getStyle(), "form", String.format(msg, "style", "form", bbox.getStyle())); + assertFalse(isExplode(bbox), String.format(msg, "explode", "false", bbox.getExplode())); + + Schema schema = bbox.getSchema(); + assertNotNull(schema, "Expected schema for bbox parameter for collections path '" + testPoint.getPath()); + assertEquals(schema.getType(), "array", String.format(msg, "schema -> type", "array", schema.getType())); + + assertNotNull(schema.getMinItems(), String.format(msg, "schema -> minItems", "null", schema.getMinItems())); + assertEquals(schema.getMinItems().intValue(), 4, + String.format(msg, "schema -> minItems", "4", schema.getMinItems())); + + assertNotNull(schema.getMaxItems(), String.format(msg, "schema -> maxItems", "null", schema.getMaxItems())); + assertEquals(schema.getMaxItems().intValue(), 6, + String.format(msg, "schema -> maxItems", "6", schema.getMaxItems())); + + String itemsType = schema.getItemsSchema().getType(); + assertEquals(itemsType, "number", String.format(msg, "schema -> items -> type", "number", itemsType)); + } + + /** + *
    +	 * Abstract Test 13: /ats/core/fc-op
    +	 * Test Purpose: Validate that features can be identified and extracted from a Collection using query parameters.
    +	 * Requirement: /req/core/fc-op
    +	 *
    +	 * Test Method
    +	 *   1. For every feature collection identified in Collections, issue an HTTP GET request to the URL /collections/{collectionId}/items where {collectionId} is the id property for a Collection described in the Collections content.
    +	 *   2. Validate that a document was returned with a status code 200.
    +	 *   3. Validate the contents of the returned document using test /ats/core/fc-response.
    +	 *
    +	 * Repeat these tests using the following parameter tests:
    +	 * Bounding Box:
    +	 *   * Parameter /ats/core/fc-bbox-definition
    +	 *   * Response /ats/core/fc-bbox-response
    +	 * 
    + * @param collection the collection under test, never null + * @param bbox bbox parameter to request, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 13: (Requirement /req/core/fc-op)", + dataProvider = "collectionItemUrisWithBboxes", dependsOnGroups = "featuresBase", alwaysRun = true) + public void validateFeaturesWithBoundingBoxOperation(Map collection, BBox bbox) { + String collectionId = (String) collection.get("id"); + + String getFeaturesUrl = findFeaturesUrlForGeoJson(rootUri, collection); + if (getFeaturesUrl.isEmpty()) + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); + ZonedDateTime timeStampBeforeResponse = ZonedDateTime.now(); + Response response = init().baseUri(getFeaturesUrl) + .accept(GEOJSON_MIME_TYPE) + .param("bbox", bbox.asQueryParameter()) + .when() + .request(GET); + response.then().statusCode(200); + ZonedDateTime timeStampAfterResponse = ZonedDateTime.now(); + ResponseData responseData = new ResponseData(response, timeStampBeforeResponse, timeStampAfterResponse); + collectionIdAndResponse.put(asKey(collectionId, bbox), responseData); + } + + /** + *
    +	 * Abstract Test 15: /ats/core/fc-bbox-response
    +	 * Test Purpose: Validate that the bounding box query parameters are processed correctly.
    +	 * Requirement: /req/core/fc-bbox-response
    +	 *
    +	 * Test Method
    +	 *   1. Verify that only features that have a spatial geometry that intersects the bounding box are returned as part of the result set.
    +	 *   2. Verify that the bbox parameter matched all features in the collection that were not associated with a spatial geometry (this is only applicable for datasets that include features without a spatial geometry).
    +	 *   3.  Verify that the coordinate reference system of the geometries is WGS 84 longitude/latitude ("http://www.opengis.net/def/crs/OGC/1.3/CRS84" or "http://www.opengis.net/def/crs/OGC/0/CRS84h") since no parameter bbox-crs was specified in the request.
    +	 * 
    + * @param collection the collection under test, never null + * @param bbox bbox parameter to request, never null + * @throws org.locationtech.jts.io.ParseException If the JSON cannot be parsed + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 15: (Requirement /req/core/fc-bbox-response)", + dataProvider = "collectionItemUrisWithBboxes", + dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) + public void validateFeaturesWithBoundingBoxResponse(Map collection, BBox bbox) + throws ParseException { + + String collectionId = (String) collection.get("id"); + // Test Method 1 + validateGeometriesInBBox(asKey(collectionId, bbox), bbox); + + // Test Method 3 + validateGeometriesInCrs84(asKey(collectionId, bbox)); + } + + /** + * Abstract Test 2, Test Method 1 + * + *
    +	 * Abstract Test 2: /ats/core/crs84
    +	 * Test Purpose: Validate that all spatial geometries provided through the API are in the CRS84 spatial reference system unless otherwise requested by the client.
    +	 * Requirement: /req/core/crs84
    +	 *
    +	 * Test Method
    +	 *  1. Do not specify a coordinate reference system in any request. All spatial data should be in the CRS84 reference system.
    +	 *  2. Validate retrieved spatial data using the CRS84 reference system.
    +	 * 
    + * @param collection the collection under test, never null + * @param bbox bbox parameter to request, never null + * @throws org.locationtech.jts.io.ParseException if the geometry could not be parsed + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 2, Test Method 2 (Requirement /req/core/crs84)", + dataProvider = "collectionItemUrisWithBboxes", + dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) + public void validateFeaturesResponse_GeometryInCRS84(Map collection, BBox bbox) + throws ParseException { + String collectionId = (String) collection.get("id"); + validateGeometriesInCrs84(asKey(collectionId, bbox)); + } + + /** + * Abstract Test 22, Test Method 1 + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   1. Validate that the type property is present and has a value of FeatureCollection
    +	 * 
    + * @param collection the collection under test, never null + * @param bbox bbox parameter to request, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 22, Test Method 1 (Requirement /req/core/fc-response)", + dataProvider = "collectionItemUrisWithBboxes", + dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) + public void validateFeaturesWithBoundingBoxResponse_TypeProperty(Map collection, BBox bbox) { + String collectionId = (String) collection.get("id"); + validateTypeProperty(asKey(collectionId, bbox)); + } + + /** + * Abstract Test 22, Test Method 2 + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   2. Validate the features property is present and that it is populated with an array of feature items.
    +	 * 
    + * @param collection the collection under test, never null + * @param bbox bbox parameter to request, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 22, Test Method 2 (Requirement /req/core/fc-response)", + dataProvider = "collectionItemUrisWithBboxes", + dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) + public void validateFeaturesWithBoundingBoxResponse_FeaturesProperty(Map collection, BBox bbox) { + String collectionId = (String) collection.get("id"); + validateFeaturesProperty(asKey(collectionId, bbox)); + } + + /** + * Abstract Test 22, Test Method 4 (Abstract Test 23) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   4. If the links property is present, validate that all entries comply with /ats/core/fc-links
    +	 * 
    + * + *
    +	 * Abstract Test 23: /ats/core/fc-links
    +	 * Test Purpose: Validate that the required links are included in the Collections document.
    +	 * Requirement: /req/core/fc-links, /req/core/fc-rel-type
    +	 *
    +	 * Test Method:
    +	 * Verify that the response document includes:
    +	 *   1. a link to this response document (relation: self),
    +	 *   2. a link to the response document in every other media type supported by the server (relation: alternate).
    +	 *
    +	 * Verify that all links include the rel and type link parameters.
    +	 * 
    + * @param collection the collection under test, never null + * @param bbox bbox parameter to request, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 22, Test Method 4 (Requirement /req/core/fc-response) - Abstract Test 23 (Requirement /req/core/fc-links, /req/core/fc-rel-type)", + dataProvider = "collectionItemUrisWithBboxes", + dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) + public void validateFeaturesWithBoundingBoxResponse_Links(Map collection, BBox bbox) { + String collectionId = (String) collection.get("id"); + validateLinks(asKey(collectionId, bbox)); + } + + /** + * Abstract Test 22, Test Method 5 (Abstract Test 24) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   5. If the timeStamp property is present, validate that it complies with /ats/core/fc-timeStamp
    +	 * 
    + * + *
    +	 * Abstract Test 24: /ats/core/fc-timeStamp
    +	 * Test Purpose: Validate the timeStamp parameter returned with a Features response
    +	 * Requirement: /req/core/fc-timeStamp
    +	 *
    +	 * Test Method: Validate that the timeStamp value is set to the time when the response was generated.
    +	 * 
    + * @param collection the collection under test, never null + * @param bbox bbox parameter to request, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 22, Test Method 5 (Requirement /req/core/fc-response) - Abstract Test 24 (Requirement /req/core/fc-timeStamp)", + dataProvider = "collectionItemUrisWithBboxes", + dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) + public void validateFeaturesWithBoundingBoxResponse_TimeStamp(Map collection, BBox bbox) { + String collectionId = (String) collection.get("id"); + validateTimeStamp(asKey(collectionId, bbox)); + } + + /** + * Abstract Test 22, Test Method 6 (Abstract Test 25) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   6. If the numberMatched property is present, validate that it complies with /ats/core/fc-numberMatched
    +	 * 
    + * + *
    +	 * Abstract Test 25: /ats/core/fc-numberMatched
    +	 * Test Purpose: Validate the numberMatched parameter returned with a Features response
    +	 * Requirement: /req/core/fc-numberMatched
    +	 *
    +	 * Test Method: Validate that the value of the numberMatched parameter is identical to the number of features in the feature collections that match the selection parameters like bbox, datetime or additional filter parameters.
    +	 * 
    + * @param collection the collection under test, never null + * @param bbox bbox parameter to request, never null + * @throws java.net.URISyntaxException if the creation of a uri fails + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 22, Test Method 6 (Requirement /req/core/fc-response) - Abstract Test 25 (Requirement /req/core/fc-numberMatched)", + dataProvider = "collectionItemUrisWithBboxes", + dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) + public void validateFeaturesWithBoundingBoxResponse_NumberMatched(Map collection, BBox bbox) + throws URISyntaxException { + String collectionId = (String) collection.get("id"); + validateNumberMatched(asKey(collectionId, bbox)); + } + + /** + * Abstract Test 22, Test Method 7 (Abstract Test 26) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   7. If the numberReturned property is present, validate that it complies with /ats/core/fc-numberReturned
    +	 * 
    + * + *
    +	 * Abstract Test 26: /ats/core/fc-numberReturned
    +	 * Test Purpose: Validate the numberReturned parameter returned with a Features response
    +	 * Requirement: /req/core/fc-numberReturned
    +	 *
    +	 * Test Method: Validate that the numberReturned value is identical to the number of features in the response.
    +	 * 
    + * @param collection the collection under test, never null + * @param bbox bbox parameter to request, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 22, Test Method 7 (Requirement /req/core/fc-response) - Abstract Test 26 (Requirement /req/core/fc-numberReturned)", + dataProvider = "collectionItemUrisWithBboxes", + dependsOnMethods = "validateFeaturesWithBoundingBoxOperation", alwaysRun = true) + public void validateFeaturesResponse_NumberReturned(Map collection, BBox bbox) { + String collectionId = (String) collection.get("id"); + validateNumberReturned(asKey(collectionId, bbox)); + } + + private CollectionIdWithBboxKey asKey(String collectionId, BBox bBox) { + return new CollectionIdWithBboxKey(collectionId, bBox); + } + + private class CollectionIdWithBboxKey extends CollectionResponseKey { + + BBox bbox; + + public CollectionIdWithBboxKey(String collectionId, BBox bbox) { + super(collectionId); + this.bbox = bbox; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + if (!super.equals(o)) + return false; + CollectionIdWithBboxKey that = (CollectionIdWithBboxKey) o; + return Objects.equals(bbox, that.bbox); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), bbox); + } + + } + } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesErrorConditions.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesErrorConditions.java index caae4a74..38fe2d93 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesErrorConditions.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesErrorConditions.java @@ -20,130 +20,145 @@ /** * A.2.7. Features {root}/collections/{collectionId}/items - Error Conditions - * + * * @author Lyn Goltz */ public class FeaturesErrorConditions extends AbstractFeatures { - public static final String INVALID_QUERY_PARAM_VALUE = "unlimited"; - - public static final String UNKNOWN_QUERY_PARAM = "unknownQueryParameter"; - - @DataProvider(name = "collectionItemUris") - public Iterator collectionItemUris( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - for ( Map collection : collections ) { - collectionsData.add( new Object[] { collection } ); - } - return collectionsData.iterator(); - } - - /** - *
    -     * Abstract Test 13: /ats/core/fc-op
    -     * Test Purpose: Validate that features can be identified and extracted from a Collection using query parameters.
    -     * Requirement: /req/core/fc-op
    -     *
    -     * Test Method
    -     *   1. For every feature collection identified in Collections, issue an HTTP GET request to the URL /collections/{collectionId}/items where {collectionId} is the id property for a Collection described in the Collections content.
    -     *   2. Validate that a document was returned with a status code 200.
    -     *   3. Validate the contents of the returned document using test /ats/core/fc-response.
    -     *
    -     * Repeat these tests using the following parameter tests:
    -     * Error conditions:
    -     *  * Query Invalid /ats/core/query-param-invalid
    -     *  * Query Unknown /ats/core/query-param-unknown
    -     * 
    - * - *
    -     * Abstract Test 20: /ats/core/query-param-invalid
    -     * Test Purpose: Validate that the API correctly deals with invalid query parameters.
    -     * Requirement: /req/core/query-param-invalid
    -     *
    -     * Test Method
    -     *   1. Enter an HTTP request with an invalid query parameter.
    -     *   2. Verify that the API returns the status code 400.
    -     * 
    - * - * @param collection - * the collection under test, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Error Conditions, Abstract Test 13/20 (Requirement /req/core/query-param-invalid)", groups = "featuresBase", dataProvider = "collectionItemUris", dependsOnGroups = "collections", alwaysRun = true) - public void validateFeaturesOperation_QueryParamInvalid( Map collection ) { - String collectionId = (String) collection.get( "id" ); - - String featuresUrl = findFeaturesUrlForGeoJson( rootUri, collection ); - if ( featuresUrl == null ) - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); - - Response response = init().baseUri( featuresUrl ).accept( GEOJSON_MIME_TYPE ).param( "limit", - INVALID_QUERY_PARAM_VALUE ).when().request( GET ); - response.then().statusCode( 400 ); - } - - /** - *
    -     * Abstract Test 13: /ats/core/fc-op
    -     * Test Purpose: Validate that features can be identified and extracted from a Collection using query parameters.
    -     * Requirement: /req/core/fc-op
    -     *
    -     * Test Method
    -     *   1. For every feature collection identified in Collections, issue an HTTP GET request to the URL /collections/{collectionId}/items where {collectionId} is the id property for a Collection described in the Collections content.
    -     *   2. Validate that a document was returned with a status code 200.
    -     *   3. Validate the contents of the returned document using test /ats/core/fc-response.
    -     *
    -     * Repeat these tests using the following parameter tests:
    -     * Error conditions:
    -     *  * Query Invalid /ats/core/query-param-invalid
    -     *  * Query Unknown /ats/core/query-param-unknown
    -     * 
    - * - *
    -     * Abstract Test 21: /ats/core/query-param-unknown
    -     * Test Purpose: Validate that the API correctly deals with unknown query parameters.
    -     * Requirement: /req/core/query-param-unknown
    -     *
    -     * Test Method
    -     *   1. Enter an HTTP request with an query parameter that is not specified in the API definition.
    -     *   2. Verify that the API returns the status code 400.
    -     * 
    - * - * @param collection - * the collection under test, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Error Conditions, Abstract Test 13/21 (Requirement /req/core/query-param-unknown)", groups = "featuresBase", dataProvider = "collectionItemUris", dependsOnGroups = "collections", alwaysRun = true) - public void validateFeaturesOperation_QueryParamUnknown( Map collection ) { - String collectionId = (String) collection.get( "id" ); - boolean freeFormParameterSupported = OpenApiUtils.isFreeFormParameterSupportedForCollection( getApiModel(), iut, collectionId ); - if ( freeFormParameterSupported ) { - throw new SkipException( "Free-form parameters are supported for collection with id " + collectionId ); - } - - String featuresUrl = findFeaturesUrlForGeoJson( rootUri, collection ); - if ( featuresUrl == null ) { - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); - } - - String queryParam = createRandomQueryParam(); - boolean parameterSupportedForCollection = OpenApiUtils.isParameterSupportedForCollection( getApiModel(), iut, collectionId, - queryParam ); - if ( parameterSupportedForCollection ) { - throw new SkipException( "Parameters " + queryParam + " is supported for collection with id " - + collectionId ); - } - - Response response = init().baseUri( featuresUrl ).accept( GEOJSON_MIME_TYPE ).param( queryParam, - 1 ).when().request( GET ); - response.then().statusCode( 400 ); - } - - - private String createRandomQueryParam() { - Random r = new Random(); - int suffix = 10000 + r.nextInt( 10000 ); - return UNKNOWN_QUERY_PARAM + suffix; - } + /** Constant INVALID_QUERY_PARAM_VALUE="unlimited" */ + public static final String INVALID_QUERY_PARAM_VALUE = "unlimited"; + + /** Constant UNKNOWN_QUERY_PARAM="unknownQueryParameter" */ + public static final String UNKNOWN_QUERY_PARAM = "unknownQueryParameter"; + + /** + *

    + * collectionItemUris. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionItemUris") + public Iterator collectionItemUris(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + for (Map collection : collections) { + collectionsData.add(new Object[] { collection }); + } + return collectionsData.iterator(); + } + + /** + *
    +	 * Abstract Test 13: /ats/core/fc-op
    +	 * Test Purpose: Validate that features can be identified and extracted from a Collection using query parameters.
    +	 * Requirement: /req/core/fc-op
    +	 *
    +	 * Test Method
    +	 *   1. For every feature collection identified in Collections, issue an HTTP GET request to the URL /collections/{collectionId}/items where {collectionId} is the id property for a Collection described in the Collections content.
    +	 *   2. Validate that a document was returned with a status code 200.
    +	 *   3. Validate the contents of the returned document using test /ats/core/fc-response.
    +	 *
    +	 * Repeat these tests using the following parameter tests:
    +	 * Error conditions:
    +	 *  * Query Invalid /ats/core/query-param-invalid
    +	 *  * Query Unknown /ats/core/query-param-unknown
    +	 * 
    + * + *
    +	 * Abstract Test 20: /ats/core/query-param-invalid
    +	 * Test Purpose: Validate that the API correctly deals with invalid query parameters.
    +	 * Requirement: /req/core/query-param-invalid
    +	 *
    +	 * Test Method
    +	 *   1. Enter an HTTP request with an invalid query parameter.
    +	 *   2. Verify that the API returns the status code 400.
    +	 * 
    + * @param collection the collection under test, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Error Conditions, Abstract Test 13/20 (Requirement /req/core/query-param-invalid)", + groups = "featuresBase", dataProvider = "collectionItemUris", dependsOnGroups = "collections", + alwaysRun = true) + public void validateFeaturesOperation_QueryParamInvalid(Map collection) { + String collectionId = (String) collection.get("id"); + + String featuresUrl = findFeaturesUrlForGeoJson(rootUri, collection); + if (featuresUrl == null) + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); + + Response response = init().baseUri(featuresUrl) + .accept(GEOJSON_MIME_TYPE) + .param("limit", INVALID_QUERY_PARAM_VALUE) + .when() + .request(GET); + response.then().statusCode(400); + } + + /** + *
    +	 * Abstract Test 13: /ats/core/fc-op
    +	 * Test Purpose: Validate that features can be identified and extracted from a Collection using query parameters.
    +	 * Requirement: /req/core/fc-op
    +	 *
    +	 * Test Method
    +	 *   1. For every feature collection identified in Collections, issue an HTTP GET request to the URL /collections/{collectionId}/items where {collectionId} is the id property for a Collection described in the Collections content.
    +	 *   2. Validate that a document was returned with a status code 200.
    +	 *   3. Validate the contents of the returned document using test /ats/core/fc-response.
    +	 *
    +	 * Repeat these tests using the following parameter tests:
    +	 * Error conditions:
    +	 *  * Query Invalid /ats/core/query-param-invalid
    +	 *  * Query Unknown /ats/core/query-param-unknown
    +	 * 
    + * + *
    +	 * Abstract Test 21: /ats/core/query-param-unknown
    +	 * Test Purpose: Validate that the API correctly deals with unknown query parameters.
    +	 * Requirement: /req/core/query-param-unknown
    +	 *
    +	 * Test Method
    +	 *   1. Enter an HTTP request with an query parameter that is not specified in the API definition.
    +	 *   2. Verify that the API returns the status code 400.
    +	 * 
    + * @param collection the collection under test, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Error Conditions, Abstract Test 13/21 (Requirement /req/core/query-param-unknown)", + groups = "featuresBase", dataProvider = "collectionItemUris", dependsOnGroups = "collections", + alwaysRun = true) + public void validateFeaturesOperation_QueryParamUnknown(Map collection) { + String collectionId = (String) collection.get("id"); + boolean freeFormParameterSupported = OpenApiUtils.isFreeFormParameterSupportedForCollection(getApiModel(), iut, + collectionId); + if (freeFormParameterSupported) { + throw new SkipException("Free-form parameters are supported for collection with id " + collectionId); + } + + String featuresUrl = findFeaturesUrlForGeoJson(rootUri, collection); + if (featuresUrl == null) { + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); + } + + String queryParam = createRandomQueryParam(); + boolean parameterSupportedForCollection = OpenApiUtils.isParameterSupportedForCollection(getApiModel(), iut, + collectionId, queryParam); + if (parameterSupportedForCollection) { + throw new SkipException( + "Parameters " + queryParam + " is supported for collection with id " + collectionId); + } + + Response response = init().baseUri(featuresUrl) + .accept(GEOJSON_MIME_TYPE) + .param(queryParam, 1) + .when() + .request(GET); + response.then().statusCode(400); + } + + private String createRandomQueryParam() { + Random r = new Random(); + int suffix = 10000 + r.nextInt(10000); + return UNKNOWN_QUERY_PARAM + suffix; + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesLimit.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesLimit.java index 48b04a52..65819c23 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesLimit.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesLimit.java @@ -38,408 +38,395 @@ /** * A.2.7. Features {root}/collections/{collectionId}/items - Limit - * + * * @author Lyn Goltz */ public class FeaturesLimit extends AbstractFeatures { - @DataProvider(name = "collectionItemUrisWithLimits") - public Iterator collectionItemUrisWithLimits( ITestContext testContext ) { - URI iut = (URI) testContext.getSuite().getAttribute( IUT.getName() ); - List collectionsWithLimits = new ArrayList<>(); - for ( Map collection : collections ) { - String collectionId = (String) collection.get( "id" ); - List testPoints = retrieveTestPointsForCollection( getApiModel(), iut, collectionId ); - for ( TestPoint testPoint : testPoints ) { - Parameter limit = retrieveParameterByName( testPoint.getPath(), getApiModel(), "limit" ); - if ( limit != null && limit.getSchema() != null ) { - int min = limit.getSchema().getMinimum().intValue(); - int max = -1; - Number maximumLimitNumber = limit.getSchema().getMaximum(); - if(maximumLimitNumber != null) { - max = maximumLimitNumber.intValue(); - } - if ( min == max ) { - collectionsWithLimits.add( new Object[] { collection, min, max } ); - } else { - collectionsWithLimits.add( new Object[] { collection, min, max } ); - int betweenMinAndMax = min + ((max - min) / 2) > 100 ? 100 : min + ((max - min) / 2); - collectionsWithLimits.add( new Object[] { collection, betweenMinAndMax, max } ); - } - } - } - } - return collectionsWithLimits.iterator(); - } + /** + *

    + * collectionItemUrisWithLimits. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionItemUrisWithLimits") + public Iterator collectionItemUrisWithLimits(ITestContext testContext) { + URI iut = (URI) testContext.getSuite().getAttribute(IUT.getName()); + List collectionsWithLimits = new ArrayList<>(); + for (Map collection : collections) { + String collectionId = (String) collection.get("id"); + List testPoints = retrieveTestPointsForCollection(getApiModel(), iut, collectionId); + for (TestPoint testPoint : testPoints) { + Parameter limit = retrieveParameterByName(testPoint.getPath(), getApiModel(), "limit"); + if (limit != null && limit.getSchema() != null) { + int min = limit.getSchema().getMinimum().intValue(); + int max = -1; + Number maximumLimitNumber = limit.getSchema().getMaximum(); + if (maximumLimitNumber != null) { + max = maximumLimitNumber.intValue(); + } + if (min == max) { + collectionsWithLimits.add(new Object[] { collection, min, max }); + } + else { + collectionsWithLimits.add(new Object[] { collection, min, max }); + int betweenMinAndMax = min + ((max - min) / 2) > 100 ? 100 : min + ((max - min) / 2); + collectionsWithLimits.add(new Object[] { collection, betweenMinAndMax, max }); + } + } + } + } + return collectionsWithLimits.iterator(); + } - /** - *
    -     * Abstract Test 16: /ats/core/fc-limit-definition
    -     * Test Purpose: Validate that the bounding box query parameters are constructed corrrectly.
    -     * Requirement: /req/core/fc-limit-definition
    -     *
    -     * Test Method: Verify that the limit query parameter complies with the following definition (using an OpenAPI Specification 3.0 fragment):
    -     *
    -     * name: limit
    -     * in: query
    -     * required: false
    -     * schema:
    -     *   type: integer
    -     * style: form
    -     * explode: false
    -     *
    -     * Note that the API can define values for "minimum", "maximum" and "default".
    -     * 
    - * - * @param testPoint - * the testPoint under test, never null - */ - @Test(description = "A.2.7. Features {root}/collections/{collectionId}/items - Limit, Abstract Test 16: (Requirement /req/core/fc-limit-definition)", dataProvider = "collectionPaths", dependsOnGroups = "featuresBase", alwaysRun = true) - public void limitParameterDefinition( TestPoint testPoint ) { - Parameter limit = retrieveParameterByName( testPoint.getPath(), getApiModel(), "limit" ); + /** + *
    +	 * Abstract Test 16: /ats/core/fc-limit-definition
    +	 * Test Purpose: Validate that the bounding box query parameters are constructed corrrectly.
    +	 * Requirement: /req/core/fc-limit-definition
    +	 *
    +	 * Test Method: Verify that the limit query parameter complies with the following definition (using an OpenAPI Specification 3.0 fragment):
    +	 *
    +	 * name: limit
    +	 * in: query
    +	 * required: false
    +	 * schema:
    +	 *   type: integer
    +	 * style: form
    +	 * explode: false
    +	 *
    +	 * Note that the API can define values for "minimum", "maximum" and "default".
    +	 * 
    + * @param testPoint the testPoint under test, never null + */ + @Test(description = "A.2.7. Features {root}/collections/{collectionId}/items - Limit, Abstract Test 16: (Requirement /req/core/fc-limit-definition)", + dataProvider = "collectionPaths", dependsOnGroups = "featuresBase", alwaysRun = true) + public void limitParameterDefinition(TestPoint testPoint) { + Parameter limit = retrieveParameterByName(testPoint.getPath(), getApiModel(), "limit"); - assertNotNull( limit, "Required limit parameter for collections path '" + testPoint.getPath() - + "' in OpenAPI document is missing" ); + assertNotNull(limit, "Required limit parameter for collections path '" + testPoint.getPath() + + "' in OpenAPI document is missing"); - String msg = "Expected property '%s' with value '%s' but was '%s'"; + String msg = "Expected property '%s' with value '%s' but was '%s'"; - assertEquals( limit.getName(), "limit", String.format( msg, "name", "limit", limit.getName() ) ); - assertEquals( limit.getIn(), "query", String.format( msg, "in", "query", limit.getIn() ) ); - assertFalse( isRequired( limit ), String.format( msg, "required", "false", limit.getRequired() ) ); - assertEquals( limit.getStyle(), "form", String.format( msg, "style", "form", limit.getStyle() ) ); - assertFalse( isExplode( limit ), String.format( msg, "explode", "false", limit.getExplode() ) ); + assertEquals(limit.getName(), "limit", String.format(msg, "name", "limit", limit.getName())); + assertEquals(limit.getIn(), "query", String.format(msg, "in", "query", limit.getIn())); + assertFalse(isRequired(limit), String.format(msg, "required", "false", limit.getRequired())); + assertEquals(limit.getStyle(), "form", String.format(msg, "style", "form", limit.getStyle())); + assertFalse(isExplode(limit), String.format(msg, "explode", "false", limit.getExplode())); - Schema schema = limit.getSchema(); - assertEquals( schema.getType(), "integer", - String.format( msg, "schema -> type", "integer", schema.getType() ) ); - assertIntegerGreaterOrEqualsZero( schema.getMinimum(), "schema -> minimum" ); - assertIntegerGreaterOrEqualsZero( schema.getDefault(), "schema -> default" ); - } + Schema schema = limit.getSchema(); + assertEquals(schema.getType(), "integer", String.format(msg, "schema -> type", "integer", schema.getType())); + assertIntegerGreaterOrEqualsZero(schema.getMinimum(), "schema -> minimum"); + assertIntegerGreaterOrEqualsZero(schema.getDefault(), "schema -> default"); + } - /** - *
    -     * Abstract Test 13: /ats/core/fc-op
    -     * Test Purpose: Validate that features can be identified and extracted from a Collection using query parameters.
    -     * Requirement: /req/core/fc-op
    -     *
    -     * Test Method
    -     *   1. For every feature collection identified in Collections, issue an HTTP GET request to the URL /collections/{collectionId}/items where {collectionId} is the id property for a Collection described in the Collections content.
    -     *   2. Validate that a document was returned with a status code 200.
    -     *   3. Validate the contents of the returned document using test /ats/core/fc-response.
    -     *
    -     * Repeat these tests using the following parameter tests:
    -     * Limit:
    -     *   * Parameter /ats/core/fc-limit-definition
    -     *   * Response /ats/core/fc-limit-response
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param limit - * limit parameter to request, never null - * @param max - * max limit defined by the service, never null - */ - @Test(description = "A.2.7. Features {root}/collections/{collectionId}/items - Limit, Abstract Test 13: (Requirement /req/core/fc-op)", dataProvider = "collectionItemUrisWithLimits", dependsOnGroups = "featuresBase", alwaysRun = true) - public void validateFeaturesWithLimitOperation( Map collection, int limit, int max ) { - String collectionId = (String) collection.get( "id" ); + /** + *
    +	 * Abstract Test 13: /ats/core/fc-op
    +	 * Test Purpose: Validate that features can be identified and extracted from a Collection using query parameters.
    +	 * Requirement: /req/core/fc-op
    +	 *
    +	 * Test Method
    +	 *   1. For every feature collection identified in Collections, issue an HTTP GET request to the URL /collections/{collectionId}/items where {collectionId} is the id property for a Collection described in the Collections content.
    +	 *   2. Validate that a document was returned with a status code 200.
    +	 *   3. Validate the contents of the returned document using test /ats/core/fc-response.
    +	 *
    +	 * Repeat these tests using the following parameter tests:
    +	 * Limit:
    +	 *   * Parameter /ats/core/fc-limit-definition
    +	 *   * Response /ats/core/fc-limit-response
    +	 * 
    + * @param collection the collection under test, never null + * @param limit limit parameter to request, never null + * @param max max limit defined by the service, never null + */ + @Test(description = "A.2.7. Features {root}/collections/{collectionId}/items - Limit, Abstract Test 13: (Requirement /req/core/fc-op)", + dataProvider = "collectionItemUrisWithLimits", dependsOnGroups = "featuresBase", alwaysRun = true) + public void validateFeaturesWithLimitOperation(Map collection, int limit, int max) { + String collectionId = (String) collection.get("id"); - String getFeaturesUrl = findFeaturesUrlForGeoJson( rootUri, collection ); - if ( getFeaturesUrl == null || getFeaturesUrl.isEmpty() ) - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); - ZonedDateTime timeStampBeforeResponse = ZonedDateTime.now(); - Response response = init().baseUri( getFeaturesUrl ).accept( GEOJSON_MIME_TYPE ).param( "limit", - limit ).when().request( GET ); - response.then().statusCode( 200 ); - ZonedDateTime timeStampAfterResponse = ZonedDateTime.now(); - ResponseData responseData = new ResponseData( response, timeStampBeforeResponse, timeStampAfterResponse ); - collectionIdAndResponse.put( asKey( collectionId, limit ), responseData ); - } + String getFeaturesUrl = findFeaturesUrlForGeoJson(rootUri, collection); + if (getFeaturesUrl == null || getFeaturesUrl.isEmpty()) + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); + ZonedDateTime timeStampBeforeResponse = ZonedDateTime.now(); + Response response = init().baseUri(getFeaturesUrl) + .accept(GEOJSON_MIME_TYPE) + .param("limit", limit) + .when() + .request(GET); + response.then().statusCode(200); + ZonedDateTime timeStampAfterResponse = ZonedDateTime.now(); + ResponseData responseData = new ResponseData(response, timeStampBeforeResponse, timeStampAfterResponse); + collectionIdAndResponse.put(asKey(collectionId, limit), responseData); + } - /** - *
    -     * Abstract Test 17: /ats/core/fc-limit-response
    -     * Test Purpose: Validate that the limit query parameters are processed correctly.
    -     * Requirement: /req/core/fc-limit-response
    -     *
    -     * Test Method
    -     *  1. Count the Features which are on the first level of the collection. Any nested objects contained within the explicitly requested items are not be counted.
    -     *  2. Verify that this count is not greater than the value specified by the limit parameter.
    -     *  3. If the API definition specifies a maximum value for limit parameter, verify that the count does not exceed this maximum value.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param limit - * limit parameter to request, never null - * @param max - * max limit defined by the service, never null - */ - @Test(description = "A.2.7. Features {root}/collections/{collectionId}/items - Limit, Abstract Test 17: (Requirement /req/core/fc-limit-response)", dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", alwaysRun = true) - public void validateFeaturesWithLimitResponse( Map collection, int limit, int max ) { - String collectionId = (String) collection.get( "id" ); - ResponseData response = collectionIdAndResponse.get( asKey( collectionId, limit ) ); - if ( response == null ) - throw new SkipException( "Could not find a response for collection with id " + collectionId ); + /** + *
    +	 * Abstract Test 17: /ats/core/fc-limit-response
    +	 * Test Purpose: Validate that the limit query parameters are processed correctly.
    +	 * Requirement: /req/core/fc-limit-response
    +	 *
    +	 * Test Method
    +	 *  1. Count the Features which are on the first level of the collection. Any nested objects contained within the explicitly requested items are not be counted.
    +	 *  2. Verify that this count is not greater than the value specified by the limit parameter.
    +	 *  3. If the API definition specifies a maximum value for limit parameter, verify that the count does not exceed this maximum value.
    +	 * 
    + * @param collection the collection under test, never null + * @param limit limit parameter to request, never null + * @param max max limit defined by the service, never null + */ + @Test(description = "A.2.7. Features {root}/collections/{collectionId}/items - Limit, Abstract Test 17: (Requirement /req/core/fc-limit-response)", + dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", + alwaysRun = true) + public void validateFeaturesWithLimitResponse(Map collection, int limit, int max) { + String collectionId = (String) collection.get("id"); + ResponseData response = collectionIdAndResponse.get(asKey(collectionId, limit)); + if (response == null) + throw new SkipException("Could not find a response for collection with id " + collectionId); - JsonPath jsonPath = response.jsonPath(); - int numberOfFeatures = parseAsList( "features", jsonPath ).size(); - int expectedLimit = limit > max ? max : limit; - assertTrue( numberOfFeatures <= expectedLimit, - "Number of features for collection with name " + collectionId + " is unexpected (was " - + numberOfFeatures + "), expected are " + limit + " or less" ); - } + JsonPath jsonPath = response.jsonPath(); + int numberOfFeatures = parseAsList("features", jsonPath).size(); + int expectedLimit = limit > max ? max : limit; + assertTrue(numberOfFeatures <= expectedLimit, "Number of features for collection with name " + collectionId + + " is unexpected (was " + numberOfFeatures + "), expected are " + limit + " or less"); + } - /** - * Abstract Test 2, Test Method 1 - * - *
    -     * Abstract Test 2: /ats/core/crs84
    -     * Test Purpose: Validate that all spatial geometries provided through the API are in the CRS84 spatial reference system unless otherwise requested by the client.
    -     * Requirement: /req/core/crs84
    -     *
    -     * Test Method
    -     *  1. Do not specify a coordinate reference system in any request. All spatial data should be in the CRS84 reference system.
    -     *  2. Validate retrieved spatial data using the CRS84 reference system.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param limit - * limit parameter to request, never null - * @param max - * max limit defined by the service, never null - * @throws ParseException - * if the geometry could not be parsed - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 2, Test Method 2 (Requirement /req/core/crs84)", dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", alwaysRun = true) - public void validateFeaturesWithLimitResponse_GeometryInCRS84( Map collection, int limit, int max ) - throws ParseException { - String collectionId = (String) collection.get( "id" ); - validateGeometriesInCrs84( asKey( collectionId, limit ) ); - } + /** + * Abstract Test 2, Test Method 1 + * + *
    +	 * Abstract Test 2: /ats/core/crs84
    +	 * Test Purpose: Validate that all spatial geometries provided through the API are in the CRS84 spatial reference system unless otherwise requested by the client.
    +	 * Requirement: /req/core/crs84
    +	 *
    +	 * Test Method
    +	 *  1. Do not specify a coordinate reference system in any request. All spatial data should be in the CRS84 reference system.
    +	 *  2. Validate retrieved spatial data using the CRS84 reference system.
    +	 * 
    + * @param collection the collection under test, never null + * @param limit limit parameter to request, never null + * @param max max limit defined by the service, never null + * @throws org.locationtech.jts.io.ParseException if the geometry could not be parsed + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 2, Test Method 2 (Requirement /req/core/crs84)", + dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", + alwaysRun = true) + public void validateFeaturesWithLimitResponse_GeometryInCRS84(Map collection, int limit, int max) + throws ParseException { + String collectionId = (String) collection.get("id"); + validateGeometriesInCrs84(asKey(collectionId, limit)); + } - /** - * Abstract Test 22, Test Method 1 - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   1. Validate that the type property is present and has a value of FeatureCollection
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param limit - * limit parameter to request, never null - * @param max - * max limit defined by the service, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 22, Test Method 1 (Requirement /req/core/fc-response)", dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", alwaysRun = true) - public void validateFeaturesWithLimitResponse_TypeProperty( Map collection, int limit, int max ) { - String collectionId = (String) collection.get( "id" ); - validateTypeProperty( asKey( collectionId, limit ) ); - } + /** + * Abstract Test 22, Test Method 1 + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   1. Validate that the type property is present and has a value of FeatureCollection
    +	 * 
    + * @param collection the collection under test, never null + * @param limit limit parameter to request, never null + * @param max max limit defined by the service, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 22, Test Method 1 (Requirement /req/core/fc-response)", + dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", + alwaysRun = true) + public void validateFeaturesWithLimitResponse_TypeProperty(Map collection, int limit, int max) { + String collectionId = (String) collection.get("id"); + validateTypeProperty(asKey(collectionId, limit)); + } - /** - * Abstract Test 22, Test Method 2 - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   2. Validate the features property is present and that it is populated with an array of feature items.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param limit - * limit parameter to request, never null - * @param max - * max limit defined by the service, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 22, Test Method 2 (Requirement /req/core/fc-response)", dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", alwaysRun = true) - public void validateFeaturesWithLimitResponse_FeaturesProperty( Map collection, int limit, - int max ) { - String collectionId = (String) collection.get( "id" ); - validateFeaturesProperty( asKey( collectionId, limit ) ); - } + /** + * Abstract Test 22, Test Method 2 + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   2. Validate the features property is present and that it is populated with an array of feature items.
    +	 * 
    + * @param collection the collection under test, never null + * @param limit limit parameter to request, never null + * @param max max limit defined by the service, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 22, Test Method 2 (Requirement /req/core/fc-response)", + dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", + alwaysRun = true) + public void validateFeaturesWithLimitResponse_FeaturesProperty(Map collection, int limit, int max) { + String collectionId = (String) collection.get("id"); + validateFeaturesProperty(asKey(collectionId, limit)); + } - /** - * Abstract Test 22, Test Method 4 (Abstract Test 23) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   4. If the links property is present, validate that all entries comply with /ats/core/fc-links
    -     * 
    - * - *
    -     * Abstract Test 23: /ats/core/fc-links
    -     * Test Purpose: Validate that the required links are included in the Collections document.
    -     * Requirement: /req/core/fc-links, /req/core/fc-rel-type
    -     *
    -     * Test Method:
    -     * Verify that the response document includes:
    -     *   1. a link to this response document (relation: self),
    -     *   2. a link to the response document in every other media type supported by the server (relation: alternate).
    -     *
    -     * Verify that all links include the rel and type link parameters.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param limit - * limit parameter to request, never null - * @param max - * max limit defined by the service, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 22, Test Method 4 (Requirement /req/core/fc-response) - Abstract Test 23 (Requirement /req/core/fc-links, /req/core/fc-rel-type)", dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", alwaysRun = true) - public void validateFeaturesWithLimitResponse_Links( Map collection, int limit, int max ) { - String collectionId = (String) collection.get( "id" ); - validateLinks( asKey( collectionId, limit ) ); - } + /** + * Abstract Test 22, Test Method 4 (Abstract Test 23) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   4. If the links property is present, validate that all entries comply with /ats/core/fc-links
    +	 * 
    + * + *
    +	 * Abstract Test 23: /ats/core/fc-links
    +	 * Test Purpose: Validate that the required links are included in the Collections document.
    +	 * Requirement: /req/core/fc-links, /req/core/fc-rel-type
    +	 *
    +	 * Test Method:
    +	 * Verify that the response document includes:
    +	 *   1. a link to this response document (relation: self),
    +	 *   2. a link to the response document in every other media type supported by the server (relation: alternate).
    +	 *
    +	 * Verify that all links include the rel and type link parameters.
    +	 * 
    + * @param collection the collection under test, never null + * @param limit limit parameter to request, never null + * @param max max limit defined by the service, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 22, Test Method 4 (Requirement /req/core/fc-response) - Abstract Test 23 (Requirement /req/core/fc-links, /req/core/fc-rel-type)", + dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", + alwaysRun = true) + public void validateFeaturesWithLimitResponse_Links(Map collection, int limit, int max) { + String collectionId = (String) collection.get("id"); + validateLinks(asKey(collectionId, limit)); + } - /** - * Abstract Test 22, Test Method 5 (Abstract Test 24) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   5. If the timeStamp property is present, validate that it complies with /ats/core/fc-timeStamp
    -     * 
    - * - *
    -     * Abstract Test 24: /ats/core/fc-timeStamp
    -     * Test Purpose: Validate the timeStamp parameter returned with a Features response
    -     * Requirement: /req/core/fc-timeStamp
    -     *
    -     * Test Method: Validate that the timeStamp value is set to the time when the response was generated.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param limit - * limit parameter to request, never null - * @param max - * max limit defined by the service, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 22, Test Method 5 (Requirement /req/core/fc-response) - Abstract Test 24 (Requirement /req/core/fc-timeStamp)", dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", alwaysRun = true) - public void validateFeaturesWithLimitResponse_TimeStamp( Map collection, int limit, int max ) { - String collectionId = (String) collection.get( "id" ); - validateTimeStamp( asKey( collectionId, limit ) ); - } + /** + * Abstract Test 22, Test Method 5 (Abstract Test 24) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   5. If the timeStamp property is present, validate that it complies with /ats/core/fc-timeStamp
    +	 * 
    + * + *
    +	 * Abstract Test 24: /ats/core/fc-timeStamp
    +	 * Test Purpose: Validate the timeStamp parameter returned with a Features response
    +	 * Requirement: /req/core/fc-timeStamp
    +	 *
    +	 * Test Method: Validate that the timeStamp value is set to the time when the response was generated.
    +	 * 
    + * @param collection the collection under test, never null + * @param limit limit parameter to request, never null + * @param max max limit defined by the service, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 22, Test Method 5 (Requirement /req/core/fc-response) - Abstract Test 24 (Requirement /req/core/fc-timeStamp)", + dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", + alwaysRun = true) + public void validateFeaturesWithLimitResponse_TimeStamp(Map collection, int limit, int max) { + String collectionId = (String) collection.get("id"); + validateTimeStamp(asKey(collectionId, limit)); + } - /** - * Abstract Test 22, Test Method 6 (Abstract Test 25) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   6. If the numberMatched property is present, validate that it complies with /ats/core/fc-numberMatched
    -     * 
    - * - *
    -     * Abstract Test 25: /ats/core/fc-numberMatched
    -     * Test Purpose: Validate the numberMatched parameter returned with a Features response
    -     * Requirement: /req/core/fc-numberMatched
    -     *
    -     * Test Method: Validate that the value of the numberMatched parameter is identical to the number of features in the feature collections that match the selection parameters like bbox, datetime or additional filter parameters.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param limit - * limit parameter to request, never null - * @param max - * max limit defined by the service, never null - * @throws URISyntaxException - * if the creation of a uri fails - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 22, Test Method 6 (Requirement /req/core/fc-response) - Abstract Test 25 (Requirement /req/core/fc-numberMatched)", dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", alwaysRun = true) - public void validateFeaturesWithLimitResponse_NumberMatched( Map collection, int limit, int max ) - throws URISyntaxException { - String collectionId = (String) collection.get( "id" ); - validateNumberMatched( asKey( collectionId, limit ) ); - } + /** + * Abstract Test 22, Test Method 6 (Abstract Test 25) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   6. If the numberMatched property is present, validate that it complies with /ats/core/fc-numberMatched
    +	 * 
    + * + *
    +	 * Abstract Test 25: /ats/core/fc-numberMatched
    +	 * Test Purpose: Validate the numberMatched parameter returned with a Features response
    +	 * Requirement: /req/core/fc-numberMatched
    +	 *
    +	 * Test Method: Validate that the value of the numberMatched parameter is identical to the number of features in the feature collections that match the selection parameters like bbox, datetime or additional filter parameters.
    +	 * 
    + * @param collection the collection under test, never null + * @param limit limit parameter to request, never null + * @param max max limit defined by the service, never null + * @throws java.net.URISyntaxException if the creation of a uri fails + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 22, Test Method 6 (Requirement /req/core/fc-response) - Abstract Test 25 (Requirement /req/core/fc-numberMatched)", + dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", + alwaysRun = true) + public void validateFeaturesWithLimitResponse_NumberMatched(Map collection, int limit, int max) + throws URISyntaxException { + String collectionId = (String) collection.get("id"); + validateNumberMatched(asKey(collectionId, limit)); + } - /** - * Abstract Test 22, Test Method 7 (Abstract Test 26) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   7. If the numberReturned property is present, validate that it complies with /ats/core/fc-numberReturned
    -     * 
    - * - *
    -     * Abstract Test 26: /ats/core/fc-numberReturned
    -     * Test Purpose: Validate the numberReturned parameter returned with a Features response
    -     * Requirement: /req/core/fc-numberReturned
    -     *
    -     * Test Method: Validate that the numberReturned value is identical to the number of features in the response.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param limit - * limit parameter to request, never null - * @param max - * max limit defined by the service, never null - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 22, Test Method 7 (Requirement /req/core/fc-response) - Abstract Test 26 (Requirement /req/core/fc-numberReturned)", dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", alwaysRun = true) - public void validateFeaturesResponse_NumberReturned( Map collection, int limit, int max ) { - String collectionId = (String) collection.get( "id" ); - validateNumberReturned( asKey( collectionId, limit ) ); - } + /** + * Abstract Test 22, Test Method 7 (Abstract Test 26) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   7. If the numberReturned property is present, validate that it complies with /ats/core/fc-numberReturned
    +	 * 
    + * + *
    +	 * Abstract Test 26: /ats/core/fc-numberReturned
    +	 * Test Purpose: Validate the numberReturned parameter returned with a Features response
    +	 * Requirement: /req/core/fc-numberReturned
    +	 *
    +	 * Test Method: Validate that the numberReturned value is identical to the number of features in the response.
    +	 * 
    + * @param collection the collection under test, never null + * @param limit limit parameter to request, never null + * @param max max limit defined by the service, never null + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items, Limit, Abstract Test 22, Test Method 7 (Requirement /req/core/fc-response) - Abstract Test 26 (Requirement /req/core/fc-numberReturned)", + dataProvider = "collectionItemUrisWithLimits", dependsOnMethods = "validateFeaturesWithLimitOperation", + alwaysRun = true) + public void validateFeaturesResponse_NumberReturned(Map collection, int limit, int max) { + String collectionId = (String) collection.get("id"); + validateNumberReturned(asKey(collectionId, limit)); + } - private CollectionIdWithLimitKey asKey( String collectionId, int limit ) { - return new CollectionIdWithLimitKey( collectionId, limit ); - } + private CollectionIdWithLimitKey asKey(String collectionId, int limit) { + return new CollectionIdWithLimitKey(collectionId, limit); + } - private class CollectionIdWithLimitKey extends CollectionResponseKey { + private class CollectionIdWithLimitKey extends CollectionResponseKey { - int limit; + int limit; - public CollectionIdWithLimitKey( String collectionId, int limit ) { - super( collectionId ); - this.limit = limit; - } + public CollectionIdWithLimitKey(String collectionId, int limit) { + super(collectionId); + this.limit = limit; + } - @Override - public boolean equals( Object o ) { - if ( this == o ) - return true; - if ( o == null || getClass() != o.getClass() ) - return false; - if ( !super.equals( o ) ) - return false; - CollectionIdWithLimitKey that = (CollectionIdWithLimitKey) o; - return limit == that.limit; - } + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + if (!super.equals(o)) + return false; + CollectionIdWithLimitKey that = (CollectionIdWithLimitKey) o; + return limit == that.limit; + } - @Override - public int hashCode() { - return Objects.hash( super.hashCode(), limit ); - } - } + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), limit); + } + + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesTime.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesTime.java index a5f90fba..2c620d3f 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesTime.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesTime.java @@ -38,447 +38,430 @@ /** * A.2.7. Features {root}/collections/{collectionId}/items - Datetime - * + * * @author Lyn Goltz */ public class FeaturesTime extends AbstractFeatures { - @DataProvider(name = "collectionItemUrisWithDateTimes") - public Iterator collectionItemUrisWithDateTimes( ITestContext testContext ) { - List collectionsWithTimes = new ArrayList<>(); - for ( Map collection : collections ) { - TemporalExtent temporalExtent = parseTemporalExtent( collection ); - if ( temporalExtent != null ) { - ZonedDateTime begin = temporalExtent.getBegin(); - ZonedDateTime end = temporalExtent.getEnd(); - - Duration between = Duration.between( begin, end ); - Duration quarter = between.dividedBy( 4 ); - ZonedDateTime beginInterval = begin.plus( quarter ); - ZonedDateTime endInterval = beginInterval.plus( quarter ); - - // Example 6. A date-time - collectionsWithTimes.add( new Object[] { collection, formatDate( begin ), beginInterval, null } ); - // Example 7. A period using a start and end time - collectionsWithTimes.add( new Object[] { collection, formatDateRange( beginInterval, endInterval ), - beginInterval, endInterval } ); - // Example 8. A period using start time and a duration - LocalDate beginIntervalDate = beginInterval.toLocalDate(); - LocalDate endIntervalDate = beginIntervalDate.plusDays( 2 ); - collectionsWithTimes.add( new Object[] { collection, - formatDateRangeWithDuration( beginIntervalDate, - endIntervalDate ), - beginIntervalDate, endIntervalDate } ); - } - } - return collectionsWithTimes.iterator(); - } - - /** - *
    -     * Abstract Test 18: /ats/core/fc-time-definition
    -     * Test Purpose: Validate that the dateTime query parameters are constructed correctly.
    -     * Requirement: /req/core/fc-time-definition
    -     *
    -     * Test Method: Verify that the datetime query parameter complies with the following definition (using an OpenAPI Specification 3.0 fragment):
    -     *
    -     * name: datetime
    -     * in: query
    -     * required: false
    -     * schema:
    -     *   type: string
    -     * style: form
    -     * explode: false
    -     * 
    - * - * @param testPoint - * the testPoint under test, never null - */ - @Test(description = "A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 18: (Requirement /req/core/fc-time-definition)", dataProvider = "collectionPaths", dependsOnGroups = "featuresBase", alwaysRun = true) - public void timeParameterDefinition( TestPoint testPoint ) { - Parameter time = retrieveParameterByName( testPoint.getPath(), getApiModel(), "datetime" ); - - assertNotNull( time, "Required datetime parameter for collections with path '" + testPoint.getPath() - + "' in OpenAPI document is missing" ); - - String msg = "Expected property '%s' with value '%s' but was '%s'"; - - assertEquals( time.getName(), "datetime", String.format( msg, "name", "datetime", time.getName() ) ); - assertEquals( time.getIn(), "query", String.format( msg, "in", "query", time.getIn() ) ); - assertFalse( isRequired( time ), String.format( msg, "required", "false", time.getRequired() ) ); - assertEquals( time.getStyle(), "form", String.format( msg, "style", "form", time.getStyle() ) ); - assertFalse( isExplode( time ), String.format( msg, "explode", "false", time.getExplode() ) ); - - Schema schema = time.getSchema(); - assertEquals( schema.getType(), "string", String.format( msg, "schema -> type", "string", schema.getType() ) ); - } - - /** - *
    -     * Abstract Test 13: /ats/core/fc-op
    -     * Test Purpose: Validate that features can be identified and extracted from a Collection using query parameters.
    -     * Requirement: /req/core/fc-op
    -     *
    -     * Test Method
    -     *   1. For every feature collection identified in Collections, issue an HTTP GET request to the URL /collections/{collectionId}/items where {collectionId} is the id property for a Collection described in the Collections content.
    -     *   2. Validate that a document was returned with a status code 200.
    -     *   3. Validate the contents of the returned document using test /ats/core/fc-response.
    -     *
    -     * Repeat these tests using the following parameter tests:
    -     * DateTime:
    -     *   * Parameter /ats/core/fc-time-definition
    -     *   * Response /ats/core/fc-time-response
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param queryParameter - * time parameter as string to use as query parameter, never null - * @param begin - * a {@link ZonedDateTime} or {@link LocalDate}, the begin of the interval (or instant), never - * null - * @param end - * a {@link ZonedDateTime} or {@link LocalDate}, the end of the interval, never null if the - * request is an instant - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 13: (Requirement /req/core/fc-op)", dataProvider = "collectionItemUrisWithDateTimes", dependsOnGroups = "featuresBase", alwaysRun = true) - public void validateFeaturesWithDateTimeOperation( Map collection, String queryParameter, - Object begin, Object end ) { - String collectionId = (String) collection.get( "id" ); - - String getFeaturesUrl = findFeaturesUrlForGeoJson( rootUri, collection ); - if ( getFeaturesUrl.isEmpty() ) - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); - ZonedDateTime timeStampBeforeResponse = ZonedDateTime.now(); - Response response = init().baseUri( getFeaturesUrl ).accept( GEOJSON_MIME_TYPE ).param( "datetime", - queryParameter ).when().request( GET ); - response.then().statusCode( 200 ); - ZonedDateTime timeStampAfterResponse = ZonedDateTime.now(); - ResponseData responseData = new ResponseData( response, timeStampBeforeResponse, timeStampAfterResponse ); - collectionIdAndResponse.put( asKey( collectionId, queryParameter ), responseData ); - - } - - /** - *
    -     * Abstract Test 19: /ats/core/fc-time-response
    -     * Test Purpose: Validate that the dataTime query parameters are processed correctly.
    -     * Requirement: /req/core/fc-time-response
    -     *
    -     * Test Method
    -     *   1. Verify that only features that have a temporal geometry that intersects the temporal information in the datetime parameter were included in the result set
    -     *   2. Verify that all features in the collection that are not associated with a temporal geometry are included in the result set
    -     *   3. Validate that the datetime parameter complies with the syntax described in /req/core/fc-time-response.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param queryParameter - * time parameter as string to use as query parameter, never null - * @param begin - * a {@link ZonedDateTime} or {@link LocalDate}, the begin of the interval (or instant), never - * null - * @param end - * a {@link ZonedDateTime} or {@link LocalDate}, the end of the interval, never null if the - * request is an instant - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 19: (Requirement /req/core/fc-time-response)", dataProvider = "collectionItemUrisWithDateTimes", dependsOnGroups = "featuresBase", alwaysRun = true) - public void validateFeaturesWithDateTimeResponse( Map collection, String queryParameter, - Object begin, Object end ) { - String collectionId = (String) collection.get( "id" ); - ResponseData response = collectionIdAndResponse.get( asKey( collectionId, queryParameter ) ); - if ( response == null ) - throw new SkipException( "Could not find a response for collection with id " + collectionId ); - - // TODO: assert returned features - } - - /** - * Abstract Test 2, Test Method 1 - * - *
    -     * Abstract Test 2: /ats/core/crs84
    -     * Test Purpose: Validate that all spatial geometries provided through the API are in the CRS84 spatial reference system unless otherwise requested by the client.
    -     * Requirement: /req/core/crs84
    -     *
    -     * Test Method
    -     *  1. Do not specify a coordinate reference system in any request. All spatial data should be in the CRS84 reference system.
    -     *  2. Validate retrieved spatial data using the CRS84 reference system.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param queryParameter - * time parameter as string to use as query parameter, never null - * @param begin - * a {@link ZonedDateTime} or {@link LocalDate}, the begin of the interval (or instant), never - * null - * @param end - * a {@link ZonedDateTime} or {@link LocalDate}, the end of the interval, never null if the - * request is an instant - * @throws ParseException - * if the geometry could not be parsed - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 2, Test Method 2 (Requirement /req/core/crs84)", dataProvider = "collectionItemUrisWithDateTimes", dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) - public void validateFeaturesWithDateTimeResponse_GeometryInCRS84( Map collection, - String queryParameter, Object begin, Object end ) - throws ParseException { - String collectionId = (String) collection.get( "id" ); - validateGeometriesInCrs84( asKey( collectionId, queryParameter ) ); - } - - /** - * Abstract Test 22, Test Method 1 - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   1. Validate that the type property is present and has a value of FeatureCollection
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param queryParameter - * time parameter as string to use as query parameter, never null - * @param begin - * a {@link ZonedDateTime} or {@link LocalDate}, the begin of the interval (or instant), never - * null - * @param end - * a {@link ZonedDateTime} or {@link LocalDate}, the end of the interval, never null if the - * request is an instant - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 22, Test Method 1 (Requirement /req/core/fc-response)", dataProvider = "collectionItemUrisWithDateTimes", dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) - public void validateFeaturesWithDateTimeResponse_TypeProperty( Map collection, - String queryParameter, Object begin, Object end ) { - String collectionId = (String) collection.get( "id" ); - validateTypeProperty( asKey( collectionId, queryParameter ) ); - } - - /** - * Abstract Test 22, Test Method 2 - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   2. Validate the features property is present and that it is populated with an array of feature items.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param queryParameter - * time parameter as string to use as query parameter, never null - * @param begin - * a {@link ZonedDateTime} or {@link LocalDate}, the begin of the interval (or instant), never - * null - * @param end - * a {@link ZonedDateTime} or {@link LocalDate}, the end of the interval, never null if the - * request is an instant - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 22, Test Method 2 (Requirement /req/core/fc-response)", dataProvider = "collectionItemUrisWithDateTimes", dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) - public void validateFeaturesWithDateTimeResponse_FeaturesProperty( Map collection, - String queryParameter, Object begin, - Object end ) { - String collectionId = (String) collection.get( "id" ); - validateFeaturesProperty( asKey( collectionId, queryParameter ) ); - } - - /** - * Abstract Test 22, Test Method 4 (Abstract Test 23) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   4. If the links property is present, validate that all entries comply with /ats/core/fc-links
    -     * 
    - * - *
    -     * Abstract Test 23: /ats/core/fc-links
    -     * Test Purpose: Validate that the required links are included in the Collections document.
    -     * Requirement: /req/core/fc-links, /req/core/fc-rel-type
    -     *
    -     * Test Method:
    -     * Verify that the response document includes:
    -     *   1. a link to this response document (relation: self),
    -     *   2. a link to the response document in every other media type supported by the server (relation: alternate).
    -     *
    -     * Verify that all links include the rel and type link parameters.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param queryParameter - * time parameter as string to use as query parameter, never null - * @param begin - * a {@link ZonedDateTime} or {@link LocalDate}, the begin of the interval (or instant), never - * null - * @param end - * a {@link ZonedDateTime} or {@link LocalDate}, the end of the interval, never null if the - * request is an instant - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 22, Test Method 4 (Requirement /req/core/fc-response) - Abstract Test 23 (Requirement /req/core/fc-links, /req/core/fc-rel-type)", dataProvider = "collectionItemUrisWithDateTimes", dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) - public void validateFeaturesWithDateTimeResponse_Links( Map collection, String queryParameter, - Object begin, Object end ) { - String collectionId = (String) collection.get( "id" ); - validateLinks( asKey( collectionId, queryParameter ) ); - } - - /** - * Abstract Test 22, Test Method 5 (Abstract Test 24) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   5. If the timeStamp property is present, validate that it complies with /ats/core/fc-timeStamp
    -     * 
    - * - *
    -     * Abstract Test 24: /ats/core/fc-timeStamp
    -     * Test Purpose: Validate the timeStamp parameter returned with a Features response
    -     * Requirement: /req/core/fc-timeStamp
    -     *
    -     * Test Method: Validate that the timeStamp value is set to the time when the response was generated.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param queryParameter - * time parameter as string to use as query parameter, never null - * @param begin - * a {@link ZonedDateTime} or {@link LocalDate}, the begin of the interval (or instant), never - * null - * @param end - * a {@link ZonedDateTime} or {@link LocalDate}, the end of the interval, never null if the - * request is an instant - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 22, Test Method 5 (Requirement /req/core/fc-response) - Abstract Test 24 (Requirement /req/core/fc-timeStamp)", dataProvider = "collectionItemUrisWithDateTimes", dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) - public void validateFeaturesWithDateTimeResponse_TimeStamp( Map collection, String queryParameter, - Object begin, Object end ) { - String collectionId = (String) collection.get( "id" ); - validateTimeStamp( asKey( collectionId, queryParameter ) ); - } - - /** - * Abstract Test 22, Test Method 6 (Abstract Test 25) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   6. If the numberMatched property is present, validate that it complies with /ats/core/fc-numberMatched
    -     * 
    - * - *
    -     * Abstract Test 25: /ats/core/fc-numberMatched
    -     * Test Purpose: Validate the numberMatched parameter returned with a Features response
    -     * Requirement: /req/core/fc-numberMatched
    -     *
    -     * Test Method: Validate that the value of the numberMatched parameter is identical to the number of features in the feature collections that match the selection parameters like bbox, datetime or additional filter parameters.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param queryParameter - * time parameter as string to use as query parameter, never null - * @param begin - * a {@link ZonedDateTime} or {@link LocalDate}, the begin of the interval (or instant), never - * null - * @param end - * a {@link ZonedDateTime} or {@link LocalDate}, the end of the interval, never null if the - * request is an instant - * - * @throws URISyntaxException - * if the creation of a uri fails - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 22, Test Method 6 (Requirement /req/core/fc-response) - Abstract Test 25 (Requirement /req/core/fc-numberMatched)", dataProvider = "collectionItemUrisWithDateTimes", dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) - public void validateFeaturesWithDateTimeResponse_NumberMatched( Map collection, - String queryParameter, Object begin, Object end ) - throws URISyntaxException { - String collectionId = (String) collection.get( "id" ); - validateNumberMatched( asKey( collectionId, queryParameter ) ); - } - - /** - * Abstract Test 22, Test Method 7 (Abstract Test 26) - * - *
    -     * Abstract Test 22: /ats/core/fc-response
    -     * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    -     * Requirement: /req/core/fc-response
    -     *
    -     * Test Method
    -     *   7. If the numberReturned property is present, validate that it complies with /ats/core/fc-numberReturned
    -     * 
    - * - *
    -     * Abstract Test 26: /ats/core/fc-numberReturned
    -     * Test Purpose: Validate the numberReturned parameter returned with a Features response
    -     * Requirement: /req/core/fc-numberReturned
    -     *
    -     * Test Method: Validate that the numberReturned value is identical to the number of features in the response.
    -     * 
    - * - * @param collection - * the collection under test, never null - * @param queryParameter - * time parameter as string to use as query parameter, never null - * @param begin - * a {@link ZonedDateTime} or {@link LocalDate}, the begin of the interval (or instant), never - * null - * @param end - * a {@link ZonedDateTime} or {@link LocalDate}, the end of the interval, never null if the - * request is an instant - */ - @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 22, Test Method 7 (Requirement /req/core/fc-response) - Abstract Test 26 (Requirement /req/core/fc-numberReturned)", dataProvider = "collectionItemUrisWithDateTimes", dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) - public void validateFeaturesResponse_NumberReturned( Map collection, String queryParameter, - Object begin, Object end ) { - String collectionId = (String) collection.get( "id" ); - validateNumberReturned( asKey( collectionId, queryParameter ) ); - } - - private CollectionIdWithTimeKey asKey( String collectionId, String queryParameter ) { - return new CollectionIdWithTimeKey( collectionId, queryParameter ); - } - - private class CollectionIdWithTimeKey extends CollectionResponseKey { - - String queryParameter; - - public CollectionIdWithTimeKey( String collectionId, String queryParameter ) { - super( collectionId ); - this.queryParameter = queryParameter; - } - - @Override - public boolean equals( Object o ) { - if ( this == o ) - return true; - if ( o == null || getClass() != o.getClass() ) - return false; - if ( !super.equals( o ) ) - return false; - CollectionIdWithTimeKey that = (CollectionIdWithTimeKey) o; - return Objects.equals( queryParameter, that.queryParameter ); - } - - @Override - public int hashCode() { - return Objects.hash( super.hashCode(), queryParameter ); - } - } + /** + *

    + * collectionItemUrisWithDateTimes. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionItemUrisWithDateTimes") + public Iterator collectionItemUrisWithDateTimes(ITestContext testContext) { + List collectionsWithTimes = new ArrayList<>(); + for (Map collection : collections) { + TemporalExtent temporalExtent = parseTemporalExtent(collection); + if (temporalExtent != null) { + ZonedDateTime begin = temporalExtent.getBegin(); + ZonedDateTime end = temporalExtent.getEnd(); + + Duration between = Duration.between(begin, end); + Duration quarter = between.dividedBy(4); + ZonedDateTime beginInterval = begin.plus(quarter); + ZonedDateTime endInterval = beginInterval.plus(quarter); + + // Example 6. A date-time + collectionsWithTimes.add(new Object[] { collection, formatDate(begin), beginInterval, null }); + // Example 7. A period using a start and end time + collectionsWithTimes.add(new Object[] { collection, formatDateRange(beginInterval, endInterval), + beginInterval, endInterval }); + // Example 8. A period using start time and a duration + LocalDate beginIntervalDate = beginInterval.toLocalDate(); + LocalDate endIntervalDate = beginIntervalDate.plusDays(2); + collectionsWithTimes + .add(new Object[] { collection, formatDateRangeWithDuration(beginIntervalDate, endIntervalDate), + beginIntervalDate, endIntervalDate }); + } + } + return collectionsWithTimes.iterator(); + } + + /** + *
    +	 * Abstract Test 18: /ats/core/fc-time-definition
    +	 * Test Purpose: Validate that the dateTime query parameters are constructed correctly.
    +	 * Requirement: /req/core/fc-time-definition
    +	 *
    +	 * Test Method: Verify that the datetime query parameter complies with the following definition (using an OpenAPI Specification 3.0 fragment):
    +	 *
    +	 * name: datetime
    +	 * in: query
    +	 * required: false
    +	 * schema:
    +	 *   type: string
    +	 * style: form
    +	 * explode: false
    +	 * 
    + * @param testPoint the testPoint under test, never null + */ + @Test(description = "A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 18: (Requirement /req/core/fc-time-definition)", + dataProvider = "collectionPaths", dependsOnGroups = "featuresBase", alwaysRun = true) + public void timeParameterDefinition(TestPoint testPoint) { + Parameter time = retrieveParameterByName(testPoint.getPath(), getApiModel(), "datetime"); + + assertNotNull(time, "Required datetime parameter for collections with path '" + testPoint.getPath() + + "' in OpenAPI document is missing"); + + String msg = "Expected property '%s' with value '%s' but was '%s'"; + + assertEquals(time.getName(), "datetime", String.format(msg, "name", "datetime", time.getName())); + assertEquals(time.getIn(), "query", String.format(msg, "in", "query", time.getIn())); + assertFalse(isRequired(time), String.format(msg, "required", "false", time.getRequired())); + assertEquals(time.getStyle(), "form", String.format(msg, "style", "form", time.getStyle())); + assertFalse(isExplode(time), String.format(msg, "explode", "false", time.getExplode())); + + Schema schema = time.getSchema(); + assertEquals(schema.getType(), "string", String.format(msg, "schema -> type", "string", schema.getType())); + } + + /** + *
    +	 * Abstract Test 13: /ats/core/fc-op
    +	 * Test Purpose: Validate that features can be identified and extracted from a Collection using query parameters.
    +	 * Requirement: /req/core/fc-op
    +	 *
    +	 * Test Method
    +	 *   1. For every feature collection identified in Collections, issue an HTTP GET request to the URL /collections/{collectionId}/items where {collectionId} is the id property for a Collection described in the Collections content.
    +	 *   2. Validate that a document was returned with a status code 200.
    +	 *   3. Validate the contents of the returned document using test /ats/core/fc-response.
    +	 *
    +	 * Repeat these tests using the following parameter tests:
    +	 * DateTime:
    +	 *   * Parameter /ats/core/fc-time-definition
    +	 *   * Response /ats/core/fc-time-response
    +	 * 
    + * @param collection the collection under test, never null + * @param queryParameter time parameter as string to use as query parameter, never + * null + * @param begin a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * begin of the interval (or instant), never null + * @param end a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * end of the interval, never null if the request is an instant + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 13: (Requirement /req/core/fc-op)", + dataProvider = "collectionItemUrisWithDateTimes", dependsOnGroups = "featuresBase", alwaysRun = true) + public void validateFeaturesWithDateTimeOperation(Map collection, String queryParameter, + Object begin, Object end) { + String collectionId = (String) collection.get("id"); + + String getFeaturesUrl = findFeaturesUrlForGeoJson(rootUri, collection); + if (getFeaturesUrl.isEmpty()) + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); + ZonedDateTime timeStampBeforeResponse = ZonedDateTime.now(); + Response response = init().baseUri(getFeaturesUrl) + .accept(GEOJSON_MIME_TYPE) + .param("datetime", queryParameter) + .when() + .request(GET); + response.then().statusCode(200); + ZonedDateTime timeStampAfterResponse = ZonedDateTime.now(); + ResponseData responseData = new ResponseData(response, timeStampBeforeResponse, timeStampAfterResponse); + collectionIdAndResponse.put(asKey(collectionId, queryParameter), responseData); + + } + + /** + *
    +	 * Abstract Test 19: /ats/core/fc-time-response
    +	 * Test Purpose: Validate that the dataTime query parameters are processed correctly.
    +	 * Requirement: /req/core/fc-time-response
    +	 *
    +	 * Test Method
    +	 *   1. Verify that only features that have a temporal geometry that intersects the temporal information in the datetime parameter were included in the result set
    +	 *   2. Verify that all features in the collection that are not associated with a temporal geometry are included in the result set
    +	 *   3. Validate that the datetime parameter complies with the syntax described in /req/core/fc-time-response.
    +	 * 
    + * @param collection the collection under test, never null + * @param queryParameter time parameter as string to use as query parameter, never + * null + * @param begin a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * begin of the interval (or instant), never null + * @param end a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * end of the interval, never null if the request is an instant + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 19: (Requirement /req/core/fc-time-response)", + dataProvider = "collectionItemUrisWithDateTimes", dependsOnGroups = "featuresBase", alwaysRun = true) + public void validateFeaturesWithDateTimeResponse(Map collection, String queryParameter, + Object begin, Object end) { + String collectionId = (String) collection.get("id"); + ResponseData response = collectionIdAndResponse.get(asKey(collectionId, queryParameter)); + if (response == null) + throw new SkipException("Could not find a response for collection with id " + collectionId); + + // TODO: assert returned features + } + + /** + * Abstract Test 2, Test Method 1 + * + *
    +	 * Abstract Test 2: /ats/core/crs84
    +	 * Test Purpose: Validate that all spatial geometries provided through the API are in the CRS84 spatial reference system unless otherwise requested by the client.
    +	 * Requirement: /req/core/crs84
    +	 *
    +	 * Test Method
    +	 *  1. Do not specify a coordinate reference system in any request. All spatial data should be in the CRS84 reference system.
    +	 *  2. Validate retrieved spatial data using the CRS84 reference system.
    +	 * 
    + * @param collection the collection under test, never null + * @param queryParameter time parameter as string to use as query parameter, never + * null + * @param begin a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * begin of the interval (or instant), never null + * @param end a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * end of the interval, never null if the request is an instant + * @throws org.locationtech.jts.io.ParseException if the geometry could not be parsed + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - BoundingBox, Abstract Test 2, Test Method 2 (Requirement /req/core/crs84)", + dataProvider = "collectionItemUrisWithDateTimes", + dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) + public void validateFeaturesWithDateTimeResponse_GeometryInCRS84(Map collection, + String queryParameter, Object begin, Object end) throws ParseException { + String collectionId = (String) collection.get("id"); + validateGeometriesInCrs84(asKey(collectionId, queryParameter)); + } + + /** + * Abstract Test 22, Test Method 1 + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   1. Validate that the type property is present and has a value of FeatureCollection
    +	 * 
    + * @param collection the collection under test, never null + * @param queryParameter time parameter as string to use as query parameter, never + * null + * @param begin a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * begin of the interval (or instant), never null + * @param end a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * end of the interval, never null if the request is an instant + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 22, Test Method 1 (Requirement /req/core/fc-response)", + dataProvider = "collectionItemUrisWithDateTimes", + dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) + public void validateFeaturesWithDateTimeResponse_TypeProperty(Map collection, String queryParameter, + Object begin, Object end) { + String collectionId = (String) collection.get("id"); + validateTypeProperty(asKey(collectionId, queryParameter)); + } + + /** + * Abstract Test 22, Test Method 2 + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   2. Validate the features property is present and that it is populated with an array of feature items.
    +	 * 
    + * @param collection the collection under test, never null + * @param queryParameter time parameter as string to use as query parameter, never + * null + * @param begin a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * begin of the interval (or instant), never null + * @param end a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * end of the interval, never null if the request is an instant + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 22, Test Method 2 (Requirement /req/core/fc-response)", + dataProvider = "collectionItemUrisWithDateTimes", + dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) + public void validateFeaturesWithDateTimeResponse_FeaturesProperty(Map collection, + String queryParameter, Object begin, Object end) { + String collectionId = (String) collection.get("id"); + validateFeaturesProperty(asKey(collectionId, queryParameter)); + } + + /** + * Abstract Test 22, Test Method 4 (Abstract Test 23) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   4. If the links property is present, validate that all entries comply with /ats/core/fc-links
    +	 * 
    + * + *
    +	 * Abstract Test 23: /ats/core/fc-links
    +	 * Test Purpose: Validate that the required links are included in the Collections document.
    +	 * Requirement: /req/core/fc-links, /req/core/fc-rel-type
    +	 *
    +	 * Test Method:
    +	 * Verify that the response document includes:
    +	 *   1. a link to this response document (relation: self),
    +	 *   2. a link to the response document in every other media type supported by the server (relation: alternate).
    +	 *
    +	 * Verify that all links include the rel and type link parameters.
    +	 * 
    + * @param collection the collection under test, never null + * @param queryParameter time parameter as string to use as query parameter, never + * null + * @param begin a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * begin of the interval (or instant), never null + * @param end a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * end of the interval, never null if the request is an instant + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 22, Test Method 4 (Requirement /req/core/fc-response) - Abstract Test 23 (Requirement /req/core/fc-links, /req/core/fc-rel-type)", + dataProvider = "collectionItemUrisWithDateTimes", + dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) + public void validateFeaturesWithDateTimeResponse_Links(Map collection, String queryParameter, + Object begin, Object end) { + String collectionId = (String) collection.get("id"); + validateLinks(asKey(collectionId, queryParameter)); + } + + /** + * Abstract Test 22, Test Method 5 (Abstract Test 24) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   5. If the timeStamp property is present, validate that it complies with /ats/core/fc-timeStamp
    +	 * 
    + * + *
    +	 * Abstract Test 24: /ats/core/fc-timeStamp
    +	 * Test Purpose: Validate the timeStamp parameter returned with a Features response
    +	 * Requirement: /req/core/fc-timeStamp
    +	 *
    +	 * Test Method: Validate that the timeStamp value is set to the time when the response was generated.
    +	 * 
    + * @param collection the collection under test, never null + * @param queryParameter time parameter as string to use as query parameter, never + * null + * @param begin a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * begin of the interval (or instant), never null + * @param end a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * end of the interval, never null if the request is an instant + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 22, Test Method 5 (Requirement /req/core/fc-response) - Abstract Test 24 (Requirement /req/core/fc-timeStamp)", + dataProvider = "collectionItemUrisWithDateTimes", + dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) + public void validateFeaturesWithDateTimeResponse_TimeStamp(Map collection, String queryParameter, + Object begin, Object end) { + String collectionId = (String) collection.get("id"); + validateTimeStamp(asKey(collectionId, queryParameter)); + } + + /** + * Abstract Test 22, Test Method 6 (Abstract Test 25) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   6. If the numberMatched property is present, validate that it complies with /ats/core/fc-numberMatched
    +	 * 
    + * + *
    +	 * Abstract Test 25: /ats/core/fc-numberMatched
    +	 * Test Purpose: Validate the numberMatched parameter returned with a Features response
    +	 * Requirement: /req/core/fc-numberMatched
    +	 *
    +	 * Test Method: Validate that the value of the numberMatched parameter is identical to the number of features in the feature collections that match the selection parameters like bbox, datetime or additional filter parameters.
    +	 * 
    + * @param collection the collection under test, never null + * @param queryParameter time parameter as string to use as query parameter, never + * null + * @param begin a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * begin of the interval (or instant), never null + * @param end a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * end of the interval, never null if the request is an instant + * @throws java.net.URISyntaxException if the creation of a uri fails + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 22, Test Method 6 (Requirement /req/core/fc-response) - Abstract Test 25 (Requirement /req/core/fc-numberMatched)", + dataProvider = "collectionItemUrisWithDateTimes", + dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) + public void validateFeaturesWithDateTimeResponse_NumberMatched(Map collection, + String queryParameter, Object begin, Object end) throws URISyntaxException { + String collectionId = (String) collection.get("id"); + validateNumberMatched(asKey(collectionId, queryParameter)); + } + + /** + * Abstract Test 22, Test Method 7 (Abstract Test 26) + * + *
    +	 * Abstract Test 22: /ats/core/fc-response
    +	 * Test Purpose: Validate that the Feature Collections complies with the require structure and contents.
    +	 * Requirement: /req/core/fc-response
    +	 *
    +	 * Test Method
    +	 *   7. If the numberReturned property is present, validate that it complies with /ats/core/fc-numberReturned
    +	 * 
    + * + *
    +	 * Abstract Test 26: /ats/core/fc-numberReturned
    +	 * Test Purpose: Validate the numberReturned parameter returned with a Features response
    +	 * Requirement: /req/core/fc-numberReturned
    +	 *
    +	 * Test Method: Validate that the numberReturned value is identical to the number of features in the response.
    +	 * 
    + * @param collection the collection under test, never null + * @param queryParameter time parameter as string to use as query parameter, never + * null + * @param begin a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * begin of the interval (or instant), never null + * @param end a {@link java.time.ZonedDateTime} or {@link java.time.LocalDate}, the + * end of the interval, never null if the request is an instant + */ + @Test(description = "Implements A.2.7. Features {root}/collections/{collectionId}/items - Datetime, Abstract Test 22, Test Method 7 (Requirement /req/core/fc-response) - Abstract Test 26 (Requirement /req/core/fc-numberReturned)", + dataProvider = "collectionItemUrisWithDateTimes", + dependsOnMethods = "validateFeaturesWithDateTimeOperation", alwaysRun = true) + public void validateFeaturesResponse_NumberReturned(Map collection, String queryParameter, + Object begin, Object end) { + String collectionId = (String) collection.get("id"); + validateNumberReturned(asKey(collectionId, queryParameter)); + } + + private CollectionIdWithTimeKey asKey(String collectionId, String queryParameter) { + return new CollectionIdWithTimeKey(collectionId, queryParameter); + } + + private class CollectionIdWithTimeKey extends CollectionResponseKey { + + String queryParameter; + + public CollectionIdWithTimeKey(String collectionId, String queryParameter) { + super(collectionId); + this.queryParameter = queryParameter; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + if (!super.equals(o)) + return false; + CollectionIdWithTimeKey that = (CollectionIdWithTimeKey) o; + return Objects.equals(queryParameter, that.queryParameter); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), queryParameter); + } + + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/conformance/Conformance.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/conformance/Conformance.java index c66c3ba7..6cfa34e2 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/conformance/Conformance.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/conformance/Conformance.java @@ -35,108 +35,119 @@ */ public class Conformance extends CommonFixture { - private List requirementClasses; - - @DataProvider(name = "conformanceUris") - public Object[][] conformanceUris( ITestContext testContext ) { - OpenApi3 apiModel = (OpenApi3) testContext.getSuite().getAttribute( API_MODEL.getName() ); - URI iut = (URI) testContext.getSuite().getAttribute( IUT.getName() ); - List testPoints = retrieveTestPointsForConformance( apiModel, iut ); - - //Set dummy TestPoint data if no testPoints found. - if (testPoints.isEmpty()) { - testPoints.add(new TestPoint("http://dummydata.com", "/conformance", null)); - } - - Object[][] testPointsData = new Object[testPoints.size()][]; - int i = 0; - for ( TestPoint testPoint : testPoints ) { - testPointsData[i++] = new Object[] { testPoint }; - } - return testPointsData; - } - - @AfterClass - public void storeRequirementClassesInTestContext( ITestContext testContext ) { - testContext.getSuite().setAttribute( REQUIREMENTCLASSES.getName(), this.requirementClasses ); - } - - /** - *
    -     * Abstract Test 7: /ats/core/conformance-op
    -     * Test Purpose: Validate that a Conformance Declaration can be retrieved from the expected location.
    -     * Requirement: /req/core/conformance-op
    -     *
    -     * Test Method:
    -     *  1. Construct a path for each "conformance" link on the landing page as well as for the {root}/conformance path.
    -     *  2. Issue an HTTP GET request on each path
    -     *  3. Validate that a document was returned with a status code 200
    -     *  4. Validate the contents of the returned document using test /ats/core/conformance-success.
    -     * 
    - * - *
    -     * Abstract Test 8: /ats/core/conformance-success
    -     * Test Purpose: Validate that the Conformance Declaration response complies with the required structure and contents.
    -     * Requirement: /req/core/conformance-success
    -     *
    -     * Test Method:
    -     *  1. Validate the response document against OpenAPI 3.0 schema confClasses.yaml
    -     *  2. Validate that the document includes the conformance class "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core"
    -     *  3. Validate that the document list all OGC API conformance classes that the API implements.
    -     * 
    - * - * @param testPoint - * the test point to test, never null - */ - @Test(description = "Implements A.2.4. Conformance Path {root}/conformance, Abstract Test 7 + 8 (Requirements /req/core/conformance-op and /req/core/conformance-success)", groups = "conformance", dataProvider = "conformanceUris", dependsOnGroups = "apidefinition") - public void validateConformanceOperationAndResponse( TestPoint testPoint ) { - String testPointUri = new UriBuilder( testPoint ).buildUrl(); - - // Check for dummy data - if (testPointUri.contains("dummydata")) { - throw new RuntimeException("No conformance classes found at the /conformance path."); - } - - Response response = init().baseUri( testPointUri ).accept( JSON ).when().request( GET ); - validateConformanceOperationResponse( testPointUri, response ); - } - - /** - * Abstract Test 8: /ats/core/conformance-success - */ - private void validateConformanceOperationResponse( String testPointUri, Response response ) { - response.then().statusCode( 200 ); - - JsonPath jsonPath = response.jsonPath(); - this.requirementClasses = parseAndValidateRequirementClasses( jsonPath ); - assertTrue( this.requirementClasses.contains( CORE ), - "Requirement class \"http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core\" is not available from path " - + testPointUri ); - } - - /** - * @param jsonPath - * never null - * @return the parsed requirement classes, never null - * @throws AssertionError - * if the json does not follow the expected structure - */ - List parseAndValidateRequirementClasses( JsonPath jsonPath ) { - List conformsTo = jsonPath.getList( "conformsTo" ); - assertNotNull( conformsTo, "Missing member 'conformsTo'." ); - - List requirementClasses = new ArrayList<>(); - for ( Object conformTo : conformsTo ) { - if ( conformTo instanceof String ) { - String conformanceClass = (String) conformTo; - RequirementClass requirementClass = RequirementClass.byConformanceClass( conformanceClass ); - if ( requirementClass != null ) - requirementClasses.add( requirementClass ); - } else - throw new AssertionError( "At least one element array 'conformsTo' is not a string value (" + conformTo - + ")" ); - } - return requirementClasses; - } - -} \ No newline at end of file + private List requirementClasses; + + /** + *

    + * conformanceUris. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return an array of {@link java.lang.Object} objects + */ + @DataProvider(name = "conformanceUris") + public Object[][] conformanceUris(ITestContext testContext) { + OpenApi3 apiModel = (OpenApi3) testContext.getSuite().getAttribute(API_MODEL.getName()); + URI iut = (URI) testContext.getSuite().getAttribute(IUT.getName()); + List testPoints = retrieveTestPointsForConformance(apiModel, iut); + + // Set dummy TestPoint data if no testPoints found. + if (testPoints.isEmpty()) { + testPoints.add(new TestPoint("http://dummydata.com", "/conformance", null)); + } + + Object[][] testPointsData = new Object[testPoints.size()][]; + int i = 0; + for (TestPoint testPoint : testPoints) { + testPointsData[i++] = new Object[] { testPoint }; + } + return testPointsData; + } + + /** + *

    + * storeRequirementClassesInTestContext. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @AfterClass + public void storeRequirementClassesInTestContext(ITestContext testContext) { + testContext.getSuite().setAttribute(REQUIREMENTCLASSES.getName(), this.requirementClasses); + } + + /** + *
    +	 * Abstract Test 7: /ats/core/conformance-op
    +	 * Test Purpose: Validate that a Conformance Declaration can be retrieved from the expected location.
    +	 * Requirement: /req/core/conformance-op
    +	 *
    +	 * Test Method:
    +	 *  1. Construct a path for each "conformance" link on the landing page as well as for the {root}/conformance path.
    +	 *  2. Issue an HTTP GET request on each path
    +	 *  3. Validate that a document was returned with a status code 200
    +	 *  4. Validate the contents of the returned document using test /ats/core/conformance-success.
    +	 * 
    + * + *
    +	 * Abstract Test 8: /ats/core/conformance-success
    +	 * Test Purpose: Validate that the Conformance Declaration response complies with the required structure and contents.
    +	 * Requirement: /req/core/conformance-success
    +	 *
    +	 * Test Method:
    +	 *  1. Validate the response document against OpenAPI 3.0 schema confClasses.yaml
    +	 *  2. Validate that the document includes the conformance class "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core"
    +	 *  3. Validate that the document list all OGC API conformance classes that the API implements.
    +	 * 
    + * @param testPoint the test point to test, never null + */ + @Test(description = "Implements A.2.4. Conformance Path {root}/conformance, Abstract Test 7 + 8 (Requirements /req/core/conformance-op and /req/core/conformance-success)", + groups = "conformance", dataProvider = "conformanceUris", dependsOnGroups = "apidefinition") + public void validateConformanceOperationAndResponse(TestPoint testPoint) { + String testPointUri = new UriBuilder(testPoint).buildUrl(); + + // Check for dummy data + if (testPointUri.contains("dummydata")) { + throw new RuntimeException("No conformance classes found at the /conformance path."); + } + + Response response = init().baseUri(testPointUri).accept(JSON).when().request(GET); + validateConformanceOperationResponse(testPointUri, response); + } + + /** + * Abstract Test 8: /ats/core/conformance-success + */ + private void validateConformanceOperationResponse(String testPointUri, Response response) { + response.then().statusCode(200); + + JsonPath jsonPath = response.jsonPath(); + this.requirementClasses = parseAndValidateRequirementClasses(jsonPath); + assertTrue(this.requirementClasses.contains(CORE), + "Requirement class \"http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core\" is not available from path " + + testPointUri); + } + + /** + * @param jsonPath never null + * @return the parsed requirement classes, never null + * @throws AssertionError if the json does not follow the expected structure + */ + List parseAndValidateRequirementClasses(JsonPath jsonPath) { + List conformsTo = jsonPath.getList("conformsTo"); + assertNotNull(conformsTo, "Missing member 'conformsTo'."); + + List requirementClasses = new ArrayList<>(); + for (Object conformTo : conformsTo) { + if (conformTo instanceof String) { + String conformanceClass = (String) conformTo; + RequirementClass requirementClass = RequirementClass.byConformanceClass(conformanceClass); + if (requirementClass != null) + requirementClasses.add(requirementClass); + } + else + throw new AssertionError( + "At least one element array 'conformsTo' is not a string value (" + conformTo + ")"); + } + return requirementClasses; + } + +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/general/GeneralHttp.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/general/GeneralHttp.java index 48c2861e..47c335e6 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/general/GeneralHttp.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/general/GeneralHttp.java @@ -15,25 +15,25 @@ */ public class GeneralHttp extends CommonFixture { - /** - *
    -     * A.2.1.1. HTTP
    -     *
    -     * Abstract Test 1: /ats/core/http
    -     * Test Purpose: Validate that the resource paths advertised through the API conform with HTTP 1.1 and, where
    -     * appropriate, TLS.
    -     * Requirement: /req/core/http
    -     *
    -     * Test Method:
    -     *  1. All compliance tests shall be configured to use the HTTP 1.1 protocol exclusively.
    -     *  2. For APIs which support HTTPS, all compliance tests shall be configured to use HTTP over TLS (RFC 2818) with
    -     * their HTTP 1.1 protocol. (untested)
    -     * 
    - */ - @Test(description = "Implements A.2.1.1. HTTP, Abstract Test 1 (Requirement /req/core/http)") - public void http() { - Response response = init().baseUri( rootUri.toString() ).when().request( GET, "/" ); - response.then().statusLine( containsString( "HTTP/1.1" ) ); - } + /** + *
    +	 * A.2.1.1. HTTP
    +	 *
    +	 * Abstract Test 1: /ats/core/http
    +	 * Test Purpose: Validate that the resource paths advertised through the API conform with HTTP 1.1 and, where
    +	 * appropriate, TLS.
    +	 * Requirement: /req/core/http
    +	 *
    +	 * Test Method:
    +	 *  1. All compliance tests shall be configured to use the HTTP 1.1 protocol exclusively.
    +	 *  2. For APIs which support HTTPS, all compliance tests shall be configured to use HTTP over TLS (RFC 2818) with
    +	 * their HTTP 1.1 protocol. (untested)
    +	 * 
    + */ + @Test(description = "Implements A.2.1.1. HTTP, Abstract Test 1 (Requirement /req/core/http)") + public void http() { + Response response = init().baseUri(rootUri.toString()).when().request(GET, "/"); + response.then().statusLine(containsString("HTTP/1.1")); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/landingpage/LandingPage.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/landingpage/LandingPage.java index ea0dd588..0650677b 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/landingpage/LandingPage.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/core/landingpage/LandingPage.java @@ -22,61 +22,62 @@ */ public class LandingPage extends CommonFixture { - private JsonPath response; + private JsonPath response; - /** - *
    -     * Abstract Test 3: /ats/core/root-op
    -     * Test Purpose: Validate that a landing page can be retrieved from the expected location.
    -     * Requirement: /req/core/root-op
    -     *
    -     * Test Method:
    -     *  1. Issue an HTTP GET request to the URL {root}/
    -     *  2. Validate that a document was returned with a status code 200
    -     *  3. Validate the contents of the returned document using test /ats/core/root-success.
    -     * 
    - */ - @Test(description = "Implements A.2.2. Landing Page {root}/, Abstract Test 3 (Requirement /req/core/root-op)", groups = "landingpage") - public void landingPageRetrieval() { - Response request = init().baseUri( rootUri.toString() ).accept( JSON ).when().request( GET, "/" ); - request.then().statusCode( 200 ); - response = request.jsonPath(); - } + /** + *
    +	 * Abstract Test 3: /ats/core/root-op
    +	 * Test Purpose: Validate that a landing page can be retrieved from the expected location.
    +	 * Requirement: /req/core/root-op
    +	 *
    +	 * Test Method:
    +	 *  1. Issue an HTTP GET request to the URL {root}/
    +	 *  2. Validate that a document was returned with a status code 200
    +	 *  3. Validate the contents of the returned document using test /ats/core/root-success.
    +	 * 
    + */ + @Test(description = "Implements A.2.2. Landing Page {root}/, Abstract Test 3 (Requirement /req/core/root-op)", + groups = "landingpage") + public void landingPageRetrieval() { + Response request = init().baseUri(rootUri.toString()).accept(JSON).when().request(GET, "/"); + request.then().statusCode(200); + response = request.jsonPath(); + } - /** - *
    -     * Abstract Test 4: /ats/core/root-success
    -     * Test Purpose: Validate that the landing page complies with the require structure and contents.
    -     * Requirement: /req/core/root-success
    -     *
    -     * Test Method: Validate the landing page for all supported media types using the resources and tests identified in
    -     * Schema and Tests for Landing Pages. For formats that require manual inspection, perform the following:
    -     *   a) Validate that the landing page includes a "service-desc" and/or "service-doc" link to an API Definition
    -     *   b) Validate that the landing page includes a "conformance" link to the conformance class declaration
    -     *   c) Validate that the landing page includes a "data" link to the Feature contents.
    -     * 
    - */ - @Test(description = "Implements A.2.2. Landing Page {root}/, Abstract Test 4 (Requirement /req/core/root-success)", groups = "landingpage", dependsOnMethods = "landingPageRetrieval") - public void landingPageValidation() { - List links = response.getList( "links" ); - Set linkTypes = collectLinkTypes( links ); + /** + *
    +	 * Abstract Test 4: /ats/core/root-success
    +	 * Test Purpose: Validate that the landing page complies with the require structure and contents.
    +	 * Requirement: /req/core/root-success
    +	 *
    +	 * Test Method: Validate the landing page for all supported media types using the resources and tests identified in
    +	 * Schema and Tests for Landing Pages. For formats that require manual inspection, perform the following:
    +	 *   a) Validate that the landing page includes a "service-desc" and/or "service-doc" link to an API Definition
    +	 *   b) Validate that the landing page includes a "conformance" link to the conformance class declaration
    +	 *   c) Validate that the landing page includes a "data" link to the Feature contents.
    +	 * 
    + */ + @Test(description = "Implements A.2.2. Landing Page {root}/, Abstract Test 4 (Requirement /req/core/root-success)", + groups = "landingpage", dependsOnMethods = "landingPageRetrieval") + public void landingPageValidation() { + List links = response.getList("links"); + Set linkTypes = collectLinkTypes(links); - boolean expectedLinkTypesExists = ( linkTypes.contains( "service-desc" ) - || linkTypes.contains( "service-doc" ) ) - && linkTypes.contains( "conformance" ) && linkTypes.contains( "data" ); - assertTrue( expectedLinkTypesExists, - "The landing page must include at least links with relation type 'service-desc' or 'service-doc', 'conformance' and 'data', but contains " - + String.join( ", ", linkTypes ) ); - } + boolean expectedLinkTypesExists = (linkTypes.contains("service-desc") || linkTypes.contains("service-doc")) + && linkTypes.contains("conformance") && linkTypes.contains("data"); + assertTrue(expectedLinkTypesExists, + "The landing page must include at least links with relation type 'service-desc' or 'service-doc', 'conformance' and 'data', but contains " + + String.join(", ", linkTypes)); + } - private Set collectLinkTypes( List links ) { - Set linkTypes = new HashSet<>(); - for ( Object link : links ) { - Map linkMap = (Map) link; - Object linkType = linkMap.get( "rel" ); - linkTypes.add( (String) linkType ); - } - return linkTypes; - } + private Set collectLinkTypes(List links) { + Set linkTypes = new HashSet<>(); + for (Object link : links) { + Map linkMap = (Map) link; + Object linkType = linkMap.get("rel"); + linkTypes.add((String) linkType); + } + return linkTypes; + } -} \ No newline at end of file +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/CrsRequirementClassPrecondition.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/CrsRequirementClassPrecondition.java index 56903509..c6634351 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/CrsRequirementClassPrecondition.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/CrsRequirementClassPrecondition.java @@ -13,31 +13,43 @@ import org.testng.annotations.Test; /** + *

    + * CrsRequirementClassPrecondition class. + *

    + * * @author Lyn Goltz */ public class CrsRequirementClassPrecondition { - private List conformanceClasses; - - @BeforeClass - public void conformanceClasses( ITestContext testContext ) { - this.conformanceClasses = (List) testContext.getSuite().getAttribute( REQUIREMENTCLASSES.getName() ); - } - - /** - * Verifies that the referenced implements the conformance class - * http://www.opengis.net/spec/ogcapi-features-2/1.0/conf/crs. - */ - @Test(description = "Precondition: conformance class http://www.opengis.net/spec/ogcapi-features-2/1.0/conf/crs must be implemented", groups = "crs-conformance") - public void verifyConformanceClass() { - boolean conformanceClassIsImplemented = this.conformanceClasses != null - && this.conformanceClasses.contains( CRS ); - if (!conformanceClassIsImplemented) { - throw new SkipException("Conformance class " + CRS.name() - + " is not supported by the test instance. Tests will be skipped." ); - } - assertTrue( conformanceClassIsImplemented, "Conformance class " + CRS.name() - + " is not supported by the test instance. Tests will be skipped." ); - } + private List conformanceClasses; + + /** + *

    + * conformanceClasses. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @BeforeClass + public void conformanceClasses(ITestContext testContext) { + this.conformanceClasses = (List) testContext.getSuite() + .getAttribute(REQUIREMENTCLASSES.getName()); + } + + /** + * Verifies that the referenced implements the conformance class + * http://www.opengis.net/spec/ogcapi-features-2/1.0/conf/crs. + */ + @Test(description = "Precondition: conformance class http://www.opengis.net/spec/ogcapi-features-2/1.0/conf/crs must be implemented", + groups = "crs-conformance") + public void verifyConformanceClass() { + boolean conformanceClassIsImplemented = this.conformanceClasses != null + && this.conformanceClasses.contains(CRS); + if (!conformanceClassIsImplemented) { + throw new SkipException("Conformance class " + CRS.name() + + " is not supported by the test instance. Tests will be skipped."); + } + assertTrue(conformanceClassIsImplemented, + "Conformance class " + CRS.name() + " is not supported by the test instance. Tests will be skipped."); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/AbstractDiscoveryCollection.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/AbstractDiscoveryCollection.java index 11b92bfa..396bb38d 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/AbstractDiscoveryCollection.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/AbstractDiscoveryCollection.java @@ -11,23 +11,35 @@ import java.util.Map; /** + *

    + * AbstractDiscoveryCollection class. + *

    + * * @author Lyn Goltz */ public class AbstractDiscoveryCollection { - @DataProvider(name = "collectionIdAndJson") - public Iterator collectionIdAndJson( ITestContext testContext ) { - Map collectionsResponses = (Map) testContext.getSuite().getAttribute( - SuiteAttribute.COLLECTION_BY_ID.getName() ); - List collectionsData = new ArrayList<>(); - try { - for ( Map.Entry collection : collectionsResponses.entrySet() ) { - collectionsData.add( new Object[] { collection.getKey(), collection.getValue() } ); - } - } catch (Exception e) { - collectionsData.add( new Object[] { null, null } ); - } - return collectionsData.iterator(); - } + /** + *

    + * collectionIdAndJson. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionIdAndJson") + public Iterator collectionIdAndJson(ITestContext testContext) { + Map collectionsResponses = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTION_BY_ID.getName()); + List collectionsData = new ArrayList<>(); + try { + for (Map.Entry collection : collectionsResponses.entrySet()) { + collectionsData.add(new Object[] { collection.getKey(), collection.getValue() }); + } + } + catch (Exception e) { + collectionsData.add(new Object[] { null, null }); + } + return collectionsData.iterator(); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/DiscoveryCollectionCrsUri.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/DiscoveryCollectionCrsUri.java index 3bb4342f..cc7539d0 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/DiscoveryCollectionCrsUri.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/DiscoveryCollectionCrsUri.java @@ -40,107 +40,129 @@ */ public class DiscoveryCollectionCrsUri { - private Map> collectionIdAndValidCrs = new HashMap<>(); + private Map> collectionIdAndValidCrs = new HashMap<>(); - @SuppressWarnings("unchecked") - @DataProvider( - name = "collectionIdAndJsonAndCrs") - public Iterator collectionIdAndJsonAndCrs(ITestContext testContext) throws AssertionError { - List collectionsData = new ArrayList<>(); - try { - Map collectionsResponses = (Map) testContext.getSuite() - .getAttribute(SuiteAttribute.COLLECTION_BY_ID.getName()); - for (Map.Entry collection : collectionsResponses.entrySet()) { - List crs = parseCrs(collection.getValue()); - int count = 0; - for (CoordinateSystem coordinateSystem : crs) { - if (count >= OgcApiFeatures10.CRS_LIMIT) { - break; - } - collectionsData.add(new Object[] { collection.getKey(), coordinateSystem }); - count++; - } - } - } catch (Exception e) { - collectionsData.add(new Object[] { null, null }); - } - return collectionsData.iterator(); - } + /** + *

    + * collectionIdAndJsonAndCrs. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + * @throws java.lang.AssertionError if any. + */ + @SuppressWarnings("unchecked") + @DataProvider(name = "collectionIdAndJsonAndCrs") + public Iterator collectionIdAndJsonAndCrs(ITestContext testContext) throws AssertionError { + List collectionsData = new ArrayList<>(); + try { + Map collectionsResponses = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTION_BY_ID.getName()); + for (Map.Entry collection : collectionsResponses.entrySet()) { + List crs = parseCrs(collection.getValue()); + int count = 0; + for (CoordinateSystem coordinateSystem : crs) { + if (count >= OgcApiFeatures10.CRS_LIMIT) { + break; + } + collectionsData.add(new Object[] { collection.getKey(), coordinateSystem }); + count++; + } + } + } + catch (Exception e) { + collectionsData.add(new Object[] { null, null }); + } + return collectionsData.iterator(); + } - @DataProvider(name = "collectionIdAndJsonAndStorageCrs") - public Iterator collectionIdAndJsonAndStorageCrs( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - try { - Map collectionsResponses = (Map) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTION_BY_ID.getName() ); - for ( Map.Entry collection : collectionsResponses.entrySet() ) { - CoordinateSystem storageCrs = parseStorageCrs( collection.getValue() ); - if ( storageCrs != null ) - collectionsData.add( new Object[] { collection.getKey(), storageCrs } ); - } - } catch (Exception e) { - collectionsData.add( new Object[] { null, null } ); - } - return collectionsData.iterator(); - } + /** + *

    + * collectionIdAndJsonAndStorageCrs. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionIdAndJsonAndStorageCrs") + public Iterator collectionIdAndJsonAndStorageCrs(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + try { + Map collectionsResponses = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTION_BY_ID.getName()); + for (Map.Entry collection : collectionsResponses.entrySet()) { + CoordinateSystem storageCrs = parseStorageCrs(collection.getValue()); + if (storageCrs != null) + collectionsData.add(new Object[] { collection.getKey(), storageCrs }); + } + } + catch (Exception e) { + collectionsData.add(new Object[] { null, null }); + } + return collectionsData.iterator(); + } - @AfterClass - public void storeCollectionInTestContext( ITestContext testContext ) { - testContext.getSuite().setAttribute( SuiteAttribute.COLLECTION_CRS_BY_ID.getName(), collectionIdAndValidCrs ); - } + /** + *

    + * storeCollectionInTestContext. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @AfterClass + public void storeCollectionInTestContext(ITestContext testContext) { + testContext.getSuite().setAttribute(SuiteAttribute.COLLECTION_CRS_BY_ID.getName(), collectionIdAndValidCrs); + } - /** - * Test: crs property in the collection objects in the path /collections - * - * @param collectionId - * id of the collection under test, never null - * @param crs - * the coordinate system, never null - */ - @Test(description = "Implements A.1 Discovery, Abstract Test 1 (Requirement /req/crs/crs-uri, /req/crs/fc-md-crs-list A, /req/crs/fc-md-storageCrs, /req/crs/fc-md-crs-list-global), " - + "crs property in the collection object in the path /collection", dataProvider = "collectionIdAndJsonAndCrs", dependsOnGroups = "crs-conformance", groups = "crs-discovery") - public void verifyCollectionCrsIdentifierOfCrsProperty( String collectionId, CoordinateSystem crs ) { - if((collectionId == null) & (crs == null)) { - throw new AssertionError("No crs information for collection available."); - } - addCrs( collectionId, crs ); - assertValidCrsIdentifier( crs, - String.format( "Collection with id '%s' contains invalid CRS identifier property 'crs': '%s'", - collectionId, crs ) ); - } + /** + * Test: crs property in the collection objects in the path /collections + * @param collectionId id of the collection under test, never null + * @param crs the coordinate system, never null + */ + @Test(description = "Implements A.1 Discovery, Abstract Test 1 (Requirement /req/crs/crs-uri, /req/crs/fc-md-crs-list A, /req/crs/fc-md-storageCrs, /req/crs/fc-md-crs-list-global), " + + "crs property in the collection object in the path /collection", + dataProvider = "collectionIdAndJsonAndCrs", dependsOnGroups = "crs-conformance", groups = "crs-discovery") + public void verifyCollectionCrsIdentifierOfCrsProperty(String collectionId, CoordinateSystem crs) { + if ((collectionId == null) & (crs == null)) { + throw new AssertionError("No crs information for collection available."); + } + addCrs(collectionId, crs); + assertValidCrsIdentifier(crs, String + .format("Collection with id '%s' contains invalid CRS identifier property 'crs': '%s'", collectionId, crs)); + } - /** - * Test: storageCrs property in the collection objects in the path /collections - * - * @param collectionId - * id of the collection under test, never null - * @param storageCrs - * the storageCrs, never null - */ - @Test(description = "Implements A.1 Discovery, Abstract Test 1 (Requirement /req/crs/crs-uri, /req/crs/fc-md-crs-list A, /req/crs/fc-md-storageCrs, /req/crs/fc-md-crs-list-global), " - + "storageCrs property in the collection object in the path /collection", dataProvider = "collectionIdAndJsonAndStorageCrs", dependsOnGroups = "crs-conformance", groups = "crs-discovery") - public void verifyCollectionCrsIdentifierOfStorageCrsProperty( String collectionId, CoordinateSystem storageCrs ) { - if((collectionId == null) & (storageCrs == null)) { - throw new AssertionError("No crs information for collection available."); - } - assertValidCrsIdentifier( storageCrs, - String.format( "Collection with id '%s' contains invalid CRS identifier property 'storageCrs': '%s'", - collectionId, storageCrs ) ); - } + /** + * Test: storageCrs property in the collection objects in the path /collections + * @param collectionId id of the collection under test, never null + * @param storageCrs the storageCrs, never null + */ + @Test(description = "Implements A.1 Discovery, Abstract Test 1 (Requirement /req/crs/crs-uri, /req/crs/fc-md-crs-list A, /req/crs/fc-md-storageCrs, /req/crs/fc-md-crs-list-global), " + + "storageCrs property in the collection object in the path /collection", + dataProvider = "collectionIdAndJsonAndStorageCrs", dependsOnGroups = "crs-conformance", + groups = "crs-discovery") + public void verifyCollectionCrsIdentifierOfStorageCrsProperty(String collectionId, CoordinateSystem storageCrs) { + if ((collectionId == null) & (storageCrs == null)) { + throw new AssertionError("No crs information for collection available."); + } + assertValidCrsIdentifier(storageCrs, + String.format("Collection with id '%s' contains invalid CRS identifier property 'storageCrs': '%s'", + collectionId, storageCrs)); + } - private List parseCrs( JsonPath collection ) { - return JsonUtils.parseAsList( "crs", - collection ).stream().map( crsValue -> new CoordinateSystem( crsValue ) ).collect( Collectors.toList() ); - } + private List parseCrs(JsonPath collection) { + return JsonUtils.parseAsList("crs", collection) + .stream() + .map(crsValue -> new CoordinateSystem(crsValue)) + .collect(Collectors.toList()); + } - private CoordinateSystem parseStorageCrs( JsonPath collection ) { - String storageCrs = JsonUtils.parseAsString( collection.get( "storageCrs" ) ); - if ( storageCrs == null ) - return null; - return new CoordinateSystem( storageCrs ); - } + private CoordinateSystem parseStorageCrs(JsonPath collection) { + String storageCrs = JsonUtils.parseAsString(collection.get("storageCrs")); + if (storageCrs == null) + return null; + return new CoordinateSystem(storageCrs); + } + + private void addCrs(String collectionId, CoordinateSystem coordinateSystem) { + collectionIdAndValidCrs.putIfAbsent(collectionId, new ArrayList<>()); + collectionIdAndValidCrs.get(collectionId).add(coordinateSystem); + } - private void addCrs( String collectionId, CoordinateSystem coordinateSystem ) { - collectionIdAndValidCrs.putIfAbsent( collectionId, new ArrayList<>() ); - collectionIdAndValidCrs.get( collectionId ).add( coordinateSystem ); - } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/DiscoveryCollectionDefaultCrs.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/DiscoveryCollectionDefaultCrs.java index 34474613..3b7d9383 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/DiscoveryCollectionDefaultCrs.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/DiscoveryCollectionDefaultCrs.java @@ -38,33 +38,37 @@ */ public class DiscoveryCollectionDefaultCrs extends AbstractDiscoveryCollection { - private Map collectionIdAndDefaultCrs = new HashMap<>(); + private Map collectionIdAndDefaultCrs = new HashMap<>(); - @AfterClass - public void storeCollectionInTestContext( ITestContext testContext ) { - testContext.getSuite().setAttribute( SuiteAttribute.COLLECTION_DEFAULT_CRS_BY_ID.getName(), - collectionIdAndDefaultCrs ); - } + /** + *

    + * storeCollectionInTestContext. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @AfterClass + public void storeCollectionInTestContext(ITestContext testContext) { + testContext.getSuite() + .setAttribute(SuiteAttribute.COLLECTION_DEFAULT_CRS_BY_ID.getName(), collectionIdAndDefaultCrs); + } + + /** + * Test: crs property in the collection objects in the path /collections + * @param collectionId id of the collection under test, never null + * @param collection the /collection object, never null + */ + @Test(description = "Implements A.1 Discovery, Abstract Test 2 (Requirement /req/crs/fc-md-crs-list B), " + + "crs property contains default crs in the collection object in the path /collection", + dataProvider = "collectionIdAndJson", dependsOnGroups = "crs-conformance", groups = "crs-discovery") + public void verifyCollectionCrsIdentifierOfCrsProperty(String collectionId, JsonPath collection) { + Object extent = collection.get("extent"); + if (hasAtLeastOneSpatialFeatureCollection(extent)) { + List crs = JsonUtils.parseAsList("crs", collection); + CoordinateSystem defaultCrs = assertDefaultCrs(crs, String.format( + "Collection with id '%s' does not specify one of the default CRS '%s' or '%s' but provides at least one spatial feature collections", + collectionId, DEFAULT_CRS_CODE, DEFAULT_CRS_WITH_HEIGHT_CODE)); + collectionIdAndDefaultCrs.put(collectionId, defaultCrs); + } + } - /** - * Test: crs property in the collection objects in the path /collections - * - * @param collectionId - * id of the collection under test, never null - * @param collection - * the /collection object, never null - */ - @Test(description = "Implements A.1 Discovery, Abstract Test 2 (Requirement /req/crs/fc-md-crs-list B), " - + "crs property contains default crs in the collection object in the path /collection", dataProvider = "collectionIdAndJson", dependsOnGroups = "crs-conformance", groups = "crs-discovery") - public void verifyCollectionCrsIdentifierOfCrsProperty( String collectionId, JsonPath collection ) { - Object extent = collection.get( "extent" ); - if ( hasAtLeastOneSpatialFeatureCollection( extent ) ) { - List crs = JsonUtils.parseAsList( "crs", collection ); - CoordinateSystem defaultCrs = assertDefaultCrs( crs, - String.format( "Collection with id '%s' does not specify one of the default CRS '%s' or '%s' but provides at least one spatial feature collections", - collectionId, DEFAULT_CRS_CODE, - DEFAULT_CRS_WITH_HEIGHT_CODE ) ); - collectionIdAndDefaultCrs.put( collectionId, defaultCrs ); - } - } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/DiscoveryCollectionStorageCrs.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/DiscoveryCollectionStorageCrs.java index 57c535e7..4644c687 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/DiscoveryCollectionStorageCrs.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collection/DiscoveryCollectionStorageCrs.java @@ -24,26 +24,26 @@ */ public class DiscoveryCollectionStorageCrs extends AbstractDiscoveryCollection { - /** - * Test: storageCrs property in the collection objects in the path /collections - * - * @param collectionId - * id of the collection under test, never null - * @param collection - * the /collection object, never null - */ - @Test(description = "Implements A.1 Discovery, Abstract Test 3 (Requirement /req/crs/fc-md-storageCrs-valid-value), " - + "storageCrs property in the collection object in the path /collection", dataProvider = "collectionIdAndJson", dependsOnGroups = "crs-conformance") - public void verifyCollectionCrsIdentifierOfCrsProperty( String collectionId, JsonPath collection ) { - String storageCrs = collection.get( "storageCrs" ); - if ( storageCrs == null ) { - throw new SkipException( String.format( "Collection with id '%s' does not specify a storageCrs", - collectionId ) ); - } - List crs = JsonUtils.parseAsList( "crs", collection ); - if ( !crs.contains( storageCrs ) ) { - throw new AssertionError( String.format( "Collection with id '%s' specifies the storageCrs '%s' which is not declared as crs property", - collectionId, storageCrs ) ); - } - } + /** + * Test: storageCrs property in the collection objects in the path /collections + * @param collectionId id of the collection under test, never null + * @param collection the /collection object, never null + */ + @Test(description = "Implements A.1 Discovery, Abstract Test 3 (Requirement /req/crs/fc-md-storageCrs-valid-value), " + + "storageCrs property in the collection object in the path /collection", + dataProvider = "collectionIdAndJson", dependsOnGroups = "crs-conformance") + public void verifyCollectionCrsIdentifierOfCrsProperty(String collectionId, JsonPath collection) { + String storageCrs = collection.get("storageCrs"); + if (storageCrs == null) { + throw new SkipException( + String.format("Collection with id '%s' does not specify a storageCrs", collectionId)); + } + List crs = JsonUtils.parseAsList("crs", collection); + if (!crs.contains(storageCrs)) { + throw new AssertionError(String.format( + "Collection with id '%s' specifies the storageCrs '%s' which is not declared as crs property", + collectionId, storageCrs)); + } + } + } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/AbstractDiscoveryCollections.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/AbstractDiscoveryCollections.java index 026e878e..ebd80414 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/AbstractDiscoveryCollections.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/AbstractDiscoveryCollections.java @@ -15,39 +15,65 @@ import io.restassured.path.json.JsonPath; /** + *

    + * AbstractDiscoveryCollections class. + *

    + * * @author Lyn Goltz */ public class AbstractDiscoveryCollections extends CommonDataFixture { - private Map collectionsResponses; - - private List> collections; - - @BeforeClass - public void retrieveRequiredInformationFromTestContext( ITestContext testContext ) { - this.collectionsResponses = (Map) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTIONS_RESPONSE.getName() ); - this.collections = (List>) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTIONS.getName() ); - } - - @DataProvider(name = "collectionsResponses") - public Iterator collectionsResponses( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - for ( Map.Entry collectionsResponse : collectionsResponses.entrySet() ) { - collectionsData.add( new Object[] { collectionsResponse.getKey(), collectionsResponse.getValue() } ); - } - return collectionsData.iterator(); - } - - @DataProvider(name = "collectionItemUris") - public Iterator collectionItemUris( ITestContext testContext ) { - // First test point is used! This may be simplified. - TestPoint testPoint = collectionsResponses.keySet().stream().findFirst().get(); - JsonPath jsonPath = collectionsResponses.get( testPoint ); - List collectionsData = new ArrayList<>(); - for ( Map collection : collections ) { - collectionsData.add( new Object[] { testPoint, jsonPath, collection } ); - } - return collectionsData.iterator(); - } + private Map collectionsResponses; + + private List> collections; + + /** + *

    + * retrieveRequiredInformationFromTestContext. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @BeforeClass + public void retrieveRequiredInformationFromTestContext(ITestContext testContext) { + this.collectionsResponses = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTIONS_RESPONSE.getName()); + this.collections = (List>) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTIONS.getName()); + } + + /** + *

    + * collectionsResponses. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionsResponses") + public Iterator collectionsResponses(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + for (Map.Entry collectionsResponse : collectionsResponses.entrySet()) { + collectionsData.add(new Object[] { collectionsResponse.getKey(), collectionsResponse.getValue() }); + } + return collectionsData.iterator(); + } + + /** + *

    + * collectionItemUris. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionItemUris") + public Iterator collectionItemUris(ITestContext testContext) { + // First test point is used! This may be simplified. + TestPoint testPoint = collectionsResponses.keySet().stream().findFirst().get(); + JsonPath jsonPath = collectionsResponses.get(testPoint); + List collectionsData = new ArrayList<>(); + for (Map collection : collections) { + collectionsData.add(new Object[] { testPoint, jsonPath, collection }); + } + return collectionsData.iterator(); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsCrsUri.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsCrsUri.java index 40a08b54..0807d75e 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsCrsUri.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsCrsUri.java @@ -14,7 +14,7 @@ /** * Verifies objects in the paths /collections - * + * *
      * Abstract Test 1:  /conf/crs/crs-uri
      * Test Purpose: Verify that each CRS identifier is a valid value
    @@ -32,103 +32,93 @@
      */
     public class DiscoveryCollectionsCrsUri extends AbstractDiscoveryCollections {
     
    -    /**
    -     * Test: crs property in the collections object in the path /collections
    -     * 
    -     * @param testPoint
    -     *            test point to test, never null
    -     * @param jsonPath
    -     *            the /collections JSON, never null
    -     */
    -    @Test(description = "Implements A.1 Discovery, Abstract Test 1 (Requirement /req/crs/crs-uri, /req/crs/fc-md-crs-list A, /req/crs/fc-md-storageCrs, /req/crs/fc-md-crs-list-global), "
    -                        + "crs property in the collections object in the path /collections", dataProvider = "collectionsResponses", dependsOnGroups = "crs-conformance")
    -    public void verifyCollectionsCrsIdentifierOfCrsProperty( TestPoint testPoint, JsonPath jsonPath ) {
    -        List crs = JsonUtils.parseAsList( "crs", jsonPath );
    -        for ( String crsValue : crs ) {
    -            if ( crsValue != null ) {
    -                assertValidCrsIdentifier( new CoordinateSystem( crsValue ),
    -                                          String.format( "Collections path %s contains invalid CRS identifier property 'crs': '%s'",
    -                                                         testPoint.getPath(), crsValue ) );
    -            }
    -        }
    -    }
    +	/**
    +	 * Test: crs property in the collections object in the path /collections
    +	 * @param testPoint test point to test, never null
    +	 * @param jsonPath the /collections JSON, never null
    +	 */
    +	@Test(description = "Implements A.1 Discovery, Abstract Test 1 (Requirement /req/crs/crs-uri, /req/crs/fc-md-crs-list A, /req/crs/fc-md-storageCrs, /req/crs/fc-md-crs-list-global), "
    +			+ "crs property in the collections object in the path /collections", dataProvider = "collectionsResponses",
    +			dependsOnGroups = "crs-conformance")
    +	public void verifyCollectionsCrsIdentifierOfCrsProperty(TestPoint testPoint, JsonPath jsonPath) {
    +		List crs = JsonUtils.parseAsList("crs", jsonPath);
    +		for (String crsValue : crs) {
    +			if (crsValue != null) {
    +				assertValidCrsIdentifier(new CoordinateSystem(crsValue),
    +						String.format("Collections path %s contains invalid CRS identifier property 'crs': '%s'",
    +								testPoint.getPath(), crsValue));
    +			}
    +		}
    +	}
     
    -    /**
    -     * Test: storageCrs property in the collections object in the path /collections
    -     *
    -     * @param testPoint
    -     *            test point to test, never null
    -     * @param jsonPath
    -     *            the /collections JSON, never null
    -     */
    -    @Test(description = "Implements A.1 Discovery, Abstract Test 1 (Requirement /req/crs/crs-uri, /req/crs/fc-md-crs-list A, /req/crs/fc-md-storageCrs, /req/crs/fc-md-crs-list-global), "
    -                        + "storageCrs property in the collections object in the path /collections", dataProvider = "collectionsResponses", dependsOnGroups = "crs-conformance")
    -    public void verifyCollectionsCrsIdentifierOfStorageCrs( TestPoint testPoint, JsonPath jsonPath ) {
    -        String crs = JsonUtils.parseAsString( jsonPath.get( "storageCrs" ) );
    -        if ( crs != null ) {
    -            assertValidCrsIdentifier( new CoordinateSystem( crs ),
    -                                      String.format( "Collections path %s contains invalid CRS identifier property 'storageCrs': '%s'",
    -                                                     testPoint.getPath(), crs ) );
    -        }
    -    }
    +	/**
    +	 * Test: storageCrs property in the collections object in the path /collections
    +	 * @param testPoint test point to test, never null
    +	 * @param jsonPath the /collections JSON, never null
    +	 */
    +	@Test(description = "Implements A.1 Discovery, Abstract Test 1 (Requirement /req/crs/crs-uri, /req/crs/fc-md-crs-list A, /req/crs/fc-md-storageCrs, /req/crs/fc-md-crs-list-global), "
    +			+ "storageCrs property in the collections object in the path /collections",
    +			dataProvider = "collectionsResponses", dependsOnGroups = "crs-conformance")
    +	public void verifyCollectionsCrsIdentifierOfStorageCrs(TestPoint testPoint, JsonPath jsonPath) {
    +		String crs = JsonUtils.parseAsString(jsonPath.get("storageCrs"));
    +		if (crs != null) {
    +			assertValidCrsIdentifier(new CoordinateSystem(crs),
    +					String.format("Collections path %s contains invalid CRS identifier property 'storageCrs': '%s'",
    +							testPoint.getPath(), crs));
    +		}
    +	}
     
    -    /**
    -     * Test: crs property in the collection objects in the path /collections
    -     *
    -     * @param testPoint
    -     *            test point to test, never null
    -     * @param jsonPath
    -     *            the /collections JSON, never null
    -     * @param collection
    -     *            the /collection object, never null
    -     */
    -    @Test(description = "Implements A.1 Discovery, Abstract Test 1 (Requirement /req/crs/crs-uri, /req/crs/fc-md-crs-list A, /req/crs/fc-md-storageCrs, /req/crs/fc-md-crs-list-global), "
    -                        + "crs property in the collection objects in the path /collections", dataProvider = "collectionItemUris", dependsOnGroups = "crs-conformance")
    -    public void verifyCollectionsCollectionCrsIdentifierOfCrsProperty( TestPoint testPoint, JsonPath jsonPath,
    -                                                                       Map collection ) {
    -        boolean collectionsHasCrsProperty = isCollectionsHasCrsProperty( jsonPath );
    -        String collectionId = (String) collection.get( "id" );
    -        List crs = JsonUtils.parseAsList( "crs", collection );
    -        for ( String crsValue : crs ) {
    -            isValidCRs( testPoint, collectionsHasCrsProperty, collectionId, crsValue, "crs" );
    -        }
    -    }
    +	/**
    +	 * Test: crs property in the collection objects in the path /collections
    +	 * @param testPoint test point to test, never null
    +	 * @param jsonPath the /collections JSON, never null
    +	 * @param collection the /collection object, never null
    +	 */
    +	@Test(description = "Implements A.1 Discovery, Abstract Test 1 (Requirement /req/crs/crs-uri, /req/crs/fc-md-crs-list A, /req/crs/fc-md-storageCrs, /req/crs/fc-md-crs-list-global), "
    +			+ "crs property in the collection objects in the path /collections", dataProvider = "collectionItemUris",
    +			dependsOnGroups = "crs-conformance")
    +	public void verifyCollectionsCollectionCrsIdentifierOfCrsProperty(TestPoint testPoint, JsonPath jsonPath,
    +			Map collection) {
    +		boolean collectionsHasCrsProperty = isCollectionsHasCrsProperty(jsonPath);
    +		String collectionId = (String) collection.get("id");
    +		List crs = JsonUtils.parseAsList("crs", collection);
    +		for (String crsValue : crs) {
    +			isValidCRs(testPoint, collectionsHasCrsProperty, collectionId, crsValue, "crs");
    +		}
    +	}
     
    -    /**
    -     * Test: storageCrs property in the collection objects in the path /collections
    -     *
    -     * @param testPoint
    -     *            test point to test, never null
    -     * @param jsonPath
    -     *            the /collections JSON, never null
    -     * @param collection
    -     *            the /collection object, never null
    -     */
    -    @Test(description = "Implements A.1 Discovery, Abstract Test 1 (Requirement /req/crs/crs-uri, /req/crs/fc-md-crs-list A, /req/crs/fc-md-storageCrs, /req/crs/fc-md-crs-list-global), "
    -                        + "storageCrs property in the collection objects in the path /collections", dataProvider = "collectionItemUris", dependsOnGroups = "crs-conformance")
    -    public void verifyCollectionsCollectionCrsIdentifierOfStorageCrs( TestPoint testPoint, JsonPath jsonPath,
    -                                                                      Map collection ) {
    -        boolean collectionsHasCrsProperty = isCollectionsHasCrsProperty( jsonPath );
    -        String collectionId = (String) collection.get( "id" );
    -        List crs = JsonUtils.parseAsList( "storageCrs", collection );
    -        for ( String crsValue : crs ) {
    -            isValidCRs( testPoint, collectionsHasCrsProperty, collectionId, crsValue, "storageCrs" );
    -        }
    -    }
    +	/**
    +	 * Test: storageCrs property in the collection objects in the path /collections
    +	 * @param testPoint test point to test, never null
    +	 * @param jsonPath the /collections JSON, never null
    +	 * @param collection the /collection object, never null
    +	 */
    +	@Test(description = "Implements A.1 Discovery, Abstract Test 1 (Requirement /req/crs/crs-uri, /req/crs/fc-md-crs-list A, /req/crs/fc-md-storageCrs, /req/crs/fc-md-crs-list-global), "
    +			+ "storageCrs property in the collection objects in the path /collections",
    +			dataProvider = "collectionItemUris", dependsOnGroups = "crs-conformance")
    +	public void verifyCollectionsCollectionCrsIdentifierOfStorageCrs(TestPoint testPoint, JsonPath jsonPath,
    +			Map collection) {
    +		boolean collectionsHasCrsProperty = isCollectionsHasCrsProperty(jsonPath);
    +		String collectionId = (String) collection.get("id");
    +		List crs = JsonUtils.parseAsList("storageCrs", collection);
    +		for (String crsValue : crs) {
    +			isValidCRs(testPoint, collectionsHasCrsProperty, collectionId, crsValue, "storageCrs");
    +		}
    +	}
     
    -    private boolean isCollectionsHasCrsProperty( JsonPath jsonPath ) {
    -        List collectionsCrs = jsonPath.getList( "crs" );
    -        return collectionsCrs != null && !collectionsCrs.isEmpty();
    -    }
    +	private boolean isCollectionsHasCrsProperty(JsonPath jsonPath) {
    +		List collectionsCrs = jsonPath.getList("crs");
    +		return collectionsCrs != null && !collectionsCrs.isEmpty();
    +	}
     
    -    private void isValidCRs( TestPoint testPoint, boolean collectionsHasCrsProperty, String collectionId,
    -                             String crsValue, String propertyName ) {
    -        if ( "#/crs".equals( crsValue ) && collectionsHasCrsProperty ) {
    -            return;
    -        }
    -        assertValidCrsIdentifier( new CoordinateSystem( crsValue ),
    -                                  String.format( "Collection with id '%s' at collections path %s contains invalid CRS identifier property '%s': '%s'",
    -                                                 collectionId, testPoint.getPath(), propertyName, crsValue ) );
    -    }
    +	private void isValidCRs(TestPoint testPoint, boolean collectionsHasCrsProperty, String collectionId,
    +			String crsValue, String propertyName) {
    +		if ("#/crs".equals(crsValue) && collectionsHasCrsProperty) {
    +			return;
    +		}
    +		assertValidCrsIdentifier(new CoordinateSystem(crsValue), String.format(
    +				"Collection with id '%s' at collections path %s contains invalid CRS identifier property '%s': '%s'",
    +				collectionId, testPoint.getPath(), propertyName, crsValue));
    +	}
     
     }
    diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsDefaultCrs.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsDefaultCrs.java
    index 945cdc7c..69c878b0 100644
    --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsDefaultCrs.java
    +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsDefaultCrs.java
    @@ -31,43 +31,41 @@
      * http://www.opengis.net/def/crs/OGC/1.3/CRS84h
      * is included in the array, if the collection has a spatial extent, i.e., is a spatial feature collection.
      * 
    - * + * * @author Lyn Goltz */ public class DiscoveryCollectionsDefaultCrs extends AbstractDiscoveryCollections { - /** - * Test: crs property in the collection objects in the path /collections - * - * @param testPoint - * test point to test, never null - * @param jsonPath - * the /collections JSON, never null - * @param collection - * the /collection object, never null - */ - @Test(description = "Implements A.1 Discovery, Abstract Test 2 (Requirement /req/crs/fc-md-crs-list B), " - + "crs property contains default crs in the collection objects in the path /collections", dataProvider = "collectionItemUris", dependsOnGroups = "crs-conformance") - public void verifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs( TestPoint testPoint, JsonPath jsonPath, - Map collection ) { - if ( hasAtLeastOneSpatialFeatureCollection( collection ) ) { - String collectionId = (String) collection.get( "id" ); - List crs = JsonUtils.parseAsList( "crs", collection ); - if(crs.contains("#/crs")) { - List globalCrsList = JsonUtils.parseAsList( "crs", jsonPath ); - List expandedCrs = Stream.of(crs, globalCrsList).flatMap(List::stream) - .filter(code -> !"#/crs".equals(code)).collect(Collectors.toList()); - assertDefaultCrs( expandedCrs, - String.format( "Collection with id '%s' at collections path %s references to global crs section but provides at least one spatial feature collections. The global crs section does not specify one of the default CRS '%s' or '%s'", - collectionId, testPoint.getPath(), DEFAULT_CRS_CODE, - DEFAULT_CRS_WITH_HEIGHT_CODE ) ); - } else { - assertDefaultCrs( crs, - String.format( "Collection with id '%s' at collections path %s does not specify one of the default CRS '%s' or '%s' but provides at least one spatial feature collections", - collectionId, testPoint.getPath(), DEFAULT_CRS_CODE, - DEFAULT_CRS_WITH_HEIGHT_CODE ) ); - } - } - } + /** + * Test: crs property in the collection objects in the path /collections + * @param testPoint test point to test, never null + * @param jsonPath the /collections JSON, never null + * @param collection the /collection object, never null + */ + @Test(description = "Implements A.1 Discovery, Abstract Test 2 (Requirement /req/crs/fc-md-crs-list B), " + + "crs property contains default crs in the collection objects in the path /collections", + dataProvider = "collectionItemUris", dependsOnGroups = "crs-conformance") + public void verifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs(TestPoint testPoint, JsonPath jsonPath, + Map collection) { + if (hasAtLeastOneSpatialFeatureCollection(collection)) { + String collectionId = (String) collection.get("id"); + List crs = JsonUtils.parseAsList("crs", collection); + if (crs.contains("#/crs")) { + List globalCrsList = JsonUtils.parseAsList("crs", jsonPath); + List expandedCrs = Stream.of(crs, globalCrsList) + .flatMap(List::stream) + .filter(code -> !"#/crs".equals(code)) + .collect(Collectors.toList()); + assertDefaultCrs(expandedCrs, String.format( + "Collection with id '%s' at collections path %s references to global crs section but provides at least one spatial feature collections. The global crs section does not specify one of the default CRS '%s' or '%s'", + collectionId, testPoint.getPath(), DEFAULT_CRS_CODE, DEFAULT_CRS_WITH_HEIGHT_CODE)); + } + else { + assertDefaultCrs(crs, String.format( + "Collection with id '%s' at collections path %s does not specify one of the default CRS '%s' or '%s' but provides at least one spatial feature collections", + collectionId, testPoint.getPath(), DEFAULT_CRS_CODE, DEFAULT_CRS_WITH_HEIGHT_CODE)); + } + } + } -} \ No newline at end of file +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsStorageCrs.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsStorageCrs.java index 1eae8972..cae0f4ef 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsStorageCrs.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsStorageCrs.java @@ -26,40 +26,41 @@ */ public class DiscoveryCollectionsStorageCrs extends AbstractDiscoveryCollections { - /** - * Test: storageCrs property in the collection objects in the path /collections - * - * @param testPoint - * test point to test, never null - * @param jsonPath - * the /collections JSON, never null - * @param collection - * the /collection object, never null - */ - @Test(description = "Implements A.1 Discovery, Abstract Test 2 (Requirement /req/crs/fc-md-storageCrs-valid-value), " - + "storageCrs property in the collection objects in the path /collections", dataProvider = "collectionItemUris", dependsOnGroups = "crs-conformance") - public void verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs( TestPoint testPoint, JsonPath jsonPath, - Map collection ) { - String collectionId = (String) collection.get( "id" ); - String storageCrs = (String) collection.get( "storageCrs" ); - if ( storageCrs == null ) { - throw new SkipException( String.format( "Collection with id '%s' at collections path %s does not specify a storageCrs", - collectionId, testPoint.getPath() ) ); - } - List crs = JsonUtils.parseAsList( "crs", collection ); + /** + * Test: storageCrs property in the collection objects in the path /collections + * @param testPoint test point to test, never null + * @param jsonPath the /collections JSON, never null + * @param collection the /collection object, never null + */ + @Test(description = "Implements A.1 Discovery, Abstract Test 2 (Requirement /req/crs/fc-md-storageCrs-valid-value), " + + "storageCrs property in the collection objects in the path /collections", + dataProvider = "collectionItemUris", dependsOnGroups = "crs-conformance") + public void verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(TestPoint testPoint, JsonPath jsonPath, + Map collection) { + String collectionId = (String) collection.get("id"); + String storageCrs = (String) collection.get("storageCrs"); + if (storageCrs == null) { + throw new SkipException( + String.format("Collection with id '%s' at collections path %s does not specify a storageCrs", + collectionId, testPoint.getPath())); + } + List crs = JsonUtils.parseAsList("crs", collection); - if ( !crs.contains( storageCrs ) ) { - if( crs.contains("#/crs") ) { - List globalCrsList = JsonUtils.parseAsList( "crs", jsonPath ); - if ( !globalCrsList.contains( storageCrs ) ) { - throw new AssertionError( String.format( "Collection with id '%s' at collections path %s specifies the storageCrs '%s' which is not declared in the global list of CRSs", - collectionId, testPoint.getPath(), storageCrs ) ); - } - } else { - throw new AssertionError( String.format( "Collection with id '%s' at collections path %s specifies the storageCrs '%s' which is not declared as crs property", - collectionId, testPoint.getPath(), storageCrs ) ); - } - } - } + if (!crs.contains(storageCrs)) { + if (crs.contains("#/crs")) { + List globalCrsList = JsonUtils.parseAsList("crs", jsonPath); + if (!globalCrsList.contains(storageCrs)) { + throw new AssertionError(String.format( + "Collection with id '%s' at collections path %s specifies the storageCrs '%s' which is not declared in the global list of CRSs", + collectionId, testPoint.getPath(), storageCrs)); + } + } + else { + throw new AssertionError(String.format( + "Collection with id '%s' at collections path %s specifies the storageCrs '%s' which is not declared as crs property", + collectionId, testPoint.getPath(), storageCrs)); + } + } + } -} \ No newline at end of file +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/AbstractBBoxCrs.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/AbstractBBoxCrs.java index 92332f57..98460c10 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/AbstractBBoxCrs.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/AbstractBBoxCrs.java @@ -17,38 +17,53 @@ import io.restassured.path.json.JsonPath; /** + *

    + * AbstractBBoxCrs class. + *

    + * * @author Lyn Goltz */ public class AbstractBBoxCrs extends CommonFixture { - public static final String BBOX_PARAM = "bbox"; + /** Constant BBOX_PARAM="bbox" */ + public static final String BBOX_PARAM = "bbox"; - public static final String BBOX_CRS_PARAM = "bbox-crs"; + /** Constant BBOX_CRS_PARAM="bbox-crs" */ + public static final String BBOX_CRS_PARAM = "bbox-crs"; - protected Map collectionsResponses; + protected Map collectionsResponses; - protected Map> collectionIdToCrs; + protected Map> collectionIdToCrs; - protected Map collectionIdToDefaultCrs; + protected Map collectionIdToDefaultCrs; - @BeforeClass - public void retrieveRequiredInformationFromTestContext( ITestContext testContext ) { - this.collectionsResponses = (Map) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTION_BY_ID.getName() ); - this.collectionIdToCrs = (Map>) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTION_CRS_BY_ID.getName() ); - this.collectionIdToDefaultCrs = (Map) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTION_DEFAULT_CRS_BY_ID.getName() ); - } + /** + *

    + * retrieveRequiredInformationFromTestContext. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @BeforeClass + public void retrieveRequiredInformationFromTestContext(ITestContext testContext) { + this.collectionsResponses = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTION_BY_ID.getName()); + this.collectionIdToCrs = (Map>) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTION_CRS_BY_ID.getName()); + this.collectionIdToDefaultCrs = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTION_DEFAULT_CRS_BY_ID.getName()); + } - void assertSameFeatures( JsonPath responseWithBBox, JsonPath responseWithoutBBox ) { - List responseWithBBoxIds = parseFeatureIds( responseWithBBox ); - List responseWithoutBBoxIds = parseFeatureIds( responseWithoutBBox ); - assertTrue( responseWithoutBBoxIds.containsAll(responseWithBBoxIds) ); - } + void assertSameFeatures(JsonPath responseWithBBox, JsonPath responseWithoutBBox) { + List responseWithBBoxIds = parseFeatureIds(responseWithBBox); + List responseWithoutBBoxIds = parseFeatureIds(responseWithoutBBox); + assertTrue(responseWithoutBBoxIds.containsAll(responseWithBBoxIds)); + } - private List parseFeatureIds( JsonPath responseWithBBox ) { - List> features = responseWithBBox.getList( "features" ); - if ( features == null ) - return Collections.emptyList(); - return features.stream().map( feature -> parseAsString( feature.get( "id" ) ) ).collect( Collectors.toList() ); - } + private List parseFeatureIds(JsonPath responseWithBBox) { + List> features = responseWithBBox.getList("features"); + if (features == null) + return Collections.emptyList(); + return features.stream().map(feature -> parseAsString(feature.get("id"))).collect(Collectors.toList()); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameter.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameter.java index 09c49647..746179f9 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameter.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameter.java @@ -37,127 +37,154 @@ */ public class BBoxCrsParameter extends AbstractBBoxCrs { - private Map collectionIdToResponseWithDefaultCRs = new HashMap<>(); - - private Map collectionIdToSpatialExtent = new HashMap(); - - @DataProvider(name = "collectionDefaultCrs") - public Iterator collectionDefaultCrs( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - try { - for ( Map.Entry collection : collectionsResponses.entrySet() ) { - String collectionId = collection.getKey(); - JsonPath json = collection.getValue(); - CoordinateSystem defaultCrs = collectionIdToDefaultCrs.get( collectionId ); - if ( defaultCrs != null ) { - collectionsData.add( new Object[] { collectionId, json, defaultCrs } ); - } - } - } catch (Exception e) { - collectionsData.add( new Object[] { null, null, null } ); - } - return collectionsData.iterator(); - } - - @DataProvider(name = "collectionCrsAndDefaultCrs") - public Iterator collectionCrs( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - try { - for ( Map.Entry collection : collectionsResponses.entrySet() ) { - String collectionId = collection.getKey(); - JsonPath json = collection.getValue(); - CoordinateSystem defaultCrs = collectionIdToDefaultCrs.get( collectionId ); - if ( defaultCrs != null ) { - for ( CoordinateSystem crs : collectionIdToCrs.get( collectionId ) ) { - collectionsData.add( new Object[] { collectionId, json, crs, defaultCrs } ); - } - } - } - } catch (Exception e) { - collectionsData.add( new Object[] { null, null, null, null } ); - } - return collectionsData.iterator(); - } - - /** - * @param collectionId - * the id of the collection, never null - * @param collection - * the /collection object, never null - * @param defaultCrs - * the defaultCrs of the collection, never null - */ - @Test(description = "Implements A.2.2 Query, Parameter bbox-crs, Abstract Test 8 (Requirement /req/crs/fc-bbox-crs-definition, /req/crs/bbox-crs-action)", dataProvider = "collectionDefaultCrs", dependsOnGroups = "crs-conformance", priority = 1) - public void verifyBboxCrsParameterWithDefaultCrs( String collectionId, JsonPath collection, - CoordinateSystem defaultCrs ) { - if((collectionId == null) & (collection == null) & (defaultCrs == null)) { - throw new AssertionError("No crs information for collection available."); - } - String featuredUrl = JsonUtils.findFeaturesUrlForGeoJson( rootUri, collection ); - if ( featuredUrl == null ) - throw new SkipException( String.format( "Could not find url for collection with id %s supporting GeoJson (type 5s)", - collectionId, GEOJSON_MIME_TYPE ) ); - BBox bbox = parseSpatialExtent( collection.get() ); - if ( bbox == null ) - throw new SkipException( String.format( "Collection with id %s has no spatial extent", collectionId ) ); - GeometryTransformer geometryTransformer = new GeometryTransformer( bbox.getCrs(), defaultCrs ); - BBox transformedBboxInDefaultCrs = geometryTransformer.transform( bbox ); - String bboxParameterValueDefaultCrs = transformedBboxInDefaultCrs.asQueryParameter(); - Response response = init().baseUri( featuredUrl ).accept( GEOJSON_MIME_TYPE ).param( BBOX_PARAM, - bboxParameterValueDefaultCrs ).when().request( Method.GET ); - response.then().statusCode( 200 ); - - collectionIdToResponseWithDefaultCRs.put( collectionId, response ); - collectionIdToSpatialExtent.put( collectionId, bbox ); - - } - - /** - * @param collectionId - * the id of the collection, never null - * @param collection - * the /collection object, never null - * @param crs - * the crs to test, never null - * @param defaultCrs - * the defaultCrs of the collection, never null - */ - @Test(description = "Implements A.2.2 Query, Parameter bbox-crs, Abstract Test 8 (Requirement /req/crs/fc-bbox-crs-definition, /req/crs/bbox-crs-action)", dataProvider = "collectionCrsAndDefaultCrs", dependsOnGroups = "crs-conformance", dependsOnMethods = "verifyBboxCrsParameterWithDefaultCrs", priority = 1) - public void verifyBboxCrsParameter( String collectionId, JsonPath collection, CoordinateSystem crs, - CoordinateSystem defaultCrs ) { - if((collectionId == null) & (collection == null) & (crs == null) & (defaultCrs == null)) { - throw new AssertionError("No crs information for collection available."); - } - if ( !collectionIdToResponseWithDefaultCRs.containsKey( collectionId ) ) - throw new SkipException( String.format( "Collection with id %s could not be requested with bbox in default crs", - collectionId ) ); - String featuredUrl = JsonUtils.findFeaturesUrlForGeoJson( rootUri, collection ); - if ( featuredUrl == null ) - throw new SkipException( String.format( "Could not find url for collection with id %s supporting GeoJson (type 5s)", - collectionId, GEOJSON_MIME_TYPE ) ); - BBox bbox = collectionIdToSpatialExtent.get( collectionId ); - GeometryTransformer geometryTransformer = new GeometryTransformer( bbox.getCrs(), crs ); - - //https://github.com/opengeospatial/ets-ogcapi-features10/issues/199 - //Transforming the maximum extent in WGS 84 to another CRS can cause problems. - //In that case, we make the extent a bit smaller. - BBox maxExtent = new BBox(-180, -90, 180, 90); - - if(bbox.equals(maxExtent)) { - if(!(crs.getCode().equals("http://www.opengis.net/def/crs/EPSG/0/4326") || crs.getCode().equals("http://www.opengis.net/def/crs/OGC/1.3/CRS84"))) { - bbox = new BBox(-175, -85, 175, 85); - } - } - - BBox transformedBbox = geometryTransformer.transform( bbox ); - - Response response = init().baseUri( featuredUrl ).param( BBOX_CRS_PARAM, - transformedBbox.getCrs().getCode() ).param( BBOX_PARAM, - transformedBbox.asQueryParameter() ).accept( GEOJSON_MIME_TYPE ).when().request( Method.GET ); - response.then().statusCode( 200 ); - - Response responseWithBBoxInDefaultCrs = collectionIdToResponseWithDefaultCRs.get( collectionId ); - assertSameFeatures( response.jsonPath(), responseWithBBoxInDefaultCrs.jsonPath() ); - } + private Map collectionIdToResponseWithDefaultCRs = new HashMap<>(); + + private Map collectionIdToSpatialExtent = new HashMap(); + + /** + *

    + * collectionDefaultCrs. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionDefaultCrs") + public Iterator collectionDefaultCrs(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + try { + for (Map.Entry collection : collectionsResponses.entrySet()) { + String collectionId = collection.getKey(); + JsonPath json = collection.getValue(); + CoordinateSystem defaultCrs = collectionIdToDefaultCrs.get(collectionId); + if (defaultCrs != null) { + collectionsData.add(new Object[] { collectionId, json, defaultCrs }); + } + } + } + catch (Exception e) { + collectionsData.add(new Object[] { null, null, null }); + } + return collectionsData.iterator(); + } + + /** + *

    + * collectionCrs. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionCrsAndDefaultCrs") + public Iterator collectionCrs(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + try { + for (Map.Entry collection : collectionsResponses.entrySet()) { + String collectionId = collection.getKey(); + JsonPath json = collection.getValue(); + CoordinateSystem defaultCrs = collectionIdToDefaultCrs.get(collectionId); + if (defaultCrs != null) { + for (CoordinateSystem crs : collectionIdToCrs.get(collectionId)) { + collectionsData.add(new Object[] { collectionId, json, crs, defaultCrs }); + } + } + } + } + catch (Exception e) { + collectionsData.add(new Object[] { null, null, null, null }); + } + return collectionsData.iterator(); + } + + /** + *

    + * verifyBboxCrsParameterWithDefaultCrs. + *

    + * @param collectionId the id of the collection, never null + * @param collection the /collection object, never null + * @param defaultCrs the defaultCrs of the collection, never null + */ + @Test(description = "Implements A.2.2 Query, Parameter bbox-crs, Abstract Test 8 (Requirement /req/crs/fc-bbox-crs-definition, /req/crs/bbox-crs-action)", + dataProvider = "collectionDefaultCrs", dependsOnGroups = "crs-conformance", priority = 1) + public void verifyBboxCrsParameterWithDefaultCrs(String collectionId, JsonPath collection, + CoordinateSystem defaultCrs) { + if ((collectionId == null) & (collection == null) & (defaultCrs == null)) { + throw new AssertionError("No crs information for collection available."); + } + String featuredUrl = JsonUtils.findFeaturesUrlForGeoJson(rootUri, collection); + if (featuredUrl == null) + throw new SkipException( + String.format("Could not find url for collection with id %s supporting GeoJson (type 5s)", + collectionId, GEOJSON_MIME_TYPE)); + BBox bbox = parseSpatialExtent(collection.get()); + if (bbox == null) + throw new SkipException(String.format("Collection with id %s has no spatial extent", collectionId)); + GeometryTransformer geometryTransformer = new GeometryTransformer(bbox.getCrs(), defaultCrs); + BBox transformedBboxInDefaultCrs = geometryTransformer.transform(bbox); + String bboxParameterValueDefaultCrs = transformedBboxInDefaultCrs.asQueryParameter(); + Response response = init().baseUri(featuredUrl) + .accept(GEOJSON_MIME_TYPE) + .param(BBOX_PARAM, bboxParameterValueDefaultCrs) + .when() + .request(Method.GET); + response.then().statusCode(200); + + collectionIdToResponseWithDefaultCRs.put(collectionId, response); + collectionIdToSpatialExtent.put(collectionId, bbox); + + } + + /** + *

    + * verifyBboxCrsParameter. + *

    + * @param collectionId the id of the collection, never null + * @param collection the /collection object, never null + * @param crs the crs to test, never null + * @param defaultCrs the defaultCrs of the collection, never null + */ + @Test(description = "Implements A.2.2 Query, Parameter bbox-crs, Abstract Test 8 (Requirement /req/crs/fc-bbox-crs-definition, /req/crs/bbox-crs-action)", + dataProvider = "collectionCrsAndDefaultCrs", dependsOnGroups = "crs-conformance", + dependsOnMethods = "verifyBboxCrsParameterWithDefaultCrs", priority = 1) + public void verifyBboxCrsParameter(String collectionId, JsonPath collection, CoordinateSystem crs, + CoordinateSystem defaultCrs) { + if ((collectionId == null) & (collection == null) & (crs == null) & (defaultCrs == null)) { + throw new AssertionError("No crs information for collection available."); + } + if (!collectionIdToResponseWithDefaultCRs.containsKey(collectionId)) + throw new SkipException(String + .format("Collection with id %s could not be requested with bbox in default crs", collectionId)); + String featuredUrl = JsonUtils.findFeaturesUrlForGeoJson(rootUri, collection); + if (featuredUrl == null) + throw new SkipException( + String.format("Could not find url for collection with id %s supporting GeoJson (type 5s)", + collectionId, GEOJSON_MIME_TYPE)); + BBox bbox = collectionIdToSpatialExtent.get(collectionId); + GeometryTransformer geometryTransformer = new GeometryTransformer(bbox.getCrs(), crs); + + // https://github.com/opengeospatial/ets-ogcapi-features10/issues/199 + // Transforming the maximum extent in WGS 84 to another CRS can cause problems. + // In that case, we make the extent a bit smaller. + BBox maxExtent = new BBox(-180, -90, 180, 90); + + if (bbox.equals(maxExtent)) { + if (!(crs.getCode().equals("http://www.opengis.net/def/crs/EPSG/0/4326") + || crs.getCode().equals("http://www.opengis.net/def/crs/OGC/1.3/CRS84"))) { + bbox = new BBox(-175, -85, 175, 85); + } + } + + BBox transformedBbox = geometryTransformer.transform(bbox); + + Response response = init().baseUri(featuredUrl) + .param(BBOX_CRS_PARAM, transformedBbox.getCrs().getCode()) + .param(BBOX_PARAM, transformedBbox.asQueryParameter()) + .accept(GEOJSON_MIME_TYPE) + .when() + .request(Method.GET); + response.then().statusCode(200); + + Response responseWithBBoxInDefaultCrs = collectionIdToResponseWithDefaultCRs.get(collectionId); + assertSameFeatures(response.jsonPath(), responseWithBBoxInDefaultCrs.jsonPath()); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterDefault.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterDefault.java index e9da5b30..46e94af3 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterDefault.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterDefault.java @@ -38,52 +38,66 @@ */ public class BBoxCrsParameterDefault extends AbstractBBoxCrs { - @DataProvider(name = "collectionDefaultCrs") - public Iterator collectionDefaultCrs( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - for ( Map.Entry collection : collectionsResponses.entrySet() ) { - String collectionId = collection.getKey(); - JsonPath json = collection.getValue(); - CoordinateSystem defaultCrs = collectionIdToDefaultCrs.get( collectionId ); - if ( defaultCrs != null ) { - collectionsData.add( new Object[] { collectionId, json, defaultCrs } ); - } - } - return collectionsData.iterator(); - } + /** + *

    + * collectionDefaultCrs. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionDefaultCrs") + public Iterator collectionDefaultCrs(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + for (Map.Entry collection : collectionsResponses.entrySet()) { + String collectionId = collection.getKey(); + JsonPath json = collection.getValue(); + CoordinateSystem defaultCrs = collectionIdToDefaultCrs.get(collectionId); + if (defaultCrs != null) { + collectionsData.add(new Object[] { collectionId, json, defaultCrs }); + } + } + return collectionsData.iterator(); + } - /** - * @param collectionId - * the id of the collection, never null - * @param collection - * the /collection object, never null - * @param defaultCrs - * the defaultCrs of the collection, never null - */ - @Test(description = "Implements A.2.2 Query, Parameter bbox-crs, Abstract Test 10 (Requirement /req/crs/fc-bbox-crs-default-value)", dataProvider = "collectionDefaultCrs", dependsOnGroups = "crs-conformance", priority = 1) - public void verifyBboxCrsParameterDefault( String collectionId, JsonPath collection, CoordinateSystem defaultCrs ) { - String featuredUrl = JsonUtils.findFeaturesUrlForGeoJson( rootUri, collection ); - if ( featuredUrl == null ) - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); - BBox bbox = parseSpatialExtent( collection.get() ); - if ( bbox == null ) - throw new SkipException( "Collection with id " + collectionId + " has no spatial extent" ); + /** + *

    + * verifyBboxCrsParameterDefault. + *

    + * @param collectionId the id of the collection, never null + * @param collection the /collection object, never null + * @param defaultCrs the defaultCrs of the collection, never null + */ + @Test(description = "Implements A.2.2 Query, Parameter bbox-crs, Abstract Test 10 (Requirement /req/crs/fc-bbox-crs-default-value)", + dataProvider = "collectionDefaultCrs", dependsOnGroups = "crs-conformance", priority = 1) + public void verifyBboxCrsParameterDefault(String collectionId, JsonPath collection, CoordinateSystem defaultCrs) { + String featuredUrl = JsonUtils.findFeaturesUrlForGeoJson(rootUri, collection); + if (featuredUrl == null) + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); + BBox bbox = parseSpatialExtent(collection.get()); + if (bbox == null) + throw new SkipException("Collection with id " + collectionId + " has no spatial extent"); - GeometryTransformer geometryTransformer = new GeometryTransformer( bbox.getCrs(), defaultCrs ); - BBox transformedBbox = geometryTransformer.transform( bbox ); - String bboxParameterValue = transformedBbox.asQueryParameter(); + GeometryTransformer geometryTransformer = new GeometryTransformer(bbox.getCrs(), defaultCrs); + BBox transformedBbox = geometryTransformer.transform(bbox); + String bboxParameterValue = transformedBbox.asQueryParameter(); - Response responseWithBBox = init().baseUri( featuredUrl ).param( BBOX_CRS_PARAM, - defaultCrs.getCode() ).param( BBOX_PARAM, - bboxParameterValue ).accept( GEOJSON_MIME_TYPE ).when().request( Method.GET ); - responseWithBBox.then().statusCode( 200 ); + Response responseWithBBox = init().baseUri(featuredUrl) + .param(BBOX_CRS_PARAM, defaultCrs.getCode()) + .param(BBOX_PARAM, bboxParameterValue) + .accept(GEOJSON_MIME_TYPE) + .when() + .request(Method.GET); + responseWithBBox.then().statusCode(200); - Response responseWithoutBBox = init().baseUri( featuredUrl ).param( BBOX_PARAM, - bboxParameterValue ).accept( GEOJSON_MIME_TYPE ).when().request( Method.GET ); - responseWithoutBBox.then().statusCode( 200 ); + Response responseWithoutBBox = init().baseUri(featuredUrl) + .param(BBOX_PARAM, bboxParameterValue) + .accept(GEOJSON_MIME_TYPE) + .when() + .request(Method.GET); + responseWithoutBBox.then().statusCode(200); - assertSameFeatures( responseWithBBox.jsonPath(), responseWithoutBBox.jsonPath() ); - } + assertSameFeatures(responseWithBBox.jsonPath(), responseWithoutBBox.jsonPath()); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterInvalid.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterInvalid.java index 983536c2..79cbc8c3 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterInvalid.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterInvalid.java @@ -34,37 +34,49 @@ */ public class BBoxCrsParameterInvalid extends AbstractBBoxCrs { - private static final BBox invalidBBox = new BBox( 5, 49, 6, 50 ); + private static final BBox invalidBBox = new BBox(5, 49, 6, 50); - @DataProvider(name = "collectionIdAndJson") - public Iterator collectionIdAndJson( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - for ( Map.Entry collection : collectionsResponses.entrySet() ) { - collectionsData.add( new Object[] { collection.getKey(), collection.getValue() } ); - } - return collectionsData.iterator(); - } + /** + *

    + * collectionIdAndJson. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionIdAndJson") + public Iterator collectionIdAndJson(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + for (Map.Entry collection : collectionsResponses.entrySet()) { + collectionsData.add(new Object[] { collection.getKey(), collection.getValue() }); + } + return collectionsData.iterator(); + } - /** - * @param collectionId - * the id of the collection, never null - * @param collection - * the /collection object, never null - */ - @Test(description = "Implements A.2.2 Query, Parameter bbox-crs, Abstract Test 9 (Requirement /conf/crs/bbox-crs-parameter-invalid)", dataProvider = "collectionIdAndJson", dependsOnGroups = "crs-conformance", priority = 1) - public void verifyBboxCrsParameterInvalid( String collectionId, JsonPath collection ) { - String featuredUrl = JsonUtils.findFeaturesUrlForGeoJson( rootUri, collection ); - if ( featuredUrl == null ) - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); - BBox bbox = parseSpatialExtent( collection.get() ); - if ( bbox == null ) - throw new SkipException( "Collection with id " + collectionId + " has no spatial extent" ); + /** + *

    + * verifyBboxCrsParameterInvalid. + *

    + * @param collectionId the id of the collection, never null + * @param collection the /collection object, never null + */ + @Test(description = "Implements A.2.2 Query, Parameter bbox-crs, Abstract Test 9 (Requirement /conf/crs/bbox-crs-parameter-invalid)", + dataProvider = "collectionIdAndJson", dependsOnGroups = "crs-conformance", priority = 1) + public void verifyBboxCrsParameterInvalid(String collectionId, JsonPath collection) { + String featuredUrl = JsonUtils.findFeaturesUrlForGeoJson(rootUri, collection); + if (featuredUrl == null) + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); + BBox bbox = parseSpatialExtent(collection.get()); + if (bbox == null) + throw new SkipException("Collection with id " + collectionId + " has no spatial extent"); - Response responseWithBBox = init().baseUri( featuredUrl ).param( BBOX_CRS_PARAM, - UNSUPPORTED_CRS ).param( BBOX_PARAM, - invalidBBox.asQueryParameter() ).accept( GEOJSON_MIME_TYPE ).when().request( Method.GET ); - responseWithBBox.then().statusCode( 400 ); - } + Response responseWithBBox = init().baseUri(featuredUrl) + .param(BBOX_CRS_PARAM, UNSUPPORTED_CRS) + .param(BBOX_PARAM, invalidBBox.asQueryParameter()) + .accept(GEOJSON_MIME_TYPE) + .when() + .request(Method.GET); + responseWithBBox.then().statusCode(400); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/CoordinateSystem.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/CoordinateSystem.java index b61b336c..223c150a 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/CoordinateSystem.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/CoordinateSystem.java @@ -12,138 +12,150 @@ /** * Encapsulates an CRS from - * + * * @author Lyn Goltz */ public class CoordinateSystem { - private final String code; - - /** - * @param code - * the coordinate system, never null - */ - public CoordinateSystem( String code ) { - this.code = code; - } - - /** - * @return the code of the crs, never null - */ - public String getCode() { - return code; - } - - /** - * @return the crs as header value (like <CODE>, never null - */ - public String getAsHeaderValue() { - return "<" + code + ">"; - } - - /** - * srid from the passed crs - * - * @return the parsed srid, -1 if the crs is null - * @throws UnknownCrsException - * if the srid could not be parsed - */ - public int getSrid() { - if ( isDefaultCrs() ) - return 84; - try { - if ( code.startsWith( "http://www.opengis.net/def/crs/" ) ) - return Integer.parseInt( code.substring( code.lastIndexOf( "/" ) + 1 ) ); - if ( code.startsWith( "urn:ogc:def:crs:" ) ) - return Integer.parseInt( code.substring( code.lastIndexOf( ":" ) + 1 ) ); - } catch ( NumberFormatException e ) { - throw new UnknownCrsException( String.format( "Could not parse srid from crs '%s', crs is not supported.", - code ) ); - } - throw new UnknownCrsException( String.format( "Could not parse srid from crs '%s', crs is not supported.", - code ) ); - } - - /** - * @return the code with the authority: EPSG:CODE, may be null - * @throws UnknownCrsException - * if the crs is not a OGC URN (starting with urn:ogc:def:crs:epsg) or OGC http-URIs (starting with - * http://www.opengis.net/def/crs/epsg) with EPSG auhority - */ - public String getCodeWithAuthority() { - if ( isDefaultCrs() ) - return "OGC:CRS84"; - if ( code.startsWith( "urn:ogc:def:crs:EPSG" ) || code.startsWith( "http://www.opengis.net/def/crs/EPSG" ) ) { - int srid = getSrid(); - return String.format( "EPSG:%s", srid ); - } - throw new UnknownCrsException( String.format( "CRS %s is not supported, only OGC URNs (starting with urn:ogc:def:crs:epsg) and OGC http-URIs (starting with http://www.opengis.net/def/crs/epsg) with EPSG auhority are supported.", - code ) ); - } - - /** - *
    -     *  1. For http-URIs (starting with http:) validate that the string conforms to the syntax specified  
    -     *     by RFC 7230, section 2.7.1. 
    -     *  2. For https-URIs (starting with https:) validate that the string conforms to the syntax specified 
    -     *     by RFC 7230, section 2.7.2. 
    -     *  3. For URNs (starting with urn:) validate that the string conforms to the syntax specified 
    -     *     by RFC 8141, section 2. 
    -     *  4. For OGC URNs (starting with urn:ogc:def:crs:) and OGC http-URIs (starting with http://www.opengis.net/def/crs/) 
    -     *     validate that the string conforms to the syntax specified by OGC Name Type Specification - definitions - part 1 – basic name.
    -     * 
    - * - * @return true if the crs is valid, false otherwise - */ - public boolean isValid() { - if ( code.startsWith( "http:" ) && !code.startsWith( "http://www.opengis.net/def/crs/" ) ) { - return assertValidHttpCrsIdentifier( code ); - } else if ( code.startsWith( "https:" ) ) { - return assertValidHttpCrsIdentifier( code ); - } else if ( code.startsWith( "urn:" ) && !code.startsWith( "urn:ogc:def:crs:" ) ) { - return assertValidUrnCrsIdentifier( code ); - } else if ( code.startsWith( "urn:ogc:def:crs:" ) || code.startsWith( "http://www.opengis.net/def/crs/" ) ) { - return assertValidOgcNameCrsIdentifier( code ); - } - return false; - } - - @Override - public String toString() { - return code; - } - - @Override - public boolean equals( Object o ) { - if ( this == o ) - return true; - if ( o == null || getClass() != o.getClass() ) - return false; - CoordinateSystem that = (CoordinateSystem) o; - return code.equals( that.code ); - } - - @Override - public int hashCode() { - return Objects.hash( code ); - } - - private boolean assertValidHttpCrsIdentifier( String valueToAssert ) { - UrlValidator urlValidator = new UrlValidator(); - return urlValidator.isValid( valueToAssert ); - } - - private boolean assertValidUrnCrsIdentifier( String valueToAssert ) { - UrnValidator urnValidator = new UrnValidator(); - return urnValidator.isValid( valueToAssert ); - } - - private boolean assertValidOgcNameCrsIdentifier( String valueToAssert ) { - OgcNameValidator ogcNameValidator = new OgcNameValidator(); - return ogcNameValidator.isValid( valueToAssert ); - } - - private boolean isDefaultCrs() { - return DEFAULT_CRS_CODE.equals( code ) || DEFAULT_CRS_WITH_HEIGHT_CODE.equals( code ); - } + private final String code; + + /** + *

    + * Constructor for CoordinateSystem. + *

    + * @param code the coordinate system, never null + */ + public CoordinateSystem(String code) { + this.code = code; + } + + /** + *

    + * Getter for the field code. + *

    + * @return the code of the crs, never null + */ + public String getCode() { + return code; + } + + /** + *

    + * getAsHeaderValue. + *

    + * @return the crs as header value (like <CODE>, never null + */ + public String getAsHeaderValue() { + return "<" + code + ">"; + } + + /** + * srid from the passed crs + * @return the parsed srid, -1 if the crs is null + */ + public int getSrid() { + if (isDefaultCrs()) + return 84; + try { + if (code.startsWith("http://www.opengis.net/def/crs/")) + return Integer.parseInt(code.substring(code.lastIndexOf("/") + 1)); + if (code.startsWith("urn:ogc:def:crs:")) + return Integer.parseInt(code.substring(code.lastIndexOf(":") + 1)); + } + catch (NumberFormatException e) { + throw new UnknownCrsException( + String.format("Could not parse srid from crs '%s', crs is not supported.", code)); + } + throw new UnknownCrsException(String.format("Could not parse srid from crs '%s', crs is not supported.", code)); + } + + /** + *

    + * getCodeWithAuthority. + *

    + * @return the code with the authority: EPSG:CODE, may be null + */ + public String getCodeWithAuthority() { + if (isDefaultCrs()) + return "OGC:CRS84"; + if (code.startsWith("urn:ogc:def:crs:EPSG") || code.startsWith("http://www.opengis.net/def/crs/EPSG")) { + int srid = getSrid(); + return String.format("EPSG:%s", srid); + } + throw new UnknownCrsException(String.format( + "CRS %s is not supported, only OGC URNs (starting with urn:ogc:def:crs:epsg) and OGC http-URIs (starting with http://www.opengis.net/def/crs/epsg) with EPSG auhority are supported.", + code)); + } + + /** + *
    +	 *  1. For http-URIs (starting with http:) validate that the string conforms to the syntax specified
    +	 *     by RFC 7230, section 2.7.1.
    +	 *  2. For https-URIs (starting with https:) validate that the string conforms to the syntax specified
    +	 *     by RFC 7230, section 2.7.2.
    +	 *  3. For URNs (starting with urn:) validate that the string conforms to the syntax specified
    +	 *     by RFC 8141, section 2.
    +	 *  4. For OGC URNs (starting with urn:ogc:def:crs:) and OGC http-URIs (starting with http://www.opengis.net/def/crs/)
    +	 *     validate that the string conforms to the syntax specified by OGC Name Type Specification - definitions - part 1 – basic name.
    +	 * 
    + * @return true if the crs is valid, false otherwise + */ + public boolean isValid() { + if (code.startsWith("http:") && !code.startsWith("http://www.opengis.net/def/crs/")) { + return assertValidHttpCrsIdentifier(code); + } + else if (code.startsWith("https:")) { + return assertValidHttpCrsIdentifier(code); + } + else if (code.startsWith("urn:") && !code.startsWith("urn:ogc:def:crs:")) { + return assertValidUrnCrsIdentifier(code); + } + else if (code.startsWith("urn:ogc:def:crs:") || code.startsWith("http://www.opengis.net/def/crs/")) { + return assertValidOgcNameCrsIdentifier(code); + } + return false; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return code; + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + CoordinateSystem that = (CoordinateSystem) o; + return code.equals(that.code); + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + return Objects.hash(code); + } + + private boolean assertValidHttpCrsIdentifier(String valueToAssert) { + UrlValidator urlValidator = new UrlValidator(); + return urlValidator.isValid(valueToAssert); + } + + private boolean assertValidUrnCrsIdentifier(String valueToAssert) { + UrnValidator urnValidator = new UrnValidator(); + return urnValidator.isValid(valueToAssert); + } + + private boolean assertValidOgcNameCrsIdentifier(String valueToAssert) { + OgcNameValidator ogcNameValidator = new OgcNameValidator(); + return ogcNameValidator.isValid(valueToAssert); + } + + private boolean isDefaultCrs() { + return DEFAULT_CRS_CODE.equals(code) || DEFAULT_CRS_WITH_HEIGHT_CODE.equals(code); + } + } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/AbstractFeatureCrs.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/AbstractFeatureCrs.java index 36a48bf6..b9d03151 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/AbstractFeatureCrs.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/AbstractFeatureCrs.java @@ -15,41 +15,64 @@ import io.restassured.path.json.JsonPath; /** + *

    + * AbstractFeatureCrs class. + *

    + * * @author Lyn Goltz */ public class AbstractFeatureCrs extends CommonFixture { - protected Map collectionsResponses; - - protected Map> collectionIdToCrs; - - protected Map collectionIdToDefaultCrs; - - protected Map collectionIdToFeatureId; - - @BeforeClass - public void retrieveRequiredInformationFromTestContext( ITestContext testContext ) { - this.collectionsResponses = (Map) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTION_BY_ID.getName() ); - this.collectionIdToCrs = (Map>) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTION_CRS_BY_ID.getName() ); - this.collectionIdToDefaultCrs = (Map) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTION_DEFAULT_CRS_BY_ID.getName() ); - this.collectionIdToFeatureId = (Map) testContext.getSuite().getAttribute( SuiteAttribute.FEATUREIDS.getName() ); - } - - @DataProvider(name = "collectionFeatureId") - public Iterator collectionFeatureId( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - try { - for ( Map.Entry collection : collectionsResponses.entrySet() ) { - String collectionId = collection.getKey(); - if ( collectionIdToFeatureId != null && collectionIdToFeatureId.containsKey( collectionId ) ) { - String featureId = collectionIdToFeatureId.get( collectionId ); - JsonPath json = collection.getValue(); - collectionsData.add( new Object[] { collectionId, json, featureId } ); - } - } - } catch (Exception e) { - collectionsData.add( new Object[] { null, null, null } ); - } - return collectionsData.iterator(); - } + protected Map collectionsResponses; + + protected Map> collectionIdToCrs; + + protected Map collectionIdToDefaultCrs; + + protected Map collectionIdToFeatureId; + + /** + *

    + * retrieveRequiredInformationFromTestContext. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @BeforeClass + public void retrieveRequiredInformationFromTestContext(ITestContext testContext) { + this.collectionsResponses = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTION_BY_ID.getName()); + this.collectionIdToCrs = (Map>) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTION_CRS_BY_ID.getName()); + this.collectionIdToDefaultCrs = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTION_DEFAULT_CRS_BY_ID.getName()); + this.collectionIdToFeatureId = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.FEATUREIDS.getName()); + } + + /** + *

    + * collectionFeatureId. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionFeatureId") + public Iterator collectionFeatureId(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + try { + for (Map.Entry collection : collectionsResponses.entrySet()) { + String collectionId = collection.getKey(); + if (collectionIdToFeatureId != null && collectionIdToFeatureId.containsKey(collectionId)) { + String featureId = collectionIdToFeatureId.get(collectionId); + JsonPath json = collection.getValue(); + collectionsData.add(new Object[] { collectionId, json, featureId }); + } + } + } + catch (Exception e) { + collectionsData.add(new Object[] { null, null, null }); + } + return collectionsData.iterator(); + } + } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameter.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameter.java index 622e80f8..b51ceca0 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameter.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameter.java @@ -46,59 +46,66 @@ */ public class FeatureCrsParameter extends AbstractFeatureCrs { - @DataProvider(name = "collectionFeatureIdCrs") - public Iterator collectionFeatureIdCrs( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - try { - for ( Map.Entry collection : collectionsResponses.entrySet() ) { - String collectionId = collection.getKey(); - String featureId = collectionIdToFeatureId.get( collectionId ); - JsonPath json = collection.getValue(); - for ( CoordinateSystem crs : collectionIdToCrs.get( collectionId ) ) { - collectionsData.add( new Object[] { collectionId, json, featureId, crs } ); - } - } - } catch (Exception e) { - collectionsData.add( new Object[] { null, null, null, null } ); - } - return collectionsData.iterator(); - } + /** + *

    + * collectionFeatureIdCrs. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionFeatureIdCrs") + public Iterator collectionFeatureIdCrs(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + try { + for (Map.Entry collection : collectionsResponses.entrySet()) { + String collectionId = collection.getKey(); + String featureId = collectionIdToFeatureId.get(collectionId); + JsonPath json = collection.getValue(); + for (CoordinateSystem crs : collectionIdToCrs.get(collectionId)) { + collectionsData.add(new Object[] { collectionId, json, featureId, crs }); + } + } + } + catch (Exception e) { + collectionsData.add(new Object[] { null, null, null, null }); + } + return collectionsData.iterator(); + } - /** - * Test: Content-Crs header in the path /collections/{collectionId}/items/{featureId} - * - * @param collectionId - * id id of the collection, never null - * @param collection - * the /collection object, never null - * @param featureId - * id id of the feature, never null - * @param crs - * the crs to test, never null - */ - @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 1 (Requirement /req/crs/fc-crs-definition, /req/crs/fc-crs-valid-value B, /req/crs/ogc-crs-header, /req/crs/ogc-crs-header-value, /req/crs/geojson), " - + "Content-Crs header in the path /collections/{collectionId}/items/{featureId}", dataProvider = "collectionFeatureIdCrs", dependsOnGroups = "crs-conformance", priority = 1) - public void verifyFeatureCrsParameter( String collectionId, JsonPath collection, String featureId, - CoordinateSystem crs ) { - if((collectionId == null) & (collection == null) & (featureId == null) & (crs == null)) { - throw new AssertionError("No crs information for collection available."); - } - String featureUrl = findFeatureUrlForGeoJson( rootUri, collection, featureId ); - if ( featureUrl == null ) - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); + /** + * Test: Content-Crs header in the path /collections/{collectionId}/items/{featureId} + * @param collectionId id id of the collection, never null + * @param collection the /collection object, never null + * @param featureId id id of the feature, never null + * @param crs the crs to test, never null + */ + @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 1 (Requirement /req/crs/fc-crs-definition, /req/crs/fc-crs-valid-value B, /req/crs/ogc-crs-header, /req/crs/ogc-crs-header-value, /req/crs/geojson), " + + "Content-Crs header in the path /collections/{collectionId}/items/{featureId}", + dataProvider = "collectionFeatureIdCrs", dependsOnGroups = "crs-conformance", priority = 1) + public void verifyFeatureCrsParameter(String collectionId, JsonPath collection, String featureId, + CoordinateSystem crs) { + if ((collectionId == null) & (collection == null) & (featureId == null) & (crs == null)) { + throw new AssertionError("No crs information for collection available."); + } + String featureUrl = findFeatureUrlForGeoJson(rootUri, collection, featureId); + if (featureUrl == null) + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); - Response response = init().baseUri( featureUrl ).queryParam( CRS_PARAMETER, - crs.getCode() ).accept( GEOJSON_MIME_TYPE ).when().request( GET ); - response.then().statusCode( 200 ); - String actualHeader = response.getHeader( "Content-Crs" ); - if ( actualHeader == null ) { - throw new AssertionError( String.format( "Feature response at '%s' does not provide the expected header 'Content-Crs'", - featureUrl ) ); - } - assertCrsHeader( actualHeader, crs, - String.format( "Features response at '%s' does not provide expected 'Content-Crs' header, was: '%s', expected: '<%s>'", - featureUrl, actualHeader, crs ) ); - } + Response response = init().baseUri(featureUrl) + .queryParam(CRS_PARAMETER, crs.getCode()) + .accept(GEOJSON_MIME_TYPE) + .when() + .request(GET); + response.then().statusCode(200); + String actualHeader = response.getHeader("Content-Crs"); + if (actualHeader == null) { + throw new AssertionError(String + .format("Feature response at '%s' does not provide the expected header 'Content-Crs'", featureUrl)); + } + assertCrsHeader(actualHeader, crs, String.format( + "Features response at '%s' does not provide expected 'Content-Crs' header, was: '%s', expected: '<%s>'", + featureUrl, actualHeader, crs)); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterDefault.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterDefault.java index ed26e1b2..e89b06d9 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterDefault.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterDefault.java @@ -30,38 +30,34 @@ */ public class FeatureCrsParameterDefault extends AbstractFeatureCrs { - /** - * Test: default CRS requesting /collections/{collectionId}/items - * - * @param collectionId - * id id of the collection, never null - * @param collection - * the /collection object, never null - * @param featureId - * id id of the feature, never null - */ - @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 6 (Requirement /req/crs/fc-crs-default-value, /req/crs/ogc-crs-header, /req/crs/ogc-crs-header-value), " - + "Default CRS requesting path /collections/{collectionId}/items/{featureId}", dataProvider = "collectionFeatureId", dependsOnGroups = "crs-conformance", priority = 1) - public void verifyFeatureCrsParameterDefault( String collectionId, JsonPath collection, String featureId ) { - if((collectionId == null) & (collection == null) & (featureId == null)) { - throw new AssertionError("No crs information for collection available."); - } - String featureUrl = findFeatureUrlForGeoJson( rootUri, collection, featureId ); - if ( featureUrl == null ) - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); + /** + * Test: default CRS requesting /collections/{collectionId}/items + * @param collectionId id id of the collection, never null + * @param collection the /collection object, never null + * @param featureId id id of the feature, never null + */ + @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 6 (Requirement /req/crs/fc-crs-default-value, /req/crs/ogc-crs-header, /req/crs/ogc-crs-header-value), " + + "Default CRS requesting path /collections/{collectionId}/items/{featureId}", + dataProvider = "collectionFeatureId", dependsOnGroups = "crs-conformance", priority = 1) + public void verifyFeatureCrsParameterDefault(String collectionId, JsonPath collection, String featureId) { + if ((collectionId == null) & (collection == null) & (featureId == null)) { + throw new AssertionError("No crs information for collection available."); + } + String featureUrl = findFeatureUrlForGeoJson(rootUri, collection, featureId); + if (featureUrl == null) + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); - Response response = init().baseUri( featureUrl ).accept( GEOJSON_MIME_TYPE ).when().request( GET ); - response.then().statusCode( 200 ); - String actualHeader = response.getHeader( "Content-Crs" ); - if ( actualHeader == null ) { - throw new AssertionError( String.format( "Feature response at '%s' does not provide the expected header 'Content-Crs'", - featureUrl ) ); - } - assertDefaultCrsHeader( actualHeader, - String.format( "Feature response at '%s' does not provide default 'Content-Crs' header, was: '%s', expected: '%s' or '%s", - featureUrl, actualHeader, DEFAULT_CRS_CODE, - DEFAULT_CRS_WITH_HEIGHT_CODE ) ); - } + Response response = init().baseUri(featureUrl).accept(GEOJSON_MIME_TYPE).when().request(GET); + response.then().statusCode(200); + String actualHeader = response.getHeader("Content-Crs"); + if (actualHeader == null) { + throw new AssertionError(String + .format("Feature response at '%s' does not provide the expected header 'Content-Crs'", featureUrl)); + } + assertDefaultCrsHeader(actualHeader, String.format( + "Feature response at '%s' does not provide default 'Content-Crs' header, was: '%s', expected: '%s' or '%s", + featureUrl, actualHeader, DEFAULT_CRS_CODE, DEFAULT_CRS_WITH_HEIGHT_CODE)); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterInvalid.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterInvalid.java index 8b36914b..e7617cd2 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterInvalid.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterInvalid.java @@ -34,30 +34,31 @@ */ public class FeatureCrsParameterInvalid extends AbstractFeatureCrs { - /** - * Test: invalid CRS requesting /collections/{collectionId}/items - * - * @param collectionId - * id id of the collection, never null - * @param collection - * the /collection object, never null - * @param featureId - * id id of the feature, never null - */ - @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 1 (Requirement /req/crs/fc-crs-valid-value), " - + "Invalid CRS requesting path /collections/{collectionId}/items/{featureId}", dataProvider = "collectionFeatureId", dependsOnGroups = "crs-conformance", priority = 1) - public void verifyFeatureCrsParameterInvalid( String collectionId, JsonPath collection, String featureId ) { - if((collectionId == null) & (collection == null) & (featureId == null)) { - throw new AssertionError("No crs information for collection available."); - } - String featureUrl = findFeatureUrlForGeoJson( rootUri, collection, featureId ); - if ( featureUrl == null ) - throw new SkipException( String.format( "Could not find url for collection with id %s supporting GeoJson (type %s)", - collectionId, GEOJSON_MIME_TYPE ) ); + /** + * Test: invalid CRS requesting /collections/{collectionId}/items + * @param collectionId id id of the collection, never null + * @param collection the /collection object, never null + * @param featureId id id of the feature, never null + */ + @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 1 (Requirement /req/crs/fc-crs-valid-value), " + + "Invalid CRS requesting path /collections/{collectionId}/items/{featureId}", + dataProvider = "collectionFeatureId", dependsOnGroups = "crs-conformance", priority = 1) + public void verifyFeatureCrsParameterInvalid(String collectionId, JsonPath collection, String featureId) { + if ((collectionId == null) & (collection == null) & (featureId == null)) { + throw new AssertionError("No crs information for collection available."); + } + String featureUrl = findFeatureUrlForGeoJson(rootUri, collection, featureId); + if (featureUrl == null) + throw new SkipException( + String.format("Could not find url for collection with id %s supporting GeoJson (type %s)", + collectionId, GEOJSON_MIME_TYPE)); - Response response = init().baseUri( featureUrl ).queryParam( CRS_PARAMETER, - UNSUPPORTED_CRS ).accept( GEOJSON_MIME_TYPE ).when().request( GET ); - response.then().statusCode( 400 ); - } + Response response = init().baseUri(featureUrl) + .queryParam(CRS_PARAMETER, UNSUPPORTED_CRS) + .accept(GEOJSON_MIME_TYPE) + .when() + .request(GET); + response.then().statusCode(400); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterTransform.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterTransform.java index 917665f2..4868105a 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterTransform.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterTransform.java @@ -48,122 +48,122 @@ * engine will have to allow for reasonable differences when assessing whether the geometries match. * * - * * @author Lyn Goltz */ public class FeatureCrsParameterTransform extends AbstractFeatureCrs { - private MultiKeyMap collectionIdAndFeatureIdToGeometry = new MultiKeyMap(); + private MultiKeyMap collectionIdAndFeatureIdToGeometry = new MultiKeyMap(); - @DataProvider( - name = "collectionFeatureIdCrsAndDefaultCrs") - public Iterator collectionFeatureIdCrsAndDefaultCrs(ITestContext testContext) { - List collectionsData = new ArrayList<>(); - try { - for (Map.Entry collection : collectionsResponses.entrySet()) { - String collectionId = collection.getKey(); - String featureId = collectionIdToFeatureId.get(collectionId); - if (featureId == null) { - continue; - } - CoordinateSystem defaultCrs = collectionIdToDefaultCrs.get(collectionId); - JsonPath json = collection.getValue(); - for (CoordinateSystem crs : collectionIdToCrs.get(collectionId)) { - collectionsData.add(new Object[] { collectionId, json, featureId, crs, defaultCrs }); - } - } - } catch (Exception e) { - collectionsData.add(new Object[] { null, null, null, null, null }); - } - return collectionsData.iterator(); - } + /** + *

    + * collectionFeatureIdCrsAndDefaultCrs. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionFeatureIdCrsAndDefaultCrs") + public Iterator collectionFeatureIdCrsAndDefaultCrs(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + try { + for (Map.Entry collection : collectionsResponses.entrySet()) { + String collectionId = collection.getKey(); + String featureId = collectionIdToFeatureId.get(collectionId); + if (featureId == null) { + continue; + } + CoordinateSystem defaultCrs = collectionIdToDefaultCrs.get(collectionId); + JsonPath json = collection.getValue(); + for (CoordinateSystem crs : collectionIdToCrs.get(collectionId)) { + collectionsData.add(new Object[] { collectionId, json, featureId, crs, defaultCrs }); + } + } + } + catch (Exception e) { + collectionsData.add(new Object[] { null, null, null, null, null }); + } + return collectionsData.iterator(); + } - /** - * Test: invalid CRS requesting /collections/{collectionId}/items - * - * @param collectionId - * id id of the collection, never null - * @param collection - * the /collection object, never null - * @param featureId - * id id of the feature, never null - * @throws ParseException - * if the geometry could not be parsed - */ - @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 7 (Requirement /req/crs/crs-action), " - + "Geometries in the path /collections/{collectionId}/items/{featureId}", dataProvider = "collectionFeatureId", dependsOnGroups = "crs-conformance", priority = 1) - public void verifyFeatureCrsParameterTransformWithCrsParameter( String collectionId, JsonPath collection, - String featureId ) - throws ParseException { - if((collectionId == null) & (collection == null) & (featureId == null)) { - throw new AssertionError("No crs information for collection available."); - } - String featureUrl = findFeatureUrlForGeoJson( rootUri, collection, featureId ); - if ( featureUrl == null ) - throw new SkipException( String.format( "Could not find url for collection with id %s supporting GeoJson (type %s)", - collectionId, GEOJSON_MIME_TYPE ) ); + /** + * Test: invalid CRS requesting /collections/{collectionId}/items + * @param collectionId id id of the collection, never null + * @param collection the /collection object, never null + * @param featureId id id of the feature, never null + * @throws org.locationtech.jts.io.ParseException if the geometry could not be parsed + */ + @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 7 (Requirement /req/crs/crs-action), " + + "Geometries in the path /collections/{collectionId}/items/{featureId}", + dataProvider = "collectionFeatureId", dependsOnGroups = "crs-conformance", priority = 1) + public void verifyFeatureCrsParameterTransformWithCrsParameter(String collectionId, JsonPath collection, + String featureId) throws ParseException { + if ((collectionId == null) & (collection == null) & (featureId == null)) { + throw new AssertionError("No crs information for collection available."); + } + String featureUrl = findFeatureUrlForGeoJson(rootUri, collection, featureId); + if (featureUrl == null) + throw new SkipException( + String.format("Could not find url for collection with id %s supporting GeoJson (type %s)", + collectionId, GEOJSON_MIME_TYPE)); - Response response = init().baseUri( featureUrl ).accept( GEOJSON_MIME_TYPE ).when().request( GET ); - response.then().statusCode( 200 ); - String crsHeader = response.getHeader( "Content-Crs" ); - if ( crsHeader == null ) { - throw new AssertionError( String.format( "Feature response at '%s' does not provide the expected header 'Content-Crs'", - featureUrl ) ); - } - assertDefaultCrs( crsHeader, - String.format( "Feature response at '%s' does not provide default 'Content-Crs' header, was: '%s', expected: '%s' or '%s'", - featureUrl, crsHeader, DEFAULT_CRS_CODE, DEFAULT_CRS_WITH_HEIGHT_CODE ) ); - String crs = crsHeader.substring( 1, crsHeader.length() - 1 ); + Response response = init().baseUri(featureUrl).accept(GEOJSON_MIME_TYPE).when().request(GET); + response.then().statusCode(200); + String crsHeader = response.getHeader("Content-Crs"); + if (crsHeader == null) { + throw new AssertionError(String + .format("Feature response at '%s' does not provide the expected header 'Content-Crs'", featureUrl)); + } + assertDefaultCrs(crsHeader, String.format( + "Feature response at '%s' does not provide default 'Content-Crs' header, was: '%s', expected: '%s' or '%s'", + featureUrl, crsHeader, DEFAULT_CRS_CODE, DEFAULT_CRS_WITH_HEIGHT_CODE)); + String crs = crsHeader.substring(1, crsHeader.length() - 1); - Map feature = response.jsonPath().get(); - Geometry geometry = JsonUtils.parseFeatureGeometry( feature, new CoordinateSystem( crs ) ); - collectionIdAndFeatureIdToGeometry.put( collectionId, featureId, geometry ); - } + Map feature = response.jsonPath().get(); + Geometry geometry = JsonUtils.parseFeatureGeometry(feature, new CoordinateSystem(crs)); + collectionIdAndFeatureIdToGeometry.put(collectionId, featureId, geometry); + } - /** - * Test: Content-Crs header in the path /collections/{collectionId}/items/{featureId} - * - * @param collectionId - * id id of the collection, never null - * @param collection - * the /collection object, never null - * @param featureId - * id id of the feature, never null - * @param crs - * the crs to test, never null - * @param defaultCRS - * the defaultCRS of the collection, never null - * @throws ParseException - * if the geometry could not be parsed - */ - @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 7 (Requirement /req/crs/crs-action), " - + "Transformed geometries in the path /collections/{collectionId}/items/{featureId}", dataProvider = "collectionFeatureIdCrsAndDefaultCrs", dependsOnGroups = "crs-conformance", dependsOnMethods = "verifyFeatureCrsParameterTransformWithCrsParameter", priority = 1) - public void verifyFeatureCrsParameterTransformWithoutCrsParameter( String collectionId, JsonPath collection, - String featureId, CoordinateSystem crs, - CoordinateSystem defaultCRS ) - throws ParseException { - if((collectionId == null) & (collection == null) & (featureId == null) & (crs == null) & (defaultCRS == null)) { - throw new AssertionError("No crs information for collection available."); - } - //https://github.com/opengeospatial/ets-ogcapi-features10/issues/227 - if(defaultCRS == null) { - //use default crs - defaultCRS = new CoordinateSystem(org.opengis.cite.ogcapifeatures10.OgcApiFeatures10.DEFAULT_CRS_CODE); - } - String featureUrl = findFeatureUrlForGeoJson( rootUri, collection, featureId ); - if ( featureUrl == null ) - throw new SkipException( String.format( "Could not find url for collection with id %s supporting GeoJson (type %s)", - collectionId, GEOJSON_MIME_TYPE ) ); + /** + * Test: Content-Crs header in the path /collections/{collectionId}/items/{featureId} + * @param collectionId id id of the collection, never null + * @param collection the /collection object, never null + * @param featureId id id of the feature, never null + * @param crs the crs to test, never null + * @param defaultCRS the defaultCRS of the collection, never null + * @throws org.locationtech.jts.io.ParseException if the geometry could not be parsed + */ + @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 7 (Requirement /req/crs/crs-action), " + + "Transformed geometries in the path /collections/{collectionId}/items/{featureId}", + dataProvider = "collectionFeatureIdCrsAndDefaultCrs", dependsOnGroups = "crs-conformance", + dependsOnMethods = "verifyFeatureCrsParameterTransformWithCrsParameter", priority = 1) + public void verifyFeatureCrsParameterTransformWithoutCrsParameter(String collectionId, JsonPath collection, + String featureId, CoordinateSystem crs, CoordinateSystem defaultCRS) throws ParseException { + if ((collectionId == null) & (collection == null) & (featureId == null) & (crs == null) + & (defaultCRS == null)) { + throw new AssertionError("No crs information for collection available."); + } + // https://github.com/opengeospatial/ets-ogcapi-features10/issues/227 + if (defaultCRS == null) { + // use default crs + defaultCRS = new CoordinateSystem(org.opengis.cite.ogcapifeatures10.OgcApiFeatures10.DEFAULT_CRS_CODE); + } + String featureUrl = findFeatureUrlForGeoJson(rootUri, collection, featureId); + if (featureUrl == null) + throw new SkipException( + String.format("Could not find url for collection with id %s supporting GeoJson (type %s)", + collectionId, GEOJSON_MIME_TYPE)); - Response response = init().baseUri( featureUrl ).queryParam( CRS_PARAMETER, - crs.getCode() ).accept( GEOJSON_MIME_TYPE ).when().request( GET ); - response.then().statusCode( 200 ); - Map feature = response.jsonPath().get(); - Geometry geometry = JsonUtils.parseFeatureGeometry( feature, crs ); - Geometry geometryInDefaultCrs = (Geometry) collectionIdAndFeatureIdToGeometry.get( collectionId, featureId ); - GeometryTransformer geometryTransformer = new GeometryTransformer( crs, defaultCRS ); - Geometry transformedGeometry = geometryTransformer.transform( geometry ); - geometryInDefaultCrs.equalsExact( transformedGeometry, 0.001 ); - } + Response response = init().baseUri(featureUrl) + .queryParam(CRS_PARAMETER, crs.getCode()) + .accept(GEOJSON_MIME_TYPE) + .when() + .request(GET); + response.then().statusCode(200); + Map feature = response.jsonPath().get(); + Geometry geometry = JsonUtils.parseFeatureGeometry(feature, crs); + Geometry geometryInDefaultCrs = (Geometry) collectionIdAndFeatureIdToGeometry.get(collectionId, featureId); + GeometryTransformer geometryTransformer = new GeometryTransformer(crs, defaultCRS); + Geometry transformedGeometry = geometryTransformer.transform(geometry); + geometryInDefaultCrs.equalsExact(transformedGeometry, 0.001); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/AbstractFeaturesCrs.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/AbstractFeaturesCrs.java index be79ceb9..a93c64a7 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/AbstractFeaturesCrs.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/AbstractFeaturesCrs.java @@ -16,79 +16,115 @@ import io.restassured.path.json.JsonPath; /** + *

    + * AbstractFeaturesCrs class. + *

    + * * @author Lyn Goltz */ public class AbstractFeaturesCrs extends CommonFixture { - private Map collectionsResponses; + private Map collectionsResponses; - private Map> collectionIdToCrs; + private Map> collectionIdToCrs; - private Map collectionIdToDefaultCrs; + private Map collectionIdToDefaultCrs; - @BeforeClass - public void retrieveRequiredInformationFromTestContext( ITestContext testContext ) { - this.collectionsResponses = (Map) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTION_BY_ID.getName() ); - this.collectionIdToCrs = (Map>) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTION_CRS_BY_ID.getName() ); - this.collectionIdToDefaultCrs = (Map) testContext.getSuite().getAttribute( SuiteAttribute.COLLECTION_DEFAULT_CRS_BY_ID.getName() ); - } + /** + *

    + * retrieveRequiredInformationFromTestContext. + *

    + * @param testContext a {@link org.testng.ITestContext} object + */ + @BeforeClass + public void retrieveRequiredInformationFromTestContext(ITestContext testContext) { + this.collectionsResponses = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTION_BY_ID.getName()); + this.collectionIdToCrs = (Map>) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTION_CRS_BY_ID.getName()); + this.collectionIdToDefaultCrs = (Map) testContext.getSuite() + .getAttribute(SuiteAttribute.COLLECTION_DEFAULT_CRS_BY_ID.getName()); + } - @DataProvider(name = "collectionIdAndJson") - public Iterator collectionIdAndJson( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - try { - for ( Map.Entry collection : collectionsResponses.entrySet() ) { - String collectionId = collection.getKey(); - JsonPath json = collection.getValue(); - collectionsData.add( new Object[] { collectionId, json } ); - } - } catch (Exception e) { - collectionsData.add( new Object[] { null, null } ); - } - return collectionsData.iterator(); - } + /** + *

    + * collectionIdAndJson. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionIdAndJson") + public Iterator collectionIdAndJson(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + try { + for (Map.Entry collection : collectionsResponses.entrySet()) { + String collectionId = collection.getKey(); + JsonPath json = collection.getValue(); + collectionsData.add(new Object[] { collectionId, json }); + } + } + catch (Exception e) { + collectionsData.add(new Object[] { null, null }); + } + return collectionsData.iterator(); + } - @DataProvider( - name = "collectionIdAndJsonAndCrs") - public Iterator collectionIdAndJsonAndCrs(ITestContext testContext) { - List collectionsData = new ArrayList<>(); - try { - for (Map.Entry collection : collectionsResponses.entrySet()) { - String collectionId = collection.getKey(); - JsonPath json = collection.getValue(); - int count = 0; - for (CoordinateSystem crs : collectionIdToCrs.get(collectionId)) { - if (count >= OgcApiFeatures10.CRS_LIMIT) { - break; - } - collectionsData.add(new Object[] { collectionId, json, crs }); - count++; - } - } - } catch (Exception e) { - collectionsData.add(new Object[] { null, null, null }); - } - return collectionsData.iterator(); - } + /** + *

    + * collectionIdAndJsonAndCrs. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionIdAndJsonAndCrs") + public Iterator collectionIdAndJsonAndCrs(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + try { + for (Map.Entry collection : collectionsResponses.entrySet()) { + String collectionId = collection.getKey(); + JsonPath json = collection.getValue(); + int count = 0; + for (CoordinateSystem crs : collectionIdToCrs.get(collectionId)) { + if (count >= OgcApiFeatures10.CRS_LIMIT) { + break; + } + collectionsData.add(new Object[] { collectionId, json, crs }); + count++; + } + } + } + catch (Exception e) { + collectionsData.add(new Object[] { null, null, null }); + } + return collectionsData.iterator(); + } - @DataProvider(name = "collectionIdAndJsonAndCrsAndDefaultCrs") - public Iterator collectionIdAndJsonAndCrsAndDefaultCrs( ITestContext testContext ) { - List collectionsData = new ArrayList<>(); - try { - for ( Map.Entry collection : collectionsResponses.entrySet() ) { - String collectionId = collection.getKey(); - JsonPath json = collection.getValue(); - CoordinateSystem defaultCrs = collectionIdToDefaultCrs.get( collectionId ); - if ( defaultCrs != null ) { - for ( CoordinateSystem crs : collectionIdToCrs.get( collectionId ) ) { - collectionsData.add( new Object[] { collectionId, json, crs, defaultCrs } ); - } - } - } - } catch (Exception e) { - collectionsData.add( new Object[] { null, null, null, null } ); - } - return collectionsData.iterator(); - } + /** + *

    + * collectionIdAndJsonAndCrsAndDefaultCrs. + *

    + * @param testContext a {@link org.testng.ITestContext} object + * @return a {@link java.util.Iterator} object + */ + @DataProvider(name = "collectionIdAndJsonAndCrsAndDefaultCrs") + public Iterator collectionIdAndJsonAndCrsAndDefaultCrs(ITestContext testContext) { + List collectionsData = new ArrayList<>(); + try { + for (Map.Entry collection : collectionsResponses.entrySet()) { + String collectionId = collection.getKey(); + JsonPath json = collection.getValue(); + CoordinateSystem defaultCrs = collectionIdToDefaultCrs.get(collectionId); + if (defaultCrs != null) { + for (CoordinateSystem crs : collectionIdToCrs.get(collectionId)) { + collectionsData.add(new Object[] { collectionId, json, crs, defaultCrs }); + } + } + } + } + catch (Exception e) { + collectionsData.add(new Object[] { null, null, null, null }); + } + return collectionsData.iterator(); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameter.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameter.java index 2e777cf1..c40621ae 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameter.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameter.java @@ -15,7 +15,7 @@ /** * Verifies header in the paths /collection/{collectionId}/items - * + * *
      * Abstract Test 4: /conf/crs/crs-parameter
      * Test Purpose: Verify that the parameter crs has been implemented correctly
    @@ -34,43 +34,43 @@
      *  * has the status code 200 and
      *  * includes a Content-Crs http header with the value of the requested CRS identifier.
      * 
    - * + * * @author Lyn Goltz */ public class FeaturesCrsParameter extends AbstractFeaturesCrs { - /** - * Test: Content-Crs header in the path /collections/{collectionId}/items - * - * @param collectionId - * id id of the collection, never null - * @param collection - * the /collection object, never null - * @param crs - * the crs to test, never null - */ - @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 4 (Requirement /req/crs/fc-crs-definition, /req/crs/fc-crs-valid-value B, /req/crs/ogc-crs-header, /req/crs/ogc-crs-header-value, /req/crs/geojson), " - + "Content-Crs header in the path /collections/{collectionId}/items", dataProvider = "collectionIdAndJsonAndCrs", dependsOnGroups = "crs-conformance", priority = 1) - public void verifyFeaturesCrsParameter( String collectionId, JsonPath collection, CoordinateSystem crs ) { - if((collectionId == null) & (collection == null) & (crs == null)) { - throw new AssertionError("No crs information for collection available."); - } - String featuresUrl = findFeaturesUrlForGeoJson( rootUri, collection ); - if ( featuresUrl == null ) - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); + /** + * Test: Content-Crs header in the path /collections/{collectionId}/items + * @param collectionId id id of the collection, never null + * @param collection the /collection object, never null + * @param crs the crs to test, never null + */ + @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 4 (Requirement /req/crs/fc-crs-definition, /req/crs/fc-crs-valid-value B, /req/crs/ogc-crs-header, /req/crs/ogc-crs-header-value, /req/crs/geojson), " + + "Content-Crs header in the path /collections/{collectionId}/items", + dataProvider = "collectionIdAndJsonAndCrs", dependsOnGroups = "crs-conformance", priority = 1) + public void verifyFeaturesCrsParameter(String collectionId, JsonPath collection, CoordinateSystem crs) { + if ((collectionId == null) & (collection == null) & (crs == null)) { + throw new AssertionError("No crs information for collection available."); + } + String featuresUrl = findFeaturesUrlForGeoJson(rootUri, collection); + if (featuresUrl == null) + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); - Response response = init().baseUri( featuresUrl ).queryParam( CRS_PARAMETER, - crs.getCode() ).accept( GEOJSON_MIME_TYPE ).when().request( GET ); - response.then().statusCode( 200 ); - String actualHeader = response.getHeader( "Content-Crs" ); - if ( actualHeader == null ) { - throw new AssertionError( String.format( "Features response at '%s' does not provide the expected header 'Content-Crs'", - featuresUrl ) ); - } - assertCrsHeader( actualHeader, crs, - String.format( "Features response at '%s' does not provide expected 'Content-Crs' header, was: '%s', expected: '<%s>'", - featuresUrl, actualHeader, crs ) ); - } + Response response = init().baseUri(featuresUrl) + .queryParam(CRS_PARAMETER, crs.getCode()) + .accept(GEOJSON_MIME_TYPE) + .when() + .request(GET); + response.then().statusCode(200); + String actualHeader = response.getHeader("Content-Crs"); + if (actualHeader == null) { + throw new AssertionError(String + .format("Features response at '%s' does not provide the expected header 'Content-Crs'", featuresUrl)); + } + assertCrsHeader(actualHeader, crs, String.format( + "Features response at '%s' does not provide expected 'Content-Crs' header, was: '%s', expected: '<%s>'", + featuresUrl, actualHeader, crs)); + } -} \ No newline at end of file +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterDefault.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterDefault.java index 6ce4fed3..913fcae4 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterDefault.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterDefault.java @@ -22,44 +22,41 @@ * Requirement: /req/crs/fc-crs-default-value, /req/crs/ogc-crs-header, /req/crs/ogc-crs-header-value * * Test Method - * For each spatial feature collection, send a request without the crs parameter and verify that the response + * For each spatial feature collection, send a request without the crs parameter and verify that the response * includes a Content-Crs http header with the value of the default CRS identifier of the collection. * - * + * * @author Lyn Goltz */ public class FeaturesCrsParameterDefault extends AbstractFeaturesCrs { - /** - * Test: default CRS requesting /collections/{collectionId}/items - * - * @param collectionId - * id id of the collection, never null - * @param collection - * the /collection object, never null - */ - @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 6 (Requirement /req/crs/fc-crs-default-value, /req/crs/ogc-crs-header, /req/crs/ogc-crs-header-value), " - + "Default CRS requesting path /collections/{collectionId}/items", dataProvider = "collectionIdAndJson", dependsOnGroups = "crs-conformance", priority = 1) - public void verifyFeaturesCrsParameterDefault( String collectionId, JsonPath collection ) { - if((collectionId == null) & (collection == null)) { - throw new AssertionError("No crs information for collection available."); - } - String featuresUrl = findFeaturesUrlForGeoJson( rootUri, collection ); - if ( featuresUrl == null ) - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); + /** + * Test: default CRS requesting /collections/{collectionId}/items + * @param collectionId id id of the collection, never null + * @param collection the /collection object, never null + */ + @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 6 (Requirement /req/crs/fc-crs-default-value, /req/crs/ogc-crs-header, /req/crs/ogc-crs-header-value), " + + "Default CRS requesting path /collections/{collectionId}/items", dataProvider = "collectionIdAndJson", + dependsOnGroups = "crs-conformance", priority = 1) + public void verifyFeaturesCrsParameterDefault(String collectionId, JsonPath collection) { + if ((collectionId == null) & (collection == null)) { + throw new AssertionError("No crs information for collection available."); + } + String featuresUrl = findFeaturesUrlForGeoJson(rootUri, collection); + if (featuresUrl == null) + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); - Response response = init().baseUri( featuresUrl ).accept( GEOJSON_MIME_TYPE ).when().request( GET ); - response.then().statusCode( 200 ); - String actualHeader = response.getHeader( "Content-Crs" ); - if ( actualHeader == null ) { - throw new AssertionError( String.format( "Features response at '%s' does not provide the expected header 'Content-Crs'", - featuresUrl ) ); - } - assertDefaultCrsHeader( actualHeader, - String.format( "Features response at '%s' does not provide default 'Content-Crs' header, was: '%s', expected: '%s' or '%s", - featuresUrl, actualHeader, DEFAULT_CRS_CODE, - DEFAULT_CRS_WITH_HEIGHT_CODE ) ); - } + Response response = init().baseUri(featuresUrl).accept(GEOJSON_MIME_TYPE).when().request(GET); + response.then().statusCode(200); + String actualHeader = response.getHeader("Content-Crs"); + if (actualHeader == null) { + throw new AssertionError(String + .format("Features response at '%s' does not provide the expected header 'Content-Crs'", featuresUrl)); + } + assertDefaultCrsHeader(actualHeader, String.format( + "Features response at '%s' does not provide default 'Content-Crs' header, was: '%s', expected: '%s' or '%s", + featuresUrl, actualHeader, DEFAULT_CRS_CODE, DEFAULT_CRS_WITH_HEIGHT_CODE)); + } -} \ No newline at end of file +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterInvalid.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterInvalid.java index 7bd759b7..85e2a722 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterInvalid.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterInvalid.java @@ -29,33 +29,35 @@ * Verify that the response has status code 400. * Unsupported CRS identifiers are all strings not included in the crs property of the collection and also not included in the global CRS list, if #/crs is included in the crs property. * - * + * * @author Lyn Goltz */ public class FeaturesCrsParameterInvalid extends AbstractFeaturesCrs { - /** - * Test: invalid CRS requesting /collections/{collectionId}/items - * - * @param collectionId - * id id of the collection, never null - * @param collection - * the /collection object, never null - */ - @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 5 (Requirement /req/crs/fc-crs-valid-value), " - + "Invalid CRS requesting path /collections/{collectionId}/items", dataProvider = "collectionIdAndJson", dependsOnGroups = "crs-conformance", priority = 1) - public void verifyFeaturesCrsParameterInvalid( String collectionId, JsonPath collection ) { - if((collectionId == null) & (collection == null)) { - throw new AssertionError("No crs information for collection available."); - } - String featuresUrl = findFeaturesUrlForGeoJson( rootUri, collection ); - if ( featuresUrl == null ) - throw new SkipException( String.format( "Could not find url for collection with id %s supporting GeoJson (type %s)", - collectionId, GEOJSON_MIME_TYPE ) ); + /** + * Test: invalid CRS requesting /collections/{collectionId}/items + * @param collectionId id id of the collection, never null + * @param collection the /collection object, never null + */ + @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 5 (Requirement /req/crs/fc-crs-valid-value), " + + "Invalid CRS requesting path /collections/{collectionId}/items", dataProvider = "collectionIdAndJson", + dependsOnGroups = "crs-conformance", priority = 1) + public void verifyFeaturesCrsParameterInvalid(String collectionId, JsonPath collection) { + if ((collectionId == null) & (collection == null)) { + throw new AssertionError("No crs information for collection available."); + } + String featuresUrl = findFeaturesUrlForGeoJson(rootUri, collection); + if (featuresUrl == null) + throw new SkipException( + String.format("Could not find url for collection with id %s supporting GeoJson (type %s)", + collectionId, GEOJSON_MIME_TYPE)); - Response response = init().baseUri( featuresUrl ).queryParam( CRS_PARAMETER, - UNSUPPORTED_CRS ).accept( GEOJSON_MIME_TYPE ).when().request( GET ); - response.then().statusCode( 400 ); - } + Response response = init().baseUri(featuresUrl) + .queryParam(CRS_PARAMETER, UNSUPPORTED_CRS) + .accept(GEOJSON_MIME_TYPE) + .when() + .request(GET); + response.then().statusCode(400); + } -} \ No newline at end of file +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterTransform.java b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterTransform.java index b1c653ff..3d412a50 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterTransform.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterTransform.java @@ -25,7 +25,7 @@ /** * Verifies transformed geometries in the paths /collection/{collectionId}/items - * + * *
      * Abstract Test 7: /conf/crs/crs-parameter-transform
      * Test Purpose: Verify that the geometries are transformed
    @@ -43,98 +43,93 @@
      *     different coordinate conversions in the test engine and by the API, there will not be an exact match and the test
      *     engine will have to allow for reasonable differences when assessing whether the geometries match.
      * 
    - * + * * @author Lyn Goltz */ public class FeaturesCrsParameterTransform extends AbstractFeaturesCrs { - private MultiKeyMap collectionIdAndFeatureIdToGeometry = new MultiKeyMap(); + private MultiKeyMap collectionIdAndFeatureIdToGeometry = new MultiKeyMap(); - /** - * Test: transformed geometries in the path /collections/{collectionId}/items - * - * @param collectionId - * id id of the collection, never null - * @param collection - * the /collection object, never null - * @throws ParseException - * if the geometry could not be parsed - */ - @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 7 (Requirement /req/crs/crs-action), " - + "Geometries in the path /collections/{collectionId}/items", dataProvider = "collectionIdAndJson", dependsOnGroups = "crs-conformance", priority = 1) - public void verifyFeaturesCrsParameterTransformWithoutCrsParameter( String collectionId, JsonPath collection ) - throws ParseException { - if((collectionId == null) & (collection == null)) { - throw new AssertionError("No crs information for collection available."); - } - String featuresUrl = findFeaturesUrlForGeoJson( rootUri, collection ); - if ( featuresUrl == null ) - throw new SkipException( "Could not find url for collection with id " + collectionId - + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")" ); + /** + * Test: transformed geometries in the path /collections/{collectionId}/items + * @param collectionId id id of the collection, never null + * @param collection the /collection object, never null + * @throws org.locationtech.jts.io.ParseException if the geometry could not be parsed + */ + @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 7 (Requirement /req/crs/crs-action), " + + "Geometries in the path /collections/{collectionId}/items", dataProvider = "collectionIdAndJson", + dependsOnGroups = "crs-conformance", priority = 1) + public void verifyFeaturesCrsParameterTransformWithoutCrsParameter(String collectionId, JsonPath collection) + throws ParseException { + if ((collectionId == null) & (collection == null)) { + throw new AssertionError("No crs information for collection available."); + } + String featuresUrl = findFeaturesUrlForGeoJson(rootUri, collection); + if (featuresUrl == null) + throw new SkipException("Could not find url for collection with id " + collectionId + + " supporting GeoJson (type " + GEOJSON_MIME_TYPE + ")"); - Response response = init().baseUri( featuresUrl ).accept( GEOJSON_MIME_TYPE ).when().request( GET ); - response.then().statusCode( 200 ); - String crsHeader = response.getHeader( "Content-Crs" ); - if ( crsHeader == null ) { - throw new AssertionError( String.format( "Features response at '%s' does not provide the expected header 'Content-Crs'", - featuresUrl ) ); - } - assertDefaultCrs( crsHeader, - String.format( "Features response at '%s' does not provide default 'Content-Crs' header, was: '%s', expected: '%s' or '%s'", - featuresUrl, crsHeader, DEFAULT_CRS_CODE, DEFAULT_CRS_WITH_HEIGHT_CODE ) ); - String crs = crsHeader.substring( 1, crsHeader.length() - 1 ); + Response response = init().baseUri(featuresUrl).accept(GEOJSON_MIME_TYPE).when().request(GET); + response.then().statusCode(200); + String crsHeader = response.getHeader("Content-Crs"); + if (crsHeader == null) { + throw new AssertionError(String + .format("Features response at '%s' does not provide the expected header 'Content-Crs'", featuresUrl)); + } + assertDefaultCrs(crsHeader, String.format( + "Features response at '%s' does not provide default 'Content-Crs' header, was: '%s', expected: '%s' or '%s'", + featuresUrl, crsHeader, DEFAULT_CRS_CODE, DEFAULT_CRS_WITH_HEIGHT_CODE)); + String crs = crsHeader.substring(1, crsHeader.length() - 1); - JsonPath jsonPath = response.jsonPath(); - List> features = jsonPath.getList( "features" ); - for ( Map feature : features ) { - String featureId = feature.get( "id" ).toString(); - Geometry geometry = JsonUtils.parseFeatureGeometry( feature, new CoordinateSystem( crs ) ); - collectionIdAndFeatureIdToGeometry.put( collectionId, featureId, geometry ); - } - } + JsonPath jsonPath = response.jsonPath(); + List> features = jsonPath.getList("features"); + for (Map feature : features) { + String featureId = feature.get("id").toString(); + Geometry geometry = JsonUtils.parseFeatureGeometry(feature, new CoordinateSystem(crs)); + collectionIdAndFeatureIdToGeometry.put(collectionId, featureId, geometry); + } + } - /** - * Test: transformed geometries in the path /collections/{collectionId}/items - * - * @param collectionId - * id id of the collection, never null - * @param collection - * the /collection object, never null - * @param crs - * the crs to test, never null - * @param defaultCRS - * the defaultCRS of the collection, never null - * @throws ParseException - * if the geometry could not be parsed - */ - @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 7 (Requirement /req/crs/crs-action), " - + "Transformed geometries in the path /collections/{collectionId}/items", dataProvider = "collectionIdAndJsonAndCrsAndDefaultCrs", dependsOnGroups = "crs-conformance", dependsOnMethods = "verifyFeaturesCrsParameterTransformWithoutCrsParameter", priority = 1) - public void verifyFeaturesCrsParameterTransformWithCrsParameter( String collectionId, JsonPath collection, CoordinateSystem crs, - CoordinateSystem defaultCRS ) - throws ParseException { - if((collectionId == null) & (collection == null) & (crs == null) & (defaultCRS == null)) { - throw new AssertionError("No crs information for collection available."); - } - String featuresUrl = findFeaturesUrlForGeoJson( rootUri, collection ); - if ( featuresUrl == null ) - throw new SkipException( String.format( "Could not find url for collection with id %s supporting GeoJson (type %s)", - collectionId, GEOJSON_MIME_TYPE ) ); + /** + * Test: transformed geometries in the path /collections/{collectionId}/items + * @param collectionId id id of the collection, never null + * @param collection the /collection object, never null + * @param crs the crs to test, never null + * @param defaultCRS the defaultCRS of the collection, never null + * @throws org.locationtech.jts.io.ParseException if the geometry could not be parsed + */ + @Test(description = "Implements A.2.1 Query, Parameter crs, Abstract Test 7 (Requirement /req/crs/crs-action), " + + "Transformed geometries in the path /collections/{collectionId}/items", + dataProvider = "collectionIdAndJsonAndCrsAndDefaultCrs", dependsOnGroups = "crs-conformance", + dependsOnMethods = "verifyFeaturesCrsParameterTransformWithoutCrsParameter", priority = 1) + public void verifyFeaturesCrsParameterTransformWithCrsParameter(String collectionId, JsonPath collection, + CoordinateSystem crs, CoordinateSystem defaultCRS) throws ParseException { + if ((collectionId == null) & (collection == null) & (crs == null) & (defaultCRS == null)) { + throw new AssertionError("No crs information for collection available."); + } + String featuresUrl = findFeaturesUrlForGeoJson(rootUri, collection); + if (featuresUrl == null) + throw new SkipException( + String.format("Could not find url for collection with id %s supporting GeoJson (type %s)", + collectionId, GEOJSON_MIME_TYPE)); - Response response = init().baseUri( featuresUrl ).queryParam( CRS_PARAMETER, - crs.getCode() ).accept( GEOJSON_MIME_TYPE ).when().request( GET ); - response.then().statusCode( 200 ); + Response response = init().baseUri(featuresUrl) + .queryParam(CRS_PARAMETER, crs.getCode()) + .accept(GEOJSON_MIME_TYPE) + .when() + .request(GET); + response.then().statusCode(200); - JsonPath jsonPath = response.jsonPath(); - List> features = jsonPath.getList( "features" ); - for ( Map feature : features ) { - String featureId = feature.get( "id" ).toString(); - Geometry geometry = JsonUtils.parseFeatureGeometry( feature, crs ); - Geometry geometryInDefaultCrs = (Geometry) collectionIdAndFeatureIdToGeometry.get( collectionId, - featureId ); - GeometryTransformer geometryTransformer = new GeometryTransformer( crs, defaultCRS ); - Geometry transformedGeometry = geometryTransformer.transform( geometry ); - geometryInDefaultCrs.equalsExact( transformedGeometry, 0.001 ); - } - } + JsonPath jsonPath = response.jsonPath(); + List> features = jsonPath.getList("features"); + for (Map feature : features) { + String featureId = feature.get("id").toString(); + Geometry geometry = JsonUtils.parseFeatureGeometry(feature, crs); + Geometry geometryInDefaultCrs = (Geometry) collectionIdAndFeatureIdToGeometry.get(collectionId, featureId); + GeometryTransformer geometryTransformer = new GeometryTransformer(crs, defaultCRS); + Geometry transformedGeometry = geometryTransformer.transform(geometry); + geometryInDefaultCrs.equalsExact(transformedGeometry, 0.001); + } + } -} \ No newline at end of file +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/exception/UnknownCrsException.java b/src/main/java/org/opengis/cite/ogcapifeatures10/exception/UnknownCrsException.java index d8f10b77..3459d38e 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/exception/UnknownCrsException.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/exception/UnknownCrsException.java @@ -3,12 +3,22 @@ import org.testng.SkipException; /** + *

    + * UnknownCrsException class. + *

    + * * @author Lyn Goltz */ public class UnknownCrsException extends SkipException { - public UnknownCrsException( String skipMessage ) { - super( skipMessage ); - } + /** + *

    + * Constructor for UnknownCrsException. + *

    + * @param skipMessage a {@link java.lang.String} object + */ + public UnknownCrsException(String skipMessage) { + super(skipMessage); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/listener/LoggingTestListener.java b/src/main/java/org/opengis/cite/ogcapifeatures10/listener/LoggingTestListener.java index 5edd71e7..89398280 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/listener/LoggingTestListener.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/listener/LoggingTestListener.java @@ -6,33 +6,43 @@ import org.testng.ITestResult; import org.testng.TestListenerAdapter; +/** + *

    + * LoggingTestListener class. + *

    + * + */ public class LoggingTestListener extends TestListenerAdapter { - - private static final Logger LOGR = Logger.getLogger(LoggingTestListener.class.getName()); - - @Override - public void onTestStart(ITestResult result) { - super.onTestStart(result); - ITestNGMethod testMethod = result.getMethod(); - LOGR.info("Invoking test " + testMethod.getMethodName() + ": " + testMethod.getDescription()); - } - - @Override - public void onTestFailure(ITestResult tr) { - super.onTestFailure(tr); - LOGR.info(tr.getMethod().getMethodName() + " failed"); - } - - @Override - public void onTestSkipped(ITestResult tr) { - super.onTestSkipped(tr); - LOGR.info(tr.getMethod().getMethodName() + " was skipped"); - } - - @Override - public void onTestSuccess(ITestResult tr) { - super.onTestSuccess(tr); - LOGR.info(tr.getMethod().getMethodName() + " passed"); - } + + private static final Logger LOGR = Logger.getLogger(LoggingTestListener.class.getName()); + + /** {@inheritDoc} */ + @Override + public void onTestStart(ITestResult result) { + super.onTestStart(result); + ITestNGMethod testMethod = result.getMethod(); + LOGR.info("Invoking test " + testMethod.getMethodName() + ": " + testMethod.getDescription()); + } + + /** {@inheritDoc} */ + @Override + public void onTestFailure(ITestResult tr) { + super.onTestFailure(tr); + LOGR.info(tr.getMethod().getMethodName() + " failed"); + } + + /** {@inheritDoc} */ + @Override + public void onTestSkipped(ITestResult tr) { + super.onTestSkipped(tr); + LOGR.info(tr.getMethod().getMethodName() + " was skipped"); + } + + /** {@inheritDoc} */ + @Override + public void onTestSuccess(ITestResult tr) { + super.onTestSuccess(tr); + LOGR.info(tr.getMethod().getMethodName() + " passed"); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/listener/SuiteFixtureListener.java b/src/main/java/org/opengis/cite/ogcapifeatures10/listener/SuiteFixtureListener.java index 55bcab82..6eac5d43 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/listener/SuiteFixtureListener.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/listener/SuiteFixtureListener.java @@ -16,103 +16,105 @@ import org.testng.ISuite; import org.testng.ISuiteListener; -import com.sun.jersey.api.client.Client; +import jakarta.ws.rs.client.Client; /** - * A listener that performs various tasks before and after a test suite is run, usually concerned with maintaining a - * shared test suite fixture. Since this listener is loaded using the ServiceLoader mechanism, its methods will be - * called before those of other suite listeners listed in the test suite definition and before any annotated + * A listener that performs various tasks before and after a test suite is run, usually + * concerned with maintaining a shared test suite fixture. Since this listener is loaded + * using the ServiceLoader mechanism, its methods will be called before those of other + * suite listeners listed in the test suite definition and before any annotated * configuration methods. * - * Attributes set on an ISuite instance are not inherited by constituent test group contexts (ITestContext). However, - * suite attributes are still accessible from lower contexts. + * Attributes set on an ISuite instance are not inherited by constituent test group + * contexts (ITestContext). However, suite attributes are still accessible from lower + * contexts. * * @see org.testng.ISuite ISuite interface */ public class SuiteFixtureListener implements ISuiteListener { - @Override - public void onStart( ISuite suite ) { - processSuiteParameters( suite ); - registerClientComponent( suite ); - } + /** {@inheritDoc} */ + @Override + public void onStart(ISuite suite) { + processSuiteParameters(suite); + registerClientComponent(suite); + } - @Override - public void onFinish( ISuite suite ) { - if ( null != System.getProperty( "deleteSubjectOnFinish" ) ) { - deleteTempFiles( suite ); - System.getProperties().remove( "deleteSubjectOnFinish" ); - } - } + /** {@inheritDoc} */ + @Override + public void onFinish(ISuite suite) { + if (null != System.getProperty("deleteSubjectOnFinish")) { + deleteTempFiles(suite); + System.getProperties().remove("deleteSubjectOnFinish"); + } + } - /** - * Processes test suite arguments and sets suite attributes accordingly. The entity referenced by the - * {@link TestRunArg#IUT iut} argument is retrieved and written to a File that is set as the value of the suite - * attribute {@link SuiteAttribute#TEST_SUBJ_FILE testSubjectFile}. - * - * @param suite - * An ISuite object representing a TestNG test suite. - */ - void processSuiteParameters( ISuite suite ) { - Map params = suite.getXmlSuite().getParameters(); - TestSuiteLogger.log( Level.CONFIG, "Suite parameters\n" + params.toString() ); - String iutParam = params.get( TestRunArg.IUT.toString() ); - if ( ( null == iutParam ) || iutParam.isEmpty() ) { - throw new IllegalArgumentException( "Required test run parameter not found: " + TestRunArg.IUT.toString() ); - } - URI iutRef = URI.create( iutParam.trim() ); - suite.setAttribute( SuiteAttribute.IUT.getName(), iutRef ); - File entityFile; - try { - entityFile = URIUtils.dereferenceURI( iutRef ); - } catch ( IOException iox ) { - throw new RuntimeException( "Failed to dereference resource located at " + iutRef, iox ); - } - TestSuiteLogger.log( Level.FINE, String.format( "Wrote test subject to file: %s (%d bytes)", - entityFile.getAbsolutePath(), entityFile.length() ) ); - suite.setAttribute( SuiteAttribute.TEST_SUBJ_FILE.getName(), entityFile ); + /** + * Processes test suite arguments and sets suite attributes accordingly. The entity + * referenced by the {@link TestRunArg#IUT iut} argument is retrieved and written to a + * File that is set as the value of the suite attribute + * {@link SuiteAttribute#TEST_SUBJ_FILE testSubjectFile}. + * @param suite An ISuite object representing a TestNG test suite. + */ + void processSuiteParameters(ISuite suite) { + Map params = suite.getXmlSuite().getParameters(); + TestSuiteLogger.log(Level.CONFIG, "Suite parameters\n" + params.toString()); + String iutParam = params.get(TestRunArg.IUT.toString()); + if ((null == iutParam) || iutParam.isEmpty()) { + throw new IllegalArgumentException("Required test run parameter not found: " + TestRunArg.IUT.toString()); + } + URI iutRef = URI.create(iutParam.trim()); + suite.setAttribute(SuiteAttribute.IUT.getName(), iutRef); + File entityFile; + try { + entityFile = URIUtils.dereferenceURI(iutRef); + } + catch (IOException iox) { + throw new RuntimeException("Failed to dereference resource located at " + iutRef, iox); + } + TestSuiteLogger.log(Level.FINE, String.format("Wrote test subject to file: %s (%d bytes)", + entityFile.getAbsolutePath(), entityFile.length())); + suite.setAttribute(SuiteAttribute.TEST_SUBJ_FILE.getName(), entityFile); - String noOfCollections = params.get( TestRunArg.NOOFCOLLECTIONS.toString() ); - try { - if ( noOfCollections != null ) { - int noOfCollectionsInt = Integer.parseInt( noOfCollections ); - suite.setAttribute( SuiteAttribute.NO_OF_COLLECTIONS.getName(), noOfCollectionsInt ); - } - } catch ( NumberFormatException e ) { - TestSuiteLogger.log( WARNING, - String.format( "Could not parse parameter %s: %s. Expected is a valid integer", - TestRunArg.NOOFCOLLECTIONS, noOfCollections ) ); - } - } + String noOfCollections = params.get(TestRunArg.NOOFCOLLECTIONS.toString()); + try { + if (noOfCollections != null) { + int noOfCollectionsInt = Integer.parseInt(noOfCollections); + suite.setAttribute(SuiteAttribute.NO_OF_COLLECTIONS.getName(), noOfCollectionsInt); + } + } + catch (NumberFormatException e) { + TestSuiteLogger.log(WARNING, String.format("Could not parse parameter %s: %s. Expected is a valid integer", + TestRunArg.NOOFCOLLECTIONS, noOfCollections)); + } + } - /** - * A client component is added to the suite fixture as the value of the {@link SuiteAttribute#CLIENT} attribute; it - * may be subsequently accessed via the {@link org.testng.ITestContext#getSuite()} method. - * - * @param suite - * The test suite instance. - */ - void registerClientComponent( ISuite suite ) { - Client client = ClientUtils.buildClient(); - if ( null != client ) { - suite.setAttribute( SuiteAttribute.CLIENT.getName(), client ); - } - } + /** + * A client component is added to the suite fixture as the value of the + * {@link SuiteAttribute#CLIENT} attribute; it may be subsequently accessed via the + * {@link org.testng.ITestContext#getSuite()} method. + * @param suite The test suite instance. + */ + void registerClientComponent(ISuite suite) { + Client client = ClientUtils.buildClient(); + if (null != client) { + suite.setAttribute(SuiteAttribute.CLIENT.getName(), client); + } + } + + /** + * Deletes temporary files created during the test run if TestSuiteLogger is enabled + * at the INFO level or higher (they are left intact at the CONFIG level or lower). + * @param suite The test suite. + */ + void deleteTempFiles(ISuite suite) { + if (TestSuiteLogger.isLoggable(Level.CONFIG)) { + return; + } + File testSubjFile = (File) suite.getAttribute(SuiteAttribute.TEST_SUBJ_FILE.getName()); + if (testSubjFile.exists()) { + testSubjFile.delete(); + } + } - /** - * Deletes temporary files created during the test run if TestSuiteLogger is enabled at the INFO level or higher - * (they are left intact at the CONFIG level or lower). - * - * @param suite - * The test suite. - */ - void deleteTempFiles( ISuite suite ) { - if ( TestSuiteLogger.isLoggable( Level.CONFIG ) ) { - return; - } - File testSubjFile = (File) suite.getAttribute( SuiteAttribute.TEST_SUBJ_FILE.getName() ); - if ( testSubjFile.exists() ) { - testSubjFile.delete(); - } - } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/listener/TestFailureListener.java b/src/main/java/org/opengis/cite/ogcapifeatures10/listener/TestFailureListener.java index e254bce8..387ea1ce 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/listener/TestFailureListener.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/listener/TestFailureListener.java @@ -1,10 +1,9 @@ package org.opengis.cite.ogcapifeatures10.listener; -import com.sun.jersey.api.client.ClientRequest; -import com.sun.jersey.api.client.ClientResponse; import java.nio.charset.StandardCharsets; -import javax.ws.rs.core.MediaType; +import org.glassfish.jersey.client.ClientRequest; +import org.glassfish.jersey.client.ClientResponse; import org.opengis.cite.ogcapifeatures10.conformance.CommonFixture; import org.opengis.cite.ogcapifeatures10.util.ClientUtils; import org.opengis.cite.ogcapifeatures10.util.XMLUtils; @@ -12,88 +11,88 @@ import org.testng.TestListenerAdapter; import org.w3c.dom.Document; +import jakarta.ws.rs.core.MediaType; + /** - * A listener that augments a test result with diagnostic information in the - * event that a test method failed. This information will appear in the XML - * report when the test run is completed. + * A listener that augments a test result with diagnostic information in the event that a + * test method failed. This information will appear in the XML report when the test run is + * completed. */ public class TestFailureListener extends TestListenerAdapter { - /** - * Sets the "request" and "response" attributes of a test result. The value - * of these attributes is a string that contains information about the - * content of an outgoing or incoming message: target resource, status code, - * headers, entity (if present). The entity is represented as a String with - * UTF-8 character encoding. - * - * @param result A description of a test result (with a fail verdict). - */ - @Override - public void onTestFailure(ITestResult result) { - super.onTestFailure(result); - Object instance = result.getInstance(); - if ( CommonFixture.class.isInstance( instance)) { - CommonFixture fixture = CommonFixture.class.cast(instance); - result.setAttribute("request", fixture.getRequest()); - result.setAttribute("response", fixture.getResponse()); - } - } + /** + * {@inheritDoc} + * + * Sets the "request" and "response" attributes of a test result. The value of these + * attributes is a string that contains information about the content of an outgoing + * or incoming message: target resource, status code, headers, entity (if present). + * The entity is represented as a String with UTF-8 character encoding. + */ + @Override + public void onTestFailure(ITestResult result) { + super.onTestFailure(result); + Object instance = result.getInstance(); + if (CommonFixture.class.isInstance(instance)) { + CommonFixture fixture = CommonFixture.class.cast(instance); + result.setAttribute("request", fixture.getRequest()); + result.setAttribute("response", fixture.getResponse()); + } + } - /** - * Gets diagnostic information about a request message. If the request - * contains a message body, it should be represented as a DOM Document node - * or as an object having a meaningful toString() implementation. - * - * @param req An object representing an HTTP request message. - * @return A string containing information gleaned from the request message. - */ - String getRequestMessageInfo(ClientRequest req) { - if (null == req) { - return "No request message."; - } - StringBuilder msgInfo = new StringBuilder(); - msgInfo.append("Method: ").append(req.getMethod()).append('\n'); - msgInfo.append("Target URI: ").append(req.getURI()).append('\n'); - msgInfo.append("Headers: ").append(req.getHeaders()).append('\n'); - if (null != req.getEntity()) { - Object entity = req.getEntity(); - String body; - if (Document.class.isInstance(entity)) { - Document doc = Document.class.cast(entity); - body = XMLUtils.writeNodeToString(doc); - } else { - body = entity.toString(); - } - msgInfo.append(body).append('\n'); - } - return msgInfo.toString(); - } + /** + * Gets diagnostic information about a request message. If the request contains a + * message body, it should be represented as a DOM Document node or as an object + * having a meaningful toString() implementation. + * @param req An object representing an HTTP request message. + * @return A string containing information gleaned from the request message. + */ + String getRequestMessageInfo(ClientRequest req) { + if (null == req) { + return "No request message."; + } + StringBuilder msgInfo = new StringBuilder(); + msgInfo.append("Method: ").append(req.getMethod()).append('\n'); + msgInfo.append("Target URI: ").append(req.getUri()).append('\n'); + msgInfo.append("Headers: ").append(req.getHeaders()).append('\n'); + if (null != req.getEntity()) { + Object entity = req.getEntity(); + String body; + if (Document.class.isInstance(entity)) { + Document doc = Document.class.cast(entity); + body = XMLUtils.writeNodeToString(doc); + } + else { + body = entity.toString(); + } + msgInfo.append(body).append('\n'); + } + return msgInfo.toString(); + } - /** - * Gets diagnostic information about a response message. - * - * @param rsp An object representing an HTTP response message. - * @return A string containing information gleaned from the response - * message. - */ - String getResponseMessageInfo(ClientResponse rsp) { - if (null == rsp) { - return "No response message."; - } - StringBuilder msgInfo = new StringBuilder(); - msgInfo.append("Status: ").append(rsp.getStatus()).append('\n'); - msgInfo.append("Headers: ").append(rsp.getHeaders()).append('\n'); - if (rsp.hasEntity()) { - if (rsp.getType().isCompatible(MediaType.APPLICATION_XML_TYPE)) { - Document doc = ClientUtils.getResponseEntityAsDocument(rsp, null); - msgInfo.append(XMLUtils.writeNodeToString(doc)); - } else { - byte[] body = rsp.getEntity(byte[].class); - msgInfo.append(new String(body, StandardCharsets.UTF_8)); - } - msgInfo.append('\n'); - } - return msgInfo.toString(); - } + /** + * Gets diagnostic information about a response message. + * @param rsp An object representing an HTTP response message. + * @return A string containing information gleaned from the response message. + */ + String getResponseMessageInfo(ClientResponse rsp) { + if (null == rsp) { + return "No response message."; + } + StringBuilder msgInfo = new StringBuilder(); + msgInfo.append("Status: ").append(rsp.getStatus()).append('\n'); + msgInfo.append("Headers: ").append(rsp.getHeaders()).append('\n'); + if (rsp.hasEntity()) { + if (rsp.getMediaType().isCompatible(MediaType.APPLICATION_XML_TYPE)) { + Document doc = ClientUtils.getResponseEntityAsDocument(rsp, null); + msgInfo.append(XMLUtils.writeNodeToString(doc)); + } + else { + byte[] body = rsp.readEntity(byte[].class); + msgInfo.append(new String(body, StandardCharsets.UTF_8)); + } + msgInfo.append('\n'); + } + return msgInfo.toString(); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/listener/TestRunListener.java b/src/main/java/org/opengis/cite/ogcapifeatures10/listener/TestRunListener.java index f315c32a..88bd1948 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/listener/TestRunListener.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/listener/TestRunListener.java @@ -3,24 +3,28 @@ import org.testng.IExecutionListener; /** - * A listener that is invoked before and after a test run. It is often used to - * configure a shared fixture that endures for the duration of the entire test - * run. A FixtureManager may be used to manage such a fixture. + * A listener that is invoked before and after a test run. It is often used to configure a + * shared fixture that endures for the duration of the entire test run. A FixtureManager + * may be used to manage such a fixture. * - *

    A shared fixture should be used with caution in order to avoid undesirable - * test interactions. In general, it should be populated with "read-only" - * objects that are not modified during the test run.

    + *

    + * A shared fixture should be used with caution in order to avoid undesirable test + * interactions. In general, it should be populated with "read-only" objects that are not + * modified during the test run. + *

    * * @see com.occamlab.te.spi.executors.FixtureManager FixtureManager - * */ public class TestRunListener implements IExecutionListener { - @Override - public void onExecutionStart() { - } + /** {@inheritDoc} */ + @Override + public void onExecutionStart() { + } + + /** {@inheritDoc} */ + @Override + public void onExecutionFinish() { + } - @Override - public void onExecutionFinish() { - } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/openapi3/OpenApiUtils.java b/src/main/java/org/opengis/cite/ogcapifeatures10/openapi3/OpenApiUtils.java index d1c3cbcc..6fc2b9a1 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/openapi3/OpenApiUtils.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/openapi3/OpenApiUtils.java @@ -15,6 +15,8 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import org.glassfish.jersey.uri.UriTemplate; +import org.glassfish.jersey.uri.internal.UriTemplateParser; import org.opengis.cite.ogcapifeatures10.OgcApiFeatures10; import com.reprezen.kaizen.oasparser.model3.MediaType; @@ -25,594 +27,622 @@ import com.reprezen.kaizen.oasparser.model3.Response; import com.reprezen.kaizen.oasparser.model3.Schema; import com.reprezen.kaizen.oasparser.model3.Server; -import com.sun.jersey.api.uri.UriTemplate; -import com.sun.jersey.api.uri.UriTemplateParser; /** + *

    + * OpenApiUtils class. + *

    + * * @author Lyn Goltz */ public class OpenApiUtils { - // as described in https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#fixed-fields - private static final String DEFAULT_SERVER_URL = "/"; - - @FunctionalInterface - private interface PathMatcherFunction { - A apply( B b, C c ); - } - - enum PATH { - - CONFORMANCE( "conformance" ), COLLECTIONS( "collections" ); - - private String pathItem; - - PATH( String pathItem ) { - - this.pathItem = pathItem; - } - - private String getPathItem() { - return pathItem; - } - } - - private static class PathMatcher implements PathMatcherFunction { - @Override - public Boolean apply( String pathUnderTest, String pathToMatch ) { - UriTemplateParser parser = new UriTemplateParser( pathUnderTest ); - Matcher matcher = parser.getPattern().matcher( pathToMatch ); - return matcher.matches(); - } - } - - private static class ExactMatchFilter implements Predicate { - - private final String requestedPath; - - ExactMatchFilter( String requestedPath ) { - this.requestedPath = requestedPath; - } - - @Override - public boolean test( TestPoint testPoint ) { - UriTemplate uriTemplate = new UriTemplate( testPoint.getPath() ); - Map templateReplacement = new HashMap<>( testPoint.getPredefinedTemplateReplacement() ); - List templateVariables = uriTemplate.getTemplateVariables(); - for ( String templateVariable : templateVariables ) { - if ( !templateReplacement.containsKey( templateVariable ) ) - templateReplacement.put( templateVariable, ".*" ); - } - String uri = uriTemplate.createURI( templateReplacement ); - Pattern pattern = Pattern.compile( uri ); - return pattern.matcher( requestedPath ).matches(); - } - } - - private OpenApiUtils() { - } - - /** - * Parse all test points from the passed OpenApi3 document as described in A.4.3. Identify the Test Points. - * - * @param apiModel - * never null - * @param iut - * the url of the instance under test, never null - * @return the parsed test points, may be empty but never null - */ - static List retrieveTestPoints( OpenApi3 apiModel, URI iut ) { - List pathItemObjects = identifyTestPoints( apiModel ); - List pathItemAndServers = identifyServerUrls( apiModel, iut, pathItemObjects ); - return processServerObjects( pathItemAndServers, true ); - } - - /** - * Parse the CONFORMANCE test points from the passed OpenApi3 document as described in A.4.3. Identify the Test - * Points. - * - * @param apiModel - * never null - * @param iut - * the url of the instance under test, never null - * @return the parsed test points, may be empty but never null - */ - public static List retrieveTestPointsForConformance( OpenApi3 apiModel, URI iut ) { - return retrieveTestPoints( apiModel, iut, CONFORMANCE, false ); - } - - /** - * Parse the COLLECTIONS METADATA test points from the passed OpenApi3 document as described in A.4.3. Identify the - * Test Points. - * - * @param apiModel - * never null - * @param iut - * the url of the instance under test, never null - * @return the parsed test points, may be empty but never null - */ - public static List retrieveTestPointsForCollectionsMetadata( OpenApi3 apiModel, URI iut ) { - return retrieveTestPoints( apiModel, iut, COLLECTIONS, false ); - } - - /** - * Parse the COLLECTION METADATA test points for the passed collectionName including the extended path from the - * passed OpenApi3 document as described in A.4.3. Identify the Test Points. - * - * @param apiModel - * never null - * @param iut - * the url of the instance under test, never null - * @param collectionName - * the extended path, may be null - * @return the parsed test points, may be empty but never null - */ - public static List retrieveTestPointsForCollectionMetadata( OpenApi3 apiModel, URI iut, String collectionName ) { - StringBuilder requestedPath = new StringBuilder(); - requestedPath.append(findBasePath(apiModel, iut)); - requestedPath.append( COLLECTIONS.getPathItem() ); - requestedPath.append( "/" ); - requestedPath.append( collectionName ); - - List testPoints = retrieveTestPoints( apiModel, iut, requestedPath.toString(), true ); - return testPoints.stream().filter( new ExactMatchFilter( requestedPath.toString() ) ).collect( Collectors.toList() ); - } - - /** - * Parse the COLLECTIONS test points from the passed OpenApi3 document as described in A.4.3. Identify the Test - * Points. - * - * @param apiModel - * never null - * @param iut - * the url of the instance under test, never null - * @param noOfCollection - * the number of collections to return test points for (-1 means the test points of all collections - * should be returned) - * @return the parsed test points, may be empty but never null - */ - public static List retrieveTestPointsForCollections( OpenApi3 apiModel, URI iut, int noOfCollection ) { - StringBuilder requestedPath = new StringBuilder(); - requestedPath.append(findBasePath(apiModel, iut)); - requestedPath.append( COLLECTIONS.getPathItem() ); - requestedPath.append( "/.*/items" ); - - List allTestPoints = retrieveTestPoints( apiModel, iut, requestedPath.toString(), - ( a, b ) -> a.matches( b ), true ); - if(noOfCollection < 0 && allTestPoints.size() > OgcApiFeatures10.COLLECTIONS_LIMIT) { - return allTestPoints.subList( 0, OgcApiFeatures10.COLLECTIONS_LIMIT ); - } else if ( noOfCollection < 0 || allTestPoints.size() <= noOfCollection) { - return allTestPoints; - } - return allTestPoints.subList( 0, noOfCollection ); - } - - /** - * Parse the test points with the passed path including the extended path from the passed OpenApi3 document as - * described in A.4.3. Identify the Test Points. - * - * @param apiModel - * never null - * @param iut - * the url of the instance under test, never null - * @param collectionName - * the extended path, may be null - * @return the parsed test points, may be empty but never null - */ - public static List retrieveTestPointsForCollection( OpenApi3 apiModel, URI iut, String collectionName ) { - String requestedPath = createCollectionPath(apiModel, iut, collectionName); - - List testPoints = retrieveTestPoints( apiModel, iut, requestedPath, true ); - return testPoints.stream().filter( new ExactMatchFilter( requestedPath ) ).collect( Collectors.toList() ); - } - - /** - * Parse the test points with the passed path including the extended path from the passed OpenApi3 document as - * described in A.4.3. Identify the Test Points. - * - * @param apiModel - * never null - * @param iut - * the url of the instance under test, never null - * @param collectionName - * the extended path, may be null - * @param featureId - * the id of the feature, never null - * @return the parsed test points, may be empty but never null - */ - public static List retrieveTestPointsForFeature( OpenApi3 apiModel, URI iut, String collectionName, - String featureId ) { - StringBuilder requestedPath = new StringBuilder(); - requestedPath.append(findBasePath(apiModel, iut)); - requestedPath.append( COLLECTIONS.getPathItem() ); - requestedPath.append( "/" ); - requestedPath.append( collectionName ); - requestedPath.append( "/items/" ); - requestedPath.append( featureId ); - - List testPoints = retrieveTestPoints( apiModel, iut, requestedPath.toString(), true ); - return testPoints.stream().filter( new ExactMatchFilter( requestedPath.toString() ) ).collect( Collectors.toList() ); - } - - public static Parameter retrieveParameterByName( String collectionItemPath, OpenApi3 apiModel, String name ) { - Path path = apiModel.getPath( collectionItemPath ); - if ( path != null ) { - for ( Parameter parameter : path.getParameters() ) - if ( name.equals( parameter.getName() ) ) - return parameter; - Operation get = path.getOperation( "get" ); - for ( Parameter parameter : get.getParameters() ) - if ( name.equals( parameter.getName() ) ) - return parameter; - } - return null; - } - - public static boolean isFreeFormParameterSupportedForCollection( OpenApi3 apiModel, URI iut, String collectionName ) { - String requestedPath = createCollectionPath(apiModel, iut, collectionName); - - List paths = identifyTestPoints( apiModel, requestedPath, new PathMatcher() ); - for ( Path path : paths ) { - Collection parameters = path.getGet().getParameters(); - for ( Parameter parameter : parameters ) { - if ( parameter.getSchema() != null && parameter.getSchema().isAdditionalProperties() ) { - return true; - } - } - } - return false; - } - - public static boolean isParameterSupportedForCollection( OpenApi3 apiModel, URI iut, String collectionName, - String queryParam ) { - String requestedPath = createCollectionPath(apiModel, iut, collectionName); - - List paths = identifyTestPoints( apiModel, requestedPath, new PathMatcher() ); - for ( Path path : paths ) { - Collection parameters = path.getGet().getParameters(); - for ( Parameter parameter : parameters ) { - if ( queryParam.equalsIgnoreCase( parameter.getName() ) ) { - return true; - } - } - } - return false; - } - - private static String createCollectionPath(OpenApi3 apiModel, URI iut, String collectionName) { - StringBuilder requestedPath = new StringBuilder(); - requestedPath.append(findBasePath(apiModel, iut)); - requestedPath.append( COLLECTIONS.getPathItem() ); - requestedPath.append( "/" ); - requestedPath.append( collectionName ); - requestedPath.append( "/items" ); - return requestedPath.toString(); - } - - private static List retrieveTestPoints( OpenApi3 apiModel, URI iut, PATH path, boolean allowEmptyTemplateReplacements ) { - String requestedPath = findBasePath(apiModel, iut) + path.getPathItem(); - return retrieveTestPoints( apiModel, iut, requestedPath, allowEmptyTemplateReplacements ); - } - - private static List retrieveTestPoints( OpenApi3 apiModel, URI iut, String requestedPath, boolean allowEmptyTemplateReplacements ) { - return retrieveTestPoints( apiModel, iut, requestedPath, new PathMatcher(), allowEmptyTemplateReplacements ); - } - - private static List retrieveTestPoints( OpenApi3 apiModel, URI iut, String requestedPath, - PathMatcherFunction pathMatcher, boolean allowEmptyTemplateReplacements ) { - List pathItemObjects = identifyTestPoints( apiModel, requestedPath, pathMatcher ); - List pathItemAndServers = identifyServerUrls( apiModel, iut, pathItemObjects ); - return processServerObjects( pathItemAndServers, allowEmptyTemplateReplacements ); - } - - /** - * A.4.3.1. Identify Test Points: - * - * a) Purpose: To identify the test points associated with each Path in the OpenAPI document - * - * b) Pre-conditions: - * - * An OpenAPI document has been obtained - * - * A list of URLs for the servers to be included in the compliance test has been provided - * - * A list of the paths specified in the WFS 3.0 specification - * - * c) Method: - * - * FOR EACH paths property in the OpenAPI document If the path name is one of those specified in the WFS 3.0 - * specification Retrieve the Server URIs using A.4.3.2. FOR EACH Server URI Concatenate the Server URI with the - * path name to form a test point. Add that test point to the list. - * - * d) References: None - * - * @param apiModel - * never null - */ - private static List identifyTestPoints( OpenApi3 apiModel ) { - List allTestPoints = new ArrayList<>(); - for ( PATH path : PATH.values() ) - allTestPoints.addAll( identifyTestPoints( apiModel, "/" + path.getPathItem(), new PathMatcher() ) ); - return allTestPoints; - } - - private static List identifyTestPoints( OpenApi3 apiModel, String path, - PathMatcherFunction pathMatch ) { - List pathItems = new ArrayList<>(); - Map pathItemObjects = apiModel.getPaths(); - for ( Path pathItemObject : pathItemObjects.values() ) { - String pathString = pathItemObject.getPathString(); - if ( pathMatch.apply( pathString, path ) ) { - pathItems.add( pathItemObject ); - } - } - return pathItems; - } - - /** - * A.4.3.2. Identify Server URIs: - * - * a) Purpose: To identify all server URIs applicable to an OpenAPI Operation Object - * - * b) Pre-conditions: - * - * Server Objects from the root level of the OpenAPI document have been obtained - * - * A Path Item Object has been retrieved - * - * An Operation Object has been retrieved - * - * The Operation Object is associated with the Path Item Object - * - * A list of URLs for the servers to be included in the compliance test has been provided - * - * c) Method: - * - * 1) Identify the Server Objects which are in-scope for this operationObject - * - * IF Server Objects are defined at the Operation level, then those and only those Server Objects apply to that - * Operation. - * - * IF Server Objects are defined at the Path Item level, then those and only those Server Objects apply to that Path - * Item. - * - * IF Server Objects are not defined at the Operation level, then the Server Objects defined for the parent Path - * Item apply to that Operation. - * - * IF Server Objects are not defined at the Path Item level, then the Server Objects defined for the root level - * apply to that Path. - * - * IF no Server Objects are defined at the root level, then the default server object is assumed as described in the - * OpenAPI specification. - * - * 2) Process each Server Object using A.4.3.3. - * - * 3) Delete any Server URI which does not reference a server on the list of servers to test. - * - * d) References: None - * - * @param apiModel - * never null - * @param iut - * never null - * @param pathItemObjects - * never null - */ - private static List identifyServerUrls( OpenApi3 apiModel, URI iut, List pathItemObjects ) { - List pathItemAndServers = new ArrayList<>(); - - for ( Path pathItemObject : pathItemObjects ) { - Map operationObjects = pathItemObject.getOperations(); - for ( Operation operationObject : operationObjects.values() ) { - List serverUrls = identifyServerObjects( apiModel, pathItemObject, operationObject ); - for ( String serverUrl : serverUrls ) { - if ( DEFAULT_SERVER_URL.equalsIgnoreCase( serverUrl ) ) { - serverUrl = iut.toString(); - } else if ( serverUrl.startsWith( "/" ) ) { - URI resolvedUri = iut.resolve( serverUrl ); - serverUrl = resolvedUri.toString(); - } - PathItemAndServer pathItemAndServer = new PathItemAndServer( pathItemObject, operationObject, - serverUrl ); - pathItemAndServers.add( pathItemAndServer ); - } - } - } - return pathItemAndServers; - } - - /** - * A.4.3.3. Process Server Object: - * - * a) Purpose: To expand the contents of a Server Object into a set of absolute URIs. - * - * b) Pre-conditions: A Server Object has been retrieved - * - * c) Method: - * - * Processing the Server Object results in a set of absolute URIs. This set contains all of the URIs that can be - * created given the URI template and variables defined in that Server Object. - * - * If there are no variables in the URI template, then add the URI to the return set. - * - * For each variable in the URI template which does not have an enumerated set of valid values: - * - * generate a URI using the default value, - * - * add this URI to the return set, - * - * flag this URI as non-exhaustive - * - * For each variable in the URI template which has an enumerated set of valid values: - * - * generate a URI for each value in the enumerated set, - * - * add each generated URI to the return set. - * - * Perform this processing in an iterative manner so that there is a unique URI for all possible combinations of - * enumerated and default values. - * - * Convert all relative URIs to absolute URIs by rooting them on the URI to the server hosting the OpenAPI document. - * - * d) References: None - * - * @param pathItemAndServers - * never null - */ - private static List processServerObjects( List pathItemAndServers, boolean allowEmptyTemplateReplacements ) { - List uris = new ArrayList<>(); - for ( PathItemAndServer pathItemAndServer : pathItemAndServers ) { - processServerObject( uris, pathItemAndServer, allowEmptyTemplateReplacements ); - } - return uris; - } - - private static void processServerObject( List uris, PathItemAndServer pathItemAndServer, boolean allowEmptyTemplateReplacements ) { - String pathString = pathItemAndServer.pathItemObject.getPathString(); - Response response = getResponse(pathItemAndServer); - if ( response == null ) - return; - Map contentMediaTypes = response.getContentMediaTypes(); - - UriTemplate uriTemplate = new UriTemplate( pathItemAndServer.serverUrl + pathString ); - if ( uriTemplate.getNumberOfTemplateVariables() == 0 ) { - TestPoint testPoint = new TestPoint( pathItemAndServer.serverUrl, pathString, contentMediaTypes ); - uris.add( testPoint ); - } else { - List> templateReplacements = collectTemplateReplacements( pathItemAndServer, - uriTemplate ); - - if ( templateReplacements.isEmpty() && allowEmptyTemplateReplacements ) { - TestPoint testPoint = new TestPoint( pathItemAndServer.serverUrl, pathString, contentMediaTypes ); - uris.add( testPoint ); - } else { - for ( Map templateReplacement : templateReplacements ) { - TestPoint testPoint = new TestPoint( pathItemAndServer.serverUrl, pathString, templateReplacement, - contentMediaTypes ); - uris.add( testPoint ); - } - } - } - } - - private static Response getResponse( PathItemAndServer pathItemAndServer ) { - if ( pathItemAndServer.operationObject.hasResponse( "200" ) ) - return pathItemAndServer.operationObject.getResponse( "200" ); - if ( pathItemAndServer.operationObject.hasResponse( "default" ) ) - return pathItemAndServer.operationObject.getResponse( "default" ); - return null; - } - - private static List> collectTemplateReplacements( PathItemAndServer pathItemAndServer, - UriTemplate uriTemplate ) { - List> templateReplacements = new ArrayList<>(); - Collection parameters = pathItemAndServer.operationObject.getParameters(); - for ( String templateVariable : uriTemplate.getTemplateVariables() ) { - for ( Parameter parameter : parameters ) { - if ( templateVariable.equals( parameter.getName() ) ) { - Schema schema = parameter.getSchema(); - if ( schema.hasEnums() ) { - addEnumTemplateValues( templateReplacements, templateVariable, schema ); - } else if ( schema.getDefault() != null ) { - addDefaultTemplateValue( templateReplacements, templateVariable, schema ); - } else { - // TODO: What should be done if the parameter does not have a default value and no - // enumerated set of valid values? - } - } - } - } - return templateReplacements; - } - - private static void addEnumTemplateValues( List> templateReplacements, String templateVariable, - Schema schema ) { - Collection enums = schema.getEnums(); - if ( enums.size() == 1 ) { - for ( Object enumValue : enums ) { - Map replacement = new HashMap<>(); - replacement.put( templateVariable, enumValue.toString() ); - templateReplacements.add( replacement ); - } - } else { - if ( templateReplacements.isEmpty() ) { - Map replacement = new HashMap<>(); - templateReplacements.add( replacement ); - } - List> templateReplacementsToAdd = new ArrayList<>(); - for ( Map templateReplacement : templateReplacements ) { - for ( Object enumValue : enums ) { - Map newTemplateReplacement = new HashMap<>(); - newTemplateReplacement.putAll( templateReplacement ); - newTemplateReplacement.put( templateVariable, enumValue.toString() ); - templateReplacementsToAdd.add( newTemplateReplacement ); - } - } - templateReplacements.clear(); - templateReplacements.addAll( templateReplacementsToAdd ); - } - } - - private static void addDefaultTemplateValue( List> templateReplacements, - String templateVariable, Schema schema ) { - if ( templateReplacements.isEmpty() ) { - Map replacement = new HashMap<>(); - templateReplacements.add( replacement ); - } - for ( Map templateReplacement : templateReplacements ) { - templateReplacement.put( templateVariable, schema.getDefault().toString() ); - } - } - - private static List identifyServerObjects( OpenApi3 apiModel, Path pathItemObject, Operation operationObject ) { - if ( operationObject.hasServers() ) - return parseUrls( operationObject.getServers() ); - if ( pathItemObject.hasServers() ) - return parseUrls( pathItemObject.getServers() ); - if ( apiModel.hasServers() ) - return parseUrls( apiModel.getServers() ); - return Collections.singletonList( DEFAULT_SERVER_URL ); - } - - private static List parseUrls( Collection servers ) { - List urls = new ArrayList<>(); - for ( Server server : servers ) - urls.add( server.getUrl() ); - return urls; - } - - private static class PathItemAndServer { - - private final Path pathItemObject; - - private Operation operationObject; - - // TODO: must be a server object to consider server variables - private String serverUrl; - - private PathItemAndServer( Path pathItemObject, Operation operationObject, String serverUrl ) { - this.pathItemObject = pathItemObject; - this.operationObject = operationObject; - this.serverUrl = serverUrl; - } - - } - - private static String findBasePath(OpenApi3 apiModel, URI iut) { - String basePath = "/"; - List serverUrls = apiModel.getServers(); - - for (Server serverUrl : serverUrls) { - Matcher matcher = Pattern.compile(serverUrl.getUrl()).matcher(iut.toString()); - - if (matcher.find()) { - String path = iut.toString().substring(matcher.end(), iut.toString().length()); - - if (!path.isEmpty()) { - basePath = path; - } - } - } - return basePath; - } + // as described in + // https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#fixed-fields + private static final String DEFAULT_SERVER_URL = "/"; + + @FunctionalInterface + private interface PathMatcherFunction { + + A apply(B b, C c); + + } + + enum PATH { + + CONFORMANCE("conformance"), COLLECTIONS("collections"); + + private String pathItem; + + PATH(String pathItem) { + + this.pathItem = pathItem; + } + + private String getPathItem() { + return pathItem; + } + + } + + private static class PathMatcher implements PathMatcherFunction { + + @Override + public Boolean apply(String pathUnderTest, String pathToMatch) { + UriTemplateParser parser = new UriTemplateParser(pathUnderTest); + Matcher matcher = parser.getPattern().matcher(pathToMatch); + return matcher.matches(); + } + + } + + private static class ExactMatchFilter implements Predicate { + + private final String requestedPath; + + ExactMatchFilter(String requestedPath) { + this.requestedPath = requestedPath; + } + + @Override + public boolean test(TestPoint testPoint) { + UriTemplate uriTemplate = new UriTemplate(testPoint.getPath()); + Map templateReplacement = new HashMap<>(testPoint.getPredefinedTemplateReplacement()); + List templateVariables = uriTemplate.getTemplateVariables(); + for (String templateVariable : templateVariables) { + if (!templateReplacement.containsKey(templateVariable)) + templateReplacement.put(templateVariable, ".*"); + } + String uri = uriTemplate.createURI(templateReplacement); + Pattern pattern = Pattern.compile(uri); + return pattern.matcher(requestedPath).matches(); + } + + } + + private OpenApiUtils() { + } + + /** + * Parse all test points from the passed OpenApi3 document as described in A.4.3. + * Identify the Test Points. + * @param apiModel never null + * @param iut the url of the instance under test, never null + * @return the parsed test points, may be empty but never null + */ + static List retrieveTestPoints(OpenApi3 apiModel, URI iut) { + List pathItemObjects = identifyTestPoints(apiModel); + List pathItemAndServers = identifyServerUrls(apiModel, iut, pathItemObjects); + return processServerObjects(pathItemAndServers, true); + } + + /** + * Parse the CONFORMANCE test points from the passed OpenApi3 document as described in + * A.4.3. Identify the Test Points. + * @param apiModel never null + * @param iut the url of the instance under test, never null + * @return the parsed test points, may be empty but never null + */ + public static List retrieveTestPointsForConformance(OpenApi3 apiModel, URI iut) { + return retrieveTestPoints(apiModel, iut, CONFORMANCE, false); + } + + /** + * Parse the COLLECTIONS METADATA test points from the passed OpenApi3 document as + * described in A.4.3. Identify the Test Points. + * @param apiModel never null + * @param iut the url of the instance under test, never null + * @return the parsed test points, may be empty but never null + */ + public static List retrieveTestPointsForCollectionsMetadata(OpenApi3 apiModel, URI iut) { + return retrieveTestPoints(apiModel, iut, COLLECTIONS, false); + } + + /** + * Parse the COLLECTION METADATA test points for the passed collectionName including + * the extended path from the passed OpenApi3 document as described in A.4.3. Identify + * the Test Points. + * @param apiModel never null + * @param iut the url of the instance under test, never null + * @param collectionName the extended path, may be null + * @return the parsed test points, may be empty but never null + */ + public static List retrieveTestPointsForCollectionMetadata(OpenApi3 apiModel, URI iut, + String collectionName) { + StringBuilder requestedPath = new StringBuilder(); + requestedPath.append(findBasePath(apiModel, iut)); + requestedPath.append(COLLECTIONS.getPathItem()); + requestedPath.append("/"); + requestedPath.append(collectionName); + + List testPoints = retrieveTestPoints(apiModel, iut, requestedPath.toString(), true); + return testPoints.stream().filter(new ExactMatchFilter(requestedPath.toString())).collect(Collectors.toList()); + } + + /** + * Parse the COLLECTIONS test points from the passed OpenApi3 document as described in + * A.4.3. Identify the Test Points. + * @param apiModel never null + * @param iut the url of the instance under test, never null + * @param noOfCollection the number of collections to return test points for (-1 means + * the test points of all collections should be returned) + * @return the parsed test points, may be empty but never null + */ + public static List retrieveTestPointsForCollections(OpenApi3 apiModel, URI iut, int noOfCollection) { + StringBuilder requestedPath = new StringBuilder(); + requestedPath.append(findBasePath(apiModel, iut)); + requestedPath.append(COLLECTIONS.getPathItem()); + requestedPath.append("/.*/items"); + + List allTestPoints = retrieveTestPoints(apiModel, iut, requestedPath.toString(), + (a, b) -> a.matches(b), true); + if (noOfCollection < 0 && allTestPoints.size() > OgcApiFeatures10.COLLECTIONS_LIMIT) { + return allTestPoints.subList(0, OgcApiFeatures10.COLLECTIONS_LIMIT); + } + else if (noOfCollection < 0 || allTestPoints.size() <= noOfCollection) { + return allTestPoints; + } + return allTestPoints.subList(0, noOfCollection); + } + + /** + * Parse the test points with the passed path including the extended path from the + * passed OpenApi3 document as described in A.4.3. Identify the Test Points. + * @param apiModel never null + * @param iut the url of the instance under test, never null + * @param collectionName the extended path, may be null + * @return the parsed test points, may be empty but never null + */ + public static List retrieveTestPointsForCollection(OpenApi3 apiModel, URI iut, String collectionName) { + String requestedPath = createCollectionPath(apiModel, iut, collectionName); + + List testPoints = retrieveTestPoints(apiModel, iut, requestedPath, true); + return testPoints.stream().filter(new ExactMatchFilter(requestedPath)).collect(Collectors.toList()); + } + + /** + * Parse the test points with the passed path including the extended path from the + * passed OpenApi3 document as described in A.4.3. Identify the Test Points. + * @param apiModel never null + * @param iut the url of the instance under test, never null + * @param collectionName the extended path, may be null + * @param featureId the id of the feature, never null + * @return the parsed test points, may be empty but never null + */ + public static List retrieveTestPointsForFeature(OpenApi3 apiModel, URI iut, String collectionName, + String featureId) { + StringBuilder requestedPath = new StringBuilder(); + requestedPath.append(findBasePath(apiModel, iut)); + requestedPath.append(COLLECTIONS.getPathItem()); + requestedPath.append("/"); + requestedPath.append(collectionName); + requestedPath.append("/items/"); + requestedPath.append(featureId); + + List testPoints = retrieveTestPoints(apiModel, iut, requestedPath.toString(), true); + return testPoints.stream().filter(new ExactMatchFilter(requestedPath.toString())).collect(Collectors.toList()); + } + + /** + *

    + * retrieveParameterByName. + *

    + * @param collectionItemPath a {@link java.lang.String} object + * @param apiModel a {@link com.reprezen.kaizen.oasparser.model3.OpenApi3} object + * @param name a {@link java.lang.String} object + * @return a {@link com.reprezen.kaizen.oasparser.model3.Parameter} object + */ + public static Parameter retrieveParameterByName(String collectionItemPath, OpenApi3 apiModel, String name) { + Path path = apiModel.getPath(collectionItemPath); + if (path != null) { + for (Parameter parameter : path.getParameters()) + if (name.equals(parameter.getName())) + return parameter; + Operation get = path.getOperation("get"); + for (Parameter parameter : get.getParameters()) + if (name.equals(parameter.getName())) + return parameter; + } + return null; + } + + /** + *

    + * isFreeFormParameterSupportedForCollection. + *

    + * @param apiModel a {@link com.reprezen.kaizen.oasparser.model3.OpenApi3} object + * @param iut a {@link java.net.URI} object + * @param collectionName a {@link java.lang.String} object + * @return a boolean + */ + public static boolean isFreeFormParameterSupportedForCollection(OpenApi3 apiModel, URI iut, String collectionName) { + String requestedPath = createCollectionPath(apiModel, iut, collectionName); + + List paths = identifyTestPoints(apiModel, requestedPath, new PathMatcher()); + for (Path path : paths) { + Collection parameters = path.getGet().getParameters(); + for (Parameter parameter : parameters) { + if (parameter.getSchema() != null && parameter.getSchema().isAdditionalProperties()) { + return true; + } + } + } + return false; + } + + /** + *

    + * isParameterSupportedForCollection. + *

    + * @param apiModel a {@link com.reprezen.kaizen.oasparser.model3.OpenApi3} object + * @param iut a {@link java.net.URI} object + * @param collectionName a {@link java.lang.String} object + * @param queryParam a {@link java.lang.String} object + * @return a boolean + */ + public static boolean isParameterSupportedForCollection(OpenApi3 apiModel, URI iut, String collectionName, + String queryParam) { + String requestedPath = createCollectionPath(apiModel, iut, collectionName); + + List paths = identifyTestPoints(apiModel, requestedPath, new PathMatcher()); + for (Path path : paths) { + Collection parameters = path.getGet().getParameters(); + for (Parameter parameter : parameters) { + if (queryParam.equalsIgnoreCase(parameter.getName())) { + return true; + } + } + } + return false; + } + + private static String createCollectionPath(OpenApi3 apiModel, URI iut, String collectionName) { + StringBuilder requestedPath = new StringBuilder(); + requestedPath.append(findBasePath(apiModel, iut)); + requestedPath.append(COLLECTIONS.getPathItem()); + requestedPath.append("/"); + requestedPath.append(collectionName); + requestedPath.append("/items"); + return requestedPath.toString(); + } + + private static List retrieveTestPoints(OpenApi3 apiModel, URI iut, PATH path, + boolean allowEmptyTemplateReplacements) { + String requestedPath = findBasePath(apiModel, iut) + path.getPathItem(); + return retrieveTestPoints(apiModel, iut, requestedPath, allowEmptyTemplateReplacements); + } + + private static List retrieveTestPoints(OpenApi3 apiModel, URI iut, String requestedPath, + boolean allowEmptyTemplateReplacements) { + return retrieveTestPoints(apiModel, iut, requestedPath, new PathMatcher(), allowEmptyTemplateReplacements); + } + + private static List retrieveTestPoints(OpenApi3 apiModel, URI iut, String requestedPath, + PathMatcherFunction pathMatcher, boolean allowEmptyTemplateReplacements) { + List pathItemObjects = identifyTestPoints(apiModel, requestedPath, pathMatcher); + List pathItemAndServers = identifyServerUrls(apiModel, iut, pathItemObjects); + return processServerObjects(pathItemAndServers, allowEmptyTemplateReplacements); + } + + /** + * A.4.3.1. Identify Test Points: + * + * a) Purpose: To identify the test points associated with each Path in the OpenAPI + * document + * + * b) Pre-conditions: + * + * An OpenAPI document has been obtained + * + * A list of URLs for the servers to be included in the compliance test has been + * provided + * + * A list of the paths specified in the WFS 3.0 specification + * + * c) Method: + * + * FOR EACH paths property in the OpenAPI document If the path name is one of those + * specified in the WFS 3.0 specification Retrieve the Server URIs using A.4.3.2. FOR + * EACH Server URI Concatenate the Server URI with the path name to form a test point. + * Add that test point to the list. + * + * d) References: None + * @param apiModel never null + */ + private static List identifyTestPoints(OpenApi3 apiModel) { + List allTestPoints = new ArrayList<>(); + for (PATH path : PATH.values()) + allTestPoints.addAll(identifyTestPoints(apiModel, "/" + path.getPathItem(), new PathMatcher())); + return allTestPoints; + } + + private static List identifyTestPoints(OpenApi3 apiModel, String path, + PathMatcherFunction pathMatch) { + List pathItems = new ArrayList<>(); + Map pathItemObjects = apiModel.getPaths(); + for (Path pathItemObject : pathItemObjects.values()) { + String pathString = pathItemObject.getPathString(); + if (pathMatch.apply(pathString, path)) { + pathItems.add(pathItemObject); + } + } + return pathItems; + } + + /** + * A.4.3.2. Identify Server URIs: + * + * a) Purpose: To identify all server URIs applicable to an OpenAPI Operation Object + * + * b) Pre-conditions: + * + * Server Objects from the root level of the OpenAPI document have been obtained + * + * A Path Item Object has been retrieved + * + * An Operation Object has been retrieved + * + * The Operation Object is associated with the Path Item Object + * + * A list of URLs for the servers to be included in the compliance test has been + * provided + * + * c) Method: + * + * 1) Identify the Server Objects which are in-scope for this operationObject + * + * IF Server Objects are defined at the Operation level, then those and only those + * Server Objects apply to that Operation. + * + * IF Server Objects are defined at the Path Item level, then those and only those + * Server Objects apply to that Path Item. + * + * IF Server Objects are not defined at the Operation level, then the Server Objects + * defined for the parent Path Item apply to that Operation. + * + * IF Server Objects are not defined at the Path Item level, then the Server Objects + * defined for the root level apply to that Path. + * + * IF no Server Objects are defined at the root level, then the default server object + * is assumed as described in the OpenAPI specification. + * + * 2) Process each Server Object using A.4.3.3. + * + * 3) Delete any Server URI which does not reference a server on the list of servers + * to test. + * + * d) References: None + * @param apiModel never null + * @param iut never null + * @param pathItemObjects never null + */ + private static List identifyServerUrls(OpenApi3 apiModel, URI iut, List pathItemObjects) { + List pathItemAndServers = new ArrayList<>(); + + for (Path pathItemObject : pathItemObjects) { + Map operationObjects = pathItemObject.getOperations(); + for (Operation operationObject : operationObjects.values()) { + List serverUrls = identifyServerObjects(apiModel, pathItemObject, operationObject); + for (String serverUrl : serverUrls) { + if (DEFAULT_SERVER_URL.equalsIgnoreCase(serverUrl)) { + serverUrl = iut.toString(); + } + else if (serverUrl.startsWith("/")) { + URI resolvedUri = iut.resolve(serverUrl); + serverUrl = resolvedUri.toString(); + } + PathItemAndServer pathItemAndServer = new PathItemAndServer(pathItemObject, operationObject, + serverUrl); + pathItemAndServers.add(pathItemAndServer); + } + } + } + return pathItemAndServers; + } + + /** + * A.4.3.3. Process Server Object: + * + * a) Purpose: To expand the contents of a Server Object into a set of absolute URIs. + * + * b) Pre-conditions: A Server Object has been retrieved + * + * c) Method: + * + * Processing the Server Object results in a set of absolute URIs. This set contains + * all of the URIs that can be created given the URI template and variables defined in + * that Server Object. + * + * If there are no variables in the URI template, then add the URI to the return set. + * + * For each variable in the URI template which does not have an enumerated set of + * valid values: + * + * generate a URI using the default value, + * + * add this URI to the return set, + * + * flag this URI as non-exhaustive + * + * For each variable in the URI template which has an enumerated set of valid values: + * + * generate a URI for each value in the enumerated set, + * + * add each generated URI to the return set. + * + * Perform this processing in an iterative manner so that there is a unique URI for + * all possible combinations of enumerated and default values. + * + * Convert all relative URIs to absolute URIs by rooting them on the URI to the server + * hosting the OpenAPI document. + * + * d) References: None + * @param pathItemAndServers never null + */ + private static List processServerObjects(List pathItemAndServers, + boolean allowEmptyTemplateReplacements) { + List uris = new ArrayList<>(); + for (PathItemAndServer pathItemAndServer : pathItemAndServers) { + processServerObject(uris, pathItemAndServer, allowEmptyTemplateReplacements); + } + return uris; + } + + private static void processServerObject(List uris, PathItemAndServer pathItemAndServer, + boolean allowEmptyTemplateReplacements) { + String pathString = pathItemAndServer.pathItemObject.getPathString(); + Response response = getResponse(pathItemAndServer); + if (response == null) + return; + Map contentMediaTypes = response.getContentMediaTypes(); + + UriTemplate uriTemplate = new UriTemplate(pathItemAndServer.serverUrl + pathString); + if (uriTemplate.getNumberOfTemplateVariables() == 0) { + TestPoint testPoint = new TestPoint(pathItemAndServer.serverUrl, pathString, contentMediaTypes); + uris.add(testPoint); + } + else { + List> templateReplacements = collectTemplateReplacements(pathItemAndServer, + uriTemplate); + + if (templateReplacements.isEmpty() && allowEmptyTemplateReplacements) { + TestPoint testPoint = new TestPoint(pathItemAndServer.serverUrl, pathString, contentMediaTypes); + uris.add(testPoint); + } + else { + for (Map templateReplacement : templateReplacements) { + TestPoint testPoint = new TestPoint(pathItemAndServer.serverUrl, pathString, templateReplacement, + contentMediaTypes); + uris.add(testPoint); + } + } + } + } + + private static Response getResponse(PathItemAndServer pathItemAndServer) { + if (pathItemAndServer.operationObject.hasResponse("200")) + return pathItemAndServer.operationObject.getResponse("200"); + if (pathItemAndServer.operationObject.hasResponse("default")) + return pathItemAndServer.operationObject.getResponse("default"); + return null; + } + + private static List> collectTemplateReplacements(PathItemAndServer pathItemAndServer, + UriTemplate uriTemplate) { + List> templateReplacements = new ArrayList<>(); + Collection parameters = pathItemAndServer.operationObject.getParameters(); + for (String templateVariable : uriTemplate.getTemplateVariables()) { + for (Parameter parameter : parameters) { + if (templateVariable.equals(parameter.getName())) { + Schema schema = parameter.getSchema(); + if (schema.hasEnums()) { + addEnumTemplateValues(templateReplacements, templateVariable, schema); + } + else if (schema.getDefault() != null) { + addDefaultTemplateValue(templateReplacements, templateVariable, schema); + } + else { + // TODO: What should be done if the parameter does not have a + // default value and no + // enumerated set of valid values? + } + } + } + } + return templateReplacements; + } + + private static void addEnumTemplateValues(List> templateReplacements, String templateVariable, + Schema schema) { + Collection enums = schema.getEnums(); + if (enums.size() == 1) { + for (Object enumValue : enums) { + Map replacement = new HashMap<>(); + replacement.put(templateVariable, enumValue.toString()); + templateReplacements.add(replacement); + } + } + else { + if (templateReplacements.isEmpty()) { + Map replacement = new HashMap<>(); + templateReplacements.add(replacement); + } + List> templateReplacementsToAdd = new ArrayList<>(); + for (Map templateReplacement : templateReplacements) { + for (Object enumValue : enums) { + Map newTemplateReplacement = new HashMap<>(); + newTemplateReplacement.putAll(templateReplacement); + newTemplateReplacement.put(templateVariable, enumValue.toString()); + templateReplacementsToAdd.add(newTemplateReplacement); + } + } + templateReplacements.clear(); + templateReplacements.addAll(templateReplacementsToAdd); + } + } + + private static void addDefaultTemplateValue(List> templateReplacements, String templateVariable, + Schema schema) { + if (templateReplacements.isEmpty()) { + Map replacement = new HashMap<>(); + templateReplacements.add(replacement); + } + for (Map templateReplacement : templateReplacements) { + templateReplacement.put(templateVariable, schema.getDefault().toString()); + } + } + + private static List identifyServerObjects(OpenApi3 apiModel, Path pathItemObject, + Operation operationObject) { + if (operationObject.hasServers()) + return parseUrls(operationObject.getServers()); + if (pathItemObject.hasServers()) + return parseUrls(pathItemObject.getServers()); + if (apiModel.hasServers()) + return parseUrls(apiModel.getServers()); + return Collections.singletonList(DEFAULT_SERVER_URL); + } + + private static List parseUrls(Collection servers) { + List urls = new ArrayList<>(); + for (Server server : servers) + urls.add(server.getUrl()); + return urls; + } + + private static class PathItemAndServer { + + private final Path pathItemObject; + + private Operation operationObject; + + // TODO: must be a server object to consider server variables + private String serverUrl; + + private PathItemAndServer(Path pathItemObject, Operation operationObject, String serverUrl) { + this.pathItemObject = pathItemObject; + this.operationObject = operationObject; + this.serverUrl = serverUrl; + } + + } + + private static String findBasePath(OpenApi3 apiModel, URI iut) { + String basePath = "/"; + List serverUrls = apiModel.getServers(); + + for (Server serverUrl : serverUrls) { + Matcher matcher = Pattern.compile(serverUrl.getUrl()).matcher(iut.toString()); + + if (matcher.find()) { + String path = iut.toString().substring(matcher.end(), iut.toString().length()); + + if (!path.isEmpty()) { + basePath = path; + } + } + } + return basePath; + } + } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/openapi3/TestPoint.java b/src/main/java/org/opengis/cite/ogcapifeatures10/openapi3/TestPoint.java index 2367bebe..968cf772 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/openapi3/TestPoint.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/openapi3/TestPoint.java @@ -13,98 +13,108 @@ */ public class TestPoint { - private final String serverUrl; - - private final String path; - - private Map predefinedTemplateReplacement; - - private Map contentMediaTypes; - - /** - * Instantiates a TestPoint with UriTemplate but without predefined replacements. - * - * @param serverUrl - * the serverUrl, never null - * @param path - * the path never, null - * @param contentMediaTypes - * the content media types for the GET operation with response "200", may be null - */ - public TestPoint( String serverUrl, String path, Map contentMediaTypes ) { - this( serverUrl, path, Collections.emptyMap(), contentMediaTypes ); - } - - /** - * Instantiates a TestPoint with UriTemplate and predefined replacements. - * - * @param serverUrl - * the serverUrl, never null - * @param path - * the path, never null - * @param predefinedTemplateReplacement - * a list of predefined replacements never null - * @param contentMediaTypes - * the content media types for the GET operation with response "200", may be null - */ - public TestPoint( String serverUrl, String path, Map predefinedTemplateReplacement, - Map contentMediaTypes ) { - this.serverUrl = serverUrl; - this.path = path; - this.predefinedTemplateReplacement = Collections.unmodifiableMap( predefinedTemplateReplacement ); - this.contentMediaTypes = contentMediaTypes; - } - - /** - * - * @return the serverUrl never null - */ - public String getServerUrl() { - return serverUrl; - } - - /** - * @return the path never, null - */ - public String getPath() { - return path; - } - - /** - * @return an unmodifiable mao with predefined replacements, may be empty but never null - */ - public Map getPredefinedTemplateReplacement() { - return predefinedTemplateReplacement; - } - - /** - * @return the content media types for the GET operation with response "200", may be null - */ - public Map getContentMediaTypes() { - return contentMediaTypes; - } - - @Override - public String toString() { - return "Server URL: " + serverUrl + " , Path: " + path + ", Replacements: " + predefinedTemplateReplacement; - } - - @Override - public boolean equals( Object o ) { - if ( this == o ) - return true; - if ( o == null || getClass() != o.getClass() ) - return false; - TestPoint testPoint = (TestPoint) o; - return Objects.equals( serverUrl, testPoint.serverUrl ) - && Objects.equals( path, testPoint.predefinedTemplateReplacement ) - && Objects.equals( predefinedTemplateReplacement, testPoint.path ) - && Objects.equals( contentMediaTypes, testPoint.contentMediaTypes ); - } - - @Override - public int hashCode() { - return Objects.hash( serverUrl, path, predefinedTemplateReplacement, contentMediaTypes ); - } + private final String serverUrl; + + private final String path; + + private Map predefinedTemplateReplacement; + + private Map contentMediaTypes; + + /** + * Instantiates a TestPoint with UriTemplate but without predefined replacements. + * @param serverUrl the serverUrl, never null + * @param path the path never, null + * @param contentMediaTypes the content media types for the GET operation with + * response "200", may be null + */ + public TestPoint(String serverUrl, String path, Map contentMediaTypes) { + this(serverUrl, path, Collections.emptyMap(), contentMediaTypes); + } + + /** + * Instantiates a TestPoint with UriTemplate and predefined replacements. + * @param serverUrl the serverUrl, never null + * @param path the path, never null + * @param predefinedTemplateReplacement a list of predefined replacements never + * null + * @param contentMediaTypes the content media types for the GET operation with + * response "200", may be null + */ + public TestPoint(String serverUrl, String path, Map predefinedTemplateReplacement, + Map contentMediaTypes) { + this.serverUrl = serverUrl; + this.path = path; + this.predefinedTemplateReplacement = Collections.unmodifiableMap(predefinedTemplateReplacement); + this.contentMediaTypes = contentMediaTypes; + } + + /** + *

    + * Getter for the field serverUrl. + *

    + * @return the serverUrl never null + */ + public String getServerUrl() { + return serverUrl; + } + + /** + *

    + * Getter for the field path. + *

    + * @return the path never, null + */ + public String getPath() { + return path; + } + + /** + *

    + * Getter for the field predefinedTemplateReplacement. + *

    + * @return an unmodifiable mao with predefined replacements, may be empty but never + * null + */ + public Map getPredefinedTemplateReplacement() { + return predefinedTemplateReplacement; + } + + /** + *

    + * Getter for the field contentMediaTypes. + *

    + * @return the content media types for the GET operation with response "200", may be + * null + */ + public Map getContentMediaTypes() { + return contentMediaTypes; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return "Server URL: " + serverUrl + " , Path: " + path + ", Replacements: " + predefinedTemplateReplacement; + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + TestPoint testPoint = (TestPoint) o; + return Objects.equals(serverUrl, testPoint.serverUrl) + && Objects.equals(path, testPoint.predefinedTemplateReplacement) + && Objects.equals(predefinedTemplateReplacement, testPoint.path) + && Objects.equals(contentMediaTypes, testPoint.contentMediaTypes); + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + return Objects.hash(serverUrl, path, predefinedTemplateReplacement, contentMediaTypes); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/openapi3/UriBuilder.java b/src/main/java/org/opengis/cite/ogcapifeatures10/openapi3/UriBuilder.java index f9db5c20..0649a7c9 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/openapi3/UriBuilder.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/openapi3/UriBuilder.java @@ -3,8 +3,9 @@ import java.util.HashMap; import java.util.Map; -import com.sun.jersey.api.uri.UriTemplate; -import com.sun.jersey.api.uri.UriTemplateParser; +import org.glassfish.jersey.uri.UriTemplate; +import org.glassfish.jersey.uri.internal.UriPart; +import org.glassfish.jersey.uri.internal.UriTemplateParser; /** * Builds a URL out of a TestPoint. @@ -13,76 +14,77 @@ */ public class UriBuilder { - private final TestPoint testPoint; + private final TestPoint testPoint; - private final Map templateReplacements = new HashMap<>(); + private final Map templateReplacements = new HashMap<>(); - /** - * @param testPoint - * never null - */ - public UriBuilder( TestPoint testPoint ) { - this.testPoint = testPoint; - this.templateReplacements.putAll( testPoint.getPredefinedTemplateReplacement() ); - } + /** + *

    + * Constructor for UriBuilder. + *

    + * @param testPoint never null + */ + public UriBuilder(TestPoint testPoint) { + this.testPoint = testPoint; + this.templateReplacements.putAll(testPoint.getPredefinedTemplateReplacement()); + } - /** - * Adds the collectionName to the URI - * - * @param collectionName - * never null - * @return this UrlBuilder - */ - public UriBuilder collectionName( String collectionName ) { - String templateName = retrieveCollectionNameTemplateName(); - addTemplateReplacement( collectionName, templateName ); - return this; - } + /** + * Adds the collectionName to the URI + * @param collectionName never null + * @return this UrlBuilder + */ + public UriBuilder collectionName(String collectionName) { + String templateName = retrieveCollectionNameTemplateName(); + addTemplateReplacement(collectionName, templateName); + return this; + } - /** - * Adds the featureId to the URI - * - * @param featureId - * never null - * @return this UrlBuilder - */ - public UriBuilder featureId( String featureId ) { - String templateName = retrieveFeatureIdTemplateName(); - addTemplateReplacement( featureId, templateName ); - return this; - } + /** + * Adds the featureId to the URI + * @param featureId never null + * @return this UrlBuilder + */ + public UriBuilder featureId(String featureId) { + String templateName = retrieveFeatureIdTemplateName(); + addTemplateReplacement(featureId, templateName); + return this; + } - /** - * @return this URI, never null - */ - public String buildUrl() { - UriTemplate uriTemplate = new UriTemplate( testPoint.getServerUrl() + testPoint.getPath() ); - return uriTemplate.createURI( templateReplacements ); - } + /** + *

    + * buildUrl. + *

    + * @return this URI, never null + */ + public String buildUrl() { + UriTemplate uriTemplate = new UriTemplate(testPoint.getServerUrl() + testPoint.getPath()); + return uriTemplate.createURI(templateReplacements); + } - private void addTemplateReplacement( String collectionName, String templateName ) { - if ( templateName != null ) - templateReplacements.put( templateName, collectionName ); - } + private void addTemplateReplacement(String collectionName, String templateName) { + if (templateName != null) + templateReplacements.put(templateName, collectionName); + } - private String retrieveCollectionNameTemplateName() { - String path = testPoint.getPath(); - UriTemplateParser uriTemplateParser = new UriTemplateParser( path ); - for ( String templateName : uriTemplateParser.getNames() ) { - if ( path.contains( "/collections/{" + templateName + "}" ) ) - return templateName; - } - return null; - } + private String retrieveCollectionNameTemplateName() { + String path = testPoint.getPath(); + UriTemplateParser uriTemplateParser = new UriTemplateParser(path); + for (UriPart templateName : uriTemplateParser.getNames()) { + if (path.contains("/collections/{" + templateName.getPart() + "}")) + return templateName.getPart(); + } + return null; + } - private String retrieveFeatureIdTemplateName() { - String path = testPoint.getPath(); - UriTemplateParser uriTemplateParser = new UriTemplateParser( path ); - for ( String templateName : uriTemplateParser.getNames() ) { - if ( path.endsWith( "items/{" + templateName + "}" ) ) - return templateName; - } - return null; - } + private String retrieveFeatureIdTemplateName() { + String path = testPoint.getPath(); + UriTemplateParser uriTemplateParser = new UriTemplateParser(path); + for (UriPart templateName : uriTemplateParser.getNames()) { + if (path.endsWith("items/{" + templateName.getPart() + "}")) + return templateName.getPart(); + } + return null; + } -} \ No newline at end of file +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/package-info.java b/src/main/java/org/opengis/cite/ogcapifeatures10/package-info.java index f1b39c14..d34d28cc 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/package-info.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/package-info.java @@ -1,8 +1,9 @@ /** - * The root package includes supporting classes of general utility such as the - * main controller, listeners, and reporters. + * The root package includes supporting classes of general utility such as the main + * controller, listeners, and reporters. * - *

    Subsidiary packages correspond to distinct test groups such as conformance - * classes.

    + *

    + * Subsidiary packages correspond to distinct test groups such as conformance classes. + *

    */ -package org.opengis.cite.ogcapifeatures10; \ No newline at end of file +package org.opengis.cite.ogcapifeatures10; \ No newline at end of file diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/util/BBox.java b/src/main/java/org/opengis/cite/ogcapifeatures10/util/BBox.java index 81edf2d8..e3762df6 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/util/BBox.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/util/BBox.java @@ -10,129 +10,152 @@ import org.opengis.cite.ogcapifeatures10.conformance.crs.query.crs.CoordinateSystem; /** + *

    + * BBox class. + *

    + * * @author Lyn Goltz */ public class BBox { - private static final String PATTERN = "###.0000000"; - - private final double minX; - - private final double minY; - - private final double maxX; - - private final double maxY; - - private final CoordinateSystem crs; - - /** - * @param minX - * Lower left corner, coordinate axis 1 - * @param minY - * Lower left corner, coordinate axis 2 - * @param maxX - * Upper right corner, coordinate axis 1 - * @param maxY - * Upper right corner, coordinate axis 2 - */ - public BBox( double minX, double minY, double maxX, double maxY ) { - this( minX, minY, maxX, maxY, DEFAULT_CRS ); - } - - /** - * @param minX - * Lower left corner, coordinate axis 1 - * @param minY - * Lower left corner, coordinate axis 2 - * @param maxX - * Upper right corner, coordinate axis 1 - * @param maxY - * Upper right corner, coordinate axis 2 - * @param crs - * CRS of the bbox, may be null - */ - public BBox( double minX, double minY, double maxX, double maxY, CoordinateSystem crs ) { - this.minX = minX; - this.minY = minY; - this.maxX = maxX; - this.maxY = maxY; - this.crs = crs; - } - - /** - * @return Lower left corner, coordinate axis 1 - */ - public double getMinX() { - return minX; - } - - /** - * @return Lower left corner, coordinate axis 2 - */ - public double getMinY() { - return minY; - } - - /** - * @return Upper right corner, coordinate axis 1 - */ - public double getMaxX() { - return maxX; - } - - /** - * @return Upper right corner, coordinate axis 2 - */ - public double getMaxY() { - return maxY; - } - - /** - * @return CRS of the bbox, never null - */ - public CoordinateSystem getCrs() { - return crs; - } - - /** - * @return the bbox as query string like '-12,10, 12,20' - */ - public String asQueryParameter() { - StringBuilder sb = new StringBuilder(); - DecimalFormat formatter = formatter(); - sb.append( formatter.format( minX ) ).append( "," ); - sb.append( formatter.format( minY ) ).append( "," ); - sb.append( formatter.format( maxX ) ).append( "," ); - sb.append( formatter.format( maxY ) ); - return sb.toString(); - } - - @Override - public String toString() { - return asQueryParameter(); - } - - @Override - public boolean equals( Object o ) { - if ( this == o ) - return true; - if ( o == null || getClass() != o.getClass() ) - return false; - BBox bBox = (BBox) o; - return Double.compare( bBox.minX, minX ) == 0 && Double.compare( bBox.minY, minY ) == 0 - && Double.compare( bBox.maxX, maxX ) == 0 && Double.compare( bBox.maxY, maxY ) == 0; - } - - @Override - public int hashCode() { - return Objects.hash( minX, minY, maxX, maxY ); - } - - private DecimalFormat formatter() { - NumberFormat nf = NumberFormat.getNumberInstance( Locale.ENGLISH ); - DecimalFormat df = (DecimalFormat) nf; - df.applyPattern( PATTERN ); - return df; - } -} \ No newline at end of file + private static final String PATTERN = "###.0000000"; + + private final double minX; + + private final double minY; + + private final double maxX; + + private final double maxY; + + private final CoordinateSystem crs; + + /** + *

    + * Constructor for BBox. + *

    + * @param minX Lower left corner, coordinate axis 1 + * @param minY Lower left corner, coordinate axis 2 + * @param maxX Upper right corner, coordinate axis 1 + * @param maxY Upper right corner, coordinate axis 2 + */ + public BBox(double minX, double minY, double maxX, double maxY) { + this(minX, minY, maxX, maxY, DEFAULT_CRS); + } + + /** + *

    + * Constructor for BBox. + *

    + * @param minX Lower left corner, coordinate axis 1 + * @param minY Lower left corner, coordinate axis 2 + * @param maxX Upper right corner, coordinate axis 1 + * @param maxY Upper right corner, coordinate axis 2 + * @param crs CRS of the bbox, may be null + */ + public BBox(double minX, double minY, double maxX, double maxY, CoordinateSystem crs) { + this.minX = minX; + this.minY = minY; + this.maxX = maxX; + this.maxY = maxY; + this.crs = crs; + } + + /** + *

    + * Getter for the field minX. + *

    + * @return Lower left corner, coordinate axis 1 + */ + public double getMinX() { + return minX; + } + + /** + *

    + * Getter for the field minY. + *

    + * @return Lower left corner, coordinate axis 2 + */ + public double getMinY() { + return minY; + } + + /** + *

    + * Getter for the field maxX. + *

    + * @return Upper right corner, coordinate axis 1 + */ + public double getMaxX() { + return maxX; + } + + /** + *

    + * Getter for the field maxY. + *

    + * @return Upper right corner, coordinate axis 2 + */ + public double getMaxY() { + return maxY; + } + + /** + *

    + * Getter for the field crs. + *

    + * @return CRS of the bbox, never null + */ + public CoordinateSystem getCrs() { + return crs; + } + + /** + *

    + * asQueryParameter. + *

    + * @return the bbox as query string like '-12,10, 12,20' + */ + public String asQueryParameter() { + StringBuilder sb = new StringBuilder(); + DecimalFormat formatter = formatter(); + sb.append(formatter.format(minX)).append(","); + sb.append(formatter.format(minY)).append(","); + sb.append(formatter.format(maxX)).append(","); + sb.append(formatter.format(maxY)); + return sb.toString(); + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return asQueryParameter(); + } + + /** {@inheritDoc} */ + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + BBox bBox = (BBox) o; + return Double.compare(bBox.minX, minX) == 0 && Double.compare(bBox.minY, minY) == 0 + && Double.compare(bBox.maxX, maxX) == 0 && Double.compare(bBox.maxY, maxY) == 0; + } + + /** {@inheritDoc} */ + @Override + public int hashCode() { + return Objects.hash(minX, minY, maxX, maxY); + } + + private DecimalFormat formatter() { + NumberFormat nf = NumberFormat.getNumberInstance(Locale.ENGLISH); + DecimalFormat df = (DecimalFormat) nf; + df.applyPattern(PATTERN); + return df; + } + +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/util/ClientUtils.java b/src/main/java/org/opengis/cite/ogcapifeatures10/util/ClientUtils.java index 5d5be96e..53b81b34 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/util/ClientUtils.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/util/ClientUtils.java @@ -5,169 +5,169 @@ import java.net.InetSocketAddress; import java.net.Proxy; import java.net.SocketAddress; -import java.net.URL; - -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientRequest; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.config.ClientConfig; -import com.sun.jersey.api.client.config.DefaultClientConfig; -import com.sun.jersey.api.client.filter.LoggingFilter; -import com.sun.jersey.client.urlconnection.HttpURLConnectionFactory; -import com.sun.jersey.client.urlconnection.URLConnectionClientHandler; import java.net.URI; -import java.util.Map; +import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; -import javax.ws.rs.HttpMethod; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriBuilder; + import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; -import org.opengis.cite.ogcapifeatures10.ReusableEntityFilter; + +import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.ClientResponse; import org.w3c.dom.Document; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.core.MediaType; + /** - * Provides various utility methods for creating and configuring HTTP client - * components. + * Provides various utility methods for creating and configuring HTTP client components. */ public class ClientUtils { - /** - * Builds a client component for interacting with HTTP endpoints. The client - * will automatically redirect to the URI declared in 3xx responses. The - * connection timeout is 10 s. Request and response messages may be logged - * to a JDK logger (in the namespace "com.sun.jersey.api.client"). - * - * @return A Client component. - */ - public static Client buildClient() { - ClientConfig config = new DefaultClientConfig(); - config.getProperties().put( - ClientConfig.PROPERTY_FOLLOW_REDIRECTS, true); - config.getProperties().put( - ClientConfig.PROPERTY_CONNECT_TIMEOUT, 10000); - Client client = Client.create(config); - client.addFilter(new ReusableEntityFilter()); - client.addFilter(new LoggingFilter()); - return client; - } - - /** - * Constructs a client component that uses a specified web proxy. Proxy - * authentication is not supported. Configuring the client to use an - * intercepting proxy can be useful when debugging a test. - * - * @param proxyHost The host name or IP address of the proxy server. - * @param proxyPort The port number of the proxy listener. - * - * @return A Client component that submits requests through a web proxy. - */ - public static Client buildClientWithProxy(final String proxyHost, - final int proxyPort) { - ClientConfig config = new DefaultClientConfig(); - config.getProperties().put( - ClientConfig.PROPERTY_FOLLOW_REDIRECTS, true); - Client client = new Client(new URLConnectionClientHandler( - new HttpURLConnectionFactory() { - SocketAddress addr = new InetSocketAddress(proxyHost, proxyPort); - Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); - - @Override - public HttpURLConnection getHttpURLConnection(URL url) throws IOException { - return (HttpURLConnection) url.openConnection(proxy); - } - }), config); - client.addFilter(new LoggingFilter()); - return client; - } - - /** - * Builds an HTTP request message that uses the GET method. - * - * @param endpoint A URI indicating the target resource. - * @param qryParams A Map containing query parameters (may be null); - * @param mediaTypes A list of acceptable media types; if not specified, - * generic XML ("application/xml") is preferred. - * - * @return A ClientRequest object. - */ - public static ClientRequest buildGetRequest(URI endpoint, - Map qryParams, MediaType... mediaTypes) { - UriBuilder uriBuilder = UriBuilder.fromUri(endpoint); - if (null != qryParams) { - for (Map.Entry param : qryParams.entrySet()) { - uriBuilder.queryParam(param.getKey(), param.getValue()); - } - } - URI uri = uriBuilder.build(); - ClientRequest.Builder reqBuilder = ClientRequest.create(); - if (null == mediaTypes || mediaTypes.length == 0) { - reqBuilder = reqBuilder.accept(MediaType.APPLICATION_XML_TYPE); - } else { - reqBuilder = reqBuilder.accept(mediaTypes); - } - ClientRequest req = reqBuilder.build(uri, HttpMethod.GET); - return req; - } - - /** - * Creates a copy of the given MediaType object but without any parameters. - * - * @param mediaType A MediaType descriptor. - * @return A new (immutable) MediaType object having the same type and - * subtype. - */ - public static MediaType removeParameters(MediaType mediaType) { - return new MediaType(mediaType.getType(), mediaType.getSubtype()); - } - - /** - * Obtains the (XML) response entity as a JAXP Source object and resets the - * entity input stream for subsequent reads. - * - * @param response A representation of an HTTP response message. - * @param targetURI The target URI from which the entity was retrieved (may - * be null). - * @return A Source to read the entity from; its system identifier is set - * using the given targetURI value (this may be used to resolve any relative - * URIs found in the source). - */ - public static Source getResponseEntityAsSource(ClientResponse response, - String targetURI) { - Source source = response.getEntity(DOMSource.class); - if (null != targetURI && !targetURI.isEmpty()) { - source.setSystemId(targetURI); - } - if (response.getEntityInputStream().markSupported()) { - try { - // NOTE: entity was buffered by client filter - response.getEntityInputStream().reset(); - } catch (IOException ex) { - Logger.getLogger(ClientUtils.class.getName()).log(Level.WARNING, - "Failed to reset response entity.", ex); - } - } - return source; - } - - /** - * Obtains the (XML) response entity as a DOM Document and resets the entity - * input stream for subsequent reads. - * - * @param response A representation of an HTTP response message. - * @param targetURI The target URI from which the entity was retrieved (may - * be null). - * @return A Document representing the entity; its base URI is set using the - * given targetURI value (this may be used to resolve any relative URIs - * found in the document). - */ - public static Document getResponseEntityAsDocument(ClientResponse response, - String targetURI) { - DOMSource domSource = (DOMSource) getResponseEntityAsSource(response, - targetURI); - Document entityDoc = (Document) domSource.getNode(); - entityDoc.setDocumentURI(domSource.getSystemId()); - return entityDoc; - } + /** + * Builds a client component for interacting with HTTP endpoints. The client will + * automatically redirect to the URI declared in 3xx responses. The connection timeout + * is 10 s. Request and response messages may be logged to a JDK logger (in the + * namespace "com.sun.jersey.api.client"). + * @return A Client component. + */ + public static Client buildClient() { + ClientConfig config = new ClientConfig(); + config.property(ClientProperties.FOLLOW_REDIRECTS, true); + config.property(ClientProperties.CONNECT_TIMEOUT, 10000); + Client client = ClientBuilder.newClient(config); + return client; + } + + /** + * Constructs a client component that uses a specified web proxy. Proxy authentication + * is not supported. Configuring the client to use an intercepting proxy can be useful + * when debugging a test. + * @param proxyHost The host name or IP address of the proxy server. + * @param proxyPort The port number of the proxy listener. + * @return A Client component that submits requests through a web proxy. + */ + public static Client buildClientWithProxy(final String proxyHost, final int proxyPort) { + ClientConfig config = new ClientConfig(); + config.connectorProvider(new ApacheConnectorProvider()); + SocketAddress addr = new InetSocketAddress(proxyHost, proxyPort); + Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); + config.property(ClientProperties.PROXY_URI, proxy); + config.property(ClientProperties.FOLLOW_REDIRECTS, true); + Client client = ClientBuilder.newClient(config); + return client; + } + + // /** + // * Builds an HTTP request message that uses the GET method. + // * + // * @param endpoint A URI indicating the target resource. + // * @param qryParams A Map containing query parameters (may be null); + // * @param mediaTypes A list of acceptable media types; if not specified, + // * generic XML ("application/xml") is preferred. + // * + // * @return A ClientRequest object. + // */ + // public static ClientRequest buildGetRequest(URI endpoint, + // Map qryParams, MediaType... mediaTypes) { + // UriBuilder uriBuilder = UriBuilder.fromUri(endpoint); + // if (null != qryParams) { + // for (Map.Entry param : qryParams.entrySet()) { + // uriBuilder.queryParam(param.getKey(), param.getValue()); + // } + // } + // URI uri = uriBuilder.build(); + // WebTarget target = buildClient().target(endpoint); + // Builder builder = target.request(); + // if (null == mediaTypes || mediaTypes.length == 0) { + // builder = builder.accept(MediaType.APPLICATION_XML_TYPE); + // } else { + // builder = builder.accept(mediaTypes); + // } + // Invocation invocation = builder.buildGet(); + // ClientRequest req = invocation.invoke() + // return req; + // } + + /** + * Creates a copy of the given MediaType object but without any parameters. + * @param mediaType A MediaType descriptor. + * @return A new (immutable) MediaType object having the same type and subtype. + */ + public static MediaType removeParameters(MediaType mediaType) { + return new MediaType(mediaType.getType(), mediaType.getSubtype()); + } + + /** + * Obtains the (XML) response entity as a JAXP Source object and resets the entity + * input stream for subsequent reads. + * @param response A representation of an HTTP response message. + * @param targetURI The target URI from which the entity was retrieved (may be null). + * @return A Source to read the entity from; its system identifier is set using the + * given targetURI value (this may be used to resolve any relative URIs found in the + * source). + */ + public static Source getResponseEntityAsSource(ClientResponse response, String targetURI) { + Source source = response.readEntity(DOMSource.class); + if (null != targetURI && !targetURI.isEmpty()) { + source.setSystemId(targetURI); + } + if (response.getEntityStream().markSupported()) { + try { + // NOTE: entity was buffered by client filter + response.getEntityStream().reset(); + } + catch (IOException ex) { + Logger.getLogger(ClientUtils.class.getName()) + .log(Level.WARNING, "Failed to reset response entity.", ex); + } + } + return source; + } + + /** + * Obtains the (XML) response entity as a DOM Document and resets the entity input + * stream for subsequent reads. + * @param response A representation of an HTTP response message. + * @param targetURI The target URI from which the entity was retrieved (may be null). + * @return A Document representing the entity; its base URI is set using the given + * targetURI value (this may be used to resolve any relative URIs found in the + * document). + */ + public static Document getResponseEntityAsDocument(ClientResponse response, String targetURI) { + DOMSource domSource = (DOMSource) getResponseEntityAsSource(response, targetURI); + Document entityDoc = (Document) domSource.getNode(); + entityDoc.setDocumentURI(domSource.getSystemId()); + return entityDoc; + } + + /** + * Checks if a GET request to a given URI returns HTTP 200 - OK + * @param uri The URI to check + * @return true, if HTTP 200 - OK was returned after a GET request, false otherwise + */ + public static boolean is200Response(URI uri) { + URL url = null; + int code = 0; + + try { + url = uri.toURL(); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.connect(); + + code = connection.getResponseCode(); + + } + catch (Exception ee) { + ee.printStackTrace(); + } + + return (code == 200); + } + } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/util/GeometryTransformer.java b/src/main/java/org/opengis/cite/ogcapifeatures10/util/GeometryTransformer.java index fb8c3aa6..98bd098f 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/util/GeometryTransformer.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/util/GeometryTransformer.java @@ -22,136 +22,211 @@ import org.opengis.cite.ogcapifeatures10.conformance.crs.query.crs.CoordinateSystem; /** + *

    + * GeometryTransformer class. + *

    + * * @author Lyn Goltz */ public class GeometryTransformer { - private final GeometryFactory geometryFactory = new GeometryFactory(); - - private final CoordinateTransform transformer; - - private final CoordinateSystem srcCrs; - - private final CoordinateSystem targetCrs; - - /** - * @param srcCrs - * source crs, , never null - * @param targetCrs - * target crs, , never null - */ - public GeometryTransformer( CoordinateSystem srcCrs, CoordinateSystem targetCrs ) { - this.srcCrs = srcCrs; - this.targetCrs = targetCrs; - CoordinateTransformFactory coordinateTransformFactory = new CoordinateTransformFactory(); - CRSFactory crsFactory = new CRSFactory(); - this.transformer = coordinateTransformFactory.createTransform( crsFactory.createFromName( srcCrs.getCodeWithAuthority() ), - crsFactory.createFromName( targetCrs.getCodeWithAuthority() ) ); - } - - /** - * @param bbox - * the bbox to transform, never null - * @return the transformed bbox (or the same if srcCrs and targetCrs) are the same, never null - */ - public BBox transform( BBox bbox ) { - if ( srcCrs.equals( targetCrs ) ) - return bbox; - Coordinate min = new Coordinate( bbox.getMinX(), bbox.getMinY() ); - Coordinate max = new Coordinate( bbox.getMaxX(), bbox.getMaxY() ); - Coordinate transformedMin = transform( min ); - Coordinate transformedMax = transform( max ); - return new BBox( transformedMin.x, transformedMin.y, transformedMax.x, transformedMax.y, targetCrs ); - } - - public Geometry transform( Geometry geometryToTransform ) { - if ( geometryToTransform == null ) - return null; - if ( geometryToTransform instanceof Point ) { - return transform( (Point) geometryToTransform ); - } else if ( geometryToTransform instanceof Polygon ) { - return transform( (Polygon) geometryToTransform ); - } else if ( ( geometryToTransform instanceof LineString ) ) { - return transform( (LineString) geometryToTransform ); - } else if ( ( geometryToTransform instanceof GeometryCollection ) ) { - return transform( (GeometryCollection) geometryToTransform ); - } - throw new IllegalArgumentException( "Unsupported geometry type: " + geometryToTransform.getClass() ); - } - - public Point transform( Point geometryToTransform ) { - Coordinate coordinate = geometryToTransform.getCoordinate(); - Coordinate transformedCoordinate = transform( coordinate ); - return geometryFactory.createPoint( transformedCoordinate ); - } - - public LineString transform( LineString geometryToTransform ) { - Coordinate[] coordinates = geometryToTransform.getCoordinates(); - Coordinate[] transformedCoordinates = transform( coordinates ); - return geometryFactory.createLineString( transformedCoordinates ); - } - - public Polygon transform( Polygon geometryToTransform ) { - Coordinate[] coordinatesExteriorRing = geometryToTransform.getExteriorRing().getCoordinates(); - Coordinate[] transformedCoordinatesExteriorRing = transform( coordinatesExteriorRing ); - LinearRing exteriorRing = geometryFactory.createLinearRing( transformedCoordinatesExteriorRing ); - LinearRing[] interiorRings = new LinearRing[geometryToTransform.getNumInteriorRing()]; - for ( int numInteriorRing = 0; numInteriorRing < geometryToTransform.getNumInteriorRing(); numInteriorRing++ ) { - LinearRing interiorRingN = geometryToTransform.getInteriorRingN( numInteriorRing ); - Coordinate[] transformedCoordinatesInteriorRingN = transform( interiorRingN.getCoordinates() ); - interiorRings[numInteriorRing] = geometryFactory.createLinearRing( transformedCoordinatesInteriorRingN ); - } - return geometryFactory.createPolygon( exteriorRing, interiorRings ); - } - - public Geometry transform( GeometryCollection geometryToTransform ) { - if ( geometryToTransform instanceof MultiPoint ) { - return transform( (MultiPoint) geometryToTransform ); - } else if ( geometryToTransform instanceof MultiLineString ) { - return transform( (MultiLineString) geometryToTransform ); - } else if ( geometryToTransform instanceof MultiPolygon ) { - return transform( (MultiPolygon) geometryToTransform ); - } - throw new IllegalArgumentException( "Unsupported geometry type: " + geometryToTransform.getClass() ); - } - - public MultiPoint transform( MultiPoint geometryToTransform ) { - Point[] points = new Point[geometryToTransform.getNumGeometries()]; - for ( int numGeometry = 0; numGeometry < geometryToTransform.getNumGeometries(); numGeometry++ ) { - Geometry geometryN = geometryToTransform.getGeometryN( numGeometry ); - points[numGeometry] = transform( (Point) geometryN ); - } - return geometryFactory.createMultiPoint( points ); - } - - public MultiLineString transform( MultiLineString geometryToTransform ) { - LineString[] lineStrings = new LineString[geometryToTransform.getNumGeometries()]; - for ( int numGeometry = 0; numGeometry < geometryToTransform.getNumGeometries(); numGeometry++ ) { - Geometry geometryN = geometryToTransform.getGeometryN( numGeometry ); - lineStrings[numGeometry] = transform( (LineString) geometryN ); - } - return geometryFactory.createMultiLineString( lineStrings ); - - } - - public MultiPolygon transform( MultiPolygon geometryToTransform ) { - Polygon[] polygons = new Polygon[geometryToTransform.getNumGeometries()]; - for ( int numGeometry = 0; numGeometry < geometryToTransform.getNumGeometries(); numGeometry++ ) { - Geometry geometryN = geometryToTransform.getGeometryN( numGeometry ); - polygons[numGeometry] = transform( (Polygon) geometryN ); - } - return geometryFactory.createMultiPolygon( polygons ); - } - - private Coordinate[] transform( Coordinate[] coordinates ) { - List transformedCoordinates = Arrays.stream( coordinates ).map( coord -> transform( coord ) ).collect( Collectors.toList() ); - return transformedCoordinates.toArray( new Coordinate[transformedCoordinates.size()] ); - } - - private Coordinate transform( Coordinate coord ) { - ProjCoordinate srcCoordinate = new ProjCoordinate( coord.x, coord.y, coord.z ); - ProjCoordinate targetCoordinate = new ProjCoordinate(); - transformer.transform( srcCoordinate, targetCoordinate ); - return new Coordinate( targetCoordinate.x, targetCoordinate.y, targetCoordinate.z ); - } -} \ No newline at end of file + private final GeometryFactory geometryFactory = new GeometryFactory(); + + private final CoordinateTransform transformer; + + private final CoordinateSystem srcCrs; + + private final CoordinateSystem targetCrs; + + /** + *

    + * Constructor for GeometryTransformer. + *

    + * @param srcCrs source crs, , never null + * @param targetCrs target crs, , never null + */ + public GeometryTransformer(CoordinateSystem srcCrs, CoordinateSystem targetCrs) { + this.srcCrs = srcCrs; + this.targetCrs = targetCrs; + CoordinateTransformFactory coordinateTransformFactory = new CoordinateTransformFactory(); + CRSFactory crsFactory = new CRSFactory(); + this.transformer = coordinateTransformFactory.createTransform( + crsFactory.createFromName(srcCrs.getCodeWithAuthority()), + crsFactory.createFromName(targetCrs.getCodeWithAuthority())); + } + + /** + *

    + * transform. + *

    + * @param bbox the bbox to transform, never null + * @return the transformed bbox (or the same if srcCrs and targetCrs) are the same, + * never null + */ + public BBox transform(BBox bbox) { + if (srcCrs.equals(targetCrs)) + return bbox; + Coordinate min = new Coordinate(bbox.getMinX(), bbox.getMinY()); + Coordinate max = new Coordinate(bbox.getMaxX(), bbox.getMaxY()); + Coordinate transformedMin = transform(min); + Coordinate transformedMax = transform(max); + return new BBox(transformedMin.x, transformedMin.y, transformedMax.x, transformedMax.y, targetCrs); + } + + /** + *

    + * transform. + *

    + * @param geometryToTransform a {@link org.locationtech.jts.geom.Geometry} object + * @return a {@link org.locationtech.jts.geom.Geometry} object + */ + public Geometry transform(Geometry geometryToTransform) { + if (geometryToTransform == null) + return null; + if (geometryToTransform instanceof Point) { + return transform((Point) geometryToTransform); + } + else if (geometryToTransform instanceof Polygon) { + return transform((Polygon) geometryToTransform); + } + else if ((geometryToTransform instanceof LineString)) { + return transform((LineString) geometryToTransform); + } + else if ((geometryToTransform instanceof GeometryCollection)) { + return transform((GeometryCollection) geometryToTransform); + } + throw new IllegalArgumentException("Unsupported geometry type: " + geometryToTransform.getClass()); + } + + /** + *

    + * transform. + *

    + * @param geometryToTransform a {@link org.locationtech.jts.geom.Point} object + * @return a {@link org.locationtech.jts.geom.Point} object + */ + public Point transform(Point geometryToTransform) { + Coordinate coordinate = geometryToTransform.getCoordinate(); + Coordinate transformedCoordinate = transform(coordinate); + return geometryFactory.createPoint(transformedCoordinate); + } + + /** + *

    + * transform. + *

    + * @param geometryToTransform a {@link org.locationtech.jts.geom.LineString} object + * @return a {@link org.locationtech.jts.geom.LineString} object + */ + public LineString transform(LineString geometryToTransform) { + Coordinate[] coordinates = geometryToTransform.getCoordinates(); + Coordinate[] transformedCoordinates = transform(coordinates); + return geometryFactory.createLineString(transformedCoordinates); + } + + /** + *

    + * transform. + *

    + * @param geometryToTransform a {@link org.locationtech.jts.geom.Polygon} object + * @return a {@link org.locationtech.jts.geom.Polygon} object + */ + public Polygon transform(Polygon geometryToTransform) { + Coordinate[] coordinatesExteriorRing = geometryToTransform.getExteriorRing().getCoordinates(); + Coordinate[] transformedCoordinatesExteriorRing = transform(coordinatesExteriorRing); + LinearRing exteriorRing = geometryFactory.createLinearRing(transformedCoordinatesExteriorRing); + LinearRing[] interiorRings = new LinearRing[geometryToTransform.getNumInteriorRing()]; + for (int numInteriorRing = 0; numInteriorRing < geometryToTransform.getNumInteriorRing(); numInteriorRing++) { + LinearRing interiorRingN = geometryToTransform.getInteriorRingN(numInteriorRing); + Coordinate[] transformedCoordinatesInteriorRingN = transform(interiorRingN.getCoordinates()); + interiorRings[numInteriorRing] = geometryFactory.createLinearRing(transformedCoordinatesInteriorRingN); + } + return geometryFactory.createPolygon(exteriorRing, interiorRings); + } + + /** + *

    + * transform. + *

    + * @param geometryToTransform a {@link org.locationtech.jts.geom.GeometryCollection} + * object + * @return a {@link org.locationtech.jts.geom.Geometry} object + */ + public Geometry transform(GeometryCollection geometryToTransform) { + if (geometryToTransform instanceof MultiPoint) { + return transform((MultiPoint) geometryToTransform); + } + else if (geometryToTransform instanceof MultiLineString) { + return transform((MultiLineString) geometryToTransform); + } + else if (geometryToTransform instanceof MultiPolygon) { + return transform((MultiPolygon) geometryToTransform); + } + throw new IllegalArgumentException("Unsupported geometry type: " + geometryToTransform.getClass()); + } + + /** + *

    + * transform. + *

    + * @param geometryToTransform a {@link org.locationtech.jts.geom.MultiPoint} object + * @return a {@link org.locationtech.jts.geom.MultiPoint} object + */ + public MultiPoint transform(MultiPoint geometryToTransform) { + Point[] points = new Point[geometryToTransform.getNumGeometries()]; + for (int numGeometry = 0; numGeometry < geometryToTransform.getNumGeometries(); numGeometry++) { + Geometry geometryN = geometryToTransform.getGeometryN(numGeometry); + points[numGeometry] = transform((Point) geometryN); + } + return geometryFactory.createMultiPoint(points); + } + + /** + *

    + * transform. + *

    + * @param geometryToTransform a {@link org.locationtech.jts.geom.MultiLineString} + * object + * @return a {@link org.locationtech.jts.geom.MultiLineString} object + */ + public MultiLineString transform(MultiLineString geometryToTransform) { + LineString[] lineStrings = new LineString[geometryToTransform.getNumGeometries()]; + for (int numGeometry = 0; numGeometry < geometryToTransform.getNumGeometries(); numGeometry++) { + Geometry geometryN = geometryToTransform.getGeometryN(numGeometry); + lineStrings[numGeometry] = transform((LineString) geometryN); + } + return geometryFactory.createMultiLineString(lineStrings); + + } + + /** + *

    + * transform. + *

    + * @param geometryToTransform a {@link org.locationtech.jts.geom.MultiPolygon} object + * @return a {@link org.locationtech.jts.geom.MultiPolygon} object + */ + public MultiPolygon transform(MultiPolygon geometryToTransform) { + Polygon[] polygons = new Polygon[geometryToTransform.getNumGeometries()]; + for (int numGeometry = 0; numGeometry < geometryToTransform.getNumGeometries(); numGeometry++) { + Geometry geometryN = geometryToTransform.getGeometryN(numGeometry); + polygons[numGeometry] = transform((Polygon) geometryN); + } + return geometryFactory.createMultiPolygon(polygons); + } + + private Coordinate[] transform(Coordinate[] coordinates) { + List transformedCoordinates = Arrays.stream(coordinates) + .map(coord -> transform(coord)) + .collect(Collectors.toList()); + return transformedCoordinates.toArray(new Coordinate[transformedCoordinates.size()]); + } + + private Coordinate transform(Coordinate coord) { + ProjCoordinate srcCoordinate = new ProjCoordinate(coord.x, coord.y, coord.z); + ProjCoordinate targetCoordinate = new ProjCoordinate(); + transformer.transform(srcCoordinate, targetCoordinate); + return new Coordinate(targetCoordinate.x, targetCoordinate.y, targetCoordinate.z); + } + +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/util/JsonUtils.java b/src/main/java/org/opengis/cite/ogcapifeatures10/util/JsonUtils.java index 1f28f8d7..15186040 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/util/JsonUtils.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/util/JsonUtils.java @@ -30,646 +30,609 @@ import io.restassured.specification.RequestSpecification; /** + *

    + * JsonUtils class. + *

    + * * @author Lyn Goltz */ public class JsonUtils { - private JsonUtils() { - } - - /** - * Parse value ass string. - * - * @param value - * to parse, may be null - * @return the value as string, null if the passed value was null - */ - public static String parseAsString( Object value ) { - if ( value == null ) - return null; - return value.toString(); - } - - /** - * Parses the id of the first feature from the passed json. - * - * @param collectionItemJson - * the json document containing the features, never null - * @return the parsed id, may be null if no feature could be found - */ - public static String parseFeatureId( JsonPath collectionItemJson ) { - List> features = collectionItemJson.get( "features" ); - if ( features == null ) - return null; - for ( Map feature : features ) { - if ( feature.containsKey( "id" ) ) - return feature.get( "id" ).toString(); - } - return null; - } - - /** - * Parses the temporal extent from the passed collection. - * - * @param collection - * the collection containing the extent to parse, never null - * @return the parsed temporal extent, null if no extent exists - * @throws IllegalArgumentException - * if the number of items in the extent invalid - * - */ - public static TemporalExtent parseTemporalExtent( Map collection ) { - Object extent = collection.get( "extent" ); - if ( extent == null || !( extent instanceof Map ) ) - return null; - Object spatial = ( (Map) extent ).get( "temporal" ); - if ( spatial == null || !( spatial instanceof List ) ) - return null; - List coords = (List) spatial; - if ( coords.size() == 2 ) { - ZonedDateTime begin = parseAsDate( (String) coords.get( 0 ) ); - ZonedDateTime end = parseAsDate( (String) coords.get( 1 ) ); - return new TemporalExtent( begin, end ); - } - throw new IllegalArgumentException( "Temporal extent with " + coords.size() + " items is invalid" ); - } - - /** - * Parses the passed string as ISO 8601 date. - * - * @param dateTime - * the dateTime to parse, never null - * @return the parsed date, never null - */ - public static ZonedDateTime parseAsDate( String dateTime ) { - return ZonedDateTime.parse( dateTime ); - } - - /** - * Formats the passed string as ISO 8601 date. Example: "2018-02-12T23:20:50Z" - * - * @param dateTime - * the dateTime to format, never null - * @return the formatted date, never null - */ - public static String formatDate( ZonedDateTime dateTime ) { - return DateTimeFormatter.ISO_INSTANT.format( dateTime ); - } - - /** - * Formats the passed string as ISO 8601 date. Example: "2018-02-12" - * - * @param date - * the dateTime to format, never null - * @return the formatted date, never null - */ - public static String formatDate( LocalDate date ) { - return DateTimeFormatter.ISO_DATE.format( date ); - } - - /** - * Formats the passed string as a period using a start and end time. Example: - * "2018-02-12T00:00:00Z/2018-03-18T12:31:12Z" - * - * @param beginDateTime - * the begin dateTime to format, never null - * @param endDateTime - * the end dateTime to format, never null - * @return the formatted date, never null - */ - public static String formatDateRange( ZonedDateTime beginDateTime, ZonedDateTime endDateTime ) { - return formatDate( beginDateTime ) + "/" + formatDate( endDateTime ); - } - - /** - * Formats the passed string as a period using start time and a duration. Example: - * "2018-02-12T00:00:00Z/P1M6DT12H31M12S" - * - * @param beginDate - * the begin date to format, never null - * @param endDate - * the end date to format, never null - * @return the formatted date, never null - */ - public static String formatDateRangeWithDuration( LocalDate beginDate, LocalDate endDate ) { - Period betweenDate = Period.between( beginDate, endDate ); - return formatDate( beginDate ) + "/" + betweenDate; - } - - /** - * Parses the spatial extent from the passed collection. - * - * @param collection - * the collection containing the extent to parse, never null - * @return the parsed bbox, null if no extent exists - * @throws IllegalArgumentException - * if the number of items in the extent invalid - * - */ - public static BBox parseSpatialExtent( Map collection ) { - Object extent = collection.get( "extent" ); - if ( extent == null || !( extent instanceof Map ) ) - return null; - Object spatial = ( (Map) extent ).get( "spatial" ); - if ( spatial == null || !( spatial instanceof Map ) ) - return null; - Object bbox = ( (Map) spatial ).get( "bbox" ); - if ( bbox == null || !( bbox instanceof List ) ) - return null; - List bboxesOrCoordinates = (List) bbox; - if ( bboxesOrCoordinates.isEmpty() ) - return null; - if ( containsMultipleBboxes( bboxesOrCoordinates ) ) { - if ( bboxesOrCoordinates.isEmpty() ) - return null; - Object firstBbox = bboxesOrCoordinates.get( 0 ); - if ( firstBbox == null || !( firstBbox instanceof List ) ) { - return null; - } - List coordinatesOfFirstBBox = (List) firstBbox; - return parseBbox( coordinatesOfFirstBBox, (Map) spatial ); - } else { - return parseBbox( bboxesOrCoordinates, (Map) spatial ); - } - } - - private static BBox parseBbox( List coords, Map spatial ) { - if ( coords.size() == 4 ) { - CoordinateSystem crs = parseCrs( spatial ); - double minX = parseValueAsDouble( coords.get( 0 ) ); - double minY = parseValueAsDouble( coords.get( 1 ) ); - double maxX = parseValueAsDouble( coords.get( 2 ) ); - double maxY = parseValueAsDouble( coords.get( 3 ) ); - return new BBox( minX, minY, maxX, maxY, crs ); - } else if ( coords.size() == 6 ) { - throw new IllegalArgumentException( "BBox with " + coords.size() - + " coordinates is currently not supported" ); - } - throw new IllegalArgumentException( "BBox with " + coords.size() + " coordinates is invalid" ); - } - - private static CoordinateSystem parseCrs( Map spatial ) { - String crs = parseAsString( spatial.get( "crs" ) ); - if ( crs != null ) - return new CoordinateSystem( crs ); - return DEFAULT_CRS; - } - - private static boolean containsMultipleBboxes( List bboxes ) { - Object first = bboxes.get( 0 ); - return first instanceof List; - } - - /** - * Parses all links with 'type' of one of the passed mediaTypes and the 'rel' property with the passed value. - * - * @param links - * list of all links, never null - * @param mediaTypesToSupport - * a list of media types the links searched for should support, may be empty but never null - * @param expectedRel - * the expected value of the property 'rel', never null - * @return a list of links supporting one of the media types and with the expected 'rel' property, may be empty but - * never null - */ - public static List> findLinksWithSupportedMediaTypeByRel( List> links, - List mediaTypesToSupport, - String expectedRel ) { - List> alternateLinks = new ArrayList<>(); - for ( Map link : links ) { - Object type = link.get( "type" ); - Object rel = link.get( "rel" ); - if ( expectedRel.equals( rel ) && isSupportedMediaType( type, mediaTypesToSupport ) ) - alternateLinks.add( link ); - } - return alternateLinks; - } - - /** - * Parsing the media types which does not have a link woth property 'type' for. - * - * @param links - * list of links to search in, never null - * @param mediaTypesToSuppport - * a list of media types which should be supported, never null - * @return the media types which does not have a link for. - */ - public static List findUnsupportedTypes( List> links, - List mediaTypesToSuppport ) { - List unsupportedType = new ArrayList<>(); - for ( String contentMediaType : mediaTypesToSuppport ) { - boolean hasLinkForContentType = hasLinkForContentType( links, contentMediaType ); - if ( !hasLinkForContentType ) - unsupportedType.add( contentMediaType ); - } - return unsupportedType; - } - - /** - * Parses the links without 'rel' or 'type' property. - * - * @param links - * list of links to search in, never null - * @param rels - * Set of relation types, never null - * @return the links without 'rel' or 'type' property - */ - public static List findLinksWithoutRelOrType( List> links, Set rels ) { - List linksWithoutRelOrType = new ArrayList<>(); - for ( Map link : links ) { - if ( rels.contains( link.get( "rel" ) ) && !linkIncludesRelAndType( link ) ) - linksWithoutRelOrType.add( (String) link.get( "href" ) ); - } - return linksWithoutRelOrType; - } - - /** - * Parses the link with 'rel=self'. - * - * @param links - * list of links to search in, never null - * @param expectedRel - * the expected value of the property 'rel', never null - * @return the link to itself or null if no such link exists - */ - public static Map findLinkByRel( List> links, String expectedRel ) { - if ( links == null ) - return null; - for ( Map link : links ) { - Object rel = link.get( "rel" ); - if ( expectedRel.equals( rel ) ) - return link; - } - return null; - } - - /** - * Checks if the passed link contains 'rel' and 'type' properties. - * - * @param link - * to check, never null - * @return true if the link contains 'rel' and 'type' properties, false otherwise - */ - public static boolean linkIncludesRelAndType( Map link ) { - Object rel = link.get( "rel" ); - Object type = link.get( "type" ); - if ( rel != null && type != null ) - return true; - return false; - } - - /** - * Checks if a property with the passed name exists in the jsonPath. - * - * @param propertyName - * name of the property to check, never null - * @param jsonPath - * to check, never null - * @return true if the property exists, false otherwise - */ - public static boolean hasProperty( String propertyName, JsonPath jsonPath ) { - return jsonPath.get( propertyName ) != null; - } - - /** - * Checks if a at least one of the collection in the /collections response has a spatial extent. - * - * @param jsonPath - * to check, never null - * @return true at least one of the collection has a spatial extent, false otherwise - */ - public static boolean hasAtLeastOneSpatialFeatureCollection( JsonPath jsonPath ) { - List collections = jsonPath.getList( "collections" ); - for ( Object collectionObj : collections ) { - if ( hasAtLeastOneSpatialFeatureCollection( (Map) collectionObj ) ) - return true; - } - return false; - } - - /** - * Checks if a at least one of the collection in the /collections response has a spatial extent. - * - * @param collection - * to check, never null - * @return true at least one of the collection has a spatial extent, false otherwise - */ - public static boolean hasAtLeastOneSpatialFeatureCollection( Map collection ) { - Object extent = collection.get( "extent" ); - return hasAtLeastOneSpatialFeatureCollection( extent ); - } - - /** - * Checks if the extent contains a spatial extent. - * - * @param extent - * to check, never null - * @return true if extent contains a spatial extent, false otherwise - */ - public static boolean hasAtLeastOneSpatialFeatureCollection( Object extent ) { - if ( extent != null && extent instanceof Map ) { - Object spatial = ( (Map) extent ).get( "spatial" ); - if ( spatial != null ) - return true; - } - return false; - } - - /** - * Retrieves the property values as list. - * - * @param propertyName - * name of the property, never null - * @param jsonPath - * the json document to retrieve properties from, never null - * @return the property values as list, may be empty but never null - */ - public static List parseAsList( String propertyName, JsonPath jsonPath ) { - Object value = jsonPath.get( propertyName ); - if ( value == null ) - return Collections.emptyList(); - if ( value instanceof String ) - return Collections.singletonList( (String) value ); - return jsonPath.getList( propertyName ); - } - - /** - * Retrieves the property values as list. - * - * @param propertyName - * name of the property, never null - * @param jsonPath - * the json document to retrieve properties from, never null - * @return the property values as list, may be empty but never null - */ - public static List> parseAsListOfMaps( String propertyName, JsonPath jsonPath ) { - Object value = jsonPath.get( propertyName ); - if ( value == null ) - return Collections.emptyList(); - return jsonPath.getList( propertyName ); - } - - /** - * Retrieves the property values as list. - * - * @param propertyName - * name of the property, never null - * @param json - * the json map to retrieve properties from, never null - * @return the property values as list, may be empty but never null - */ - public static List parseAsList( String propertyName, Map json ) { - Object value = json.get( propertyName ); - if ( value == null ) - return Collections.emptyList(); - if ( value instanceof String ) - return Collections.singletonList( (String) value ); - return (List) json.get( propertyName ); - } - - /** - * Collects the number of all returned features by iterating over all 'next' links and summarizing the size of - * features in 'features' array property. - * - * @param jsonPath - * the initial collection, never null - * @param maximumLimit - * the limit parameter value to use, if <= 0 the parameter is omitted - * @return the number of all returned features - * @throws URISyntaxException - * if the creation of a uri fails - */ - public static int collectNumberOfAllReturnedFeatures( JsonPath jsonPath, int maximumLimit ) - throws URISyntaxException { - int numberOfAllReturnedFeatures = parseAsList( "features", jsonPath ).size(); - Map nextLink = findLinkByRel( jsonPath.getList( "links" ), "next" ); - int count = 0; - while ( nextLink != null && (count <= OgcApiFeatures10.PAGING_LIMIT)) { - String nextUrl = (String) nextLink.get( "href" ); - URI uri = new URI( nextUrl ); - - RequestSpecification accept = given().log().all().baseUri( nextUrl ).accept( GEOJSON_MIME_TYPE ); - String[] pairs = uri.getQuery().split( "&" ); - String limitParamFromUri = null; - for ( String pair : pairs ) { - int idx = pair.indexOf( "=" ); - String key = pair.substring( 0, idx ); - String value = pair.substring( idx + 1 ); - if ( "limit".equals( key ) ) { - limitParamFromUri = value; - } else { - accept.param( key, value ); - } - } - if ( maximumLimit > 0 ) { - accept.param( "limit", maximumLimit ); - } else if ( limitParamFromUri != null ) { - accept.param( "limit", limitParamFromUri ); - } - - Response response = accept.when().request( GET ); - response.then().statusCode( 200 ); - - JsonPath nextJsonPath = response.jsonPath(); - int features = parseAsList( "features", nextJsonPath ).size(); - if ( features > 0 ) { - numberOfAllReturnedFeatures += features; - nextLink = findLinkByRel( nextJsonPath.getList( "links" ), "next" ); - } else { - nextLink = null; - } - count++; - } - return numberOfAllReturnedFeatures; - } - - /** - * Finds the URL to the resource /collections/{collectionId}/items from the path /collections/{collectionId} - * - * @param rootUri - * never null - * @param collection - * the /collections/{collectionId} response, never null - * @return the url to the resource /collections/{collectionId}/items or null - */ - public static String findFeaturesUrlForGeoJson( URI rootUri, JsonPath collection ) { - List links = collection.get( "links" ); - return findFeaturesUrlForGeoJson( rootUri, links ); - } - - /** - * Finds the URL to the resource /collections/{collectionId}/items from the path /collections - * - * @param rootUri - * never null - * @param collection - * the collection object /collections response, never null - * @return the url to the resource /collections/{collectionId}/items or null - */ - public static String findFeaturesUrlForGeoJson( URI rootUri, Map collection ) { - List links = (List) collection.get( "links" ); - return findFeaturesUrlForGeoJson( rootUri, links ); - } - - /** - * Finds the URL to the resource /collections/{collectionId}/items/{featureId} from the path /collections and - * creates an valid url to this resource - * - * @param rootUri - * never null - * @param collection - * the /collections/{collectionId} response, never null - * @param featureId - * id of the feature, never null - * @return the url to the resource /collections/{collectionId}/items or null - */ - public static String findFeatureUrlForGeoJson( URI rootUri, JsonPath collection, String featureId ) { - List links = collection.get( "links" ); - return findFeatureUrlForGeoJson( rootUri, featureId, links ); - } - - /** - * Finds the URL to the resource /collections/{collectionId}/items/{featureId} from the path /collections and - * creates an valid url to this resource - * - * @param rootUri - * never null - * @param collection - * the collection object /collections response, never null - * @param featureId - * id of the feature, never null - * @return the url to the resource /collections/{collectionId}/items or null - */ - public static String findFeatureUrlForGeoJson( URI rootUri, Map collection, String featureId ) { - List links = (List) collection.get( "links" ); - return findFeatureUrlForGeoJson( rootUri, featureId, links ); - } - - /** - * Parse the geometry property as geometry. - * - * @param feature - * to parse, never null - * @param crs - * the crs of the geometry, may be null - * @return the parsed geometry, null if the feature has no geometry property - * @throws ParseException - * if the geometry could not be parsed - */ - public static Geometry parseFeatureGeometry( Map feature, CoordinateSystem crs ) - throws ParseException { - Map geometry = (Map) feature.get( "geometry" ); - if ( geometry == null ) - return null; - JSONObject jsonObject = new JSONObject( geometry ); - String geomAsString = jsonObject.toJSONString(); - GeoJsonReader geoJsonReader = new GeoJsonReader(); - Geometry parsedGeometry = geoJsonReader.read( geomAsString ); - parsedGeometry.setSRID( crs.getSrid() ); - return parsedGeometry; - } - - - private static String findFeaturesUrlForGeoJson( URI rootUri, List links ) { - for ( Object linkObject : links ) { - Map link = (Map) linkObject; - Object rel = link.get( "rel" ); - Object type = link.get( "type" ); - if ( "items".equals( rel ) && GEOJSON_MIME_TYPE.equals( type ) ) { - String url = (String) link.get( "href" ); - if ( !url.startsWith( "http" ) ) { - String path = url; - if ( null != rootUri.getScheme() && !rootUri.getScheme().isEmpty() ) - url = rootUri.getScheme() + ":"; - if ( null != rootUri.getAuthority() && !rootUri.getAuthority().isEmpty() ) - url = url + "//" + rootUri.getAuthority(); - url = url + path; - if ( null != rootUri.getQuery() && !rootUri.getQuery().isEmpty() ) - url = url + "?" + rootUri.getQuery(); - if ( null != rootUri.getFragment() && !rootUri.getFragment().isEmpty() ) - url = url + "#" + rootUri.getFragment(); - } - return url; - } - } - return null; - } - - private static String findFeatureUrlForGeoJson( URI rootUri, String featureId, List links ) { - String featuresUrlForGeoJson = findFeaturesUrlForGeoJson( rootUri, links ); - if ( featuresUrlForGeoJson != null ) { - return createFeatureUrl( featuresUrlForGeoJson, featureId ); - } - return null; - } - - private static String createFeatureUrl( String getFeatureUrl, String featureId ) { - if ( getFeatureUrl.indexOf( "?" ) != -1 ) { - return getFeatureUrl.substring( 0, getFeatureUrl.indexOf( "?" ) ) + "/" + featureId; - } else if ( getFeatureUrl.matches( "^.*\\/items.[a-zA-Z]*$" ) ) { - return getFeatureUrl.substring( 0, getFeatureUrl.lastIndexOf( "." ) ) + "/" + featureId - + getFeatureUrl.substring( getFeatureUrl.lastIndexOf( "." ) ); - } - return getFeatureUrl + "/" + featureId; - } - - private static boolean isSameMediaType( String mediaType1, String mediaType2 ) { - if ( mediaType1.contains( ";" ) || mediaType2.contains( ";" ) ) { - // media types are not case sensitive - String[] components1 = mediaType1.toLowerCase().split( ";" ); - String[] components2 = mediaType2.toLowerCase().split( ";" ); - // type and subtype must match - if ( !components1[0].trim().equals( components2[0].trim() ) ) - return false; - Set parameters1 = new HashSet<>(); - Set parameters2 = new HashSet<>(); - // normalize parameter values and compare them - for ( int i = 1; i < components1.length; i++ ) { - String parameter = components1[i].trim().replace( "\"", "" ); - if ( !parameter.isEmpty() ) - parameters1.add( parameter ); - } - for ( int i = 1; i < components2.length; i++ ) { - String parameter = components2[i].trim().replace( "\"", "" ); - if ( !parameter.isEmpty() ) - parameters2.add( parameter ); - } - if ( parameters1.size() != parameters2.size() ) - return false; - if ( !parameters1.containsAll( parameters2 ) ) - return false; - } else if ( !mediaType1.trim().equalsIgnoreCase( mediaType2.trim() ) ) - return false; - - return true; - } - - private static boolean hasLinkForContentType( List> alternateLinks, String mediaType ) { - for ( Map alternateLink : alternateLinks ) { - Object type = alternateLink.get( "type" ); - if ( type instanceof String && isSameMediaType( mediaType, (String) type ) ) - return true; - } - return false; - } - - private static boolean isSupportedMediaType( Object type, List mediaTypes ) { - for ( String mediaType : mediaTypes ) { - if ( type instanceof String && isSameMediaType( mediaType, (String) type ) ) - return true; - } - return false; - } - - private static double parseValueAsDouble( Object value ) { - if ( value instanceof Integer ) { - return ( (Integer) value ).doubleValue(); - } else if ( value instanceof Float ) { - return ( (Float) value ).doubleValue(); - } else if ( value instanceof Double ) { - return (Double) value; - } else { - return Double.parseDouble( value.toString() ); - } - } + private JsonUtils() { + } + + /** + * Parse value ass string. + * @param value to parse, may be null + * @return the value as string, null if the passed value was + * null + */ + public static String parseAsString(Object value) { + if (value == null) + return null; + return value.toString(); + } + + /** + * Parses the id of the first feature from the passed json. + * @param collectionItemJson the json document containing the features, never + * null + * @return the parsed id, may be null if no feature could be found + */ + public static String parseFeatureId(JsonPath collectionItemJson) { + List> features = collectionItemJson.get("features"); + if (features == null) + return null; + for (Map feature : features) { + if (feature.containsKey("id")) + return feature.get("id").toString(); + } + return null; + } + + /** + * Parses the temporal extent from the passed collection. + * @param collection the collection containing the extent to parse, never + * null + * @return the parsed temporal extent, null if no extent exists + * @throws java.lang.IllegalArgumentException if the number of items in the extent + * invalid + */ + public static TemporalExtent parseTemporalExtent(Map collection) { + Object extent = collection.get("extent"); + if (extent == null || !(extent instanceof Map)) + return null; + Object spatial = ((Map) extent).get("temporal"); + if (spatial == null || !(spatial instanceof List)) + return null; + List coords = (List) spatial; + if (coords.size() == 2) { + ZonedDateTime begin = parseAsDate((String) coords.get(0)); + ZonedDateTime end = parseAsDate((String) coords.get(1)); + return new TemporalExtent(begin, end); + } + throw new IllegalArgumentException("Temporal extent with " + coords.size() + " items is invalid"); + } + + /** + * Parses the passed string as ISO 8601 date. + * @param dateTime the dateTime to parse, never null + * @return the parsed date, never null + */ + public static ZonedDateTime parseAsDate(String dateTime) { + return ZonedDateTime.parse(dateTime); + } + + /** + * Formats the passed string as ISO 8601 date. Example: "2018-02-12T23:20:50Z" + * @param dateTime the dateTime to format, never null + * @return the formatted date, never null + */ + public static String formatDate(ZonedDateTime dateTime) { + return DateTimeFormatter.ISO_INSTANT.format(dateTime); + } + + /** + * Formats the passed string as ISO 8601 date. Example: "2018-02-12" + * @param date the dateTime to format, never null + * @return the formatted date, never null + */ + public static String formatDate(LocalDate date) { + return DateTimeFormatter.ISO_DATE.format(date); + } + + /** + * Formats the passed string as a period using a start and end time. Example: + * "2018-02-12T00:00:00Z/2018-03-18T12:31:12Z" + * @param beginDateTime the begin dateTime to format, never null + * @param endDateTime the end dateTime to format, never null + * @return the formatted date, never null + */ + public static String formatDateRange(ZonedDateTime beginDateTime, ZonedDateTime endDateTime) { + return formatDate(beginDateTime) + "/" + formatDate(endDateTime); + } + + /** + * Formats the passed string as a period using start time and a duration. Example: + * "2018-02-12T00:00:00Z/P1M6DT12H31M12S" + * @param beginDate the begin date to format, never null + * @param endDate the end date to format, never null + * @return the formatted date, never null + */ + public static String formatDateRangeWithDuration(LocalDate beginDate, LocalDate endDate) { + Period betweenDate = Period.between(beginDate, endDate); + return formatDate(beginDate) + "/" + betweenDate; + } + + /** + * Parses the spatial extent from the passed collection. + * @param collection the collection containing the extent to parse, never + * null + * @return the parsed bbox, null if no extent exists + * @throws java.lang.IllegalArgumentException if the number of items in the extent + * invalid + */ + public static BBox parseSpatialExtent(Map collection) { + Object extent = collection.get("extent"); + if (extent == null || !(extent instanceof Map)) + return null; + Object spatial = ((Map) extent).get("spatial"); + if (spatial == null || !(spatial instanceof Map)) + return null; + Object bbox = ((Map) spatial).get("bbox"); + if (bbox == null || !(bbox instanceof List)) + return null; + List bboxesOrCoordinates = (List) bbox; + if (bboxesOrCoordinates.isEmpty()) + return null; + if (containsMultipleBboxes(bboxesOrCoordinates)) { + if (bboxesOrCoordinates.isEmpty()) + return null; + Object firstBbox = bboxesOrCoordinates.get(0); + if (firstBbox == null || !(firstBbox instanceof List)) { + return null; + } + List coordinatesOfFirstBBox = (List) firstBbox; + return parseBbox(coordinatesOfFirstBBox, (Map) spatial); + } + else { + return parseBbox(bboxesOrCoordinates, (Map) spatial); + } + } + + private static BBox parseBbox(List coords, Map spatial) { + if (coords.size() == 4) { + CoordinateSystem crs = parseCrs(spatial); + double minX = parseValueAsDouble(coords.get(0)); + double minY = parseValueAsDouble(coords.get(1)); + double maxX = parseValueAsDouble(coords.get(2)); + double maxY = parseValueAsDouble(coords.get(3)); + return new BBox(minX, minY, maxX, maxY, crs); + } + else if (coords.size() == 6) { + throw new IllegalArgumentException( + "BBox with " + coords.size() + " coordinates is currently not supported"); + } + throw new IllegalArgumentException("BBox with " + coords.size() + " coordinates is invalid"); + } + + private static CoordinateSystem parseCrs(Map spatial) { + String crs = parseAsString(spatial.get("crs")); + if (crs != null) + return new CoordinateSystem(crs); + return DEFAULT_CRS; + } + + private static boolean containsMultipleBboxes(List bboxes) { + Object first = bboxes.get(0); + return first instanceof List; + } + + /** + * Parses all links with 'type' of one of the passed mediaTypes and the 'rel' property + * with the passed value. + * @param links list of all links, never null + * @param mediaTypesToSupport a list of media types the links searched for should + * support, may be empty but never null + * @param expectedRel the expected value of the property 'rel', never + * null + * @return a list of links supporting one of the media types and with the expected + * 'rel' property, may be empty but never null + */ + public static List> findLinksWithSupportedMediaTypeByRel(List> links, + List mediaTypesToSupport, String expectedRel) { + List> alternateLinks = new ArrayList<>(); + for (Map link : links) { + Object type = link.get("type"); + Object rel = link.get("rel"); + if (expectedRel.equals(rel) && isSupportedMediaType(type, mediaTypesToSupport)) + alternateLinks.add(link); + } + return alternateLinks; + } + + /** + * Parsing the media types which does not have a link woth property 'type' for. + * @param links list of links to search in, never null + * @param mediaTypesToSuppport a list of media types which should be supported, never + * null + * @return the media types which does not have a link for. + */ + public static List findUnsupportedTypes(List> links, + List mediaTypesToSuppport) { + List unsupportedType = new ArrayList<>(); + for (String contentMediaType : mediaTypesToSuppport) { + boolean hasLinkForContentType = hasLinkForContentType(links, contentMediaType); + if (!hasLinkForContentType) + unsupportedType.add(contentMediaType); + } + return unsupportedType; + } + + /** + * Parses the links without 'rel' or 'type' property. + * @param links list of links to search in, never null + * @param rels Set of relation types, never null + * @return the links without 'rel' or 'type' property + */ + public static List findLinksWithoutRelOrType(List> links, Set rels) { + List linksWithoutRelOrType = new ArrayList<>(); + for (Map link : links) { + if (rels.contains(link.get("rel")) && !linkIncludesRelAndType(link)) + linksWithoutRelOrType.add((String) link.get("href")); + } + return linksWithoutRelOrType; + } + + /** + * Parses the link with 'rel=self'. + * @param links list of links to search in, never null + * @param expectedRel the expected value of the property 'rel', never + * null + * @return the link to itself or null if no such link exists + */ + public static Map findLinkByRel(List> links, String expectedRel) { + if (links == null) + return null; + for (Map link : links) { + Object rel = link.get("rel"); + if (expectedRel.equals(rel)) + return link; + } + return null; + } + + /** + * Checks if the passed link contains 'rel' and 'type' properties. + * @param link to check, never null + * @return true if the link contains 'rel' and 'type' properties, + * false otherwise + */ + public static boolean linkIncludesRelAndType(Map link) { + Object rel = link.get("rel"); + Object type = link.get("type"); + if (rel != null && type != null) + return true; + return false; + } + + /** + * Checks if a property with the passed name exists in the jsonPath. + * @param propertyName name of the property to check, never null + * @param jsonPath to check, never null + * @return true if the property exists, false otherwise + */ + public static boolean hasProperty(String propertyName, JsonPath jsonPath) { + return jsonPath.get(propertyName) != null; + } + + /** + * Checks if a at least one of the collection in the /collections response has a + * spatial extent. + * @param jsonPath to check, never null + * @return true at least one of the collection has a spatial extent, + * false otherwise + */ + public static boolean hasAtLeastOneSpatialFeatureCollection(JsonPath jsonPath) { + List collections = jsonPath.getList("collections"); + for (Object collectionObj : collections) { + if (hasAtLeastOneSpatialFeatureCollection((Map) collectionObj)) + return true; + } + return false; + } + + /** + * Checks if a at least one of the collection in the /collections response has a + * spatial extent. + * @param collection to check, never null + * @return true at least one of the collection has a spatial extent, + * false otherwise + */ + public static boolean hasAtLeastOneSpatialFeatureCollection(Map collection) { + Object extent = collection.get("extent"); + return hasAtLeastOneSpatialFeatureCollection(extent); + } + + /** + * Checks if the extent contains a spatial extent. + * @param extent to check, never null + * @return true if extent contains a spatial extent, false + * otherwise + */ + public static boolean hasAtLeastOneSpatialFeatureCollection(Object extent) { + if (extent != null && extent instanceof Map) { + Object spatial = ((Map) extent).get("spatial"); + if (spatial != null) + return true; + } + return false; + } + + /** + * Retrieves the property values as list. + * @param propertyName name of the property, never null + * @param jsonPath the json document to retrieve properties from, never + * null + * @return the property values as list, may be empty but never null + */ + public static List parseAsList(String propertyName, JsonPath jsonPath) { + Object value = jsonPath.get(propertyName); + if (value == null) + return Collections.emptyList(); + if (value instanceof String) + return Collections.singletonList((String) value); + return jsonPath.getList(propertyName); + } + + /** + * Retrieves the property values as list. + * @param propertyName name of the property, never null + * @param jsonPath the json document to retrieve properties from, never + * null + * @return the property values as list, may be empty but never null + */ + public static List> parseAsListOfMaps(String propertyName, JsonPath jsonPath) { + Object value = jsonPath.get(propertyName); + if (value == null) + return Collections.emptyList(); + return jsonPath.getList(propertyName); + } + + /** + * Retrieves the property values as list. + * @param propertyName name of the property, never null + * @param json the json map to retrieve properties from, never null + * @return the property values as list, may be empty but never null + */ + public static List parseAsList(String propertyName, Map json) { + Object value = json.get(propertyName); + if (value == null) + return Collections.emptyList(); + if (value instanceof String) + return Collections.singletonList((String) value); + return (List) json.get(propertyName); + } + + /** + * Collects the number of all returned features by iterating over all 'next' links and + * summarizing the size of features in 'features' array property. + * @param jsonPath the initial collection, never null + * @param maximumLimit the limit parameter value to use, if <= 0 the parameter is + * omitted + * @return the number of all returned features + * @throws java.net.URISyntaxException if the creation of a uri fails + */ + public static int collectNumberOfAllReturnedFeatures(JsonPath jsonPath, int maximumLimit) + throws URISyntaxException { + int numberOfAllReturnedFeatures = parseAsList("features", jsonPath).size(); + Map nextLink = findLinkByRel(jsonPath.getList("links"), "next"); + int count = 0; + while (nextLink != null && (count <= OgcApiFeatures10.PAGING_LIMIT)) { + String nextUrl = (String) nextLink.get("href"); + URI uri = new URI(nextUrl); + + RequestSpecification accept = given().log().all().baseUri(nextUrl).accept(GEOJSON_MIME_TYPE); + String[] pairs = uri.getQuery().split("&"); + String limitParamFromUri = null; + for (String pair : pairs) { + int idx = pair.indexOf("="); + String key = pair.substring(0, idx); + String value = pair.substring(idx + 1); + if ("limit".equals(key)) { + limitParamFromUri = value; + } + else { + accept.param(key, value); + } + } + if (maximumLimit > 0) { + accept.param("limit", maximumLimit); + } + else if (limitParamFromUri != null) { + accept.param("limit", limitParamFromUri); + } + + Response response = accept.when().request(GET); + response.then().statusCode(200); + + JsonPath nextJsonPath = response.jsonPath(); + int features = parseAsList("features", nextJsonPath).size(); + if (features > 0) { + numberOfAllReturnedFeatures += features; + nextLink = findLinkByRel(nextJsonPath.getList("links"), "next"); + } + else { + nextLink = null; + } + count++; + } + return numberOfAllReturnedFeatures; + } + + /** + * Finds the URL to the resource /collections/{collectionId}/items from the path + * /collections/{collectionId} + * @param rootUri never null + * @param collection the /collections/{collectionId} response, never null + * @return the url to the resource /collections/{collectionId}/items or + * null + */ + public static String findFeaturesUrlForGeoJson(URI rootUri, JsonPath collection) { + List links = collection.get("links"); + return findFeaturesUrlForGeoJson(rootUri, links); + } + + /** + * Finds the URL to the resource /collections/{collectionId}/items from the path + * /collections + * @param rootUri never null + * @param collection the collection object /collections response, never + * null + * @return the url to the resource /collections/{collectionId}/items or + * null + */ + public static String findFeaturesUrlForGeoJson(URI rootUri, Map collection) { + List links = (List) collection.get("links"); + return findFeaturesUrlForGeoJson(rootUri, links); + } + + /** + * Finds the URL to the resource /collections/{collectionId}/items/{featureId} from + * the path /collections and creates an valid url to this resource + * @param rootUri never null + * @param collection the /collections/{collectionId} response, never null + * @param featureId id of the feature, never null + * @return the url to the resource /collections/{collectionId}/items or + * null + */ + public static String findFeatureUrlForGeoJson(URI rootUri, JsonPath collection, String featureId) { + List links = collection.get("links"); + return findFeatureUrlForGeoJson(rootUri, featureId, links); + } + + /** + * Finds the URL to the resource /collections/{collectionId}/items/{featureId} from + * the path /collections and creates an valid url to this resource + * @param rootUri never null + * @param collection the collection object /collections response, never + * null + * @param featureId id of the feature, never null + * @return the url to the resource /collections/{collectionId}/items or + * null + */ + public static String findFeatureUrlForGeoJson(URI rootUri, Map collection, String featureId) { + List links = (List) collection.get("links"); + return findFeatureUrlForGeoJson(rootUri, featureId, links); + } + + /** + * Parse the geometry property as geometry. + * @param feature to parse, never null + * @param crs the crs of the geometry, may be null + * @return the parsed geometry, null if the feature has no geometry + * property + * @throws org.locationtech.jts.io.ParseException if the geometry could not be parsed + */ + public static Geometry parseFeatureGeometry(Map feature, CoordinateSystem crs) + throws ParseException { + Map geometry = (Map) feature.get("geometry"); + if (geometry == null) + return null; + JSONObject jsonObject = new JSONObject(geometry); + String geomAsString = jsonObject.toJSONString(); + GeoJsonReader geoJsonReader = new GeoJsonReader(); + Geometry parsedGeometry = geoJsonReader.read(geomAsString); + parsedGeometry.setSRID(crs.getSrid()); + return parsedGeometry; + } + + private static String findFeaturesUrlForGeoJson(URI rootUri, List links) { + for (Object linkObject : links) { + Map link = (Map) linkObject; + Object rel = link.get("rel"); + Object type = link.get("type"); + if ("items".equals(rel) && GEOJSON_MIME_TYPE.equals(type)) { + String url = (String) link.get("href"); + if (!url.startsWith("http")) { + String path = url; + if (null != rootUri.getScheme() && !rootUri.getScheme().isEmpty()) + url = rootUri.getScheme() + ":"; + if (null != rootUri.getAuthority() && !rootUri.getAuthority().isEmpty()) + url = url + "//" + rootUri.getAuthority(); + url = url + path; + if (null != rootUri.getQuery() && !rootUri.getQuery().isEmpty()) + url = url + "?" + rootUri.getQuery(); + if (null != rootUri.getFragment() && !rootUri.getFragment().isEmpty()) + url = url + "#" + rootUri.getFragment(); + } + return url; + } + } + return null; + } + + private static String findFeatureUrlForGeoJson(URI rootUri, String featureId, List links) { + String featuresUrlForGeoJson = findFeaturesUrlForGeoJson(rootUri, links); + if (featuresUrlForGeoJson != null) { + return createFeatureUrl(featuresUrlForGeoJson, featureId); + } + return null; + } + + private static String createFeatureUrl(String getFeatureUrl, String featureId) { + if (getFeatureUrl.indexOf("?") != -1) { + return getFeatureUrl.substring(0, getFeatureUrl.indexOf("?")) + "/" + featureId; + } + else if (getFeatureUrl.matches("^.*\\/items.[a-zA-Z]*$")) { + return getFeatureUrl.substring(0, getFeatureUrl.lastIndexOf(".")) + "/" + featureId + + getFeatureUrl.substring(getFeatureUrl.lastIndexOf(".")); + } + return getFeatureUrl + "/" + featureId; + } + + private static boolean isSameMediaType(String mediaType1, String mediaType2) { + if (mediaType1.contains(";") || mediaType2.contains(";")) { + // media types are not case sensitive + String[] components1 = mediaType1.toLowerCase().split(";"); + String[] components2 = mediaType2.toLowerCase().split(";"); + // type and subtype must match + if (!components1[0].trim().equals(components2[0].trim())) + return false; + Set parameters1 = new HashSet<>(); + Set parameters2 = new HashSet<>(); + // normalize parameter values and compare them + for (int i = 1; i < components1.length; i++) { + String parameter = components1[i].trim().replace("\"", ""); + if (!parameter.isEmpty()) + parameters1.add(parameter); + } + for (int i = 1; i < components2.length; i++) { + String parameter = components2[i].trim().replace("\"", ""); + if (!parameter.isEmpty()) + parameters2.add(parameter); + } + if (parameters1.size() != parameters2.size()) + return false; + if (!parameters1.containsAll(parameters2)) + return false; + } + else if (!mediaType1.trim().equalsIgnoreCase(mediaType2.trim())) + return false; + + return true; + } + + private static boolean hasLinkForContentType(List> alternateLinks, String mediaType) { + for (Map alternateLink : alternateLinks) { + Object type = alternateLink.get("type"); + if (type instanceof String && isSameMediaType(mediaType, (String) type)) + return true; + } + return false; + } + + private static boolean isSupportedMediaType(Object type, List mediaTypes) { + for (String mediaType : mediaTypes) { + if (type instanceof String && isSameMediaType(mediaType, (String) type)) + return true; + } + return false; + } + + private static double parseValueAsDouble(Object value) { + if (value instanceof Integer) { + return ((Integer) value).doubleValue(); + } + else if (value instanceof Float) { + return ((Float) value).doubleValue(); + } + else if (value instanceof Double) { + return (Double) value; + } + else { + return Double.parseDouble(value.toString()); + } + } + } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/util/NamespaceBindings.java b/src/main/java/org/opengis/cite/ogcapifeatures10/util/NamespaceBindings.java index fd3a697a..f9fe1983 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/util/NamespaceBindings.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/util/NamespaceBindings.java @@ -9,96 +9,91 @@ import org.opengis.cite.ogcapifeatures10.Namespaces; /** - * Provides namespace bindings for evaluating XPath 1.0 expressions using the - * JAXP XPath API. A namespace name (URI) may be bound to only one prefix. + * Provides namespace bindings for evaluating XPath 1.0 expressions using the JAXP XPath + * API. A namespace name (URI) may be bound to only one prefix. */ public class NamespaceBindings implements NamespaceContext { - private Map bindings = new HashMap(); + private Map bindings = new HashMap(); - @Override - public String getNamespaceURI(String prefix) { - String nsName = null; - for (Map.Entry binding : bindings.entrySet()) { - if (binding.getValue().equals(prefix)) { - nsName = binding.getKey(); - break; - } - } - return nsName; - } + /** {@inheritDoc} */ + @Override + public String getNamespaceURI(String prefix) { + String nsName = null; + for (Map.Entry binding : bindings.entrySet()) { + if (binding.getValue().equals(prefix)) { + nsName = binding.getKey(); + break; + } + } + return nsName; + } - @Override - public String getPrefix(String namespaceURI) { - return bindings.get(namespaceURI); - } + /** {@inheritDoc} */ + @Override + public String getPrefix(String namespaceURI) { + return bindings.get(namespaceURI); + } - @Override - public Iterator getPrefixes(String namespaceURI) { - return Arrays.asList(getPrefix(namespaceURI)).iterator(); - } + /** {@inheritDoc} */ + @Override + public Iterator getPrefixes(String namespaceURI) { + return Arrays.asList(getPrefix(namespaceURI)).iterator(); + } - /** - * Adds a namespace binding that associates a namespace name with a prefix. - * If a binding for a given namespace name already exists it will be - * replaced. - * - * @param namespaceURI - * A String denoting a namespace name (an absolute URI value). - * @param prefix - * A prefix associated with the namespace name. - */ - public void addNamespaceBinding(String namespaceURI, String prefix) { - bindings.put(namespaceURI, prefix); - } + /** + * Adds a namespace binding that associates a namespace name with a prefix. If a + * binding for a given namespace name already exists it will be replaced. + * @param namespaceURI A String denoting a namespace name (an absolute URI value). + * @param prefix A prefix associated with the namespace name. + */ + public void addNamespaceBinding(String namespaceURI, String prefix) { + bindings.put(namespaceURI, prefix); + } - /** - * Adds all of the supplied namespace bindings to the existing set of - * entries. - * - * @param nsBindings - * A Map containing a collection of namespace bindings where the - * key is an absolute URI specifying the namespace name and the - * value denotes the associated prefix. - */ - public void addAllBindings(Map nsBindings) { - if (null != nsBindings) - bindings.putAll(nsBindings); - } + /** + * Adds all of the supplied namespace bindings to the existing set of entries. + * @param nsBindings A Map containing a collection of namespace bindings where the key + * is an absolute URI specifying the namespace name and the value denotes the + * associated prefix. + */ + public void addAllBindings(Map nsBindings) { + if (null != nsBindings) + bindings.putAll(nsBindings); + } - /** - * Returns an unmodifiable view of the declared namespace bindings. - * - * @return An immutable Map containing zero or more namespace bindings where - * the key is an absolute URI specifying the namespace name and the - * value is the associated prefix. - */ - public Map getAllBindings() { - return Collections.unmodifiableMap(this.bindings); - } + /** + * Returns an unmodifiable view of the declared namespace bindings. + * @return An immutable Map containing zero or more namespace bindings where the key + * is an absolute URI specifying the namespace name and the value is the associated + * prefix. + */ + public Map getAllBindings() { + return Collections.unmodifiableMap(this.bindings); + } - /** - * Creates a NamespaceBindings object that declares the following namespace - * bindings: - * - *
      - *
    • ows: {@value org.opengis.cite.ogcapifeatures10.Namespaces#OWS}
    • - *
    • xlink: {@value org.opengis.cite.ogcapifeatures10.Namespaces#XLINK}
    • - *
    • gml: {@value org.opengis.cite.ogcapifeatures10.Namespaces#GML}
    • - *
    - * - * @return A NamespaceBindings object. - */ - public static NamespaceBindings withStandardBindings() { - NamespaceBindings nsBindings = new NamespaceBindings(); - nsBindings.addNamespaceBinding(Namespaces.OWS, "ows"); - nsBindings.addNamespaceBinding(Namespaces.XLINK, "xlink"); - nsBindings.addNamespaceBinding(Namespaces.GML, "gml"); - return nsBindings; - } + /** + * Creates a NamespaceBindings object that declares the following namespace bindings: + * + *
      + *
    • ows: {@value org.opengis.cite.ogcapifeatures10.Namespaces#OWS}
    • + *
    • xlink: {@value org.opengis.cite.ogcapifeatures10.Namespaces#XLINK}
    • + *
    • gml: {@value org.opengis.cite.ogcapifeatures10.Namespaces#GML}
    • + *
    + * @return A NamespaceBindings object. + */ + public static NamespaceBindings withStandardBindings() { + NamespaceBindings nsBindings = new NamespaceBindings(); + nsBindings.addNamespaceBinding(Namespaces.OWS, "ows"); + nsBindings.addNamespaceBinding(Namespaces.XLINK, "xlink"); + nsBindings.addNamespaceBinding(Namespaces.GML, "gml"); + return nsBindings; + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return "NamespaceBindings:\n" + bindings; + } - @Override - public String toString() { - return "NamespaceBindings:\n" + bindings; - } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/util/OgcNameValidator.java b/src/main/java/org/opengis/cite/ogcapifeatures10/util/OgcNameValidator.java index 8d728260..00d2ab00 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/util/OgcNameValidator.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/util/OgcNameValidator.java @@ -1,117 +1,121 @@ package org.opengis.cite.ogcapifeatures10.util; /** + *

    + * OgcNameValidator class. + *

    + * * @author Lyn Goltz */ public class OgcNameValidator { - /** - *
    -     * unreserved  =  ALPHA / DIGIT / "-" / "." / "_" / "~"
    -     * HEXDIG      =  DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
    -     * pct-encoded =  "%" HEXDIG HEXDIG ;
    -     * sub-delims  =  "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
    -     * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
    -     * 
    - */ - private static String PCHAR = "[a-zA-Z0-9\\-\\._~!\\$&'\\(\\)\\*\\+,;=:@]|(%[0-9A-F]{2})"; + /** + *
    +	 * unreserved  =  ALPHA / DIGIT / "-" / "." / "_" / "~"
    +	 * HEXDIG      =  DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
    +	 * pct-encoded =  "%" HEXDIG HEXDIG ;
    +	 * sub-delims  =  "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
    +	 * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
    +	 * 
    + */ + private static String PCHAR = "[a-zA-Z0-9\\-\\._~!\\$&'\\(\\)\\*\\+,;=:@]|(%[0-9A-F]{2})"; - /** - *
    -     * unreserved  =  ALPHA / DIGIT / "-" / "." / "_" / "~"
    -     * HEXDIG      =  DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
    -     * pct-encoded =  "%" HEXDIG HEXDIG ;
    -     * sub-delims  =  "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
    -     * pchar = unreserved / pct-encoded / sub-delims / "@"
    -     * 
    - */ - private static String PCHAR_NC = "[a-zA-Z0-9\\-\\._~!\\$&'\\(\\)\\*\\+,;=@]|(%[0-9A-F]{2})"; + /** + *
    +	 * unreserved  =  ALPHA / DIGIT / "-" / "." / "_" / "~"
    +	 * HEXDIG      =  DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
    +	 * pct-encoded =  "%" HEXDIG HEXDIG ;
    +	 * sub-delims  =  "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
    +	 * pchar = unreserved / pct-encoded / sub-delims / "@"
    +	 * 
    + */ + private static String PCHAR_NC = "[a-zA-Z0-9\\-\\._~!\\$&'\\(\\)\\*\\+,;=@]|(%[0-9A-F]{2})"; - /** - *
    -     * code          = segment-nz-nc *( "/" segment-nz-nc )
    -     * 
    - */ - private static String CODE = "(" + PCHAR_NC + ")+" + "(/(" + PCHAR_NC + ")+)*"; + /** + *
    +	 * code          = segment-nz-nc *( "/" segment-nz-nc )
    +	 * 
    + */ + private static String CODE = "(" + PCHAR_NC + ")+" + "(/(" + PCHAR_NC + ")+)*"; - /** - *
    -     * codeURN       = segment-nz-nc *( ":" segment-nz-nc )
    -     * 
    - */ - private static String CODE_URN = "(" + PCHAR_NC + ")+" + "(:(" + PCHAR_NC + ")+)*"; + /** + *
    +	 * codeURN       = segment-nz-nc *( ":" segment-nz-nc )
    +	 * 
    + */ + private static String CODE_URN = "(" + PCHAR_NC + ")+" + "(:(" + PCHAR_NC + ")+)*"; - /** - *
    -     * authority     = segment-nz-nc ; a token from the register of OGC authorities2
    -     * 
    - */ - private static String VERSION = "(" + PCHAR_NC + ")+"; + /** + *
    +	 * authority     = segment-nz-nc ; a token from the register of OGC authorities2
    +	 * 
    + */ + private static String VERSION = "(" + PCHAR_NC + ")+"; - /** - *
    -     * authority     = segment-nz-nc ; a token from the register of OGC authorities2
    -     * 
    - */ - private static String VERSION_URN = "(" + PCHAR_NC + ")*"; + /** + *
    +	 * authority     = segment-nz-nc ; a token from the register of OGC authorities2
    +	 * 
    + */ + private static String VERSION_URN = "(" + PCHAR_NC + ")*"; - /** - *
    -     * authority     = segment-nz-nc ; a token from the register of OGC authorities2
    -     * 
    - */ - private static String AUTHORIY = "(" + PCHAR_NC + ")+"; + /** + *
    +	 * authority     = segment-nz-nc ; a token from the register of OGC authorities2
    +	 * 
    + */ + private static String AUTHORIY = "(" + PCHAR_NC + ")+"; - /** - *
    -     * definition-type = segment-nz-nc ; a token from the register of OGC definition types1
    -     * 
    - */ - private static String DEFINITION_TYPE = "crs"; + /** + *
    +	 * definition-type = segment-nz-nc ; a token from the register of OGC definition types1
    +	 * 
    + */ + private static String DEFINITION_TYPE = "crs"; - /** - *
    -     * ResourceSpecificPath = definition-type "/" authority "/" version "/" code
    -     * 
    - */ - private static String RESOURCE_SPECIFIC_PATH = DEFINITION_TYPE + "/" + AUTHORIY + "/" + VERSION + "/" + CODE; + /** + *
    +	 * ResourceSpecificPath = definition-type "/" authority "/" version "/" code
    +	 * 
    + */ + private static String RESOURCE_SPECIFIC_PATH = DEFINITION_TYPE + "/" + AUTHORIY + "/" + VERSION + "/" + CODE; - /** - *
    -     * ResourceSpecificString = definition-type ":" authority ":" versionURN ":" codeURN
    -     * 
    - */ - private static String RESOURCE_SPECIFIC_URN = DEFINITION_TYPE + ":" + AUTHORIY + ":" + VERSION_URN + ":" + CODE_URN; + /** + *
    +	 * ResourceSpecificString = definition-type ":" authority ":" versionURN ":" codeURN
    +	 * 
    + */ + private static String RESOURCE_SPECIFIC_URN = DEFINITION_TYPE + ":" + AUTHORIY + ":" + VERSION_URN + ":" + CODE_URN; - /** - *
    -     * OGCResource   = "def"
    -     * URI           = "http://www.opengis.net/" OGCResource "/" ResourceSpecificPath
    -     * 
    - */ - private static String OGC_NAME_URI = "http://www.opengis.net/def/" + RESOURCE_SPECIFIC_PATH; + /** + *
    +	 * OGCResource   = "def"
    +	 * URI           = "http://www.opengis.net/" OGCResource "/" ResourceSpecificPath
    +	 * 
    + */ + private static String OGC_NAME_URI = "http://www.opengis.net/def/" + RESOURCE_SPECIFIC_PATH; - /** - *
    -     * OGCResource   = "def"
    -     * URN           = "urn:ogc:" OGCResource ":" ResourceSpecificString
    -     * 
    - */ - private static String OGC_NAME_URN = "urn:ogc:def:" + RESOURCE_SPECIFIC_URN; + /** + *
    +	 * OGCResource   = "def"
    +	 * URN           = "urn:ogc:" OGCResource ":" ResourceSpecificString
    +	 * 
    + */ + private static String OGC_NAME_URN = "urn:ogc:def:" + RESOURCE_SPECIFIC_URN; - /** - * Checks if the passed urn is a valid urn according OGC Name Type Specification - definitions - part 1 – basic name - * (https://docs.opengeospatial.org/pol/09-048r5.html) - * - * @param urn - * the urn to check, null results in a invalid URN. - * @return true if the urn is valid according to OGC Name Type Specification - definitions - part 1 – - * basic name, false if the urn is null, empty or not valid. - */ - public boolean isValid( String urn ) { - if ( urn == null ) - return false; - return urn.matches( OGC_NAME_URI ) || urn.matches( OGC_NAME_URN ); - } + /** + * Checks if the passed urn is a valid urn according OGC Name Type Specification - + * definitions - part 1 – basic name + * (https://docs.opengeospatial.org/pol/09-048r5.html) + * @param urn the urn to check, null results in a invalid URN. + * @return true if the urn is valid according to OGC Name Type + * Specification - definitions - part 1 – basic name, false if the urn is + * null, empty or not valid. + */ + public boolean isValid(String urn) { + if (urn == null) + return false; + return urn.matches(OGC_NAME_URI) || urn.matches(OGC_NAME_URN); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/util/RequestLimitFilter.java b/src/main/java/org/opengis/cite/ogcapifeatures10/util/RequestLimitFilter.java index b462ded8..77b87f70 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/util/RequestLimitFilter.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/util/RequestLimitFilter.java @@ -7,31 +7,35 @@ import io.restassured.specification.FilterableResponseSpecification; /** + *

    + * RequestLimitFilter class. + *

    + * * @author Benjamin Pross (b.pross @52north.org) - * - * This class sets a limit for certain request to collection items. - * If a limit parameter is already set, nothing is done. - * + * + * This class sets a limit for certain request to collection items. If a limit parameter + * is already set, nothing is done. */ public class RequestLimitFilter implements Filter { - private static String ITEMS = "items"; - private static String LIMIT = "limit"; - - @Override - public Response filter(FilterableRequestSpecification requestSpec, - FilterableResponseSpecification responseSpec, - FilterContext ctx) { - //make sure that the limit is set only for requests to collection items - if(requestSpec.getURI().endsWith(ITEMS) || requestSpec.getURI().endsWith(ITEMS + "/") - || requestSpec.getURI().contains(ITEMS + "?")){ - //do nothing if a limit was already specified - if(!(requestSpec.getQueryParams().containsKey(LIMIT) - || requestSpec.getRequestParams().containsKey(LIMIT))) { - requestSpec.queryParam(LIMIT, 10); - } - } - return ctx.next(requestSpec, responseSpec); - } + private static String ITEMS = "items"; + + private static String LIMIT = "limit"; + + /** {@inheritDoc} */ + @Override + public Response filter(FilterableRequestSpecification requestSpec, FilterableResponseSpecification responseSpec, + FilterContext ctx) { + // make sure that the limit is set only for requests to collection items + if (requestSpec.getURI().endsWith(ITEMS) || requestSpec.getURI().endsWith(ITEMS + "/") + || requestSpec.getURI().contains(ITEMS + "?")) { + // do nothing if a limit was already specified + if (!(requestSpec.getQueryParams().containsKey(LIMIT) + || requestSpec.getRequestParams().containsKey(LIMIT))) { + requestSpec.queryParam(LIMIT, 10); + } + } + return ctx.next(requestSpec, responseSpec); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/util/TemporalExtent.java b/src/main/java/org/opengis/cite/ogcapifeatures10/util/TemporalExtent.java index ab155557..42bf911f 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/util/TemporalExtent.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/util/TemporalExtent.java @@ -3,25 +3,48 @@ import java.time.ZonedDateTime; /** + *

    + * TemporalExtent class. + *

    + * * @author Lyn Goltz */ public class TemporalExtent { - private ZonedDateTime begin; - - private ZonedDateTime end; - - public TemporalExtent( ZonedDateTime begin, ZonedDateTime end ) { - this.begin = begin; - this.end = end; - } - - public ZonedDateTime getBegin() { - return begin; - } - - public ZonedDateTime getEnd() { - return end; - } - -} \ No newline at end of file + private ZonedDateTime begin; + + private ZonedDateTime end; + + /** + *

    + * Constructor for TemporalExtent. + *

    + * @param begin a {@link java.time.ZonedDateTime} object + * @param end a {@link java.time.ZonedDateTime} object + */ + public TemporalExtent(ZonedDateTime begin, ZonedDateTime end) { + this.begin = begin; + this.end = end; + } + + /** + *

    + * Getter for the field begin. + *

    + * @return a {@link java.time.ZonedDateTime} object + */ + public ZonedDateTime getBegin() { + return begin; + } + + /** + *

    + * Getter for the field end. + *

    + * @return a {@link java.time.ZonedDateTime} object + */ + public ZonedDateTime getEnd() { + return end; + } + +} diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/util/TestSuiteLogger.java b/src/main/java/org/opengis/cite/ogcapifeatures10/util/TestSuiteLogger.java index 9f5e7afc..81fbc337 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/util/TestSuiteLogger.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/util/TestSuiteLogger.java @@ -4,70 +4,65 @@ import java.util.logging.Logger; /** - * Logging utility class that provides simple access to the JDK Logging API. Set - * the "java.util.logging.config.file" system property to specify the location - * of the desired logging configuration file. A sample configuration file is - * available at {@code src/main/config/logging.properties}. + * Logging utility class that provides simple access to the JDK Logging API. Set the + * "java.util.logging.config.file" system property to specify the location of the desired + * logging configuration file. A sample configuration file is available at + * {@code src/main/config/logging.properties}. * * @see java.util.logging.LogManager LogManager */ public class TestSuiteLogger { - private static final Logger LOGR = - Logger.getLogger(TestSuiteLogger.class.getPackage().getName()); + private static final Logger LOGR = Logger.getLogger(TestSuiteLogger.class.getPackage().getName()); - /** - * Logs a message at the specified logging level with the given message - * parameters. - * - * @param level The logging {@link Level level}. - * @param message A String representing the content of the log message. - * @param params An array of message parameters. - */ - public static void log(Level level, String message, Object[] params) { - if (LOGR.isLoggable(level)) { - LOGR.log(level, message, params); - } - } + /** + * Logs a message at the specified logging level with the given message parameters. + * @param level The logging {@link Level level}. + * @param message A String representing the content of the log message. + * @param params An array of message parameters. + */ + public static void log(Level level, String message, Object[] params) { + if (LOGR.isLoggable(level)) { + LOGR.log(level, message, params); + } + } - /** - * Logs a message at the specified logging level with the given Exception - * object that represents a noteworthy error condition. - * - * @param level The logging {@link Level level}. - * @param message A String representing the content of the log message. - * @param except An object that indicates an exceptional situation. - */ - public static void log(Level level, String message, Exception except) { - if (LOGR.isLoggable(level)) { - LOGR.log(level, message, except); - } - } + /** + * Logs a message at the specified logging level with the given Exception object that + * represents a noteworthy error condition. + * @param level The logging {@link Level level}. + * @param message A String representing the content of the log message. + * @param except An object that indicates an exceptional situation. + */ + public static void log(Level level, String message, Exception except) { + if (LOGR.isLoggable(level)) { + LOGR.log(level, message, except); + } + } - /** - * Logs a simple message at the specified logging level. - * - * @param level The logging {@link Level level}. - * @param message A String representing the content of the log message. - */ - public static void log(Level level, String message) { - if (LOGR.isLoggable(level)) { - LOGR.log(level, message); - } - } + /** + * Logs a simple message at the specified logging level. + * @param level The logging {@link Level level}. + * @param message A String representing the content of the log message. + */ + public static void log(Level level, String message) { + if (LOGR.isLoggable(level)) { + LOGR.log(level, message); + } + } - /** - * Indicates if the logger is enabled at a given logging level. Message - * levels lower than this value will be discarded. - * - * @param level The logging {@link Level level}. - * @return true if the logger is currently enabled for this logging level; - * false otherwise. - */ - public static boolean isLoggable(Level level) { - return LOGR.isLoggable(level); - } + /** + * Indicates if the logger is enabled at a given logging level. Message levels lower + * than this value will be discarded. + * @param level The logging {@link Level level}. + * @return true if the logger is currently enabled for this logging level; false + * otherwise. + */ + public static boolean isLoggable(Level level) { + return LOGR.isLoggable(level); + } + + private TestSuiteLogger() { + } - private TestSuiteLogger() { - } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/util/URIUtils.java b/src/main/java/org/opengis/cite/ogcapifeatures10/util/URIUtils.java index 0f2eca34..e0b978a1 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/util/URIUtils.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/util/URIUtils.java @@ -8,58 +8,60 @@ import java.net.URI; import java.util.logging.Level; -import javax.ws.rs.core.HttpHeaders; - -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.WebResource; +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.Invocation.Builder; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Response; /** * Provides a collection of utility methods for manipulating or resolving URI references. */ public class URIUtils { - /** - * Dereferences the given URI and stores the resulting resource representation in a local file. The file will be - * located in the default temporary file directory. - * - * @param uriRef - * An absolute URI specifying the location of some resource. - * @return A File containing the content of the resource; it may be empty if resolution failed for any reason. - * @throws IOException - * If an IO error occurred. - */ - public static File dereferenceURI( URI uriRef ) - throws IOException { - if ( ( null == uriRef ) || !uriRef.isAbsolute() ) { - throw new IllegalArgumentException( "Absolute URI is required, but received " + uriRef ); - } - if ( uriRef.getScheme().equalsIgnoreCase( "file" ) ) { - return new File( uriRef ); - } - Client client = Client.create(); - WebResource webRes = client.resource( uriRef ); - ClientResponse rsp = webRes.get( ClientResponse.class ); - String suffix = null; - if ( rsp.getHeaders().getFirst( HttpHeaders.CONTENT_TYPE ).endsWith( "xml" ) ) { - suffix = ".xml"; - } - File destFile = File.createTempFile( "entity-", suffix ); - if ( rsp.hasEntity() ) { - InputStream is = rsp.getEntityInputStream(); - OutputStream os = new FileOutputStream( destFile ); - byte[] buffer = new byte[8 * 1024]; - int bytesRead; - while ( ( bytesRead = is.read( buffer ) ) != -1 ) { - os.write( buffer, 0, bytesRead ); - } - is.close(); - os.flush(); - os.close(); - } - TestSuiteLogger.log( Level.FINE, - "Wrote " + destFile.length() + " bytes to file at " + destFile.getAbsolutePath() ); - return destFile; - } + /** + * Dereferences the given URI and stores the resulting resource representation in a + * local file. The file will be located in the default temporary file directory. + * @param uriRef An absolute URI specifying the location of some resource. + * @return A File containing the content of the resource; it may be empty if + * resolution failed for any reason. + * @throws java.io.IOException If an IO error occurred. + */ + public static File dereferenceURI(URI uriRef) throws IOException { + if ((null == uriRef) || !uriRef.isAbsolute()) { + throw new IllegalArgumentException("Absolute URI is required, but received " + uriRef); + } + if (uriRef.getScheme().equalsIgnoreCase("file")) { + return new File(uriRef); + } + Client client = ClientUtils.buildClient(); + WebTarget target = client.target(uriRef); + Builder builder = target.request(); + Response rsp = builder.buildGet().invoke(); + String suffix = null; + if (rsp.getHeaders().getFirst(HttpHeaders.CONTENT_TYPE).toString().endsWith("xml")) { + suffix = ".xml"; + } + File destFile = File.createTempFile("entity-", suffix); + if (rsp.hasEntity()) { + Object entity = rsp.getEntity(); + if (!(entity instanceof InputStream)) { + return null; + } + InputStream is = (InputStream) entity; + OutputStream os = new FileOutputStream(destFile); + byte[] buffer = new byte[8 * 1024]; + int bytesRead; + while ((bytesRead = is.read(buffer)) != -1) { + os.write(buffer, 0, bytesRead); + } + is.close(); + os.flush(); + os.close(); + } + TestSuiteLogger.log(Level.FINE, + "Wrote " + destFile.length() + " bytes to file at " + destFile.getAbsolutePath()); + return destFile; + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/util/UrnValidator.java b/src/main/java/org/opengis/cite/ogcapifeatures10/util/UrnValidator.java index 89f6c333..5ce486b6 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/util/UrnValidator.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/util/UrnValidator.java @@ -2,100 +2,100 @@ /** * https://github.com/BruceZu/broken_colored_glass/blob/master/project/src/main/java/URN8141.java - * + * * @author Lyn Goltz */ public class UrnValidator { - /** - *
    -     * DIGIT         =  0-9
    -     * ALPHA         =  A-Z / a-z
    -     * alphanum      =  ALPHA / DIGIT
    -     * ldh           =  alphanum / "-"
    -     * NID           = (alphanum) 0*30(ldh) (alphanum)
    -     * 
    - */ - private static String NID = "\\p{Alnum}[a-zA-Z0-9\\-]{0,30}\\p{Alnum}"; + /** + *
    +	 * DIGIT         =  0-9
    +	 * ALPHA         =  A-Z / a-z
    +	 * alphanum      =  ALPHA / DIGIT
    +	 * ldh           =  alphanum / "-"
    +	 * NID           = (alphanum) 0*30(ldh) (alphanum)
    +	 * 
    + */ + private static String NID = "\\p{Alnum}[a-zA-Z0-9\\-]{0,30}\\p{Alnum}"; - /** - *
    -     * unreserved  =  ALPHA / DIGIT / "-" / "." / "_" / "~"
    -     * HEXDIG      =  DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
    -     * pct-encoded =  "%" HEXDIG HEXDIG ;
    -     * sub-delims  =  "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
    -     * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
    -     * 
    - */ - private static String PCHAR = "[a-zA-Z0-9\\-\\._~!\\$&'\\(\\)\\*\\+,;=:@]|(%[0-9A-F]{2})"; + /** + *
    +	 * unreserved  =  ALPHA / DIGIT / "-" / "." / "_" / "~"
    +	 * HEXDIG      =  DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
    +	 * pct-encoded =  "%" HEXDIG HEXDIG ;
    +	 * sub-delims  =  "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
    +	 * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
    +	 * 
    + */ + private static String PCHAR = "[a-zA-Z0-9\\-\\._~!\\$&'\\(\\)\\*\\+,;=:@]|(%[0-9A-F]{2})"; - /** - *
    -     * NSS = pchar * ( pchar / "/" )
    -     * 
    - * - * @see #PCHAR - */ - private static String NSS = "(" + PCHAR + ")((" + PCHAR + ")|/)*"; + /** + *
    +	 * NSS = pchar * ( pchar / "/" )
    +	 * 
    + * + * @see #PCHAR + */ + private static String NSS = "(" + PCHAR + ")((" + PCHAR + ")|/)*"; - /** - *
    -     * assigned-name = "urn" ":" NID ":" NSS
    -     * 
    - * - * The leading scheme (urn:) is case-insensitive - * - * @see Wiki: Uniform Resource Name - */ - private static String ASSIGNED_NAME = "([uU][rR][nN]):(" + NID + "):(" + NSS + ")"; + /** + *
    +	 * assigned-name = "urn" ":" NID ":" NSS
    +	 * 
    + * + * The leading scheme (urn:) is case-insensitive + * + * @see Wiki: Uniform + * Resource Name + */ + private static String ASSIGNED_NAME = "([uU][rR][nN]):(" + NID + "):(" + NSS + ")"; - /** - *
    -     * fragment      =       *( pchar / "/" / "?" )
    -     * 
    - */ - private static String FRAGMENT = "((" + PCHAR + ")|/|\\?)*"; + /** + *
    +	 * fragment      =       *( pchar / "/" / "?" )
    +	 * 
    + */ + private static String FRAGMENT = "((" + PCHAR + ")|/|\\?)*"; - /** - *
    -     * r-component   = pchar *( pchar / "/" / "?" )
    -     * q-component   = pchar *( pchar / "/" / "?" )
    -     * 
    - */ - private static String R_Q_COMPONENT = "(" + PCHAR + ")" + FRAGMENT; + /** + *
    +	 * r-component   = pchar *( pchar / "/" / "?" )
    +	 * q-component   = pchar *( pchar / "/" / "?" )
    +	 * 
    + */ + private static String R_Q_COMPONENT = "(" + PCHAR + ")" + FRAGMENT; - /** - *
    -     * rq-components = [ "?+" r-component ] [ "?=" q-component ]
    -     * 
    - * - * The order is not gurantee as the '?' can be used in fragment, and the '+' and '=' can be used in pchar. - * - * @see #R_Q_COMPONENT - */ - private static String RQ_COMPONENTS = "((\\?\\+)(" + R_Q_COMPONENT + "))?((\\?=)(" + R_Q_COMPONENT + "))?"; + /** + *
    +	 * rq-components = [ "?+" r-component ] [ "?=" q-component ]
    +	 * 
    + * + * The order is not gurantee as the '?' can be used in fragment, and the '+' and '=' + * can be used in pchar. + * + * @see #R_Q_COMPONENT + */ + private static String RQ_COMPONENTS = "((\\?\\+)(" + R_Q_COMPONENT + "))?((\\?=)(" + R_Q_COMPONENT + "))?"; - /** - *
    -     * f-component   = fragment
    -     * namestring    = assigned-name  [ rq-components ]  [ "#" f-component ]
    -     * 
    - */ - private static String URN_RFC8141 = "^" + ASSIGNED_NAME + RQ_COMPONENTS + "(#" + FRAGMENT + ")?$"; + /** + *
    +	 * f-component   = fragment
    +	 * namestring    = assigned-name  [ rq-components ]  [ "#" f-component ]
    +	 * 
    + */ + private static String URN_RFC8141 = "^" + ASSIGNED_NAME + RQ_COMPONENTS + "(#" + FRAGMENT + ")?$"; - /** - * Checks if the passed urn is a valid urn according RFC 8141, Section 2 - * (https://tools.ietf.org/html/rfc8141#section-2) - * - * @param urn - * the urn to check, null results in a invalid URN. - * @return true if the urn is valid according to RFC 8141, Section 2, false if the urn is - * null, empty or not valid. - */ - public boolean isValid( String urn ) { - if ( urn == null ) - return false; - return urn.matches( URN_RFC8141 ); - } + /** + * Checks if the passed urn is a valid urn according RFC 8141, Section 2 + * (https://tools.ietf.org/html/rfc8141#section-2) + * @param urn the urn to check, null results in a invalid URN. + * @return true if the urn is valid according to RFC 8141, Section 2, + * false if the urn is null, empty or not valid. + */ + public boolean isValid(String urn) { + if (urn == null) + return false; + return urn.matches(URN_RFC8141); + } } diff --git a/src/main/java/org/opengis/cite/ogcapifeatures10/util/XMLUtils.java b/src/main/java/org/opengis/cite/ogcapifeatures10/util/XMLUtils.java index e80c2679..442c5c08 100644 --- a/src/main/java/org/opengis/cite/ogcapifeatures10/util/XMLUtils.java +++ b/src/main/java/org/opengis/cite/ogcapifeatures10/util/XMLUtils.java @@ -19,32 +19,32 @@ */ public class XMLUtils { - /** - * Writes the content of a DOM Node to a string. The XML declaration is omitted and the character encoding is set to - * "US-ASCII" (any character outside of this set is serialized as a numeric character reference). - * - * @param node - * The DOM Node to be serialized. - * @return A String representing the content of the given node. - */ - public static String writeNodeToString( Node node ) { - if ( null == node ) { - return ""; - } - Writer writer = null; - try { - Transformer idTransformer = TransformerFactory.newInstance().newTransformer(); - Properties outProps = new Properties(); - outProps.setProperty( OutputKeys.ENCODING, "US-ASCII" ); - outProps.setProperty( OutputKeys.OMIT_XML_DECLARATION, "yes" ); - outProps.setProperty( OutputKeys.INDENT, "yes" ); - idTransformer.setOutputProperties( outProps ); - writer = new StringWriter(); - idTransformer.transform( new DOMSource( node ), new StreamResult( writer ) ); - } catch ( TransformerException ex ) { - TestSuiteLogger.log( Level.WARNING, "Failed to serialize node " + node.getNodeName(), ex ); - } - return writer.toString(); - } + /** + * Writes the content of a DOM Node to a string. The XML declaration is omitted and + * the character encoding is set to "US-ASCII" (any character outside of this set is + * serialized as a numeric character reference). + * @param node The DOM Node to be serialized. + * @return A String representing the content of the given node. + */ + public static String writeNodeToString(Node node) { + if (null == node) { + return ""; + } + Writer writer = null; + try { + Transformer idTransformer = TransformerFactory.newInstance().newTransformer(); + Properties outProps = new Properties(); + outProps.setProperty(OutputKeys.ENCODING, "US-ASCII"); + outProps.setProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + outProps.setProperty(OutputKeys.INDENT, "yes"); + idTransformer.setOutputProperties(outProps); + writer = new StringWriter(); + idTransformer.transform(new DOMSource(node), new StreamResult(writer)); + } + catch (TransformerException ex) { + TestSuiteLogger.log(Level.WARNING, "Failed to serialize node " + node.getNodeName(), ex); + } + return writer.toString(); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/EtsAssertTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/EtsAssertTest.java index d54adbe1..36eb743a 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/EtsAssertTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/EtsAssertTest.java @@ -27,105 +27,105 @@ */ public class EtsAssertTest { - @Test - public void testAssertTrue() { - EtsAssert.assertTrue( true, "OK" ); - } - - @Test - public void testAssertFalse() { - EtsAssert.assertFalse( false, "OK" ); - } - - @Test(expected = AssertionError.class) - public void testAssertTrue_false() { - EtsAssert.assertTrue( false, "FAIlURE" ); - } - - @Test(expected = AssertionError.class) - public void testAssertFalse_true() { - EtsAssert.assertFalse( true, "FAIlURE" ); - } - - @Test - public void testAssertValidCrsIdentifier_OGC_URL() { - assertValidCrsIdentifier( new CoordinateSystem( "http://www.opengis.net/def/crs/OGC/1.3/CRS84" ), "OK" ); - } - - @Test - public void testAssertValidCrsIdentifier_OGC_URN() { - assertValidCrsIdentifier( new CoordinateSystem( "urn:ogc:def:crs:OGC:1.3:CRS84" ), "OK" ); - } - - @Test - public void testAssertValidCrsIdentifier_URL() { - assertValidCrsIdentifier( new CoordinateSystem( "http://www.test.de/crs/4326" ), "OK" ); - } - - @Test - public void testAssertValidCrsIdentifier_URN() { - assertValidCrsIdentifier( new CoordinateSystem( "urn:test:crs:CRS84" ), "OK" ); - } - - @Test(expected = AssertionError.class) - public void testAssertValidCrsIdentifier_null() { - assertValidCrsIdentifier( null, "FAIlURE" ); - } - - @Test(expected = AssertionError.class) - public void testAssertValidCrsIdentifier_empty() { - assertValidCrsIdentifier( new CoordinateSystem( "" ), "FAIlURE" ); - } - - @Test - public void testAssertDefaultCrs() { - CoordinateSystem defaultCrs = assertDefaultCrs( Arrays.asList( "urn:test:crs:CRS84", - OgcApiFeatures10.DEFAULT_CRS_CODE ), - "OK" ); - Assert.assertThat( defaultCrs, is( OgcApiFeatures10.DEFAULT_CRS ) ); - } - - @Test(expected = AssertionError.class) - public void testAssertDefaultCrs_Missing() { - assertDefaultCrs( Arrays.asList( "urn:test:crs:CRS84" ), "OK" ); - } - - @Test - public void testAssertDefaultCrsAtFirst() { - assertDefaultCrsAtFirst( Arrays.asList( OgcApiFeatures10.DEFAULT_CRS_CODE, "urn:test:crs:CRS84" ), "OK" ); - } - - @Test(expected = AssertionError.class) - public void testAssertDefaultCrsAtFirst_firstNotDefault() { - assertDefaultCrsAtFirst( Arrays.asList( "urn:test:crs:CRS84", OgcApiFeatures10.DEFAULT_CRS_CODE ), "FAIlURE" ); - } - - @Test - public void testAssertCrsHeader() { - assertCrsHeader( "", - new CoordinateSystem( "http://www.opengis.net/def/crs/OGC/1.3/CRS84" ), "OK" ); - } - - @Test(expected = AssertionError.class) - public void testAssertCrsHeader_UnexpectedCode() { - assertCrsHeader( "", - new CoordinateSystem( "http://www.opengis.net/def/crs/OGC/1.3/CRS84" ), "FAIlURE" ); - } - - @Test(expected = AssertionError.class) - public void testAssertCrsHeader_MissingBracket() { - assertCrsHeader( "http://www.opengis.net/def/crs/OGC/1.3/CRS84", - new CoordinateSystem( "http://www.opengis.net/def/crs/OGC/1.3/CRS84" ), "FAIlURE" ); - } - - @Test - public void testAssertInCrs84() - throws Exception { - InputStream collectionItemsJson = EtsAssertTest.class.getResourceAsStream( "conformance/core/collections/collectionItems-flurstueck.json" ); - JsonPath jsonCollectionItem = new JsonPath( collectionItemsJson ); - List> features = jsonCollectionItem.getList( "features" ); - Map firstFeature = features.get( 0 ); - Geometry geometry = parseFeatureGeometry( firstFeature, DEFAULT_CRS ); - assertInCrs84( geometry, "OK" ); - } + @Test + public void testAssertTrue() { + EtsAssert.assertTrue(true, "OK"); + } + + @Test + public void testAssertFalse() { + EtsAssert.assertFalse(false, "OK"); + } + + @Test(expected = AssertionError.class) + public void testAssertTrue_false() { + EtsAssert.assertTrue(false, "FAIlURE"); + } + + @Test(expected = AssertionError.class) + public void testAssertFalse_true() { + EtsAssert.assertFalse(true, "FAIlURE"); + } + + @Test + public void testAssertValidCrsIdentifier_OGC_URL() { + assertValidCrsIdentifier(new CoordinateSystem("http://www.opengis.net/def/crs/OGC/1.3/CRS84"), "OK"); + } + + @Test + public void testAssertValidCrsIdentifier_OGC_URN() { + assertValidCrsIdentifier(new CoordinateSystem("urn:ogc:def:crs:OGC:1.3:CRS84"), "OK"); + } + + @Test + public void testAssertValidCrsIdentifier_URL() { + assertValidCrsIdentifier(new CoordinateSystem("http://www.test.de/crs/4326"), "OK"); + } + + @Test + public void testAssertValidCrsIdentifier_URN() { + assertValidCrsIdentifier(new CoordinateSystem("urn:test:crs:CRS84"), "OK"); + } + + @Test(expected = AssertionError.class) + public void testAssertValidCrsIdentifier_null() { + assertValidCrsIdentifier(null, "FAIlURE"); + } + + @Test(expected = AssertionError.class) + public void testAssertValidCrsIdentifier_empty() { + assertValidCrsIdentifier(new CoordinateSystem(""), "FAIlURE"); + } + + @Test + public void testAssertDefaultCrs() { + CoordinateSystem defaultCrs = assertDefaultCrs( + Arrays.asList("urn:test:crs:CRS84", OgcApiFeatures10.DEFAULT_CRS_CODE), "OK"); + Assert.assertThat(defaultCrs, is(OgcApiFeatures10.DEFAULT_CRS)); + } + + @Test(expected = AssertionError.class) + public void testAssertDefaultCrs_Missing() { + assertDefaultCrs(Arrays.asList("urn:test:crs:CRS84"), "OK"); + } + + @Test + public void testAssertDefaultCrsAtFirst() { + assertDefaultCrsAtFirst(Arrays.asList(OgcApiFeatures10.DEFAULT_CRS_CODE, "urn:test:crs:CRS84"), "OK"); + } + + @Test(expected = AssertionError.class) + public void testAssertDefaultCrsAtFirst_firstNotDefault() { + assertDefaultCrsAtFirst(Arrays.asList("urn:test:crs:CRS84", OgcApiFeatures10.DEFAULT_CRS_CODE), "FAIlURE"); + } + + @Test + public void testAssertCrsHeader() { + assertCrsHeader("", + new CoordinateSystem("http://www.opengis.net/def/crs/OGC/1.3/CRS84"), "OK"); + } + + @Test(expected = AssertionError.class) + public void testAssertCrsHeader_UnexpectedCode() { + assertCrsHeader("", + new CoordinateSystem("http://www.opengis.net/def/crs/OGC/1.3/CRS84"), "FAIlURE"); + } + + @Test(expected = AssertionError.class) + public void testAssertCrsHeader_MissingBracket() { + assertCrsHeader("http://www.opengis.net/def/crs/OGC/1.3/CRS84", + new CoordinateSystem("http://www.opengis.net/def/crs/OGC/1.3/CRS84"), "FAIlURE"); + } + + @Test + public void testAssertInCrs84() throws Exception { + InputStream collectionItemsJson = EtsAssertTest.class + .getResourceAsStream("conformance/core/collections/collectionItems-flurstueck.json"); + JsonPath jsonCollectionItem = new JsonPath(collectionItemsJson); + List> features = jsonCollectionItem.getList("features"); + Map firstFeature = features.get(0); + Geometry geometry = parseFeatureGeometry(firstFeature, DEFAULT_CRS); + assertInCrs84(geometry, "OK"); + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/SuiteFixtureListenerTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/SuiteFixtureListenerTest.java index fc11ee05..4a63393f 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/SuiteFixtureListenerTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/SuiteFixtureListenerTest.java @@ -1,7 +1,7 @@ package org.opengis.cite.ogcapifeatures10; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isA; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -21,35 +21,34 @@ public class SuiteFixtureListenerTest { - private static XmlSuite xmlSuite; - - private static ISuite suite; - - @BeforeClass - public static void setUpClass() { - xmlSuite = mock( XmlSuite.class ); - suite = mock( ISuite.class ); - when( suite.getXmlSuite() ).thenReturn( xmlSuite ); - } - - @Test(expected = IllegalArgumentException.class) - public void noSuiteParameters() { - Map params = new HashMap<>(); - when( xmlSuite.getParameters() ).thenReturn( params ); - SuiteFixtureListener iut = new SuiteFixtureListener(); - iut.onStart( suite ); - } - - @Test - public void processIUTParameter() - throws URISyntaxException { - URL url = this.getClass().getResource( "landingPage.html" ); - Map params = new HashMap<>(); - params.put( TestRunArg.IUT.toString(), url.toURI().toString() ); - when( xmlSuite.getParameters() ).thenReturn( params ); - SuiteFixtureListener iut = new SuiteFixtureListener(); - iut.onStart( suite ); - verify( suite ).setAttribute( eq( SuiteAttribute.TEST_SUBJ_FILE.getName() ), isA( File.class ) ); - } + private static XmlSuite xmlSuite; + + private static ISuite suite; + + @BeforeClass + public static void setUpClass() { + xmlSuite = mock(XmlSuite.class); + suite = mock(ISuite.class); + when(suite.getXmlSuite()).thenReturn(xmlSuite); + } + + @Test(expected = IllegalArgumentException.class) + public void noSuiteParameters() { + Map params = new HashMap<>(); + when(xmlSuite.getParameters()).thenReturn(params); + SuiteFixtureListener iut = new SuiteFixtureListener(); + iut.onStart(suite); + } + + @Test + public void processIUTParameter() throws URISyntaxException { + URL url = this.getClass().getResource("landingPage.html"); + Map params = new HashMap<>(); + params.put(TestRunArg.IUT.toString(), url.toURI().toString()); + when(xmlSuite.getParameters()).thenReturn(params); + SuiteFixtureListener iut = new SuiteFixtureListener(); + iut.onStart(suite); + verify(suite).setAttribute(eq(SuiteAttribute.TEST_SUBJ_FILE.getName()), isA(File.class)); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/TestNGControllerTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/TestNGControllerTest.java index 39b7f638..df6e58a9 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/TestNGControllerTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/TestNGControllerTest.java @@ -16,54 +16,51 @@ import org.w3c.dom.Document; /** - * Verifies the results of executing a test run using the main controller (TestNGController). + * Verifies the results of executing a test run using the main controller + * (TestNGController). */ public class TestNGControllerTest { - private static DocumentBuilder docBuilder; + private static DocumentBuilder docBuilder; - private Properties testRunProps; + private Properties testRunProps; - @BeforeClass - public static void initParser() - throws ParserConfigurationException { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware( true ); - dbf.setValidating( false ); - dbf.setFeature( "http://apache.org/xml/features/nonvalidating/load-external-dtd", false ); - docBuilder = dbf.newDocumentBuilder(); - } + @BeforeClass + public static void initParser() throws ParserConfigurationException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + dbf.setValidating(false); + dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + docBuilder = dbf.newDocumentBuilder(); + } - @Before - public void loadDefaultTestRunProperties() - throws IOException { - this.testRunProps = new Properties(); - this.testRunProps.loadFromXML( getClass().getResourceAsStream( "/test-run-props.xml" ) ); - } + @Before + public void loadDefaultTestRunProperties() throws IOException { + this.testRunProps = new Properties(); + this.testRunProps.loadFromXML(getClass().getResourceAsStream("/test-run-props.xml")); + } - @Test - public void testValidateTestRunArgs() - throws Exception { - URL testSubject = getClass().getResource( "landingPage.html" ); - this.testRunProps.setProperty( TestRunArg.IUT.toString(), testSubject.toURI().toString() ); - ByteArrayOutputStream outStream = new ByteArrayOutputStream( 1024 ); - this.testRunProps.storeToXML( outStream, "Integration test" ); - Document testRunArgs = docBuilder.parse( new ByteArrayInputStream( outStream.toByteArray() ) ); + @Test + public void testValidateTestRunArgs() throws Exception { + URL testSubject = getClass().getResource("landingPage.html"); + this.testRunProps.setProperty(TestRunArg.IUT.toString(), testSubject.toURI().toString()); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024); + this.testRunProps.storeToXML(outStream, "Integration test"); + Document testRunArgs = docBuilder.parse(new ByteArrayInputStream(outStream.toByteArray())); - TestNGController controller = new TestNGController(); - controller.validateTestRunArgs( testRunArgs ); - } + TestNGController controller = new TestNGController(); + controller.validateTestRunArgs(testRunArgs); + } - @Test(expected = IllegalArgumentException.class) - public void testValidateTestRunArgs_missingIUT() - throws Exception { - this.testRunProps.remove( TestRunArg.IUT.toString() ); - ByteArrayOutputStream outStream = new ByteArrayOutputStream( 1024 ); - this.testRunProps.storeToXML( outStream, "Integration test" ); - Document testRunArgs = docBuilder.parse( new ByteArrayInputStream( outStream.toByteArray() ) ); + @Test(expected = IllegalArgumentException.class) + public void testValidateTestRunArgs_missingIUT() throws Exception { + this.testRunProps.remove(TestRunArg.IUT.toString()); + ByteArrayOutputStream outStream = new ByteArrayOutputStream(1024); + this.testRunProps.storeToXML(outStream, "Integration test"); + Document testRunArgs = docBuilder.parse(new ByteArrayInputStream(outStream.toByteArray())); - TestNGController controller = new TestNGController(); - controller.validateTestRunArgs( testRunArgs ); - } + TestNGController controller = new TestNGController(); + controller.validateTestRunArgs(testRunArgs); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/apidefinition/ApiDefinitionIT.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/apidefinition/ApiDefinitionIT.java index c4a353e7..1b3041ba 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/apidefinition/ApiDefinitionIT.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/apidefinition/ApiDefinitionIT.java @@ -18,29 +18,27 @@ @Ignore("Stable service is required") public class ApiDefinitionIT { - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - URI landingPageUri = new URI( "https://www.ldproxy.nrw.de/kataster" ); - when( suite.getAttribute( SuiteAttribute.IUT.getName() ) ).thenReturn( landingPageUri ); - } - - @Test - public void testOpenApi() - throws Exception { - ApiDefinition openApi = new ApiDefinition(); - openApi.initCommonFixture( testContext ); - openApi.retrieveApiUrl(); - openApi.openapiDocumentRetrieval(); - openApi.apiDefinitionValidation( testContext ); - } + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + URI landingPageUri = new URI("https://www.ldproxy.nrw.de/kataster"); + when(suite.getAttribute(SuiteAttribute.IUT.getName())).thenReturn(landingPageUri); + } + + @Test + public void testOpenApi() throws Exception { + ApiDefinition openApi = new ApiDefinition(); + openApi.initCommonFixture(testContext); + openApi.retrieveApiUrl(); + openApi.openapiDocumentRetrieval(); + openApi.apiDefinitionValidation(testContext); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollectionTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollectionTest.java index c1001a8a..2c2002bd 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollectionTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollectionTest.java @@ -36,87 +36,91 @@ */ public class FeatureCollectionTest { - private static ITestContext testContext; - - private static ISuite suite; - - private static URI iut; - - @BeforeClass - public static void instantiateUri() - throws URISyntaxException { - iut = new URI( "http://localhost:8080/oaf" ); - } - - @BeforeClass - public static void initTestFixture() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - URL openAppiDocument = FeatureCollectionTest.class.getResource( "../../../openapi3/openapi.json" ); - OpenApi3 apiModel = parser.parse( openAppiDocument, true ); - - List requirementClasses = new ArrayList(); - requirementClasses.add( RequirementClass.CORE ); - List> collections = prepareCollections(); - - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - URI landingPageUri = new URI( "https://www.ldproxy.nrw.de/kataster" ); - when( suite.getAttribute( SuiteAttribute.IUT.getName() ) ).thenReturn( landingPageUri ); - when( suite.getAttribute( SuiteAttribute.API_MODEL.getName() ) ).thenReturn( apiModel ); - when( suite.getAttribute( SuiteAttribute.REQUIREMENTCLASSES.getName() ) ).thenReturn( requirementClasses ); - when( suite.getAttribute( SuiteAttribute.COLLECTIONS.getName() ) ).thenReturn( collections ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void testValidateFeatureCollectionMetadataOperationResponse() { - prepareJadler(); - FeatureCollection featureCollection = new FeatureCollection(); - featureCollection.initCommonFixture( testContext ); - featureCollection.retrieveApiModel( testContext ); - featureCollection.requirementClasses( testContext ); - - Object[][] collections = featureCollection.collections( testContext ); - for ( Object[] object : collections ) { - Map collection = (Map) object[0]; - featureCollection.validateFeatureCollectionMetadataOperation( testContext, collection ); - featureCollection.validateFeatureCollectionMetadataResponse( collection ); - } - } - - private static List> prepareCollections() { - List> collections = new ArrayList<>(); - - JsonPathConfig config = JsonPathConfig.jsonPathConfig().numberReturnType(NumberReturnType.DOUBLE); - collections.add( new JsonPath( FeatureCollectionTest.class.getResourceAsStream( "collection-flurstueck.json" ) ).using(config).get() ); - collections.add( new JsonPath( FeatureCollectionTest.class.getResourceAsStream( "collection-gebaeudebauwerk.json" ) ).using(config).get() ); - return collections; - } - - private void prepareJadler() { - InputStream collections = getClass().getResourceAsStream( "collections.json" ); - onRequest().havingPath( endsWith( "collections" ) ).respond().withBody( collections ); - - InputStream collectionFlurstueck = getClass().getResourceAsStream( "collection-flurstueck.json" ); - onRequest().havingPath( endsWith( "collections/flurstueck" ) ).respond().withBody( collectionFlurstueck ); - - InputStream collectionGebaeudebauwerk = getClass().getResourceAsStream( "collection-gebaeudebauwerk.json" ); - onRequest().havingPath( endsWith( "collections/gebaeudebauwerk" ) ).respond().withBody( collectionGebaeudebauwerk ); - - InputStream collectionVerwaltungseinheit = getClass().getResourceAsStream( "collection-verwaltungseinheit.json" ); - onRequest().havingPath( endsWith( "collections/verwaltungseinheit" ) ).respond().withBody( collectionVerwaltungseinheit ); - } + private static ITestContext testContext; + + private static ISuite suite; + + private static URI iut; + + @BeforeClass + public static void instantiateUri() throws URISyntaxException { + iut = new URI("http://localhost:8080/oaf"); + } + + @BeforeClass + public static void initTestFixture() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + URL openAppiDocument = FeatureCollectionTest.class.getResource("../../../openapi3/openapi.json"); + OpenApi3 apiModel = parser.parse(openAppiDocument, true); + + List requirementClasses = new ArrayList(); + requirementClasses.add(RequirementClass.CORE); + List> collections = prepareCollections(); + + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + URI landingPageUri = new URI("https://www.ldproxy.nrw.de/kataster"); + when(suite.getAttribute(SuiteAttribute.IUT.getName())).thenReturn(landingPageUri); + when(suite.getAttribute(SuiteAttribute.API_MODEL.getName())).thenReturn(apiModel); + when(suite.getAttribute(SuiteAttribute.REQUIREMENTCLASSES.getName())).thenReturn(requirementClasses); + when(suite.getAttribute(SuiteAttribute.COLLECTIONS.getName())).thenReturn(collections); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testValidateFeatureCollectionMetadataOperationResponse() { + prepareJadler(); + FeatureCollection featureCollection = new FeatureCollection(); + featureCollection.initCommonFixture(testContext); + featureCollection.retrieveApiModel(testContext); + featureCollection.requirementClasses(testContext); + + Object[][] collections = featureCollection.collections(testContext); + for (Object[] object : collections) { + Map collection = (Map) object[0]; + featureCollection.validateFeatureCollectionMetadataOperation(testContext, collection); + featureCollection.validateFeatureCollectionMetadataResponse(collection); + } + } + + private static List> prepareCollections() { + List> collections = new ArrayList<>(); + + JsonPathConfig config = JsonPathConfig.jsonPathConfig().numberReturnType(NumberReturnType.DOUBLE); + collections.add(new JsonPath(FeatureCollectionTest.class.getResourceAsStream("collection-flurstueck.json")) + .using(config) + .get()); + collections.add(new JsonPath(FeatureCollectionTest.class.getResourceAsStream("collection-gebaeudebauwerk.json")) + .using(config) + .get()); + return collections; + } + + private void prepareJadler() { + InputStream collections = getClass().getResourceAsStream("collections.json"); + onRequest().havingPath(endsWith("collections")).respond().withBody(collections); + + InputStream collectionFlurstueck = getClass().getResourceAsStream("collection-flurstueck.json"); + onRequest().havingPath(endsWith("collections/flurstueck")).respond().withBody(collectionFlurstueck); + + InputStream collectionGebaeudebauwerk = getClass().getResourceAsStream("collection-gebaeudebauwerk.json"); + onRequest().havingPath(endsWith("collections/gebaeudebauwerk")).respond().withBody(collectionGebaeudebauwerk); + + InputStream collectionVerwaltungseinheit = getClass().getResourceAsStream("collection-verwaltungseinheit.json"); + onRequest().havingPath(endsWith("collections/verwaltungseinheit")) + .respond() + .withBody(collectionVerwaltungseinheit); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollectionsTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollectionsTest.java index a15f05ab..a645b30c 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollectionsTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureCollectionsTest.java @@ -6,7 +6,7 @@ import static org.hamcrest.CoreMatchers.endsWith; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.eq; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -27,8 +27,8 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; -import org.opengis.cite.ogcapifeatures10.conformance.SuiteAttribute; import org.opengis.cite.ogcapifeatures10.conformance.RequirementClass; +import org.opengis.cite.ogcapifeatures10.conformance.SuiteAttribute; import org.opengis.cite.ogcapifeatures10.openapi3.TestPoint; import org.testng.ISuite; import org.testng.ITestContext; @@ -42,87 +42,87 @@ */ public class FeatureCollectionsTest { - private static ITestContext testContext; - - private static ISuite suite; - - private static URI iut; - - @BeforeClass - public static void instantiateUri() - throws URISyntaxException { - iut = new URI( "http://localhost:8080/oaf" ); - } - - @BeforeClass - public static void initTestFixture() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - URL openAppiDocument = FeatureCollectionsTest.class.getResource( "../../../openapi3/openapi.json" ); - OpenApi3 apiModel = parser.parse( openAppiDocument, true ); - - List requirementClasses = new ArrayList(); - requirementClasses.add( RequirementClass.CORE ); - - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - URI landingPageUri = new URI( "https://www.ldproxy.nrw.de/kataster" ); - when( suite.getAttribute( SuiteAttribute.IUT.getName() ) ).thenReturn( landingPageUri ); - when( suite.getAttribute( SuiteAttribute.API_MODEL.getName() ) ).thenReturn( apiModel ); - when( suite.getAttribute( SuiteAttribute.REQUIREMENTCLASSES.getName() ) ).thenReturn( requirementClasses ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void testValidateFeatureCollectionsMetadataOperationResponse() { - prepareJadler(); - FeatureCollections featureCollectionsMetadataOperation = new FeatureCollections(); - featureCollectionsMetadataOperation.initCommonFixture( testContext ); - featureCollectionsMetadataOperation.retrieveApiModel( testContext ); - featureCollectionsMetadataOperation.requirementClasses( testContext ); - TestPoint testPoint = new TestPoint( "http://localhost:8090/rest/services/kataster", "/collections", - mediaTypes() ); - featureCollectionsMetadataOperation.validateFeatureCollectionsMetadataOperation( testPoint ); - featureCollectionsMetadataOperation.validateFeatureCollectionsMetadataOperationResponse_Links( testPoint ); - featureCollectionsMetadataOperation.validateFeatureCollectionsMetadataOperationResponse_Items( testPoint ); - featureCollectionsMetadataOperation.storeCollectionsInTestContext( testContext ); - - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass( List.class ); - verify( suite ).setAttribute( eq( COLLECTIONS.getName() ), argumentCaptor.capture() ); - List capturedArgument = argumentCaptor.getValue(); - assertThat( capturedArgument.size(), is( 3 ) ); - } - - private Map mediaTypes() { - Map mediaTypes = new HashMap<>(); - mediaTypes.put( "application/json", Mockito.mock( MediaType.class ) ); - mediaTypes.put( "text/html", Mockito.mock( MediaType.class ) ); - return mediaTypes; - } - - private void prepareJadler() { - InputStream collections = getClass().getResourceAsStream( "collections.json" ); - onRequest().havingPath( endsWith( "collections" ) ).respond().withBody( collections ); - - InputStream collectionFlurstueck = getClass().getResourceAsStream( "collection-flurstueck.json" ); - onRequest().havingPath( endsWith( "collections/flurstueck" ) ).respond().withBody( collectionFlurstueck ); - - InputStream collectionGebaeudebauwerk = getClass().getResourceAsStream( "collection-gebaeudebauwerk.json" ); - onRequest().havingPath( endsWith( "collections/gebaeudebauwerk" ) ).respond().withBody( collectionGebaeudebauwerk ); - - InputStream collectionVerwaltungseinheit = getClass().getResourceAsStream( "collection-verwaltungseinheit.json" ); - onRequest().havingPath( endsWith( "collections/verwaltungseinheit" ) ).respond().withBody( collectionVerwaltungseinheit ); - } + private static ITestContext testContext; + + private static ISuite suite; + + private static URI iut; + + @BeforeClass + public static void instantiateUri() throws URISyntaxException { + iut = new URI("http://localhost:8080/oaf"); + } + + @BeforeClass + public static void initTestFixture() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + URL openAppiDocument = FeatureCollectionsTest.class.getResource("../../../openapi3/openapi.json"); + OpenApi3 apiModel = parser.parse(openAppiDocument, true); + + List requirementClasses = new ArrayList(); + requirementClasses.add(RequirementClass.CORE); + + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + URI landingPageUri = new URI("https://www.ldproxy.nrw.de/kataster"); + when(suite.getAttribute(SuiteAttribute.IUT.getName())).thenReturn(landingPageUri); + when(suite.getAttribute(SuiteAttribute.API_MODEL.getName())).thenReturn(apiModel); + when(suite.getAttribute(SuiteAttribute.REQUIREMENTCLASSES.getName())).thenReturn(requirementClasses); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testValidateFeatureCollectionsMetadataOperationResponse() { + prepareJadler(); + FeatureCollections featureCollectionsMetadataOperation = new FeatureCollections(); + featureCollectionsMetadataOperation.initCommonFixture(testContext); + featureCollectionsMetadataOperation.retrieveApiModel(testContext); + featureCollectionsMetadataOperation.requirementClasses(testContext); + TestPoint testPoint = new TestPoint("http://localhost:8090/rest/services/kataster", "/collections", + mediaTypes()); + featureCollectionsMetadataOperation.validateFeatureCollectionsMetadataOperation(testPoint); + featureCollectionsMetadataOperation.validateFeatureCollectionsMetadataOperationResponse_Links(testPoint); + featureCollectionsMetadataOperation.validateFeatureCollectionsMetadataOperationResponse_Items(testPoint); + featureCollectionsMetadataOperation.storeCollectionsInTestContext(testContext); + + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(List.class); + verify(suite).setAttribute(eq(COLLECTIONS.getName()), argumentCaptor.capture()); + List capturedArgument = argumentCaptor.getValue(); + assertThat(capturedArgument.size(), is(3)); + } + + private Map mediaTypes() { + Map mediaTypes = new HashMap<>(); + mediaTypes.put("application/json", Mockito.mock(MediaType.class)); + mediaTypes.put("text/html", Mockito.mock(MediaType.class)); + return mediaTypes; + } + + private void prepareJadler() { + InputStream collections = getClass().getResourceAsStream("collections.json"); + onRequest().havingPath(endsWith("collections")).respond().withBody(collections); + + InputStream collectionFlurstueck = getClass().getResourceAsStream("collection-flurstueck.json"); + onRequest().havingPath(endsWith("collections/flurstueck")).respond().withBody(collectionFlurstueck); + + InputStream collectionGebaeudebauwerk = getClass().getResourceAsStream("collection-gebaeudebauwerk.json"); + onRequest().havingPath(endsWith("collections/gebaeudebauwerk")).respond().withBody(collectionGebaeudebauwerk); + + InputStream collectionVerwaltungseinheit = getClass().getResourceAsStream("collection-verwaltungseinheit.json"); + onRequest().havingPath(endsWith("collections/verwaltungseinheit")) + .respond() + .withBody(collectionVerwaltungseinheit); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureTest.java index b7479d70..211972cf 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeatureTest.java @@ -36,86 +36,85 @@ */ public class FeatureTest { - public static final String COLLECTION_NAME = "flurstueck"; - - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - URL openAppiDocument = FeatureTest.class.getResource( "../../../openapi3/openapi.json" ); - OpenApi3 apiModel = parser.parse( openAppiDocument, true ); - - InputStream json = FeatureTest.class.getResourceAsStream( "../collections/collections.json" ); - JsonPath collectionsResponse = new JsonPath( json ); - List> collections = collectionsResponse.getList( "collections" ); - - Map featureIds = new HashMap<>(); - featureIds.put( COLLECTION_NAME, "DENW19AL0000geMFFL" ); - - List requirementClasses = new ArrayList(); - requirementClasses.add( RequirementClass.CORE ); - - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - URI landingPageUri = new URI( "https://localhost:8090" ); - when( suite.getAttribute( SuiteAttribute.IUT.getName() ) ).thenReturn( landingPageUri ); - when( suite.getAttribute( SuiteAttribute.API_MODEL.getName() ) ).thenReturn( apiModel ); - when( suite.getAttribute( SuiteAttribute.COLLECTIONS.getName() ) ).thenReturn( collections ); - when( suite.getAttribute( SuiteAttribute.FEATUREIDS.getName() ) ).thenReturn( featureIds ); - when( suite.getAttribute( SuiteAttribute.REQUIREMENTCLASSES.getName() ) ).thenReturn( requirementClasses ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void testGetFeatureOperations() { - prepareJadler(); - Feature getFeatureOperation = new Feature(); - getFeatureOperation.initCommonFixture( testContext ); - getFeatureOperation.retrieveRequiredInformationFromTestContext( testContext ); - getFeatureOperation.requirementClasses( testContext ); - - Iterator collections = getFeatureOperation.collectionFeatureId( testContext ); - Object[] collectionAndFeatureId = findCollectionById( COLLECTION_NAME, collections ); - assertThat( collectionAndFeatureId, notNullValue() ); - - Map collection = (Map) collectionAndFeatureId[0]; - assertThat( collection, notNullValue() ); - - String featureId = (String) collectionAndFeatureId[1]; - assertThat( featureId, notNullValue() ); - - getFeatureOperation.featureOperation( collection, featureId ); - getFeatureOperation.validateFeatureResponse( collection, featureId ); - } - - private void prepareJadler() { - InputStream collectionItemById = getClass().getResourceAsStream( "collectionItem1-flurstueck.json" ); - onRequest().respond().withBody( collectionItemById ); - } - - private Object[] findCollectionById( String collectionName, Iterator collections ) { - for ( Iterator it = collections; it.hasNext(); ) { - Object[] collection = it.next(); - Map parameter = (Map) collection[0]; - if ( collectionName.equals( parameter.get( "id" ) ) ) - return collection; - } - return null; - } + public static final String COLLECTION_NAME = "flurstueck"; + + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + URL openAppiDocument = FeatureTest.class.getResource("../../../openapi3/openapi.json"); + OpenApi3 apiModel = parser.parse(openAppiDocument, true); + + InputStream json = FeatureTest.class.getResourceAsStream("../collections/collections.json"); + JsonPath collectionsResponse = new JsonPath(json); + List> collections = collectionsResponse.getList("collections"); + + Map featureIds = new HashMap<>(); + featureIds.put(COLLECTION_NAME, "DENW19AL0000geMFFL"); + + List requirementClasses = new ArrayList(); + requirementClasses.add(RequirementClass.CORE); + + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + URI landingPageUri = new URI("https://localhost:8090"); + when(suite.getAttribute(SuiteAttribute.IUT.getName())).thenReturn(landingPageUri); + when(suite.getAttribute(SuiteAttribute.API_MODEL.getName())).thenReturn(apiModel); + when(suite.getAttribute(SuiteAttribute.COLLECTIONS.getName())).thenReturn(collections); + when(suite.getAttribute(SuiteAttribute.FEATUREIDS.getName())).thenReturn(featureIds); + when(suite.getAttribute(SuiteAttribute.REQUIREMENTCLASSES.getName())).thenReturn(requirementClasses); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testGetFeatureOperations() { + prepareJadler(); + Feature getFeatureOperation = new Feature(); + getFeatureOperation.initCommonFixture(testContext); + getFeatureOperation.retrieveRequiredInformationFromTestContext(testContext); + getFeatureOperation.requirementClasses(testContext); + + Iterator collections = getFeatureOperation.collectionFeatureId(testContext); + Object[] collectionAndFeatureId = findCollectionById(COLLECTION_NAME, collections); + assertThat(collectionAndFeatureId, notNullValue()); + + Map collection = (Map) collectionAndFeatureId[0]; + assertThat(collection, notNullValue()); + + String featureId = (String) collectionAndFeatureId[1]; + assertThat(featureId, notNullValue()); + + getFeatureOperation.featureOperation(collection, featureId); + getFeatureOperation.validateFeatureResponse(collection, featureId); + } + + private void prepareJadler() { + InputStream collectionItemById = getClass().getResourceAsStream("collectionItem1-flurstueck.json"); + onRequest().respond().withBody(collectionItemById); + } + + private Object[] findCollectionById(String collectionName, Iterator collections) { + for (Iterator it = collections; it.hasNext();) { + Object[] collection = it.next(); + Map parameter = (Map) collection[0]; + if (collectionName.equals(parameter.get("id"))) + return collection; + } + return null; + } } \ No newline at end of file diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesBBoxTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesBBoxTest.java index 34af06fb..b0a47305 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesBBoxTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesBBoxTest.java @@ -36,93 +36,96 @@ */ public class FeaturesBBoxTest { - private static ITestContext testContext; - - private static ISuite suite; - - private static TestPoint testPoint; - - @BeforeClass - public static void initTestFixture() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - URL openAppiDocument = FeaturesBBoxTest.class.getResource( "../../../openapi3/openapi.json" ); - OpenApi3 apiModel = parser.parse( openAppiDocument, true ); - - InputStream json = FeaturesBBoxTest.class.getResourceAsStream( "../collections/collections.json" ); - JsonPath collectionsResponse = new JsonPath( json ); - List> collections = collectionsResponse.getList( "collections" ); - - List requirementClasses = new ArrayList(); - requirementClasses.add( RequirementClass.CORE ); - - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - testPoint = new TestPoint( "http://localhost:8090/rest/services/kataster", "/collections/flurstueck/items", - Collections.emptyMap() ); - - URI landingPageUri = new URI( "https://www.ldproxy.nrw.de/kataster" ); - when( suite.getAttribute( SuiteAttribute.IUT.getName() ) ).thenReturn( landingPageUri ); - when( suite.getAttribute( SuiteAttribute.API_MODEL.getName() ) ).thenReturn( apiModel ); - when( suite.getAttribute( SuiteAttribute.COLLECTIONS.getName() ) ).thenReturn( collections ); - when( suite.getAttribute( SuiteAttribute.REQUIREMENTCLASSES.getName() ) ).thenReturn( requirementClasses ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void testParameterDefinition() { - prepareJadler(); - FeaturesBBox features = initFeaturesBbox(); - - features.boundingBoxParameterDefinition( testPoint ); - } - - @Test - public void test() { - prepareJadler(); - FeaturesBBox features = initFeaturesBbox(); - - Map collection = prepareCollection(); - BBox bbox = new BBox( 5, 48, 9, 50 ); - features.validateFeaturesWithBoundingBoxOperation( collection, bbox ); - features.validateFeaturesWithBoundingBoxResponse_TypeProperty( collection, bbox ); - features.validateFeaturesWithBoundingBoxResponse_FeaturesProperty( collection, bbox ); - features.validateFeaturesWithBoundingBoxResponse_Links( collection, bbox ); - // skipped (collection missing): - // features.validateFeaturesWithBoundingBoxResponse_TimeStamp( collection, bbox ); - // skipped (collection missing): - // features.validateFeaturesWithBoundingBoxResponse_NumberMatched( collection , bbox ); - // skipped (collection missing): - // features.validateFeaturesResponse_NumberReturned( collection, bbox ); - } - - private FeaturesBBox initFeaturesBbox() { - FeaturesBBox features = new FeaturesBBox(); - features.initCommonFixture( testContext ); - features.retrieveRequiredInformationFromTestContext( testContext ); - features.requirementClasses( testContext ); - features.retrieveApiModel( testContext ); - return features; - } - - private static Map prepareCollection() { - return new JsonPath( FeatureCollectionTest.class.getResourceAsStream( "collection-flurstueck.json" ) ).get(); - } - - private void prepareJadler() { - InputStream flurstueckItems = getClass().getResourceAsStream( "collectionItems-flurstueck.json" ); - onRequest().havingPath( endsWith( "collections/flurstueck/items" ) ).havingParameter( "bbox" ).respond().withBody( flurstueckItems ); - } + private static ITestContext testContext; + + private static ISuite suite; + + private static TestPoint testPoint; + + @BeforeClass + public static void initTestFixture() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + URL openAppiDocument = FeaturesBBoxTest.class.getResource("../../../openapi3/openapi.json"); + OpenApi3 apiModel = parser.parse(openAppiDocument, true); + + InputStream json = FeaturesBBoxTest.class.getResourceAsStream("../collections/collections.json"); + JsonPath collectionsResponse = new JsonPath(json); + List> collections = collectionsResponse.getList("collections"); + + List requirementClasses = new ArrayList(); + requirementClasses.add(RequirementClass.CORE); + + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + testPoint = new TestPoint("http://localhost:8090/rest/services/kataster", "/collections/flurstueck/items", + Collections.emptyMap()); + + URI landingPageUri = new URI("https://www.ldproxy.nrw.de/kataster"); + when(suite.getAttribute(SuiteAttribute.IUT.getName())).thenReturn(landingPageUri); + when(suite.getAttribute(SuiteAttribute.API_MODEL.getName())).thenReturn(apiModel); + when(suite.getAttribute(SuiteAttribute.COLLECTIONS.getName())).thenReturn(collections); + when(suite.getAttribute(SuiteAttribute.REQUIREMENTCLASSES.getName())).thenReturn(requirementClasses); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testParameterDefinition() { + prepareJadler(); + FeaturesBBox features = initFeaturesBbox(); + + features.boundingBoxParameterDefinition(testPoint); + } + + @Test + public void test() { + prepareJadler(); + FeaturesBBox features = initFeaturesBbox(); + + Map collection = prepareCollection(); + BBox bbox = new BBox(5, 48, 9, 50); + features.validateFeaturesWithBoundingBoxOperation(collection, bbox); + features.validateFeaturesWithBoundingBoxResponse_TypeProperty(collection, bbox); + features.validateFeaturesWithBoundingBoxResponse_FeaturesProperty(collection, bbox); + features.validateFeaturesWithBoundingBoxResponse_Links(collection, bbox); + // skipped (collection missing): + // features.validateFeaturesWithBoundingBoxResponse_TimeStamp( collection, bbox ); + // skipped (collection missing): + // features.validateFeaturesWithBoundingBoxResponse_NumberMatched( collection , + // bbox ); + // skipped (collection missing): + // features.validateFeaturesResponse_NumberReturned( collection, bbox ); + } + + private FeaturesBBox initFeaturesBbox() { + FeaturesBBox features = new FeaturesBBox(); + features.initCommonFixture(testContext); + features.retrieveRequiredInformationFromTestContext(testContext); + features.requirementClasses(testContext); + features.retrieveApiModel(testContext); + return features; + } + + private static Map prepareCollection() { + return new JsonPath(FeatureCollectionTest.class.getResourceAsStream("collection-flurstueck.json")).get(); + } + + private void prepareJadler() { + InputStream flurstueckItems = getClass().getResourceAsStream("collectionItems-flurstueck.json"); + onRequest().havingPath(endsWith("collections/flurstueck/items")) + .havingParameter("bbox") + .respond() + .withBody(flurstueckItems); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesErrorConditionsTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesErrorConditionsTest.java index b51a7850..009b4040 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesErrorConditionsTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesErrorConditionsTest.java @@ -32,68 +32,73 @@ */ public class FeaturesErrorConditionsTest { - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - URL openAppiDocument = FeaturesTest.class.getResource( "../../../openapi3/openapi.json" ); - OpenApi3 apiModel = parser.parse( openAppiDocument, true ); - - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - URI landingPageUri = new URI( "https://www.ldproxy.nrw.de/kataster" ); - when( suite.getAttribute( SuiteAttribute.IUT.getName() ) ).thenReturn( landingPageUri ); - when( suite.getAttribute( SuiteAttribute.API_MODEL.getName() ) ).thenReturn( apiModel ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void testValidateFeaturesOperation_QueryParamInvalid() { - prepareJadler(); - FeaturesErrorConditions featuresErrorConditions = new FeaturesErrorConditions(); - featuresErrorConditions.initCommonFixture( testContext ); - featuresErrorConditions.retrieveRequiredInformationFromTestContext( testContext ); - featuresErrorConditions.requirementClasses( testContext ); - - Map parameter = prepareCollection(); - featuresErrorConditions.validateFeaturesOperation_QueryParamInvalid( parameter ); - } - - @Ignore - @Test - public void testValidateFeaturesOperation_QueryParamUnknown() { - prepareJadler(); - FeaturesErrorConditions featuresErrorConditions = new FeaturesErrorConditions(); - featuresErrorConditions.initCommonFixture( testContext ); - featuresErrorConditions.retrieveRequiredInformationFromTestContext( testContext ); - featuresErrorConditions.requirementClasses( testContext ); - - Map parameter = prepareCollection(); - featuresErrorConditions.validateFeaturesOperation_QueryParamUnknown( parameter ); - } - - private static Map prepareCollection() { - return new JsonPath( FeatureCollectionTest.class.getResourceAsStream( "collection-flurstueck.json" ) ).get(); - } - - private void prepareJadler() { - onRequest().havingPath( endsWith( "collections/flurstueck/items" ) ).havingParameterEqualTo( "limit", - INVALID_QUERY_PARAM_VALUE ).respond().withStatus( 400 ); - onRequest().havingPath( endsWith( "collections/flurstueck/items" ) ).havingParameter( UNKNOWN_QUERY_PARAM ).respond().withStatus( 400 ); - } + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + URL openAppiDocument = FeaturesTest.class.getResource("../../../openapi3/openapi.json"); + OpenApi3 apiModel = parser.parse(openAppiDocument, true); + + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + URI landingPageUri = new URI("https://www.ldproxy.nrw.de/kataster"); + when(suite.getAttribute(SuiteAttribute.IUT.getName())).thenReturn(landingPageUri); + when(suite.getAttribute(SuiteAttribute.API_MODEL.getName())).thenReturn(apiModel); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testValidateFeaturesOperation_QueryParamInvalid() { + prepareJadler(); + FeaturesErrorConditions featuresErrorConditions = new FeaturesErrorConditions(); + featuresErrorConditions.initCommonFixture(testContext); + featuresErrorConditions.retrieveRequiredInformationFromTestContext(testContext); + featuresErrorConditions.requirementClasses(testContext); + + Map parameter = prepareCollection(); + featuresErrorConditions.validateFeaturesOperation_QueryParamInvalid(parameter); + } + + @Ignore + @Test + public void testValidateFeaturesOperation_QueryParamUnknown() { + prepareJadler(); + FeaturesErrorConditions featuresErrorConditions = new FeaturesErrorConditions(); + featuresErrorConditions.initCommonFixture(testContext); + featuresErrorConditions.retrieveRequiredInformationFromTestContext(testContext); + featuresErrorConditions.requirementClasses(testContext); + + Map parameter = prepareCollection(); + featuresErrorConditions.validateFeaturesOperation_QueryParamUnknown(parameter); + } + + private static Map prepareCollection() { + return new JsonPath(FeatureCollectionTest.class.getResourceAsStream("collection-flurstueck.json")).get(); + } + + private void prepareJadler() { + onRequest().havingPath(endsWith("collections/flurstueck/items")) + .havingParameterEqualTo("limit", INVALID_QUERY_PARAM_VALUE) + .respond() + .withStatus(400); + onRequest().havingPath(endsWith("collections/flurstueck/items")) + .havingParameter(UNKNOWN_QUERY_PARAM) + .respond() + .withStatus(400); + } + } \ No newline at end of file diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesLimitTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesLimitTest.java index 132eec39..2a39712d 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesLimitTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesLimitTest.java @@ -37,97 +37,101 @@ */ public class FeaturesLimitTest { - private static ITestContext testContext; - - private static ISuite suite; - - private static TestPoint testPoint; - - @BeforeClass - public static void initTestFixture() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - URL openAppiDocument = FeaturesLimitTest.class.getResource( "../../../openapi3/openapi.json" ); - OpenApi3 apiModel = parser.parse( openAppiDocument, true ); - - InputStream json = FeaturesLimitTest.class.getResourceAsStream( "../collections/collections.json" ); - JsonPath collectionsResponse = new JsonPath( json ); - List> collections = collectionsResponse.getList( "collections" ); - - List requirementClasses = new ArrayList(); - requirementClasses.add( RequirementClass.CORE ); - - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - testPoint = new TestPoint( "http://localhost:8090/rest/services/kataster", "/collections/flurstueck/items", - Collections.emptyMap() ); - - URI landingPageUri = new URI( "https://www.ldproxy.nrw.de/kataster" ); - when( suite.getAttribute( SuiteAttribute.IUT.getName() ) ).thenReturn( landingPageUri ); - when( suite.getAttribute( SuiteAttribute.API_MODEL.getName() ) ).thenReturn( apiModel ); - when( suite.getAttribute( SuiteAttribute.COLLECTIONS.getName() ) ).thenReturn( collections ); - when( suite.getAttribute( SuiteAttribute.REQUIREMENTCLASSES.getName() ) ).thenReturn( requirementClasses ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void testParameterDefinition() { - prepareJadler(); - FeaturesLimit features = initFeaturesLimit(); - - features.limitParameterDefinition( testPoint ); - } - - @Test - public void test() { - prepareJadler(); - FeaturesLimit features = initFeaturesLimit(); - - Map collection = prepareCollection(); - features.validateFeaturesWithLimitOperation( collection, 10, 15 ); - features.validateFeaturesWithLimitResponse_TypeProperty( collection, 10, 15 ); - features.validateFeaturesWithLimitResponse_FeaturesProperty( collection, 10, 15 ); - features.validateFeaturesWithLimitResponse_Links( collection, 10, 15 ); - // skipped (collection missing): - // features.validateFeaturesWithLimitResponse_TimeStamp( collection, 10, 15 ); - // skipped (collection missing): - // features.validateFeaturesWithLimitResponse_NumberMatched( collection , 10, 15 ); - // skipped (collection missing): - // features.validateFeaturesResponse_NumberReturned( collection, 10, 15 ); - } - - private FeaturesLimit initFeaturesLimit() { - FeaturesLimit features = new FeaturesLimit(); - features.initCommonFixture( testContext ); - features.retrieveRequiredInformationFromTestContext( testContext ); - features.requirementClasses( testContext ); - features.retrieveApiModel( testContext ); - return features; - } - - private static Map prepareCollection() { - return new JsonPath( FeatureCollectionTest.class.getResourceAsStream( "collection-flurstueck.json" ) ).get(); - } - - private void prepareJadler() { - InputStream flurstueckItems = getClass().getResourceAsStream( "collectionItems-flurstueck.json" ); - onRequest().havingPath( endsWith( "collections/flurstueck/items" ) ).havingParameter( "limit", - nullValue() ).respond().withBody( flurstueckItems ); - - InputStream flurstueckItemsLimit = getClass().getResourceAsStream( "collectionItems-flurstueck.json" ); - onRequest().havingPath( containsString( "collections/flurstueck/items" ) ).havingParameterEqualTo( "limit", - "10" ).respond().withBody( flurstueckItemsLimit ); - } + private static ITestContext testContext; + + private static ISuite suite; + + private static TestPoint testPoint; + + @BeforeClass + public static void initTestFixture() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + URL openAppiDocument = FeaturesLimitTest.class.getResource("../../../openapi3/openapi.json"); + OpenApi3 apiModel = parser.parse(openAppiDocument, true); + + InputStream json = FeaturesLimitTest.class.getResourceAsStream("../collections/collections.json"); + JsonPath collectionsResponse = new JsonPath(json); + List> collections = collectionsResponse.getList("collections"); + + List requirementClasses = new ArrayList(); + requirementClasses.add(RequirementClass.CORE); + + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + testPoint = new TestPoint("http://localhost:8090/rest/services/kataster", "/collections/flurstueck/items", + Collections.emptyMap()); + + URI landingPageUri = new URI("https://www.ldproxy.nrw.de/kataster"); + when(suite.getAttribute(SuiteAttribute.IUT.getName())).thenReturn(landingPageUri); + when(suite.getAttribute(SuiteAttribute.API_MODEL.getName())).thenReturn(apiModel); + when(suite.getAttribute(SuiteAttribute.COLLECTIONS.getName())).thenReturn(collections); + when(suite.getAttribute(SuiteAttribute.REQUIREMENTCLASSES.getName())).thenReturn(requirementClasses); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testParameterDefinition() { + prepareJadler(); + FeaturesLimit features = initFeaturesLimit(); + + features.limitParameterDefinition(testPoint); + } + + @Test + public void test() { + prepareJadler(); + FeaturesLimit features = initFeaturesLimit(); + + Map collection = prepareCollection(); + features.validateFeaturesWithLimitOperation(collection, 10, 15); + features.validateFeaturesWithLimitResponse_TypeProperty(collection, 10, 15); + features.validateFeaturesWithLimitResponse_FeaturesProperty(collection, 10, 15); + features.validateFeaturesWithLimitResponse_Links(collection, 10, 15); + // skipped (collection missing): + // features.validateFeaturesWithLimitResponse_TimeStamp( collection, 10, 15 ); + // skipped (collection missing): + // features.validateFeaturesWithLimitResponse_NumberMatched( collection , 10, 15 + // ); + // skipped (collection missing): + // features.validateFeaturesResponse_NumberReturned( collection, 10, 15 ); + } + + private FeaturesLimit initFeaturesLimit() { + FeaturesLimit features = new FeaturesLimit(); + features.initCommonFixture(testContext); + features.retrieveRequiredInformationFromTestContext(testContext); + features.requirementClasses(testContext); + features.retrieveApiModel(testContext); + return features; + } + + private static Map prepareCollection() { + return new JsonPath(FeatureCollectionTest.class.getResourceAsStream("collection-flurstueck.json")).get(); + } + + private void prepareJadler() { + InputStream flurstueckItems = getClass().getResourceAsStream("collectionItems-flurstueck.json"); + onRequest().havingPath(endsWith("collections/flurstueck/items")) + .havingParameter("limit", nullValue()) + .respond() + .withBody(flurstueckItems); + + InputStream flurstueckItemsLimit = getClass().getResourceAsStream("collectionItems-flurstueck.json"); + onRequest().havingPath(containsString("collections/flurstueck/items")) + .havingParameterEqualTo("limit", "10") + .respond() + .withBody(flurstueckItemsLimit); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesTest.java index 5178a0f1..d43bf8b9 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesTest.java @@ -33,73 +33,72 @@ */ public class FeaturesTest { - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - URL openAppiDocument = FeaturesTest.class.getResource( "../../../openapi3/openapi.json" ); - OpenApi3 apiModel = parser.parse( openAppiDocument, true ); - - InputStream json = FeaturesTest.class.getResourceAsStream( "../collections/collections.json" ); - JsonPath collectionsResponse = new JsonPath( json ); - List> collections = collectionsResponse.getList( "collections" ); - - List requirementClasses = new ArrayList(); - requirementClasses.add( RequirementClass.CORE ); - - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - URI landingPageUri = new URI( "https://www.ldproxy.nrw.de/kataster" ); - when( suite.getAttribute( SuiteAttribute.IUT.getName() ) ).thenReturn( landingPageUri ); - when( suite.getAttribute( SuiteAttribute.API_MODEL.getName() ) ).thenReturn( apiModel ); - when( suite.getAttribute( SuiteAttribute.COLLECTIONS.getName() ) ).thenReturn( collections ); - when( suite.getAttribute( SuiteAttribute.REQUIREMENTCLASSES.getName() ) ).thenReturn( requirementClasses ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void test() { - prepareJadler(); - Features features = new Features(); - features.initCommonFixture( testContext ); - features.retrieveRequiredInformationFromTestContext( testContext ); - features.requirementClasses( testContext ); - - Map collection = prepareCollection(); - features.validateFeaturesOperation( testContext, collection ); - features.validateFeaturesResponse_TypeProperty( collection ); - features.validateFeaturesResponse_FeaturesProperty( collection ); - features.validateFeaturesResponse_Links( collection ); - // skipped (collection missing): - // features.validateFeaturesResponse_TimeStamp( collection ); - // skipped (collection missing): - // features.validateFeaturesResponse_NumberMatched( collection ); - // skipped (collection missing): - // features.validateFeaturesResponse_NumberReturned( collection ); - } - - private static Map prepareCollection() { - return new JsonPath( FeatureCollectionTest.class.getResourceAsStream( "collection-flurstueck.json" ) ).get(); - } - - private void prepareJadler() { - InputStream flurstueckItems = getClass().getResourceAsStream( "collectionItems-flurstueck.json" ); - onRequest().havingPath( endsWith( "collections/flurstueck/items" ) ).respond().withBody( flurstueckItems ); - } + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + URL openAppiDocument = FeaturesTest.class.getResource("../../../openapi3/openapi.json"); + OpenApi3 apiModel = parser.parse(openAppiDocument, true); + + InputStream json = FeaturesTest.class.getResourceAsStream("../collections/collections.json"); + JsonPath collectionsResponse = new JsonPath(json); + List> collections = collectionsResponse.getList("collections"); + + List requirementClasses = new ArrayList(); + requirementClasses.add(RequirementClass.CORE); + + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + URI landingPageUri = new URI("https://www.ldproxy.nrw.de/kataster"); + when(suite.getAttribute(SuiteAttribute.IUT.getName())).thenReturn(landingPageUri); + when(suite.getAttribute(SuiteAttribute.API_MODEL.getName())).thenReturn(apiModel); + when(suite.getAttribute(SuiteAttribute.COLLECTIONS.getName())).thenReturn(collections); + when(suite.getAttribute(SuiteAttribute.REQUIREMENTCLASSES.getName())).thenReturn(requirementClasses); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void test() { + prepareJadler(); + Features features = new Features(); + features.initCommonFixture(testContext); + features.retrieveRequiredInformationFromTestContext(testContext); + features.requirementClasses(testContext); + + Map collection = prepareCollection(); + features.validateFeaturesOperation(testContext, collection); + features.validateFeaturesResponse_TypeProperty(collection); + features.validateFeaturesResponse_FeaturesProperty(collection); + features.validateFeaturesResponse_Links(collection); + // skipped (collection missing): + // features.validateFeaturesResponse_TimeStamp( collection ); + // skipped (collection missing): + // features.validateFeaturesResponse_NumberMatched( collection ); + // skipped (collection missing): + // features.validateFeaturesResponse_NumberReturned( collection ); + } + + private static Map prepareCollection() { + return new JsonPath(FeatureCollectionTest.class.getResourceAsStream("collection-flurstueck.json")).get(); + } + + private void prepareJadler() { + InputStream flurstueckItems = getClass().getResourceAsStream("collectionItems-flurstueck.json"); + onRequest().havingPath(endsWith("collections/flurstueck/items")).respond().withBody(flurstueckItems); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesTimeTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesTimeTest.java index df052a11..d7b5eefd 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesTimeTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/collections/FeaturesTimeTest.java @@ -35,95 +35,100 @@ */ public class FeaturesTimeTest { - private static ITestContext testContext; - - private static ISuite suite; - - private static TestPoint testPoint; - - @BeforeClass - public static void initTestFixture() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - URL openAppiDocument = FeaturesTimeTest.class.getResource( "../../../openapi3/openapi.json" ); - OpenApi3 apiModel = parser.parse( openAppiDocument, true ); - - InputStream json = FeaturesTimeTest.class.getResourceAsStream( "../collections/collections.json" ); - JsonPath collectionsResponse = new JsonPath( json ); - List> collections = collectionsResponse.getList( "collections" ); - - List requirementClasses = new ArrayList(); - requirementClasses.add( RequirementClass.CORE ); - - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - testPoint = new TestPoint( "http://localhost:8090/rest/services/kataster", "/collections/flurstueck/items", - Collections.emptyMap() ); - - URI landingPageUri = new URI( "https://www.ldproxy.nrw.de/kataster" ); - when( suite.getAttribute( SuiteAttribute.IUT.getName() ) ).thenReturn( landingPageUri ); - when( suite.getAttribute( SuiteAttribute.API_MODEL.getName() ) ).thenReturn( apiModel ); - when( suite.getAttribute( SuiteAttribute.COLLECTIONS.getName() ) ).thenReturn( collections ); - when( suite.getAttribute( SuiteAttribute.REQUIREMENTCLASSES.getName() ) ).thenReturn( requirementClasses ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void testParameterDefinition() { - prepareJadler(); - FeaturesTime features = initFeaturesTime(); - - features.timeParameterDefinition( testPoint ); - } - - @Test - public void test() { - prepareJadler(); - FeaturesTime features = initFeaturesTime(); - - Map collection = prepareCollection(); - String queryString = "2014-08-09"; - Object begin = null; - Object end = null; - features.validateFeaturesWithDateTimeOperation( collection, queryString, begin, end ); - features.validateFeaturesWithDateTimeResponse_TypeProperty( collection, queryString, begin, end ); - features.validateFeaturesWithDateTimeResponse_FeaturesProperty( collection, queryString, begin, end ); - features.validateFeaturesWithDateTimeResponse_Links( collection, queryString, begin, end ); - // skipped (collection missing): - // features.validateFeaturesWithDateTimeResponse_TimeStamp( collection, queryString, begin, end ); - // skipped (collection missing): - // features.validateFeaturesWithDateTimeResponse_NumberMatched( collection , queryString, begin, end ); - // skipped (collection missing): - // features.validateFeaturesResponse_NumberReturned( collection, queryString, begin, end ); - } - - private FeaturesTime initFeaturesTime() { - FeaturesTime features = new FeaturesTime(); - features.initCommonFixture( testContext ); - features.retrieveRequiredInformationFromTestContext( testContext ); - features.requirementClasses( testContext ); - features.retrieveApiModel( testContext ); - return features; - } - - private static Map prepareCollection() { - return new JsonPath( FeatureCollectionTest.class.getResourceAsStream( "collection-flurstueck.json" ) ).get(); - } - - private void prepareJadler() { - InputStream flurstueckItems = getClass().getResourceAsStream( "collectionItems-flurstueck.json" ); - onRequest().havingPath( endsWith( "collections/flurstueck/items" ) ).havingParameter( "datetime" ).respond().withBody( flurstueckItems ); - } + private static ITestContext testContext; + + private static ISuite suite; + + private static TestPoint testPoint; + + @BeforeClass + public static void initTestFixture() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + URL openAppiDocument = FeaturesTimeTest.class.getResource("../../../openapi3/openapi.json"); + OpenApi3 apiModel = parser.parse(openAppiDocument, true); + + InputStream json = FeaturesTimeTest.class.getResourceAsStream("../collections/collections.json"); + JsonPath collectionsResponse = new JsonPath(json); + List> collections = collectionsResponse.getList("collections"); + + List requirementClasses = new ArrayList(); + requirementClasses.add(RequirementClass.CORE); + + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + testPoint = new TestPoint("http://localhost:8090/rest/services/kataster", "/collections/flurstueck/items", + Collections.emptyMap()); + + URI landingPageUri = new URI("https://www.ldproxy.nrw.de/kataster"); + when(suite.getAttribute(SuiteAttribute.IUT.getName())).thenReturn(landingPageUri); + when(suite.getAttribute(SuiteAttribute.API_MODEL.getName())).thenReturn(apiModel); + when(suite.getAttribute(SuiteAttribute.COLLECTIONS.getName())).thenReturn(collections); + when(suite.getAttribute(SuiteAttribute.REQUIREMENTCLASSES.getName())).thenReturn(requirementClasses); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testParameterDefinition() { + prepareJadler(); + FeaturesTime features = initFeaturesTime(); + + features.timeParameterDefinition(testPoint); + } + + @Test + public void test() { + prepareJadler(); + FeaturesTime features = initFeaturesTime(); + + Map collection = prepareCollection(); + String queryString = "2014-08-09"; + Object begin = null; + Object end = null; + features.validateFeaturesWithDateTimeOperation(collection, queryString, begin, end); + features.validateFeaturesWithDateTimeResponse_TypeProperty(collection, queryString, begin, end); + features.validateFeaturesWithDateTimeResponse_FeaturesProperty(collection, queryString, begin, end); + features.validateFeaturesWithDateTimeResponse_Links(collection, queryString, begin, end); + // skipped (collection missing): + // features.validateFeaturesWithDateTimeResponse_TimeStamp( collection, + // queryString, begin, end ); + // skipped (collection missing): + // features.validateFeaturesWithDateTimeResponse_NumberMatched( collection , + // queryString, begin, end ); + // skipped (collection missing): + // features.validateFeaturesResponse_NumberReturned( collection, queryString, + // begin, end ); + } + + private FeaturesTime initFeaturesTime() { + FeaturesTime features = new FeaturesTime(); + features.initCommonFixture(testContext); + features.retrieveRequiredInformationFromTestContext(testContext); + features.requirementClasses(testContext); + features.retrieveApiModel(testContext); + return features; + } + + private static Map prepareCollection() { + return new JsonPath(FeatureCollectionTest.class.getResourceAsStream("collection-flurstueck.json")).get(); + } + + private void prepareJadler() { + InputStream flurstueckItems = getClass().getResourceAsStream("collectionItems-flurstueck.json"); + onRequest().havingPath(endsWith("collections/flurstueck/items")) + .havingParameter("datetime") + .respond() + .withBody(flurstueckItems); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/conformance/ConformanceIT.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/conformance/ConformanceIT.java index 0df622fe..977d00af 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/conformance/ConformanceIT.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/conformance/ConformanceIT.java @@ -24,34 +24,33 @@ @Ignore("Stable service is required") public class ConformanceIT { - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - URI landingPageUri = new URI( "https://www.ldproxy.nrw.de/kataster" ); - when( suite.getAttribute( SuiteAttribute.IUT.getName() ) ).thenReturn( landingPageUri ); - } - - @Test - public void testApiDefinition() { - Conformance conformanceOperation = new Conformance(); - conformanceOperation.initCommonFixture( testContext ); - TestPoint testPoint = new TestPoint( "https://www.ldproxy.nrw.de/kataster", "/conformance", mediaTypes() ); - conformanceOperation.validateConformanceOperationAndResponse( testPoint ); - } - - private Map mediaTypes() { - Map mediaTypes = new HashMap<>(); - mediaTypes.put( "application/json", Mockito.mock( MediaType.class ) ); - mediaTypes.put( "text/html", Mockito.mock( MediaType.class ) ); - return mediaTypes; - } + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + URI landingPageUri = new URI("https://www.ldproxy.nrw.de/kataster"); + when(suite.getAttribute(SuiteAttribute.IUT.getName())).thenReturn(landingPageUri); + } + + @Test + public void testApiDefinition() { + Conformance conformanceOperation = new Conformance(); + conformanceOperation.initCommonFixture(testContext); + TestPoint testPoint = new TestPoint("https://www.ldproxy.nrw.de/kataster", "/conformance", mediaTypes()); + conformanceOperation.validateConformanceOperationAndResponse(testPoint); + } + + private Map mediaTypes() { + Map mediaTypes = new HashMap<>(); + mediaTypes.put("application/json", Mockito.mock(MediaType.class)); + mediaTypes.put("text/html", Mockito.mock(MediaType.class)); + return mediaTypes; + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/conformance/ConformanceTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/conformance/ConformanceTest.java index 5e71d8ee..38389c7d 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/conformance/ConformanceTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/conformance/ConformanceTest.java @@ -22,31 +22,32 @@ */ public class ConformanceTest { - @Test - public void testParseAndValidateRequirementClasses() { - Conformance conformanceOperationTest = new Conformance(); - InputStream json = ConformanceTest.class.getResourceAsStream( "req-classes.json" ); - JsonPath jsonPath = new JsonPath( json ); - List requirementClasses = conformanceOperationTest.parseAndValidateRequirementClasses( jsonPath ); - - assertThat( requirementClasses.size(), is( 5 ) ); - assertThat( requirementClasses, hasItems( CORE, OPENAPI30, HTML, GEOJSON, GMLSF2 ) ); - } - - @Test(expected = AssertionError.class) - public void testParseAndValidateRequirementClasses_invalidConformsTo() { - Conformance conformanceOperationTest = new Conformance(); - InputStream json = ConformanceTest.class.getResourceAsStream( "req-classes_invalidConformsTo.json" ); - JsonPath jsonPath = new JsonPath( json ); - conformanceOperationTest.parseAndValidateRequirementClasses( jsonPath ); - } - - @Test(expected = AssertionError.class) - public void testParseAndValidateRequirementClasses_invalidElementDataType() { - Conformance conformanceOperationTest = new Conformance(); - InputStream json = ConformanceTest.class.getResourceAsStream( "req-classes_invalidElementDataType.json" ); - JsonPath jsonPath = new JsonPath( json ); - conformanceOperationTest.parseAndValidateRequirementClasses( jsonPath ); - } + @Test + public void testParseAndValidateRequirementClasses() { + Conformance conformanceOperationTest = new Conformance(); + InputStream json = ConformanceTest.class.getResourceAsStream("req-classes.json"); + JsonPath jsonPath = new JsonPath(json); + List requirementClasses = conformanceOperationTest + .parseAndValidateRequirementClasses(jsonPath); + + assertThat(requirementClasses.size(), is(5)); + assertThat(requirementClasses, hasItems(CORE, OPENAPI30, HTML, GEOJSON, GMLSF2)); + } + + @Test(expected = AssertionError.class) + public void testParseAndValidateRequirementClasses_invalidConformsTo() { + Conformance conformanceOperationTest = new Conformance(); + InputStream json = ConformanceTest.class.getResourceAsStream("req-classes_invalidConformsTo.json"); + JsonPath jsonPath = new JsonPath(json); + conformanceOperationTest.parseAndValidateRequirementClasses(jsonPath); + } + + @Test(expected = AssertionError.class) + public void testParseAndValidateRequirementClasses_invalidElementDataType() { + Conformance conformanceOperationTest = new Conformance(); + InputStream json = ConformanceTest.class.getResourceAsStream("req-classes_invalidElementDataType.json"); + JsonPath jsonPath = new JsonPath(json); + conformanceOperationTest.parseAndValidateRequirementClasses(jsonPath); + } } \ No newline at end of file diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/general/GeneralHttpIT.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/general/GeneralHttpIT.java index 9125e93b..80d2ffe7 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/general/GeneralHttpIT.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/core/general/GeneralHttpIT.java @@ -16,27 +16,25 @@ */ public class GeneralHttpIT { - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - URI landingPageUri = new URI( "https://www.ldproxy.nrw.de/kataster" ); - when( suite.getAttribute( SuiteAttribute.IUT.getName() ) ).thenReturn( landingPageUri ); - } - - @Test - public void testGeneralHttp() - throws Exception { - GeneralHttp generalHttp = new GeneralHttp(); - generalHttp.initCommonFixture( testContext ); - generalHttp.http(); - } + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + URI landingPageUri = new URI("https://www.ldproxy.nrw.de/kataster"); + when(suite.getAttribute(SuiteAttribute.IUT.getName())).thenReturn(landingPageUri); + } + + @Test + public void testGeneralHttp() throws Exception { + GeneralHttp generalHttp = new GeneralHttp(); + generalHttp.initCommonFixture(testContext); + generalHttp.http(); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/CoordinateSystemTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/CoordinateSystemTest.java index 633dcc58..ea164bbc 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/CoordinateSystemTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/CoordinateSystemTest.java @@ -13,43 +13,44 @@ */ public class CoordinateSystemTest { - @Test - public void testGetSrid_CRS84() { - assertThat( DEFAULT_CRS.getSrid(), is( 84 ) ); - } - - @Test - public void testGetSrid_HTTP() { - CoordinateSystem coordinateSystem = new CoordinateSystem( "http://www.opengis.net/def/crs/EPSG/0/3163" ); - assertThat( coordinateSystem.getSrid(), is( 3163 ) ); - } - - @Test - public void testGetSrid_URN() { - CoordinateSystem coordinateSystem = new CoordinateSystem( "urn:ogc:def:crs:EPSG::3163" ); - assertThat( coordinateSystem.getSrid(), is( 3163 ) ); - } - - @Test - public void testGetCodeWithAuthority_CRS84() { - assertThat( DEFAULT_CRS.getCodeWithAuthority(), is( "OGC:CRS84" ) ); - } - - @Test - public void testGetCodeWithAuthority_HTTP() { - CoordinateSystem coordinateSystem = new CoordinateSystem( "http://www.opengis.net/def/crs/EPSG/0/3163" ); - assertThat( coordinateSystem.getCodeWithAuthority(), is( "EPSG:3163" ) ); - } - - @Test - public void testGetCodeWithAuthority_URN() { - CoordinateSystem coordinateSystem = new CoordinateSystem( "urn:ogc:def:crs:EPSG::3163" ); - assertThat( coordinateSystem.getCodeWithAuthority(), is( "EPSG:3163" ) ); - } - - @Test(expected = UnknownCrsException.class) - public void testGetCodeWithAuthority_Unknown() { - CoordinateSystem coordinateSystem = new CoordinateSystem( "urn:io:crs:EPSG::3163" ); - coordinateSystem.getCodeWithAuthority(); - } + @Test + public void testGetSrid_CRS84() { + assertThat(DEFAULT_CRS.getSrid(), is(84)); + } + + @Test + public void testGetSrid_HTTP() { + CoordinateSystem coordinateSystem = new CoordinateSystem("http://www.opengis.net/def/crs/EPSG/0/3163"); + assertThat(coordinateSystem.getSrid(), is(3163)); + } + + @Test + public void testGetSrid_URN() { + CoordinateSystem coordinateSystem = new CoordinateSystem("urn:ogc:def:crs:EPSG::3163"); + assertThat(coordinateSystem.getSrid(), is(3163)); + } + + @Test + public void testGetCodeWithAuthority_CRS84() { + assertThat(DEFAULT_CRS.getCodeWithAuthority(), is("OGC:CRS84")); + } + + @Test + public void testGetCodeWithAuthority_HTTP() { + CoordinateSystem coordinateSystem = new CoordinateSystem("http://www.opengis.net/def/crs/EPSG/0/3163"); + assertThat(coordinateSystem.getCodeWithAuthority(), is("EPSG:3163")); + } + + @Test + public void testGetCodeWithAuthority_URN() { + CoordinateSystem coordinateSystem = new CoordinateSystem("urn:ogc:def:crs:EPSG::3163"); + assertThat(coordinateSystem.getCodeWithAuthority(), is("EPSG:3163")); + } + + @Test(expected = UnknownCrsException.class) + public void testGetCodeWithAuthority_Unknown() { + CoordinateSystem coordinateSystem = new CoordinateSystem("urn:io:crs:EPSG::3163"); + coordinateSystem.getCodeWithAuthority(); + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/CrsRequirementClassPreconditionTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/CrsRequirementClassPreconditionTest.java index c5c4b466..f8ba96bf 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/CrsRequirementClassPreconditionTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/CrsRequirementClassPreconditionTest.java @@ -21,43 +21,44 @@ */ public class CrsRequirementClassPreconditionTest { - @Test - public void verifyConformanceClass_ImplementsCrs() { - CrsRequirementClassPrecondition requirementClassPrecondition = new CrsRequirementClassPrecondition(); - List allRequirementClasses = Arrays.asList( RequirementClass.values() ); - requirementClassPrecondition.conformanceClasses( mockTestContext( allRequirementClasses ) ); - requirementClassPrecondition.verifyConformanceClass(); - } - - @Test(expected = SkipException.class) - public void verifyConformanceClass_NotImplementsCrs() { - CrsRequirementClassPrecondition requirementClassPrecondition = new CrsRequirementClassPrecondition(); - List requirementClasses = Arrays.asList( CORE, OPENAPI30 ); - requirementClassPrecondition.conformanceClasses( mockTestContext( requirementClasses ) ); - requirementClassPrecondition.verifyConformanceClass(); - } - - @Test(expected = SkipException.class) - public void verifyConformanceClass_Null() { - CrsRequirementClassPrecondition requirementClassPrecondition = new CrsRequirementClassPrecondition(); - requirementClassPrecondition.conformanceClasses( mockTestContext( null ) ); - requirementClassPrecondition.verifyConformanceClass(); - } - - @Test(expected = SkipException.class) - public void verifyConformanceClass_Empty() { - CrsRequirementClassPrecondition requirementClassPrecondition = new CrsRequirementClassPrecondition(); - List requirementClasses = Collections.emptyList(); - requirementClassPrecondition.conformanceClasses( mockTestContext( requirementClasses ) ); - requirementClassPrecondition.verifyConformanceClass(); - } - - private ITestContext mockTestContext( List requirementClasses ) { - ITestContext testContext = mock( ITestContext.class ); - ISuite suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - when( suite.getAttribute( SuiteAttribute.REQUIREMENTCLASSES.getName() ) ).thenReturn( requirementClasses ); - return testContext; - } + @Test + public void verifyConformanceClass_ImplementsCrs() { + CrsRequirementClassPrecondition requirementClassPrecondition = new CrsRequirementClassPrecondition(); + List allRequirementClasses = Arrays.asList(RequirementClass.values()); + requirementClassPrecondition.conformanceClasses(mockTestContext(allRequirementClasses)); + requirementClassPrecondition.verifyConformanceClass(); + } + + @Test(expected = SkipException.class) + public void verifyConformanceClass_NotImplementsCrs() { + CrsRequirementClassPrecondition requirementClassPrecondition = new CrsRequirementClassPrecondition(); + List requirementClasses = Arrays.asList(CORE, OPENAPI30); + requirementClassPrecondition.conformanceClasses(mockTestContext(requirementClasses)); + requirementClassPrecondition.verifyConformanceClass(); + } + + @Test(expected = SkipException.class) + public void verifyConformanceClass_Null() { + CrsRequirementClassPrecondition requirementClassPrecondition = new CrsRequirementClassPrecondition(); + requirementClassPrecondition.conformanceClasses(mockTestContext(null)); + requirementClassPrecondition.verifyConformanceClass(); + } + + @Test(expected = SkipException.class) + public void verifyConformanceClass_Empty() { + CrsRequirementClassPrecondition requirementClassPrecondition = new CrsRequirementClassPrecondition(); + List requirementClasses = Collections.emptyList(); + requirementClassPrecondition.conformanceClasses(mockTestContext(requirementClasses)); + requirementClassPrecondition.verifyConformanceClass(); + } + + private ITestContext mockTestContext(List requirementClasses) { + ITestContext testContext = mock(ITestContext.class); + ISuite suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + when(suite.getAttribute(SuiteAttribute.REQUIREMENTCLASSES.getName())).thenReturn(requirementClasses); + return testContext; + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsDefaultCrsTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsDefaultCrsTest.java index 9bd16eb5..24741616 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsDefaultCrsTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsDefaultCrsTest.java @@ -27,112 +27,114 @@ * @author Gabriel Roldan */ public class DiscoveryCollectionsDefaultCrsTest { - private static ITestContext testContext; - - private static TestPoint testPoint; - - /** - * Sample response from a {@code /collections} endpoint. Contains ex - */ - private static JsonPath collectionsResponse; - - private DiscoveryCollectionsDefaultCrs discoveryCollectionsDefaultCrs; - - @BeforeClass - public static void initTestFixture() throws Exception { - testContext = mock(ITestContext.class); - ISuite suite = mock(ISuite.class); - when(testContext.getSuite()).thenReturn(suite); - - testPoint = new TestPoint("http://localhost:8080/api/ogc/features/v1", "/collections", Collections.emptyMap()); - - collectionsResponse = prepareCollections(); - } - - @Before - public void setUp() { - discoveryCollectionsDefaultCrs = new DiscoveryCollectionsDefaultCrs(); - discoveryCollectionsDefaultCrs.initCommonFixture(testContext); - } - - /** - * Test a collection whose crs contains both its {@code storageCrs} and the - * global {@code #/crs} pointer - */ - @Test - public void testVerifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs_globalCrsAndStorageCrs() { - Map collection = collectionsResponse.getMap("collections[0]"); - // preflight checks - assertNotNull(collection); - assertEquals("sf:archsites", collection.get("id")); - @SuppressWarnings("unchecked") - List crs = (List) collection.get("crs"); - assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/26713")); - assertThat(crs, containsInAnyOrder("#/crs", "http://www.opengis.net/def/crs/EPSG/0/26713")); - - // test - discoveryCollectionsDefaultCrs.verifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs(testPoint, - collectionsResponse, collection); - } - - /** - * Test a collection whose crs contains only the global {@code #/crs} pointer - */ - @Test - public void testVerifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs_globalCrs() { - Map collection = collectionsResponse.getMap("collections[1]"); - // preflight checks - assertNotNull(collection); - assertEquals("ne:populated_places", collection.get("id")); - @SuppressWarnings("unchecked") - List crs = (List) collection.get("crs"); - assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/OGC/1.3/CRS84")); - assertThat(crs, contains("#/crs")); - - // test - discoveryCollectionsDefaultCrs.verifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs(testPoint, - collectionsResponse, collection); - } - - /** - * Test a collection whose crs contains a list of crs identifiers without the - * global {@code #/crs} pointer - */ - @Test - public void testVerifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs() { - Map collection = collectionsResponse.getMap("collections[2]"); - // preflight checks - assertNotNull(collection); - assertEquals("sf:bugsites", collection.get("id")); - @SuppressWarnings("unchecked") - List crs = (List) collection.get("crs"); - assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/26713")); - assertThat(crs, contains("http://www.opengis.net/def/crs/EPSG/0/26713", - "http://www.opengis.net/def/crs/OGC/1.3/CRS84")); - - // test - discoveryCollectionsDefaultCrs.verifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs(testPoint, - collectionsResponse, collection); - } - - /** - * Test a collection whose crs does not declare any of the default CRS nor has - * the global {@code #/crs} pointer - */ - @Test(expected = AssertionError.class) - public void testVerifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs_no_default_crs() { - Map collection = collectionsResponse.getMap("collections[3]"); - // preflight checks - assertNotNull(collection); - assertEquals("no_default_crs", collection.get("id")); - - // AssertionError expected here - discoveryCollectionsDefaultCrs.verifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs(testPoint, - collectionsResponse, collection); - } - - private static JsonPath prepareCollections() { - return new JsonPath(Objects - .requireNonNull(DiscoveryCollectionsDefaultCrsTest.class.getResourceAsStream("collections.json"))); - } + + private static ITestContext testContext; + + private static TestPoint testPoint; + + /** + * Sample response from a {@code /collections} endpoint. Contains ex + */ + private static JsonPath collectionsResponse; + + private DiscoveryCollectionsDefaultCrs discoveryCollectionsDefaultCrs; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + ISuite suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + testPoint = new TestPoint("http://localhost:8080/api/ogc/features/v1", "/collections", Collections.emptyMap()); + + collectionsResponse = prepareCollections(); + } + + @Before + public void setUp() { + discoveryCollectionsDefaultCrs = new DiscoveryCollectionsDefaultCrs(); + discoveryCollectionsDefaultCrs.initCommonFixture(testContext); + } + + /** + * Test a collection whose crs contains both its {@code storageCrs} and the global + * {@code #/crs} pointer + */ + @Test + public void testVerifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs_globalCrsAndStorageCrs() { + Map collection = collectionsResponse.getMap("collections[0]"); + // preflight checks + assertNotNull(collection); + assertEquals("sf:archsites", collection.get("id")); + @SuppressWarnings("unchecked") + List crs = (List) collection.get("crs"); + assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/26713")); + assertThat(crs, containsInAnyOrder("#/crs", "http://www.opengis.net/def/crs/EPSG/0/26713")); + + // test + discoveryCollectionsDefaultCrs.verifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs(testPoint, + collectionsResponse, collection); + } + + /** + * Test a collection whose crs contains only the global {@code #/crs} pointer + */ + @Test + public void testVerifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs_globalCrs() { + Map collection = collectionsResponse.getMap("collections[1]"); + // preflight checks + assertNotNull(collection); + assertEquals("ne:populated_places", collection.get("id")); + @SuppressWarnings("unchecked") + List crs = (List) collection.get("crs"); + assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/OGC/1.3/CRS84")); + assertThat(crs, contains("#/crs")); + + // test + discoveryCollectionsDefaultCrs.verifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs(testPoint, + collectionsResponse, collection); + } + + /** + * Test a collection whose crs contains a list of crs identifiers without the global + * {@code #/crs} pointer + */ + @Test + public void testVerifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs() { + Map collection = collectionsResponse.getMap("collections[2]"); + // preflight checks + assertNotNull(collection); + assertEquals("sf:bugsites", collection.get("id")); + @SuppressWarnings("unchecked") + List crs = (List) collection.get("crs"); + assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/26713")); + assertThat(crs, contains("http://www.opengis.net/def/crs/EPSG/0/26713", + "http://www.opengis.net/def/crs/OGC/1.3/CRS84")); + + // test + discoveryCollectionsDefaultCrs.verifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs(testPoint, + collectionsResponse, collection); + } + + /** + * Test a collection whose crs does not declare any of the default CRS nor has the + * global {@code #/crs} pointer + */ + @Test(expected = AssertionError.class) + public void testVerifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs_no_default_crs() { + Map collection = collectionsResponse.getMap("collections[3]"); + // preflight checks + assertNotNull(collection); + assertEquals("no_default_crs", collection.get("id")); + + // AssertionError expected here + discoveryCollectionsDefaultCrs.verifyCollectionsPathCollectionCrsPropertyContainsDefaultCrs(testPoint, + collectionsResponse, collection); + } + + private static JsonPath prepareCollections() { + return new JsonPath(Objects + .requireNonNull(DiscoveryCollectionsDefaultCrsTest.class.getResourceAsStream("collections.json"))); + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsStorageCrsTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsStorageCrsTest.java index 0d0b2650..67c3645f 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsStorageCrsTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/discovery/collections/DiscoveryCollectionsStorageCrsTest.java @@ -30,168 +30,170 @@ * @author Gabriel Roldan */ public class DiscoveryCollectionsStorageCrsTest { - private static ITestContext testContext; - - private static TestPoint testPoint; - - /** - * Sample response from a {@code /collections} endpoint. Contains ex - */ - private static JsonPath collectionsResponse; - - private DiscoveryCollectionsStorageCrs discoveryCollectionsStorageCrs; - - @BeforeClass - public static void initTestFixture() throws Exception { - testContext = mock(ITestContext.class); - ISuite suite = mock(ISuite.class); - when(testContext.getSuite()).thenReturn(suite); - - testPoint = new TestPoint("http://localhost:8080/api/ogc/features/v1", "/collections", Collections.emptyMap()); - - collectionsResponse = prepareCollections(); - } - - @Before - public void setUp() { - discoveryCollectionsStorageCrs = new DiscoveryCollectionsStorageCrs(); - discoveryCollectionsStorageCrs.initCommonFixture(testContext); - } - - /** - * Test a collection whose crs contains both its {@code storageCrs} and the - * global {@code #/crs} pointer - */ - @Test - public void testVerifyCollectionsPathCollectionCrsPropertyContainsStorageCrs_globalCrsAndStorageCrs() { - Map collection = collectionsResponse.getMap("collections[0]"); - // preflight checks - assertNotNull(collection); - assertEquals("sf:archsites", collection.get("id")); - - @SuppressWarnings("unchecked") - List crs = (List) collection.get("crs"); - assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/26713")); - assertThat(crs, contains("http://www.opengis.net/def/crs/EPSG/0/26713", "#/crs")); - - // test - discoveryCollectionsStorageCrs.verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(testPoint, - collectionsResponse, collection); - } - - /** - * Test a collection whose crs contains only the global {@code #/crs} pointer, - * and the global crs property contains the collection's storageCrs - */ - @Test - public void testVerifyCollectionsPathCollectionCrsPropertyContainsStorageCrs_globalCrs_only() { - Map collection = collectionsResponse.getMap("collections[1]"); - // preflight checks - assertNotNull(collection); - assertEquals("ne:populated_places", collection.get("id")); - @SuppressWarnings("unchecked") - List crs = (List) collection.get("crs"); - assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/OGC/1.3/CRS84")); - assertThat(crs, contains("#/crs")); - - // test - discoveryCollectionsStorageCrs.verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(testPoint, - collectionsResponse, collection); - } - - /** - * Test a collection whose crs contains its {@code storageCrs} and no global - * {@code #/crs} pointer - */ - @Test - public void testVerifyCollectionsPathCollectionCrsPropertyContainsStorageCrs() { - Map collection = collectionsResponse.getMap("collections[2]"); - // preflight checks - assertNotNull(collection); - assertEquals("sf:bugsites", collection.get("id")); - @SuppressWarnings("unchecked") - List crs = (List) collection.get("crs"); - assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/26713")); - assertThat(crs, containsInAnyOrder("http://www.opengis.net/def/crs/OGC/1.3/CRS84", - "http://www.opengis.net/def/crs/EPSG/0/26713")); - - // test - discoveryCollectionsStorageCrs.verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(testPoint, - collectionsResponse, collection); - } - - /** - * Test a collection whose storageCrs is declared in the global crs but not on - * its crs property, but it does contain the global {@code #/crs} pointer. - */ - @Test - public void testVerifyCollectionsPathCollectionCrsPropertyContainsStorageCrs_globalCrs_and_custom_crs() { - Map collection = collectionsResponse.getMap("collections[4]"); - // preflight checks - assertNotNull(collection); - assertEquals("storageCrsInGlobalCrs", collection.get("id")); - @SuppressWarnings("unchecked") - List crs = (List) collection.get("crs"); - assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/4087")); - assertThat(crs, containsInAnyOrder("#/crs", "http://www.opengis.net/def/crs/EPSG/0/3786")); - - @SuppressWarnings("unchecked") - List globalCrs = (List) collectionsResponse.get("crs"); - assertTrue(globalCrs.contains("http://www.opengis.net/def/crs/EPSG/0/4087")); - - // AssertionError expected here - discoveryCollectionsStorageCrs.verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(testPoint, - collectionsResponse, collection); - } - - /** - * Test a collection whose storageCrs is not declared in its crs and has no - * pointer to the global crs - */ - @Test(expected = AssertionError.class) - public void testVerifyCollectionsPathCollectionCrsPropertyContainsStorageCrs_no_storage_crs() { - Map collection = collectionsResponse.getMap("collections[5]"); - // preflight checks - assertNotNull(collection); - assertEquals("storageCrsUndeclared", collection.get("id")); - - @SuppressWarnings("unchecked") - List crs = (List) collection.get("crs"); - assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/4088")); - assertThat(crs, not(contains("#/crs"))); - - @SuppressWarnings("unchecked") - List globalCrs = (List) collectionsResponse.get("crs"); - assertFalse(globalCrs.contains("http://www.opengis.net/def/crs/EPSG/0/4088")); - - // AssertionError expected here - discoveryCollectionsStorageCrs.verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(testPoint, - collectionsResponse, collection); - } - - @Test(expected = AssertionError.class) - public void testVerifyCollectionsPathCollectionCrsPropertyContainsStorageCrs_no_storage_crs_in_global_crs() { - Map collection = collectionsResponse.getMap("collections[6]"); - // preflight checks - assertNotNull(collection); - assertEquals("storageCrsUndeclaredInGlobalCrs", collection.get("id")); - - @SuppressWarnings("unchecked") - List crs = (List) collection.get("crs"); - assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/4088")); - assertThat(crs, contains("#/crs")); - - @SuppressWarnings("unchecked") - List globalCrs = (List) collectionsResponse.get("crs"); - assertFalse(globalCrs.contains("http://www.opengis.net/def/crs/EPSG/0/4088")); - - // AssertionError expected here - discoveryCollectionsStorageCrs.verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(testPoint, - collectionsResponse, collection); - } - - private static JsonPath prepareCollections() { - return new JsonPath(Objects - .requireNonNull(DiscoveryCollectionsStorageCrsTest.class.getResourceAsStream("collections.json"))); - } + + private static ITestContext testContext; + + private static TestPoint testPoint; + + /** + * Sample response from a {@code /collections} endpoint. Contains ex + */ + private static JsonPath collectionsResponse; + + private DiscoveryCollectionsStorageCrs discoveryCollectionsStorageCrs; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + ISuite suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + testPoint = new TestPoint("http://localhost:8080/api/ogc/features/v1", "/collections", Collections.emptyMap()); + + collectionsResponse = prepareCollections(); + } + + @Before + public void setUp() { + discoveryCollectionsStorageCrs = new DiscoveryCollectionsStorageCrs(); + discoveryCollectionsStorageCrs.initCommonFixture(testContext); + } + + /** + * Test a collection whose crs contains both its {@code storageCrs} and the global + * {@code #/crs} pointer + */ + @Test + public void testVerifyCollectionsPathCollectionCrsPropertyContainsStorageCrs_globalCrsAndStorageCrs() { + Map collection = collectionsResponse.getMap("collections[0]"); + // preflight checks + assertNotNull(collection); + assertEquals("sf:archsites", collection.get("id")); + + @SuppressWarnings("unchecked") + List crs = (List) collection.get("crs"); + assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/26713")); + assertThat(crs, contains("http://www.opengis.net/def/crs/EPSG/0/26713", "#/crs")); + + // test + discoveryCollectionsStorageCrs.verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(testPoint, + collectionsResponse, collection); + } + + /** + * Test a collection whose crs contains only the global {@code #/crs} pointer, and the + * global crs property contains the collection's storageCrs + */ + @Test + public void testVerifyCollectionsPathCollectionCrsPropertyContainsStorageCrs_globalCrs_only() { + Map collection = collectionsResponse.getMap("collections[1]"); + // preflight checks + assertNotNull(collection); + assertEquals("ne:populated_places", collection.get("id")); + @SuppressWarnings("unchecked") + List crs = (List) collection.get("crs"); + assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/OGC/1.3/CRS84")); + assertThat(crs, contains("#/crs")); + + // test + discoveryCollectionsStorageCrs.verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(testPoint, + collectionsResponse, collection); + } + + /** + * Test a collection whose crs contains its {@code storageCrs} and no global + * {@code #/crs} pointer + */ + @Test + public void testVerifyCollectionsPathCollectionCrsPropertyContainsStorageCrs() { + Map collection = collectionsResponse.getMap("collections[2]"); + // preflight checks + assertNotNull(collection); + assertEquals("sf:bugsites", collection.get("id")); + @SuppressWarnings("unchecked") + List crs = (List) collection.get("crs"); + assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/26713")); + assertThat(crs, containsInAnyOrder("http://www.opengis.net/def/crs/OGC/1.3/CRS84", + "http://www.opengis.net/def/crs/EPSG/0/26713")); + + // test + discoveryCollectionsStorageCrs.verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(testPoint, + collectionsResponse, collection); + } + + /** + * Test a collection whose storageCrs is declared in the global crs but not on its crs + * property, but it does contain the global {@code #/crs} pointer. + */ + @Test + public void testVerifyCollectionsPathCollectionCrsPropertyContainsStorageCrs_globalCrs_and_custom_crs() { + Map collection = collectionsResponse.getMap("collections[4]"); + // preflight checks + assertNotNull(collection); + assertEquals("storageCrsInGlobalCrs", collection.get("id")); + @SuppressWarnings("unchecked") + List crs = (List) collection.get("crs"); + assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/4087")); + assertThat(crs, containsInAnyOrder("#/crs", "http://www.opengis.net/def/crs/EPSG/0/3786")); + + @SuppressWarnings("unchecked") + List globalCrs = (List) collectionsResponse.get("crs"); + assertTrue(globalCrs.contains("http://www.opengis.net/def/crs/EPSG/0/4087")); + + // AssertionError expected here + discoveryCollectionsStorageCrs.verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(testPoint, + collectionsResponse, collection); + } + + /** + * Test a collection whose storageCrs is not declared in its crs and has no pointer to + * the global crs + */ + @Test(expected = AssertionError.class) + public void testVerifyCollectionsPathCollectionCrsPropertyContainsStorageCrs_no_storage_crs() { + Map collection = collectionsResponse.getMap("collections[5]"); + // preflight checks + assertNotNull(collection); + assertEquals("storageCrsUndeclared", collection.get("id")); + + @SuppressWarnings("unchecked") + List crs = (List) collection.get("crs"); + assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/4088")); + assertThat(crs, not(contains("#/crs"))); + + @SuppressWarnings("unchecked") + List globalCrs = (List) collectionsResponse.get("crs"); + assertFalse(globalCrs.contains("http://www.opengis.net/def/crs/EPSG/0/4088")); + + // AssertionError expected here + discoveryCollectionsStorageCrs.verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(testPoint, + collectionsResponse, collection); + } + + @Test(expected = AssertionError.class) + public void testVerifyCollectionsPathCollectionCrsPropertyContainsStorageCrs_no_storage_crs_in_global_crs() { + Map collection = collectionsResponse.getMap("collections[6]"); + // preflight checks + assertNotNull(collection); + assertEquals("storageCrsUndeclaredInGlobalCrs", collection.get("id")); + + @SuppressWarnings("unchecked") + List crs = (List) collection.get("crs"); + assertThat(collection.get("storageCrs"), equalTo("http://www.opengis.net/def/crs/EPSG/0/4088")); + assertThat(crs, contains("#/crs")); + + @SuppressWarnings("unchecked") + List globalCrs = (List) collectionsResponse.get("crs"); + assertFalse(globalCrs.contains("http://www.opengis.net/def/crs/EPSG/0/4088")); + + // AssertionError expected here + discoveryCollectionsStorageCrs.verifyCollectionsPathCollectionCrsPropertyContainsStorageCrs(testPoint, + collectionsResponse, collection); + } + + private static JsonPath prepareCollections() { + return new JsonPath(Objects + .requireNonNull(DiscoveryCollectionsStorageCrsTest.class.getResourceAsStream("collections.json"))); + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterDefaultTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterDefaultTest.java index 261ef591..efa2f01e 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterDefaultTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterDefaultTest.java @@ -26,61 +26,76 @@ */ public class BBoxCrsParameterDefaultTest { - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void testVerifyBboxCrsParameterDefault() { - prepareJadler(); - BBoxCrsParameterDefault bBoxCrsParameterDefault = new BBoxCrsParameterDefault(); - bBoxCrsParameterDefault.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - bBoxCrsParameterDefault.verifyBboxCrsParameterDefault( "vineyards", collection, DEFAULT_CRS ); - } - - @Test(expected = AssertionError.class) - public void testVerifyBboxCrsParameterDefault_unexpectedResponse() { - prepareJadlerUnexpectedResponse(); - BBoxCrsParameterDefault bBoxCrsParameterDefault = new BBoxCrsParameterDefault(); - bBoxCrsParameterDefault.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - bBoxCrsParameterDefault.verifyBboxCrsParameterDefault( "vineyards", collection, DEFAULT_CRS ); - } - - private static JsonPath prepareCollection() { - return new JsonPath( BBoxCrsParameterDefaultTest.class.getResourceAsStream( "../collection-vineyards.json" ) ); - } - - private void prepareJadler() { - onRequest().havingPath( endsWith( "collections/vineyards/items" ) ).havingQueryString( containsString( "bbox-crs=" - + URLEncoder.encode( DEFAULT_CRS.getCode() ) ) ).respond().withBody( BBoxCrsParameterDefaultTest.class.getResourceAsStream( "../collectionItems-vineyards.json" ) ).withStatus( 200 ); - onRequest().havingPath( endsWith( "collections/vineyards/items" ) ).havingQueryString( not( containsString( "bbox-crs=" ) ) ).respond().withBody( BBoxCrsParameterDefaultTest.class.getResourceAsStream( "../collectionItems-vineyards.json" ) ).withStatus( 200 ); - } - - private void prepareJadlerUnexpectedResponse() { - onRequest().havingPath( endsWith( "collections/vineyards/items" ) ).havingQueryString( containsString( "bbox-crs=" - + URLEncoder.encode( DEFAULT_CRS.getCode() ) ) ).respond().withStatus( 200 ).withBody( BBoxCrsParameterDefaultTest.class.getResourceAsStream( "../collectionItems-vineyards.json" ) ); - onRequest().havingPath( endsWith( "collections/vineyards/items" ) ).havingQueryString( not( containsString( "bbox-crs=" ) ) ).respond().withStatus( 200 ).withBody( BBoxCrsParameterDefaultTest.class.getResourceAsStream( "../collectionItems-vineyards-offset-9.json" ) ); - } + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testVerifyBboxCrsParameterDefault() { + prepareJadler(); + BBoxCrsParameterDefault bBoxCrsParameterDefault = new BBoxCrsParameterDefault(); + bBoxCrsParameterDefault.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + bBoxCrsParameterDefault.verifyBboxCrsParameterDefault("vineyards", collection, DEFAULT_CRS); + } + + @Test(expected = AssertionError.class) + public void testVerifyBboxCrsParameterDefault_unexpectedResponse() { + prepareJadlerUnexpectedResponse(); + BBoxCrsParameterDefault bBoxCrsParameterDefault = new BBoxCrsParameterDefault(); + bBoxCrsParameterDefault.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + bBoxCrsParameterDefault.verifyBboxCrsParameterDefault("vineyards", collection, DEFAULT_CRS); + } + + private static JsonPath prepareCollection() { + return new JsonPath(BBoxCrsParameterDefaultTest.class.getResourceAsStream("../collection-vineyards.json")); + } + + private void prepareJadler() { + onRequest().havingPath(endsWith("collections/vineyards/items")) + .havingQueryString(containsString("bbox-crs=" + URLEncoder.encode(DEFAULT_CRS.getCode()))) + .respond() + .withBody(BBoxCrsParameterDefaultTest.class.getResourceAsStream("../collectionItems-vineyards.json")) + .withStatus(200); + onRequest().havingPath(endsWith("collections/vineyards/items")) + .havingQueryString(not(containsString("bbox-crs="))) + .respond() + .withBody(BBoxCrsParameterDefaultTest.class.getResourceAsStream("../collectionItems-vineyards.json")) + .withStatus(200); + } + + private void prepareJadlerUnexpectedResponse() { + onRequest().havingPath(endsWith("collections/vineyards/items")) + .havingQueryString(containsString("bbox-crs=" + URLEncoder.encode(DEFAULT_CRS.getCode()))) + .respond() + .withStatus(200) + .withBody(BBoxCrsParameterDefaultTest.class.getResourceAsStream("../collectionItems-vineyards.json")); + onRequest().havingPath(endsWith("collections/vineyards/items")) + .havingQueryString(not(containsString("bbox-crs="))) + .respond() + .withStatus(200) + .withBody(BBoxCrsParameterDefaultTest.class + .getResourceAsStream("../collectionItems-vineyards-offset-9.json")); + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterInvalidTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterInvalidTest.java index aa21838f..ac2c6a59 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterInvalidTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterInvalidTest.java @@ -25,59 +25,63 @@ */ public class BBoxCrsParameterInvalidTest { - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void testVerifyBboxCrsParameterInvalid() { - prepareJadler(); - BBoxCrsParameterInvalid bBoxCrsParameterInvalid = new BBoxCrsParameterInvalid(); - bBoxCrsParameterInvalid.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - bBoxCrsParameterInvalid.verifyBboxCrsParameterInvalid( "vineyards", collection ); - } - - @Test(expected = AssertionError.class) - public void testVerifyBboxCrsParameterInvalid_unexpectedResponse() { - prepareJadlerResponseStatusCode200(); - BBoxCrsParameterInvalid bBoxCrsParameterInvalid = new BBoxCrsParameterInvalid(); - bBoxCrsParameterInvalid.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - bBoxCrsParameterInvalid.verifyBboxCrsParameterInvalid( "vineyards", collection ); - } - - private static JsonPath prepareCollection() { - return new JsonPath( BBoxCrsParameterInvalidTest.class.getResourceAsStream( "../collection-vineyards.json" ) ); - } - - private void prepareJadler() { - onRequest().havingPath( endsWith( "collections/vineyards/items" ) ).havingQueryString( containsString( "bbox-crs=" - + URLEncoder.encode( UNSUPPORTED_CRS ) ) ).respond().withStatus( 400 ); - } - - private void prepareJadlerResponseStatusCode200() { - onRequest().havingPath( endsWith( "collections/vineyards/items" ) ).havingQueryString( containsString( "bbox-crs=" - + URLEncoder.encode( UNSUPPORTED_CRS ) ) ).respond().withStatus( 200 ); - } + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testVerifyBboxCrsParameterInvalid() { + prepareJadler(); + BBoxCrsParameterInvalid bBoxCrsParameterInvalid = new BBoxCrsParameterInvalid(); + bBoxCrsParameterInvalid.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + bBoxCrsParameterInvalid.verifyBboxCrsParameterInvalid("vineyards", collection); + } + + @Test(expected = AssertionError.class) + public void testVerifyBboxCrsParameterInvalid_unexpectedResponse() { + prepareJadlerResponseStatusCode200(); + BBoxCrsParameterInvalid bBoxCrsParameterInvalid = new BBoxCrsParameterInvalid(); + bBoxCrsParameterInvalid.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + bBoxCrsParameterInvalid.verifyBboxCrsParameterInvalid("vineyards", collection); + } + + private static JsonPath prepareCollection() { + return new JsonPath(BBoxCrsParameterInvalidTest.class.getResourceAsStream("../collection-vineyards.json")); + } + + private void prepareJadler() { + onRequest().havingPath(endsWith("collections/vineyards/items")) + .havingQueryString(containsString("bbox-crs=" + URLEncoder.encode(UNSUPPORTED_CRS))) + .respond() + .withStatus(400); + } + + private void prepareJadlerResponseStatusCode200() { + onRequest().havingPath(endsWith("collections/vineyards/items")) + .havingQueryString(containsString("bbox-crs=" + URLEncoder.encode(UNSUPPORTED_CRS))) + .respond() + .withStatus(200); + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterTest.java index 9e41b99b..62e7c379 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/bboxcrs/BBoxCrsParameterTest.java @@ -27,65 +27,80 @@ */ public class BBoxCrsParameterTest { - private static final CoordinateSystem EPSG_25832 = new CoordinateSystem( "http://www.opengis.net/def/crs/EPSG/0/25832" ); - - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void testVerifyBboxCrsParameter() { - prepareJadler(); - BBoxCrsParameter bBoxCrsParameter = new BBoxCrsParameter(); - bBoxCrsParameter.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - bBoxCrsParameter.verifyBboxCrsParameterWithDefaultCrs( "vineyards", collection, DEFAULT_CRS ); - bBoxCrsParameter.verifyBboxCrsParameter( "vineyards", collection, EPSG_25832, DEFAULT_CRS ); - } - - @Test(expected = AssertionError.class) - public void testVerifyBboxCrsParameter_unexpectedResponse() { - prepareJadlerUnexpectedResponse(); - BBoxCrsParameter bBoxCrsParameter = new BBoxCrsParameter(); - bBoxCrsParameter.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - bBoxCrsParameter.verifyBboxCrsParameterWithDefaultCrs( "vineyards", collection, DEFAULT_CRS ); - bBoxCrsParameter.verifyBboxCrsParameter( "vineyards", collection, EPSG_25832, DEFAULT_CRS ); - } - - private static JsonPath prepareCollection() { - return new JsonPath( BBoxCrsParameterTest.class.getResourceAsStream( "../collection-vineyards.json" ) ); - } - - private void prepareJadler() { - onRequest().havingPath( endsWith( "collections/vineyards/items" ) ).havingQueryString( not( containsString( "bbox-crs=" ) ) ).respond().withBody( BBoxCrsParameterTest.class.getResourceAsStream( "../collectionItems-vineyards.json" ) ).withStatus( 200 ); - onRequest().havingPath( endsWith( "collections/vineyards/items" ) ).havingQueryString( containsString( "bbox-crs=" - + URLEncoder.encode( EPSG_25832.getCode() ) ) ).respond().withBody( BBoxCrsParameterTest.class.getResourceAsStream( "../collectionItems-vineyards-25832.json" ) ).withStatus( 200 ); - } - - private void prepareJadlerUnexpectedResponse() { - onRequest().havingPath( endsWith( "collections/vineyards/items" ) ).havingQueryString( not( containsString( "bbox-crs=" ) ) ).respond().withBody( BBoxCrsParameterTest.class.getResourceAsStream( "../collectionItems-vineyards-offset-9.json" ) ).withStatus( 200 ); - onRequest().havingPath( endsWith( "collections/vineyards/items" ) ).havingQueryString( containsString( "bbox-crs=" - + URLEncoder.encode( EPSG_25832.getCode() ) ) ).respond().withBody( BBoxCrsParameterTest.class.getResourceAsStream( "../collectionItems-vineyards-25832.json" ) ).withStatus( 200 ); - } + private static final CoordinateSystem EPSG_25832 = new CoordinateSystem( + "http://www.opengis.net/def/crs/EPSG/0/25832"); + + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testVerifyBboxCrsParameter() { + prepareJadler(); + BBoxCrsParameter bBoxCrsParameter = new BBoxCrsParameter(); + bBoxCrsParameter.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + bBoxCrsParameter.verifyBboxCrsParameterWithDefaultCrs("vineyards", collection, DEFAULT_CRS); + bBoxCrsParameter.verifyBboxCrsParameter("vineyards", collection, EPSG_25832, DEFAULT_CRS); + } + + @Test(expected = AssertionError.class) + public void testVerifyBboxCrsParameter_unexpectedResponse() { + prepareJadlerUnexpectedResponse(); + BBoxCrsParameter bBoxCrsParameter = new BBoxCrsParameter(); + bBoxCrsParameter.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + bBoxCrsParameter.verifyBboxCrsParameterWithDefaultCrs("vineyards", collection, DEFAULT_CRS); + bBoxCrsParameter.verifyBboxCrsParameter("vineyards", collection, EPSG_25832, DEFAULT_CRS); + } + + private static JsonPath prepareCollection() { + return new JsonPath(BBoxCrsParameterTest.class.getResourceAsStream("../collection-vineyards.json")); + } + + private void prepareJadler() { + onRequest().havingPath(endsWith("collections/vineyards/items")) + .havingQueryString(not(containsString("bbox-crs="))) + .respond() + .withBody(BBoxCrsParameterTest.class.getResourceAsStream("../collectionItems-vineyards.json")) + .withStatus(200); + onRequest().havingPath(endsWith("collections/vineyards/items")) + .havingQueryString(containsString("bbox-crs=" + URLEncoder.encode(EPSG_25832.getCode()))) + .respond() + .withBody(BBoxCrsParameterTest.class.getResourceAsStream("../collectionItems-vineyards-25832.json")) + .withStatus(200); + } + + private void prepareJadlerUnexpectedResponse() { + onRequest().havingPath(endsWith("collections/vineyards/items")) + .havingQueryString(not(containsString("bbox-crs="))) + .respond() + .withBody(BBoxCrsParameterTest.class.getResourceAsStream("../collectionItems-vineyards-offset-9.json")) + .withStatus(200); + onRequest().havingPath(endsWith("collections/vineyards/items")) + .havingQueryString(containsString("bbox-crs=" + URLEncoder.encode(EPSG_25832.getCode()))) + .respond() + .withBody(BBoxCrsParameterTest.class.getResourceAsStream("../collectionItems-vineyards-25832.json")) + .withStatus(200); + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterDefaultTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterDefaultTest.java index 5dc27ac0..57cf46d9 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterDefaultTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterDefaultTest.java @@ -25,61 +25,66 @@ */ public class FeatureCrsParameterDefaultTest { - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void test() { - prepareJadler(); - FeatureCrsParameterDefault featureDefaultCrsParameter = new FeatureCrsParameterDefault(); - featureDefaultCrsParameter.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - featureDefaultCrsParameter.verifyFeatureCrsParameterDefault( "flurstueck", collection, "testId" ); - } - - @Test(expected = AssertionError.class) - public void test_unexpectedHeader() { - prepareJadlerContentCrsHeaderUnexpected(); - FeatureCrsParameterDefault featureDefaultCrsParameter = new FeatureCrsParameterDefault(); - featureDefaultCrsParameter.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - featureDefaultCrsParameter.verifyFeatureCrsParameterDefault( "flurstueck", collection, "testId" ); - } - - private static JsonPath prepareCollection() { - return new JsonPath( FeaturesCrsParameterInvalidTest.class.getResourceAsStream( "../../../../core/collections/collection-flurstueck.json" ) ); - } - - private void prepareJadler() { - onRequest().havingPath( endsWith( "collections/flurstueck/items/testId" ) ).havingQueryString( not( containsString( "crs=" ) ) ).respond().withHeader( "Content-Crs", - DEFAULT_CRS.getAsHeaderValue() ).withStatus( 200 ); - } - - private void prepareJadlerContentCrsHeaderUnexpected() { - onRequest().havingPath( endsWith( "collections/flurstueck/items/testId" ) ).havingQueryString( not( containsString( "crs=" ) ) ).respond().withHeader( "Content-Crs", - "<" + "www.opengis.net/def/crs/EPSG/0/25832" - + ">" ).withStatus( 200 ); - } + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void test() { + prepareJadler(); + FeatureCrsParameterDefault featureDefaultCrsParameter = new FeatureCrsParameterDefault(); + featureDefaultCrsParameter.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + featureDefaultCrsParameter.verifyFeatureCrsParameterDefault("flurstueck", collection, "testId"); + } + + @Test(expected = AssertionError.class) + public void test_unexpectedHeader() { + prepareJadlerContentCrsHeaderUnexpected(); + FeatureCrsParameterDefault featureDefaultCrsParameter = new FeatureCrsParameterDefault(); + featureDefaultCrsParameter.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + featureDefaultCrsParameter.verifyFeatureCrsParameterDefault("flurstueck", collection, "testId"); + } + + private static JsonPath prepareCollection() { + return new JsonPath(FeaturesCrsParameterInvalidTest.class + .getResourceAsStream("../../../../core/collections/collection-flurstueck.json")); + } + + private void prepareJadler() { + onRequest().havingPath(endsWith("collections/flurstueck/items/testId")) + .havingQueryString(not(containsString("crs="))) + .respond() + .withHeader("Content-Crs", DEFAULT_CRS.getAsHeaderValue()) + .withStatus(200); + } + + private void prepareJadlerContentCrsHeaderUnexpected() { + onRequest().havingPath(endsWith("collections/flurstueck/items/testId")) + .havingQueryString(not(containsString("crs="))) + .respond() + .withHeader("Content-Crs", "<" + "www.opengis.net/def/crs/EPSG/0/25832" + ">") + .withStatus(200); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterInvalidTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterInvalidTest.java index 1460f0bf..1dc0f24d 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterInvalidTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterInvalidTest.java @@ -26,59 +26,64 @@ */ public class FeatureCrsParameterInvalidTest { - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void test() { - prepareJadler(); - FeatureCrsParameterInvalid featureInvalidCrsParameter = new FeatureCrsParameterInvalid(); - featureInvalidCrsParameter.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - featureInvalidCrsParameter.verifyFeatureCrsParameterInvalid( "flurstueck", collection, "testId" ); - } - - @Test(expected = AssertionError.class) - public void test_unexpectedResponse() { - prepareJadlerResponseStatusCode200(); - FeatureCrsParameterInvalid featureInvalidCrsParameter = new FeatureCrsParameterInvalid(); - featureInvalidCrsParameter.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - featureInvalidCrsParameter.verifyFeatureCrsParameterInvalid( "flurstueck", collection, "testId" ); - } - - private static JsonPath prepareCollection() { - return new JsonPath( FeaturesCrsParameterInvalidTest.class.getResourceAsStream( "../../../../core/collections/collection-flurstueck.json" ) ); - } - - private void prepareJadler() { - onRequest().havingPath( endsWith( "collections/flurstueck/items/testId" ) ).havingQueryString( containsString( "crs=" - + URLEncoder.encode( UNSUPPORTED_CRS ) ) ).respond().withStatus( 400 ); - } - - private void prepareJadlerResponseStatusCode200() { - onRequest().havingPath( endsWith( "collections/flurstueck/items/testId" ) ).havingQueryString( containsString( "crs=" - + URLEncoder.encode( UNSUPPORTED_CRS ) ) ).respond().withStatus( 200 ); - } + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void test() { + prepareJadler(); + FeatureCrsParameterInvalid featureInvalidCrsParameter = new FeatureCrsParameterInvalid(); + featureInvalidCrsParameter.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + featureInvalidCrsParameter.verifyFeatureCrsParameterInvalid("flurstueck", collection, "testId"); + } + + @Test(expected = AssertionError.class) + public void test_unexpectedResponse() { + prepareJadlerResponseStatusCode200(); + FeatureCrsParameterInvalid featureInvalidCrsParameter = new FeatureCrsParameterInvalid(); + featureInvalidCrsParameter.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + featureInvalidCrsParameter.verifyFeatureCrsParameterInvalid("flurstueck", collection, "testId"); + } + + private static JsonPath prepareCollection() { + return new JsonPath(FeaturesCrsParameterInvalidTest.class + .getResourceAsStream("../../../../core/collections/collection-flurstueck.json")); + } + + private void prepareJadler() { + onRequest().havingPath(endsWith("collections/flurstueck/items/testId")) + .havingQueryString(containsString("crs=" + URLEncoder.encode(UNSUPPORTED_CRS))) + .respond() + .withStatus(400); + } + + private void prepareJadlerResponseStatusCode200() { + onRequest().havingPath(endsWith("collections/flurstueck/items/testId")) + .havingQueryString(containsString("crs=" + URLEncoder.encode(UNSUPPORTED_CRS))) + .respond() + .withStatus(200); + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterTest.java index c88a427d..b2f2c9d5 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterTest.java @@ -24,47 +24,50 @@ */ public class FeatureCrsParameterTest { - private static ITestContext testContext; + private static ITestContext testContext; - private static ISuite suite; + private static ISuite suite; - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - } + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + } - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } + @Before + public void setUp() { + initJadlerListeningOn(8090); + } - @After - public void tearDown() { - closeJadler(); - } + @After + public void tearDown() { + closeJadler(); + } - @Test - public void test() { - prepareJadler(); - FeatureCrsParameter featureValidCrsParameter = new FeatureCrsParameter(); - featureValidCrsParameter.initCommonFixture( testContext ); + @Test + public void test() { + prepareJadler(); + FeatureCrsParameter featureValidCrsParameter = new FeatureCrsParameter(); + featureValidCrsParameter.initCommonFixture(testContext); - JsonPath collection = prepareCollection(); - featureValidCrsParameter.verifyFeatureCrsParameter( "flurstueck", collection, "testId", DEFAULT_CRS ); - } + JsonPath collection = prepareCollection(); + featureValidCrsParameter.verifyFeatureCrsParameter("flurstueck", collection, "testId", DEFAULT_CRS); + } - private static JsonPath prepareCollection() { - return new JsonPath( FeatureCrsParameterTest.class.getResourceAsStream( "../../../../core/collections/collection-flurstueck.json" ) ); - } + private static JsonPath prepareCollection() { + return new JsonPath(FeatureCrsParameterTest.class + .getResourceAsStream("../../../../core/collections/collection-flurstueck.json")); + } - private void prepareJadler() { - InputStream flurstueckItem = getClass().getResourceAsStream( "../../../../core/collections/collectionItem1-flurstueck.json" ); - String expectedHeader = DEFAULT_CRS.getAsHeaderValue(); - onRequest().havingPath( endsWith( "collections/flurstueck/items/testId" ) ).respond().withBody( flurstueckItem ).withHeader( "Content-Crs", - expectedHeader ); - } + private void prepareJadler() { + InputStream flurstueckItem = getClass() + .getResourceAsStream("../../../../core/collections/collectionItem1-flurstueck.json"); + String expectedHeader = DEFAULT_CRS.getAsHeaderValue(); + onRequest().havingPath(endsWith("collections/flurstueck/items/testId")) + .respond() + .withBody(flurstueckItem) + .withHeader("Content-Crs", expectedHeader); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterTransformTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterTransformTest.java index 7e37f20f..6a7477e2 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterTransformTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/feature/FeatureCrsParameterTransformTest.java @@ -30,57 +30,63 @@ */ public class FeatureCrsParameterTransformTest { - private static final CoordinateSystem EPSG_25832 = new CoordinateSystem( "http://www.opengis.net/def/crs/EPSG/0/25832" ); - - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void test() - throws ParseException { - prepareJadler(); - FeatureCrsParameterTransform featureCrsParameterTransform = new FeatureCrsParameterTransform(); - featureCrsParameterTransform.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - featureCrsParameterTransform.verifyFeatureCrsParameterTransformWithCrsParameter( "vineyards", collection, - "testId" ); - featureCrsParameterTransform.verifyFeatureCrsParameterTransformWithoutCrsParameter( "vineyards", collection, - "testId", EPSG_25832, - DEFAULT_CRS ); - } - - private static JsonPath prepareCollection() { - return new JsonPath( FeaturesCrsParameterInvalidTest.class.getResourceAsStream( "../../collection-vineyards.json" ) ); - } - - private void prepareJadler() { - InputStream items = getClass().getResourceAsStream( "../../collectionItem-vineyards.json" ); - onRequest().havingPath( endsWith( "collections/vineyards/items/testId" ) ).havingQueryString( not( containsString( "crs=" ) ) ).respond().withBody( items ).withHeader( "Content-Crs", - DEFAULT_CRS.getAsHeaderValue() ).withStatus( 200 ); - InputStream itemsIn25832 = getClass().getResourceAsStream( "../../collectionItem-vineyards-25832.json" ); - onRequest().havingPath( endsWith( "collections/vineyards/items/testId" ) ).havingQueryString( containsString( "crs=" - + URLEncoder.encode( EPSG_25832.getCode() ) ) ).respond().withBody( itemsIn25832 ).withHeader( "Content-Crs", - EPSG_25832.getAsHeaderValue() ).withStatus( 200 ); - } + private static final CoordinateSystem EPSG_25832 = new CoordinateSystem( + "http://www.opengis.net/def/crs/EPSG/0/25832"); + + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void test() throws ParseException { + prepareJadler(); + FeatureCrsParameterTransform featureCrsParameterTransform = new FeatureCrsParameterTransform(); + featureCrsParameterTransform.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + featureCrsParameterTransform.verifyFeatureCrsParameterTransformWithCrsParameter("vineyards", collection, + "testId"); + featureCrsParameterTransform.verifyFeatureCrsParameterTransformWithoutCrsParameter("vineyards", collection, + "testId", EPSG_25832, DEFAULT_CRS); + } + + private static JsonPath prepareCollection() { + return new JsonPath( + FeaturesCrsParameterInvalidTest.class.getResourceAsStream("../../collection-vineyards.json")); + } + + private void prepareJadler() { + InputStream items = getClass().getResourceAsStream("../../collectionItem-vineyards.json"); + onRequest().havingPath(endsWith("collections/vineyards/items/testId")) + .havingQueryString(not(containsString("crs="))) + .respond() + .withBody(items) + .withHeader("Content-Crs", DEFAULT_CRS.getAsHeaderValue()) + .withStatus(200); + InputStream itemsIn25832 = getClass().getResourceAsStream("../../collectionItem-vineyards-25832.json"); + onRequest().havingPath(endsWith("collections/vineyards/items/testId")) + .havingQueryString(containsString("crs=" + URLEncoder.encode(EPSG_25832.getCode()))) + .respond() + .withBody(itemsIn25832) + .withHeader("Content-Crs", EPSG_25832.getAsHeaderValue()) + .withStatus(200); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterDefaultTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterDefaultTest.java index 056dd193..f68cd8bd 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterDefaultTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterDefaultTest.java @@ -24,61 +24,66 @@ */ public class FeaturesCrsParameterDefaultTest { - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void test() { - prepareJadler(); - FeaturesCrsParameterDefault featuresDefaultCrsParameter = new FeaturesCrsParameterDefault(); - featuresDefaultCrsParameter.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - featuresDefaultCrsParameter.verifyFeaturesCrsParameterDefault( "flurstueck", collection ); - } - - @Test(expected = AssertionError.class) - public void test_unexpectedHeader() { - prepareJadlerContentCrsHeaderUnexpected(); - FeaturesCrsParameterDefault featuresDefaultCrsParameter = new FeaturesCrsParameterDefault(); - featuresDefaultCrsParameter.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - featuresDefaultCrsParameter.verifyFeaturesCrsParameterDefault( "flurstueck", collection ); - } - - private static JsonPath prepareCollection() { - return new JsonPath( FeaturesCrsParameterDefaultTest.class.getResourceAsStream( "../../../../core/collections/collection-flurstueck.json" ) ); - } - - private void prepareJadler() { - onRequest().havingPath( endsWith( "collections/flurstueck/items" ) ).havingQueryString( not( containsString( "crs=" ) ) ).respond().withHeader( "Content-Crs", - "<" + DEFAULT_CRS_CODE - + ">" ).withStatus( 200 ); - } - - private void prepareJadlerContentCrsHeaderUnexpected() { - onRequest().havingPath( endsWith( "collections/flurstueck/items" ) ).havingQueryString( not( containsString( "crs=" ) ) ).respond().withHeader( "Content-Crs", - "<" + "www.opengis.net/def/crs/EPSG/0/25832" - + ">" ).withStatus( 200 ); - } + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void test() { + prepareJadler(); + FeaturesCrsParameterDefault featuresDefaultCrsParameter = new FeaturesCrsParameterDefault(); + featuresDefaultCrsParameter.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + featuresDefaultCrsParameter.verifyFeaturesCrsParameterDefault("flurstueck", collection); + } + + @Test(expected = AssertionError.class) + public void test_unexpectedHeader() { + prepareJadlerContentCrsHeaderUnexpected(); + FeaturesCrsParameterDefault featuresDefaultCrsParameter = new FeaturesCrsParameterDefault(); + featuresDefaultCrsParameter.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + featuresDefaultCrsParameter.verifyFeaturesCrsParameterDefault("flurstueck", collection); + } + + private static JsonPath prepareCollection() { + return new JsonPath(FeaturesCrsParameterDefaultTest.class + .getResourceAsStream("../../../../core/collections/collection-flurstueck.json")); + } + + private void prepareJadler() { + onRequest().havingPath(endsWith("collections/flurstueck/items")) + .havingQueryString(not(containsString("crs="))) + .respond() + .withHeader("Content-Crs", "<" + DEFAULT_CRS_CODE + ">") + .withStatus(200); + } + + private void prepareJadlerContentCrsHeaderUnexpected() { + onRequest().havingPath(endsWith("collections/flurstueck/items")) + .havingQueryString(not(containsString("crs="))) + .respond() + .withHeader("Content-Crs", "<" + "www.opengis.net/def/crs/EPSG/0/25832" + ">") + .withStatus(200); + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterInvalidTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterInvalidTest.java index df3ac66a..194a1e79 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterInvalidTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterInvalidTest.java @@ -25,59 +25,64 @@ */ public class FeaturesCrsParameterInvalidTest { - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void test() { - prepareJadler(); - FeaturesCrsParameterInvalid featuresInvalidCrsParameter = new FeaturesCrsParameterInvalid(); - featuresInvalidCrsParameter.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - featuresInvalidCrsParameter.verifyFeaturesCrsParameterInvalid( "flurstueck", collection ); - } - - @Test(expected = AssertionError.class) - public void test_unexpectedResponse() { - prepareJadlerResponseStatusCode200(); - FeaturesCrsParameterInvalid featuresInvalidCrsParameter = new FeaturesCrsParameterInvalid(); - featuresInvalidCrsParameter.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - featuresInvalidCrsParameter.verifyFeaturesCrsParameterInvalid( "flurstueck", collection ); - } - - private static JsonPath prepareCollection() { - return new JsonPath( FeaturesCrsParameterInvalidTest.class.getResourceAsStream( "../../../../core/collections/collection-flurstueck.json" ) ); - } - - private void prepareJadler() { - onRequest().havingPath( endsWith( "collections/flurstueck/items" ) ).havingQueryString( containsString( "crs=" - + URLEncoder.encode( UNSUPPORTED_CRS ) ) ).respond().withStatus( 400 ); - } - - private void prepareJadlerResponseStatusCode200() { - onRequest().havingPath( endsWith( "collections/flurstueck/items" ) ).havingQueryString( containsString( "crs=" - + URLEncoder.encode( UNSUPPORTED_CRS ) ) ).respond().withStatus( 200 ); - } + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void test() { + prepareJadler(); + FeaturesCrsParameterInvalid featuresInvalidCrsParameter = new FeaturesCrsParameterInvalid(); + featuresInvalidCrsParameter.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + featuresInvalidCrsParameter.verifyFeaturesCrsParameterInvalid("flurstueck", collection); + } + + @Test(expected = AssertionError.class) + public void test_unexpectedResponse() { + prepareJadlerResponseStatusCode200(); + FeaturesCrsParameterInvalid featuresInvalidCrsParameter = new FeaturesCrsParameterInvalid(); + featuresInvalidCrsParameter.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + featuresInvalidCrsParameter.verifyFeaturesCrsParameterInvalid("flurstueck", collection); + } + + private static JsonPath prepareCollection() { + return new JsonPath(FeaturesCrsParameterInvalidTest.class + .getResourceAsStream("../../../../core/collections/collection-flurstueck.json")); + } + + private void prepareJadler() { + onRequest().havingPath(endsWith("collections/flurstueck/items")) + .havingQueryString(containsString("crs=" + URLEncoder.encode(UNSUPPORTED_CRS))) + .respond() + .withStatus(400); + } + + private void prepareJadlerResponseStatusCode200() { + onRequest().havingPath(endsWith("collections/flurstueck/items")) + .havingQueryString(containsString("crs=" + URLEncoder.encode(UNSUPPORTED_CRS))) + .respond() + .withStatus(200); + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterTest.java index 04060f05..09835495 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterTest.java @@ -24,47 +24,50 @@ */ public class FeaturesCrsParameterTest { - private static ITestContext testContext; + private static ITestContext testContext; - private static ISuite suite; + private static ISuite suite; - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - } + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + } - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } + @Before + public void setUp() { + initJadlerListeningOn(8090); + } - @After - public void tearDown() { - closeJadler(); - } + @After + public void tearDown() { + closeJadler(); + } - @Test - public void test() { - prepareJadler(); - FeaturesCrsParameter featuresValidCrsParameter = new FeaturesCrsParameter(); - featuresValidCrsParameter.initCommonFixture( testContext ); + @Test + public void test() { + prepareJadler(); + FeaturesCrsParameter featuresValidCrsParameter = new FeaturesCrsParameter(); + featuresValidCrsParameter.initCommonFixture(testContext); - JsonPath collection = prepareCollection(); - featuresValidCrsParameter.verifyFeaturesCrsParameter( "flurstueck", collection, DEFAULT_CRS ); - } + JsonPath collection = prepareCollection(); + featuresValidCrsParameter.verifyFeaturesCrsParameter("flurstueck", collection, DEFAULT_CRS); + } - private static JsonPath prepareCollection() { - return new JsonPath( FeaturesCrsParameterTest.class.getResourceAsStream( "../../../../core/collections/collection-flurstueck.json" ) ); - } + private static JsonPath prepareCollection() { + return new JsonPath(FeaturesCrsParameterTest.class + .getResourceAsStream("../../../../core/collections/collection-flurstueck.json")); + } - private void prepareJadler() { - InputStream flurstueckItems = getClass().getResourceAsStream( "../../../../core/collections/collectionItems-flurstueck.json" ); - String expectedHeader = DEFAULT_CRS.getAsHeaderValue(); - onRequest().havingPath( endsWith( "collections/flurstueck/items" ) ).respond().withBody( flurstueckItems ).withHeader( "Content-Crs", - expectedHeader ); - } + private void prepareJadler() { + InputStream flurstueckItems = getClass() + .getResourceAsStream("../../../../core/collections/collectionItems-flurstueck.json"); + String expectedHeader = DEFAULT_CRS.getAsHeaderValue(); + onRequest().havingPath(endsWith("collections/flurstueck/items")) + .respond() + .withBody(flurstueckItems) + .withHeader("Content-Crs", expectedHeader); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterTransformTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterTransformTest.java index 0efc5a75..60f9b319 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterTransformTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/conformance/crs/query/crs/features/FeaturesCrsParameterTransformTest.java @@ -29,55 +29,62 @@ */ public class FeaturesCrsParameterTransformTest { - private static final CoordinateSystem EPSG_25832 = new CoordinateSystem( "http://www.opengis.net/def/crs/EPSG/0/25832" ); - - private static ITestContext testContext; - - private static ISuite suite; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void test() - throws ParseException { - prepareJadler(); - FeaturesCrsParameterTransform featuresCrsParameterTransform = new FeaturesCrsParameterTransform(); - featuresCrsParameterTransform.initCommonFixture( testContext ); - - JsonPath collection = prepareCollection(); - featuresCrsParameterTransform.verifyFeaturesCrsParameterTransformWithoutCrsParameter( "vineyards", collection ); - featuresCrsParameterTransform.verifyFeaturesCrsParameterTransformWithCrsParameter( "vineyards", collection, - EPSG_25832, DEFAULT_CRS ); - } - - private static JsonPath prepareCollection() { - return new JsonPath( FeaturesCrsParameterTransformTest.class.getResourceAsStream( "../../collection-vineyards.json" ) ); - } - - private void prepareJadler() { - InputStream items = getClass().getResourceAsStream( "../../collectionItems-vineyards.json" ); - onRequest().havingPath( endsWith( "collections/vineyards/items" ) ).havingQueryString( not( containsString( "crs=" ) ) ).respond().withBody( items ).withHeader( "Content-Crs", - DEFAULT_CRS.getAsHeaderValue() ).withStatus( 200 ); - InputStream itemsIn25832 = getClass().getResourceAsStream( "../../collectionItems-vineyards-25832.json" ); - onRequest().havingPath( endsWith( "collections/vineyards/items" ) ).havingQueryString( containsString( "crs=" - + URLEncoder.encode( EPSG_25832.getCode() ) ) ).respond().withBody( itemsIn25832 ).withHeader( "Content-Crs", - EPSG_25832.getAsHeaderValue() ).withStatus( 200 ); - } + private static final CoordinateSystem EPSG_25832 = new CoordinateSystem( + "http://www.opengis.net/def/crs/EPSG/0/25832"); + + private static ITestContext testContext; + + private static ISuite suite; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void test() throws ParseException { + prepareJadler(); + FeaturesCrsParameterTransform featuresCrsParameterTransform = new FeaturesCrsParameterTransform(); + featuresCrsParameterTransform.initCommonFixture(testContext); + + JsonPath collection = prepareCollection(); + featuresCrsParameterTransform.verifyFeaturesCrsParameterTransformWithoutCrsParameter("vineyards", collection); + featuresCrsParameterTransform.verifyFeaturesCrsParameterTransformWithCrsParameter("vineyards", collection, + EPSG_25832, DEFAULT_CRS); + } + + private static JsonPath prepareCollection() { + return new JsonPath( + FeaturesCrsParameterTransformTest.class.getResourceAsStream("../../collection-vineyards.json")); + } + + private void prepareJadler() { + InputStream items = getClass().getResourceAsStream("../../collectionItems-vineyards.json"); + onRequest().havingPath(endsWith("collections/vineyards/items")) + .havingQueryString(not(containsString("crs="))) + .respond() + .withBody(items) + .withHeader("Content-Crs", DEFAULT_CRS.getAsHeaderValue()) + .withStatus(200); + InputStream itemsIn25832 = getClass().getResourceAsStream("../../collectionItems-vineyards-25832.json"); + onRequest().havingPath(endsWith("collections/vineyards/items")) + .havingQueryString(containsString("crs=" + URLEncoder.encode(EPSG_25832.getCode()))) + .respond() + .withBody(itemsIn25832) + .withHeader("Content-Crs", EPSG_25832.getAsHeaderValue()) + .withStatus(200); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/landinpage/LandingPageIT.java b/src/test/java/org/opengis/cite/ogcapifeatures10/landinpage/LandingPageIT.java index 8f3eace9..6e2b5612 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/landinpage/LandingPageIT.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/landinpage/LandingPageIT.java @@ -19,29 +19,28 @@ @Ignore("Stable service is required") public class LandingPageIT { - private static ITestContext testContext; - - private static ISuite suite; - - private static final String SUT = "https://www.ldproxy.nrw.de/kataster"; - - @BeforeClass - public static void initTestFixture() - throws Exception { - testContext = mock( ITestContext.class ); - suite = mock( ISuite.class ); - when( testContext.getSuite() ).thenReturn( suite ); - - URI landingPageUri = new URI( SUT ); - when( suite.getAttribute( SuiteAttribute.IUT.getName() ) ).thenReturn( landingPageUri ); - } - - @Test - public void testLandingPage() { - LandingPage landingPage = new LandingPage(); - landingPage.initCommonFixture( testContext ); - landingPage.landingPageRetrieval(); - landingPage.landingPageValidation(); - } + private static ITestContext testContext; + + private static ISuite suite; + + private static final String SUT = "https://www.ldproxy.nrw.de/kataster"; + + @BeforeClass + public static void initTestFixture() throws Exception { + testContext = mock(ITestContext.class); + suite = mock(ISuite.class); + when(testContext.getSuite()).thenReturn(suite); + + URI landingPageUri = new URI(SUT); + when(suite.getAttribute(SuiteAttribute.IUT.getName())).thenReturn(landingPageUri); + } + + @Test + public void testLandingPage() { + LandingPage landingPage = new LandingPage(); + landingPage.initCommonFixture(testContext); + landingPage.landingPageRetrieval(); + landingPage.landingPageValidation(); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/openapi3/OpenApiUtilsTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/openapi3/OpenApiUtilsTest.java index 1d603de5..8be5fd3c 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/openapi3/OpenApiUtilsTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/openapi3/OpenApiUtilsTest.java @@ -34,328 +34,315 @@ */ public class OpenApiUtilsTest { - private static URI iut; - - @BeforeClass - public static void instantiateUri() - throws URISyntaxException { - iut = new URI( "http://localhost:8080/example" ); - } - - @Test - public void testRetrieveTestPoints() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPoints( apiModel, iut ); - - assertThat( testPoints.size(), is( 2 ) ); + private static URI iut; - } - - @Test - public void testRelativeServerPath() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi-relativeServerPath.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPoints( apiModel, iut ); + @BeforeClass + public static void instantiateUri() throws URISyntaxException { + iut = new URI("http://localhost:8080/example"); + } - assertThat( testPoints.size(), is( 2 ) ); - assertThat( testPoints.get( 0 ).getServerUrl(), is( "http://localhost:8080/path" ) ); - assertThat( testPoints.get( 1 ).getServerUrl(), is( "http://localhost:8080/path" ) ); - } - - @Ignore - @Test - public void testRetrieveTestPoints_moreComplex() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi_moreComplex.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPoints( apiModel, iut ); - - assertThat( testPoints.size(), is( 4 ) ); - - TestPoint testPointWIthIndex = testPoints.get( 0 ); - assertThat( testPointWIthIndex.getPredefinedTemplateReplacement().size(), is( 1 ) ); - assertThat( testPointWIthIndex.getPredefinedTemplateReplacement().get( "index" ), is( "10" ) ); - - TestPoint testPointWIthIndexAndEnum1 = testPoints.get( 1 ); - assertThat( testPointWIthIndexAndEnum1.getPredefinedTemplateReplacement().size(), is( 2 ) ); - assertThat( testPointWIthIndexAndEnum1.getPredefinedTemplateReplacement().get( "index" ), is( "10" ) ); - assertThat( testPointWIthIndexAndEnum1.getPredefinedTemplateReplacement().get( "enum" ), is( "eins" ) ); - - TestPoint testPointWIthIndexAndEnum2 = testPoints.get( 2 ); - assertThat( testPointWIthIndexAndEnum2.getPredefinedTemplateReplacement().size(), is( 2 ) ); - assertThat( testPointWIthIndexAndEnum2.getPredefinedTemplateReplacement().get( "index" ), is( "10" ) ); - assertThat( testPointWIthIndexAndEnum2.getPredefinedTemplateReplacement().get( "enum" ), is( "zwei" ) ); - - TestPoint testPointWIthIndexAndEnum3 = testPoints.get( 3 ); - assertThat( testPointWIthIndexAndEnum3.getPredefinedTemplateReplacement().size(), is( 2 ) ); - assertThat( testPointWIthIndexAndEnum3.getPredefinedTemplateReplacement().get( "index" ), is( "10" ) ); - assertThat( testPointWIthIndexAndEnum3.getPredefinedTemplateReplacement().get( "enum" ), is( "drei" ) ); - } - - @Test - public void testRetrieveTestPoints_COLLECTIONS() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForCollectionsMetadata( apiModel, iut ); - - assertThat( testPoints.size(), is( 1 ) ); - Map contentMediaTypes = testPoints.get( 0 ).getContentMediaTypes(); - assertThat( contentMediaTypes.size(), is( 2 ) ); - } - - @Test - public void testRetrieveTestPointsForCollectionMetadata() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForCollectionMetadata( apiModel, iut, "flurstueck" ); - - assertThat( testPoints.size(), is( 1 ) ); - - TestPoint testPoint = testPoints.get( 0 ); - assertThat( testPoint.getServerUrl(), is( "http://localhost:8090/rest/services/kataster" ) ); - assertThat( testPoint.getPath(), is( "/collections/flurstueck" ) ); - - Map contentMediaTypes = testPoint.getContentMediaTypes(); - assertThat( contentMediaTypes.size(), is( 2 ) ); - } - - @Test - public void testRetrieveTestPointsForCollection() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForCollection( apiModel, iut, "flurstueck" ); - - assertThat( testPoints.size(), is( 1 ) ); - - TestPoint testPoint = testPoints.get( 0 ); - assertThat( testPoint.getServerUrl(), is( "http://localhost:8090/rest/services/kataster" ) ); - assertThat( testPoint.getPath(), is( "/collections/flurstueck/items" ) ); - - Map contentMediaTypes = testPoint.getContentMediaTypes(); - assertThat( contentMediaTypes.size(), is( 2 ) ); - } - - @Test - public void testRetrieveTestPointsForFeature() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForFeature( apiModel, iut, "flurstueck", "abc" ); - - assertThat( testPoints.size(), is( 1 ) ); - - TestPoint testPoint = testPoints.get( 0 ); - assertThat( testPoint.getServerUrl(), is( "http://localhost:8090/rest/services/kataster" ) ); - assertThat( testPoint.getPath(), is( "/collections/flurstueck/items/{featureId}" ) ); - Map contentMediaTypes = testPoint.getContentMediaTypes(); - assertThat( contentMediaTypes.size(), is( 2 ) ); - } - - @Test - public void testRetrieveTestPointsForCollections_all() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForCollections( apiModel, iut, -1 ); - - assertThat( testPoints.size(), is( 3 ) ); - List paths = testPoints.stream().map( tp -> tp.getPath() ).collect( Collectors.toCollection( ArrayList::new ) ); - assertThat( paths, hasItem( "/collections/flurstueck/items" ) ); - assertThat( paths, hasItem( "/collections/gebaeudebauwerk/items" ) ); - assertThat( paths, hasItem( "/collections/verwaltungseinheit/items" ) ); - } - - @Test - public void testRetrieveTestPointsForCollections_limit1() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForCollections( apiModel, iut, 1 ); - - assertThat( testPoints.size(), is( 1 ) ); - List paths = testPoints.stream().map( tp -> tp.getPath() ).collect( Collectors.toCollection( ArrayList::new ) ); - assertThat( paths, hasItem( "/collections/flurstueck/items" ) ); - } - - @Test - public void testRetrieveTestPointsForCollections_limitGreaterThanSize() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); + @Test + public void testRetrieveTestPoints() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForCollections( apiModel, iut, 6 ); + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPoints(apiModel, iut); - assertThat( testPoints.size(), is( 3 ) ); - List paths = testPoints.stream().map( tp -> tp.getPath() ).collect( Collectors.toCollection( ArrayList::new ) ); - assertThat( paths, hasItem( "/collections/flurstueck/items" ) ); - } + assertThat(testPoints.size(), is(2)); - @Test - public void testRetrieveTestPoints_COLLECTIONS_compactAPI() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); + } - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi_compact-api.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForCollectionsMetadata( apiModel, iut ); + @Test + public void testRelativeServerPath() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); - assertThat( testPoints.size(), is( 1 ) ); - - TestPoint testPoint = testPoints.get( 0 ); - // assertThat( testPoint.createUri(), is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3/collections" ) ); - - assertThat( testPoint.getServerUrl(), is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3" ) ); - assertThat( testPoint.getPath(), is( "/collections" ) ); - - assertThat( testPoint.getContentMediaTypes().size(), is( 4 ) ); - } - - @Test - public void testRetrieveTestPointsForCollectionMetadata_compactAPI() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi_compact-api.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForCollectionMetadata( apiModel, iut, "test__countries" ); - - assertThat( testPoints.size(), is( 1 ) ); - - TestPoint testPoint = testPoints.get( 0 ); - - assertThat( testPoint.getServerUrl(), is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3" ) ); - assertThat( testPoint.getPath(), is( "/collections/{collectionId}" ) ); - } - - @Test - public void testRetrieveTestPointsForCollection_compactAPI() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi_compact-api.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForCollection( apiModel, iut, "test__countries" ); - - assertThat( testPoints.size(), is( 1 ) ); - - TestPoint testPoint = testPoints.get( 0 ); - assertThat( testPoint.getServerUrl(), is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3" ) ); - assertThat( testPoint.getPath(), is( "/collections/{collectionId}/items" ) ); - } - - @Test - public void testRetrieveTestPointsForFeature_compactAPI() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi_compact-api.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForFeature( apiModel, iut, "test__countries", "abc" ); - - assertThat( testPoints.size(), is( 1 ) ); - - TestPoint testPoint = testPoints.get( 0 ); - assertThat( testPoint.getServerUrl(), is( "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3" ) ); - assertThat( testPoint.getPath(), is( "/collections/{collectionId}/items/{featureId}" ) ); - } + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi-relativeServerPath.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPoints(apiModel, iut); - @Test - public void testRetrieveTestPointsForCollections_all_compactAPI() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); + assertThat(testPoints.size(), is(2)); + assertThat(testPoints.get(0).getServerUrl(), is("http://localhost:8080/path")); + assertThat(testPoints.get(1).getServerUrl(), is("http://localhost:8080/path")); + } - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi_compact-api.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForCollections( apiModel, iut, -1 ); + @Ignore + @Test + public void testRetrieveTestPoints_moreComplex() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); - assertThat( testPoints.size(), is( OgcApiFeatures10.COLLECTIONS_LIMIT ) ); - assertThat( testPoints.get( 0 ).getPath(), is( "/collections/{collectionId}/items" ) ); - } + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi_moreComplex.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPoints(apiModel, iut); - @Test - public void testRetrieveTestPointsForCollections_limit1_compactAPI() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); + assertThat(testPoints.size(), is(4)); - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi_compact-api.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - List testPoints = retrieveTestPointsForCollections( apiModel, iut, 1 ); + TestPoint testPointWIthIndex = testPoints.get(0); + assertThat(testPointWIthIndex.getPredefinedTemplateReplacement().size(), is(1)); + assertThat(testPointWIthIndex.getPredefinedTemplateReplacement().get("index"), is("10")); - assertThat( testPoints.size(), is( 1 ) ); - assertThat( testPoints.get( 0 ).getPath(), is( "/collections/{collectionId}/items" ) ); - } + TestPoint testPointWIthIndexAndEnum1 = testPoints.get(1); + assertThat(testPointWIthIndexAndEnum1.getPredefinedTemplateReplacement().size(), is(2)); + assertThat(testPointWIthIndexAndEnum1.getPredefinedTemplateReplacement().get("index"), is("10")); + assertThat(testPointWIthIndexAndEnum1.getPredefinedTemplateReplacement().get("enum"), is("eins")); + + TestPoint testPointWIthIndexAndEnum2 = testPoints.get(2); + assertThat(testPointWIthIndexAndEnum2.getPredefinedTemplateReplacement().size(), is(2)); + assertThat(testPointWIthIndexAndEnum2.getPredefinedTemplateReplacement().get("index"), is("10")); + assertThat(testPointWIthIndexAndEnum2.getPredefinedTemplateReplacement().get("enum"), is("zwei")); + + TestPoint testPointWIthIndexAndEnum3 = testPoints.get(3); + assertThat(testPointWIthIndexAndEnum3.getPredefinedTemplateReplacement().size(), is(2)); + assertThat(testPointWIthIndexAndEnum3.getPredefinedTemplateReplacement().get("index"), is("10")); + assertThat(testPointWIthIndexAndEnum3.getPredefinedTemplateReplacement().get("enum"), is("drei")); + } + + @Test + public void testRetrieveTestPoints_COLLECTIONS() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForCollectionsMetadata(apiModel, iut); + + assertThat(testPoints.size(), is(1)); + Map contentMediaTypes = testPoints.get(0).getContentMediaTypes(); + assertThat(contentMediaTypes.size(), is(2)); + } + + @Test + public void testRetrieveTestPointsForCollectionMetadata() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForCollectionMetadata(apiModel, iut, "flurstueck"); + + assertThat(testPoints.size(), is(1)); + + TestPoint testPoint = testPoints.get(0); + assertThat(testPoint.getServerUrl(), is("http://localhost:8090/rest/services/kataster")); + assertThat(testPoint.getPath(), is("/collections/flurstueck")); + + Map contentMediaTypes = testPoint.getContentMediaTypes(); + assertThat(contentMediaTypes.size(), is(2)); + } + + @Test + public void testRetrieveTestPointsForCollection() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForCollection(apiModel, iut, "flurstueck"); + + assertThat(testPoints.size(), is(1)); + + TestPoint testPoint = testPoints.get(0); + assertThat(testPoint.getServerUrl(), is("http://localhost:8090/rest/services/kataster")); + assertThat(testPoint.getPath(), is("/collections/flurstueck/items")); - @Test - public void testIsFreeFormParameterSupportedForCollection() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); + Map contentMediaTypes = testPoint.getContentMediaTypes(); + assertThat(contentMediaTypes.size(), is(2)); + } - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - boolean isFreeFormParameterSupported = isFreeFormParameterSupportedForCollection( apiModel, iut, "flurstueck" ); + @Test + public void testRetrieveTestPointsForFeature() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); - assertThat( isFreeFormParameterSupported, is( false ) ); - } + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForFeature(apiModel, iut, "flurstueck", "abc"); + + assertThat(testPoints.size(), is(1)); - @Test - public void testIsFreeFormParameterSupportedForCollection_supported() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); + TestPoint testPoint = testPoints.get(0); + assertThat(testPoint.getServerUrl(), is("http://localhost:8090/rest/services/kataster")); + assertThat(testPoint.getPath(), is("/collections/flurstueck/items/{featureId}")); + Map contentMediaTypes = testPoint.getContentMediaTypes(); + assertThat(contentMediaTypes.size(), is(2)); + } + + @Test + public void testRetrieveTestPointsForCollections_all() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForCollections(apiModel, iut, -1); - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi-freeformparam.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - boolean isFreeFormParameterSupported = isFreeFormParameterSupportedForCollection( apiModel, iut, "flurstueck" ); + assertThat(testPoints.size(), is(3)); + List paths = testPoints.stream() + .map(tp -> tp.getPath()) + .collect(Collectors.toCollection(ArrayList::new)); + assertThat(paths, hasItem("/collections/flurstueck/items")); + assertThat(paths, hasItem("/collections/gebaeudebauwerk/items")); + assertThat(paths, hasItem("/collections/verwaltungseinheit/items")); + } - assertThat( isFreeFormParameterSupported, is( true ) ); - } + @Test + public void testRetrieveTestPointsForCollections_limit1() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); - @Test - public void testIsParameterSupportedForCollection() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForCollections(apiModel, iut, 1); - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - boolean isFreeFormParameterSupported = isParameterSupportedForCollection( apiModel, iut, "flurstueck", "unknown" ); + assertThat(testPoints.size(), is(1)); + List paths = testPoints.stream() + .map(tp -> tp.getPath()) + .collect(Collectors.toCollection(ArrayList::new)); + assertThat(paths, hasItem("/collections/flurstueck/items")); + } - assertThat( isFreeFormParameterSupported, is( false ) ); - } + @Test + public void testRetrieveTestPointsForCollections_limitGreaterThanSize() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForCollections(apiModel, iut, 6); + + assertThat(testPoints.size(), is(3)); + List paths = testPoints.stream() + .map(tp -> tp.getPath()) + .collect(Collectors.toCollection(ArrayList::new)); + assertThat(paths, hasItem("/collections/flurstueck/items")); + } + + @Test + public void testRetrieveTestPoints_COLLECTIONS_compactAPI() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi_compact-api.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForCollectionsMetadata(apiModel, iut); + + assertThat(testPoints.size(), is(1)); + + TestPoint testPoint = testPoints.get(0); + // assertThat( testPoint.createUri(), is( + // "http://cloudsdi.geo-solutions.it:80/geoserver/wfs3/collections" ) ); + + assertThat(testPoint.getServerUrl(), is("http://cloudsdi.geo-solutions.it:80/geoserver/wfs3")); + assertThat(testPoint.getPath(), is("/collections")); + + assertThat(testPoint.getContentMediaTypes().size(), is(4)); + } + + @Test + public void testRetrieveTestPointsForCollectionMetadata_compactAPI() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi_compact-api.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForCollectionMetadata(apiModel, iut, "test__countries"); + + assertThat(testPoints.size(), is(1)); + + TestPoint testPoint = testPoints.get(0); + + assertThat(testPoint.getServerUrl(), is("http://cloudsdi.geo-solutions.it:80/geoserver/wfs3")); + assertThat(testPoint.getPath(), is("/collections/{collectionId}")); + } + + @Test + public void testRetrieveTestPointsForCollection_compactAPI() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi_compact-api.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForCollection(apiModel, iut, "test__countries"); + + assertThat(testPoints.size(), is(1)); + + TestPoint testPoint = testPoints.get(0); + assertThat(testPoint.getServerUrl(), is("http://cloudsdi.geo-solutions.it:80/geoserver/wfs3")); + assertThat(testPoint.getPath(), is("/collections/{collectionId}/items")); + } + + @Test + public void testRetrieveTestPointsForFeature_compactAPI() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi_compact-api.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForFeature(apiModel, iut, "test__countries", "abc"); + + assertThat(testPoints.size(), is(1)); + + TestPoint testPoint = testPoints.get(0); + assertThat(testPoint.getServerUrl(), is("http://cloudsdi.geo-solutions.it:80/geoserver/wfs3")); + assertThat(testPoint.getPath(), is("/collections/{collectionId}/items/{featureId}")); + } + + @Test + public void testRetrieveTestPointsForCollections_all_compactAPI() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi_compact-api.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForCollections(apiModel, iut, -1); + + assertThat(testPoints.size(), is(OgcApiFeatures10.COLLECTIONS_LIMIT)); + assertThat(testPoints.get(0).getPath(), is("/collections/{collectionId}/items")); + } + + @Test + public void testRetrieveTestPointsForCollections_limit1_compactAPI() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi_compact-api.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + List testPoints = retrieveTestPointsForCollections(apiModel, iut, 1); + + assertThat(testPoints.size(), is(1)); + assertThat(testPoints.get(0).getPath(), is("/collections/{collectionId}/items")); + } + + @Test + public void testIsFreeFormParameterSupportedForCollection() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + boolean isFreeFormParameterSupported = isFreeFormParameterSupportedForCollection(apiModel, iut, "flurstueck"); + + assertThat(isFreeFormParameterSupported, is(false)); + } + + @Test + public void testIsFreeFormParameterSupportedForCollection_supported() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi-freeformparam.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + boolean isFreeFormParameterSupported = isFreeFormParameterSupportedForCollection(apiModel, iut, "flurstueck"); + + assertThat(isFreeFormParameterSupported, is(true)); + } + + @Test + public void testIsParameterSupportedForCollection() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + boolean isFreeFormParameterSupported = isParameterSupportedForCollection(apiModel, iut, "flurstueck", + "unknown"); + + assertThat(isFreeFormParameterSupported, is(false)); + } + + @Test + public void testIsParameterSupportedForCollection_supported() throws Exception { + OpenApi3Parser parser = new OpenApi3Parser(); + + URL openApiDocument = OpenApiUtilsTest.class.getResource("openapi.json"); + OpenApi3 apiModel = parser.parse(openApiDocument, true); + boolean isFreeFormParameterSupported = isParameterSupportedForCollection(apiModel, iut, "flurstueck", "limit"); + + assertThat(isFreeFormParameterSupported, is(true)); + } - @Test - public void testIsParameterSupportedForCollection_supported() - throws Exception { - OpenApi3Parser parser = new OpenApi3Parser(); - - URL openApiDocument = OpenApiUtilsTest.class.getResource( "openapi.json" ); - OpenApi3 apiModel = parser.parse( openApiDocument, true ); - boolean isFreeFormParameterSupported = isParameterSupportedForCollection( apiModel, iut, "flurstueck", "limit" ); - - assertThat( isFreeFormParameterSupported, is( true ) ); - } - } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/openapi3/UrlBuilderTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/openapi3/UrlBuilderTest.java index bd0bccbe..32e95b3c 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/openapi3/UrlBuilderTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/openapi3/UrlBuilderTest.java @@ -12,64 +12,65 @@ */ public class UrlBuilderTest { - @Test - public void testBuildUrl_collectionMetadata_withTemplate() { - TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/{name}", Collections.emptyMap() ); - String url = new UriBuilder( tp ).collectionName( "water" ).buildUrl(); - - assertThat( url, is( "http://localhost:8080/service/collections/water" ) ); - } - - @Test - public void testBuildUrl_collectionMetadata_withoutTemplate() { - TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/forest", Collections.emptyMap() ); - String url = new UriBuilder( tp ).collectionName( "forest" ).buildUrl(); - - assertThat( url, is( "http://localhost:8080/service/collections/forest" ) ); - } - - @Test - public void testBuildUrl_collection_withTemplate() { - TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/{name}/items", - Collections.emptyMap() ); - String url = new UriBuilder( tp ).collectionName( "water" ).buildUrl(); - - assertThat( url, is( "http://localhost:8080/service/collections/water/items" ) ); - } - - @Test - public void testBuildUrl_collection_withoutTemplate() { - TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/forest/items", - Collections.emptyMap() ); - String url = new UriBuilder( tp ).collectionName( "forest" ).buildUrl(); - - assertThat( url, is( "http://localhost:8080/service/collections/forest/items" ) ); - } - - @Test - public void testBuildUrl_feature_withFeatureIdTemplate() { - TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/forest/items/{featureId}", - Collections.emptyMap() ); - String url = new UriBuilder( tp ).collectionName( "forest" ).featureId( "1" ).buildUrl(); - - assertThat( url, is( "http://localhost:8080/service/collections/forest/items/1" ) ); - } - - @Test - public void testBuildUrl_feature_withCollectionNameAndFeatureIdTemplate() { - TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/{name}/items/{featureId}", - Collections.emptyMap() ); - String url = new UriBuilder( tp ).collectionName( "water" ).featureId( "2" ).buildUrl(); - - assertThat( url, is( "http://localhost:8080/service/collections/water/items/2" ) ); - } - - @Test - public void testBuildUrl_feature_withoutTemplates() { - TestPoint tp = new TestPoint( "http://localhost:8080/service", "/collections/forest/items/3", - Collections.emptyMap() ); - String url = new UriBuilder( tp ).collectionName( "forest" ).featureId( "3" ).buildUrl(); - - assertThat( url, is( "http://localhost:8080/service/collections/forest/items/3" ) ); - } + @Test + public void testBuildUrl_collectionMetadata_withTemplate() { + TestPoint tp = new TestPoint("http://localhost:8080/service", "/collections/{name}", Collections.emptyMap()); + String url = new UriBuilder(tp).collectionName("water").buildUrl(); + + assertThat(url, is("http://localhost:8080/service/collections/water")); + } + + @Test + public void testBuildUrl_collectionMetadata_withoutTemplate() { + TestPoint tp = new TestPoint("http://localhost:8080/service", "/collections/forest", Collections.emptyMap()); + String url = new UriBuilder(tp).collectionName("forest").buildUrl(); + + assertThat(url, is("http://localhost:8080/service/collections/forest")); + } + + @Test + public void testBuildUrl_collection_withTemplate() { + TestPoint tp = new TestPoint("http://localhost:8080/service", "/collections/{name}/items", + Collections.emptyMap()); + String url = new UriBuilder(tp).collectionName("water").buildUrl(); + + assertThat(url, is("http://localhost:8080/service/collections/water/items")); + } + + @Test + public void testBuildUrl_collection_withoutTemplate() { + TestPoint tp = new TestPoint("http://localhost:8080/service", "/collections/forest/items", + Collections.emptyMap()); + String url = new UriBuilder(tp).collectionName("forest").buildUrl(); + + assertThat(url, is("http://localhost:8080/service/collections/forest/items")); + } + + @Test + public void testBuildUrl_feature_withFeatureIdTemplate() { + TestPoint tp = new TestPoint("http://localhost:8080/service", "/collections/forest/items/{featureId}", + Collections.emptyMap()); + String url = new UriBuilder(tp).collectionName("forest").featureId("1").buildUrl(); + + assertThat(url, is("http://localhost:8080/service/collections/forest/items/1")); + } + + @Test + public void testBuildUrl_feature_withCollectionNameAndFeatureIdTemplate() { + TestPoint tp = new TestPoint("http://localhost:8080/service", "/collections/{name}/items/{featureId}", + Collections.emptyMap()); + String url = new UriBuilder(tp).collectionName("water").featureId("2").buildUrl(); + + assertThat(url, is("http://localhost:8080/service/collections/water/items/2")); + } + + @Test + public void testBuildUrl_feature_withoutTemplates() { + TestPoint tp = new TestPoint("http://localhost:8080/service", "/collections/forest/items/3", + Collections.emptyMap()); + String url = new UriBuilder(tp).collectionName("forest").featureId("3").buildUrl(); + + assertThat(url, is("http://localhost:8080/service/collections/forest/items/3")); + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/util/GeometryTransformerTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/util/GeometryTransformerTest.java index 31ca8dd2..b57112b4 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/util/GeometryTransformerTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/util/GeometryTransformerTest.java @@ -14,65 +14,68 @@ */ public class GeometryTransformerTest { - private static final CoordinateSystem EPSG_25832 = new CoordinateSystem( "http://www.opengis.net/def/crs/EPSG/0/25832" ); + private static final CoordinateSystem EPSG_25832 = new CoordinateSystem( + "http://www.opengis.net/def/crs/EPSG/0/25832"); - private static final CoordinateSystem EPSG_4326 = new CoordinateSystem( "http://www.opengis.net/def/crs/EPSG/0/4326" ); + private static final CoordinateSystem EPSG_4326 = new CoordinateSystem( + "http://www.opengis.net/def/crs/EPSG/0/4326"); - private final GeometryFactory geometryFactory = new GeometryFactory(); + private final GeometryFactory geometryFactory = new GeometryFactory(); - @Test - public void test_transform_Point_CRS84_4326() { - GeometryTransformer geometryTransformer = new GeometryTransformer( DEFAULT_CRS, EPSG_4326 ); - Point pointToTransform = geometryFactory.createPoint( new Coordinate( 7.55, 51.82 ) ); - Point transformedPoint = geometryTransformer.transform( pointToTransform ); - assertEquals( 51.82, transformedPoint.getX(), 0.01 ); - assertEquals( 7.55, transformedPoint.getY(), 0.01 ); - } + @Test + public void test_transform_Point_CRS84_4326() { + GeometryTransformer geometryTransformer = new GeometryTransformer(DEFAULT_CRS, EPSG_4326); + Point pointToTransform = geometryFactory.createPoint(new Coordinate(7.55, 51.82)); + Point transformedPoint = geometryTransformer.transform(pointToTransform); + assertEquals(51.82, transformedPoint.getX(), 0.01); + assertEquals(7.55, transformedPoint.getY(), 0.01); + } - @Test - public void test_transform_Point_CRS84_25832() { - GeometryTransformer geometryTransformer = new GeometryTransformer( DEFAULT_CRS, EPSG_25832 ); - Point pointToTransform = geometryFactory.createPoint( new Coordinate( 7.55, 51.82 ) ); - Point transformedPoint = geometryTransformer.transform( pointToTransform ); - assertEquals( 400060.46, transformedPoint.getX(), 0.01 ); - assertEquals( 5742012.57, transformedPoint.getY(), 0.01 ); - } + @Test + public void test_transform_Point_CRS84_25832() { + GeometryTransformer geometryTransformer = new GeometryTransformer(DEFAULT_CRS, EPSG_25832); + Point pointToTransform = geometryFactory.createPoint(new Coordinate(7.55, 51.82)); + Point transformedPoint = geometryTransformer.transform(pointToTransform); + assertEquals(400060.46, transformedPoint.getX(), 0.01); + assertEquals(5742012.57, transformedPoint.getY(), 0.01); + } - @Test - public void test_transform_Point_4326_25832() { - GeometryTransformer geometryTransformer = new GeometryTransformer( EPSG_4326, EPSG_25832 ); - Point pointToTransform = geometryFactory.createPoint( new Coordinate( 51.82, 7.55 ) ); - Point transformedPoint = geometryTransformer.transform( pointToTransform ); - assertEquals( 400060.46, transformedPoint.getX(), 0.01 ); - assertEquals( 5742012.57, transformedPoint.getY(), 0.01 ); - } + @Test + public void test_transform_Point_4326_25832() { + GeometryTransformer geometryTransformer = new GeometryTransformer(EPSG_4326, EPSG_25832); + Point pointToTransform = geometryFactory.createPoint(new Coordinate(51.82, 7.55)); + Point transformedPoint = geometryTransformer.transform(pointToTransform); + assertEquals(400060.46, transformedPoint.getX(), 0.01); + assertEquals(5742012.57, transformedPoint.getY(), 0.01); + } - @Test - public void test_transform_Point_25832_4326() { - GeometryTransformer geometryTransformer = new GeometryTransformer( EPSG_25832, EPSG_4326 ); - Point pointToTransform = geometryFactory.createPoint( new Coordinate( 400060.46, 5742012.57 ) ); - Point transformedPoint = geometryTransformer.transform( pointToTransform ); - assertEquals( 51.82, transformedPoint.getX(), 0.01 ); - assertEquals( 7.55, transformedPoint.getY(), 0.01 ); - } + @Test + public void test_transform_Point_25832_4326() { + GeometryTransformer geometryTransformer = new GeometryTransformer(EPSG_25832, EPSG_4326); + Point pointToTransform = geometryFactory.createPoint(new Coordinate(400060.46, 5742012.57)); + Point transformedPoint = geometryTransformer.transform(pointToTransform); + assertEquals(51.82, transformedPoint.getX(), 0.01); + assertEquals(7.55, transformedPoint.getY(), 0.01); + } - @Test - public void test_transform_Point_25832_CRS84() { - GeometryTransformer geometryTransformer = new GeometryTransformer( EPSG_25832, DEFAULT_CRS ); - Point pointToTransform = geometryFactory.createPoint( new Coordinate( 400060.46, 5742012.57 ) ); - Point transformedPoint = geometryTransformer.transform( pointToTransform ); - assertEquals( 7.55, transformedPoint.getX(), 0.01 ); - assertEquals( 51.82, transformedPoint.getY(), 0.01 ); - } + @Test + public void test_transform_Point_25832_CRS84() { + GeometryTransformer geometryTransformer = new GeometryTransformer(EPSG_25832, DEFAULT_CRS); + Point pointToTransform = geometryFactory.createPoint(new Coordinate(400060.46, 5742012.57)); + Point transformedPoint = geometryTransformer.transform(pointToTransform); + assertEquals(7.55, transformedPoint.getX(), 0.01); + assertEquals(51.82, transformedPoint.getY(), 0.01); + } + + @Test + public void test_transform_BBox() { + GeometryTransformer geometryTransformer = new GeometryTransformer(DEFAULT_CRS, EPSG_25832); + BBox bbox = new BBox(7.55, 51.82, 8.11, 52.14, DEFAULT_CRS); + BBox transformedBbox = geometryTransformer.transform(bbox); + assertEquals(400060.46, transformedBbox.getMinX(), 0.01); + assertEquals(5742012.57, transformedBbox.getMinY(), 0.01); + assertEquals(439092.40, transformedBbox.getMaxX(), 0.01); + assertEquals(5776983.09, transformedBbox.getMaxY(), 0.01); + } - @Test - public void test_transform_BBox() { - GeometryTransformer geometryTransformer = new GeometryTransformer( DEFAULT_CRS, EPSG_25832 ); - BBox bbox = new BBox( 7.55, 51.82, 8.11, 52.14, DEFAULT_CRS ); - BBox transformedBbox = geometryTransformer.transform( bbox ); - assertEquals( 400060.46, transformedBbox.getMinX(), 0.01 ); - assertEquals( 5742012.57, transformedBbox.getMinY(), 0.01 ); - assertEquals( 439092.40, transformedBbox.getMaxX(), 0.01 ); - assertEquals( 5776983.09, transformedBbox.getMaxY(), 0.01 ); - } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/util/JsonUtilsTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/util/JsonUtilsTest.java index 72b20eb8..b1e4fece 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/util/JsonUtilsTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/util/JsonUtilsTest.java @@ -62,273 +62,270 @@ */ public class JsonUtilsTest { - private static JsonPath jsonCollection; - - private static JsonPath jsonCollectionItem; - - @BeforeClass - public static void parseJson() { - InputStream collectionJson = JsonUtilsTest.class.getResourceAsStream( "../conformance/core/collections/collections.json" ); - jsonCollection = new JsonPath( collectionJson ); - InputStream collectionItemsJson = JsonUtilsTest.class.getResourceAsStream( "../conformance/core/collections/collectionItems-flurstueck.json" ); - jsonCollectionItem = new JsonPath( collectionItemsJson ); - } - - @Before - public void setUp() { - initJadlerListeningOn( 8090 ); - } - - @After - public void tearDown() { - closeJadler(); - } - - @Test - public void testParseFeatureId() { - String featureId = parseFeatureId( jsonCollectionItem ); - assertThat( featureId, is( "DENW19AL0000geMFFL" ) ); - } - - @Test - public void testParseAsDate() { - String timeStamp = "2017-03-04T01:02:33Z"; - ZonedDateTime dateTime = parseAsDate( timeStamp ); - - assertThat( dateTime.getYear(), is( 2017 ) ); - assertThat( dateTime.getMonth(), is( Month.MARCH ) ); - assertThat( dateTime.getDayOfMonth(), is( 4 ) ); - assertThat( dateTime.getHour(), is( 1 ) ); - assertThat( dateTime.getMinute(), is( 2 ) ); - assertThat( dateTime.getSecond(), is( 33 ) ); - } - - @Test - public void testFormatDate() { - String dateTime = "2017-03-04T01:02:33Z"; - ZonedDateTime dateTimeAsZonedDateTime = parseAsDate( dateTime ); - - String dateTimeAsString = formatDate( dateTimeAsZonedDateTime ); - assertThat( dateTimeAsString, is( dateTime ) ); - - String dateAsString = formatDate( dateTimeAsZonedDateTime.toLocalDate() ); - assertThat( dateAsString, is( "2017-03-04" ) ); - } - - @Test - public void testFormatDateRange() { - String beginDateTime = "2017-03-04T01:02:33Z"; - ZonedDateTime begin = parseAsDate( beginDateTime ); - String endDateTime = "2018-03-04T01:02:33Z"; - ZonedDateTime end = parseAsDate( endDateTime ); - - String asString = formatDateRange( begin, end ); - assertThat( asString, is( "2017-03-04T01:02:33Z/2018-03-04T01:02:33Z" ) ); - } - - @Test - public void testFormatDateRangeWithDuration() { - String beginDate = "2017-03-04"; - LocalDate begin = LocalDate.parse( beginDate ); - String endDate = "2017-04-06"; - LocalDate end = LocalDate.parse( endDate ); - - String asString = formatDateRangeWithDuration( begin, end ); - assertThat( asString, is( "2017-03-04/P1M2D" ) ); - } - - @Test - public void testTemporalExtent() { - List collections = jsonCollection.getList( "collections" ); - TemporalExtent extent = parseTemporalExtent( (Map) collections.get( 0 ) ); - - ZonedDateTime begin = extent.getBegin(); - ZonedDateTime end = extent.getEnd(); - assertThat( begin, is( ZonedDateTime.parse( "2017-01-01T00:00:00Z" ) ) ); - assertThat( end, is( ZonedDateTime.parse( "2017-12-31T23:59:59Z" ) ) ); - } - - @Test - public void testParseSpatialExtent() { - List collections = jsonCollection.getList( "collections" ); - BBox extent = parseSpatialExtent( (Map) collections.get( 0 ) ); - - String queryParam = extent.asQueryParameter(); - String[] queryParams = queryParam.split( "," ); - assertThat( queryParams.length, is( 4 ) ); - assertEquals( Double.parseDouble( queryParams[0] ), 5.61272621360749, 0.00001 ); - assertEquals( Double.parseDouble( queryParams[1] ), 50.2373512077239, 0.00001 ); - assertEquals( Double.parseDouble( queryParams[2] ), 9.58963433710139, 0.00001 ); - assertEquals( Double.parseDouble( queryParams[3] ), 52.5286304537795, 0.00001 ); - } - - @Test - public void testParseSpatialExtent_WithIntegerValues() { - List collections = jsonCollection.getList( "collections" ); - BBox extent = parseSpatialExtent( (Map) collections.get( 1 ) ); - - String queryParam = extent.asQueryParameter(); - String[] queryParams = queryParam.split( "," ); - assertThat( queryParams.length, is( 4 ) ); - assertThat( Double.parseDouble( queryParams[0] ), is( 5d ) ); - assertThat( Double.parseDouble( queryParams[1] ), is( 50d ) ); - assertThat( Double.parseDouble( queryParams[2] ), is( 9d ) ); - assertThat( Double.parseDouble( queryParams[3] ), is( 52d ) ); - } - - @Test - public void testFindLinkToItself() { - List> links = jsonCollection.getList( "links" ); - Map linkToItself = findLinkByRel( links, "self" ); - - assertThat( linkToItself.get( "href" ), - is( "http://localhost:8090/rest/services/kataster/collections/?f=json" ) ); - assertThat( linkToItself.get( "rel" ), is( "self" ) ); - assertThat( linkToItself.get( "type" ), is( "application/json" ) ); - assertThat( linkToItself.get( "title" ), is( "this document" ) ); - } - - @Test - public void testLinkIncludesRelAndType() { - List> links = jsonCollection.getList( "links" ); - Map linkToItself = findLinkByRel( links, "self" ); - boolean includesRelAndType = linkIncludesRelAndType( linkToItself ); - - assertThat( includesRelAndType, is( true ) ); - } - - @Test - public void testFindLinksWithoutRelOrType() { - List> links = jsonCollection.getList( "links" ); - Set rels = new HashSet<>(); - rels.add( "self" ); - rels.add( "alternate" ); - List linksWithoutRelOrType = findLinksWithoutRelOrType( links, rels ); - - assertThat( linksWithoutRelOrType.size(), is( 0 ) ); - } - - @Test - public void testFindLinksWithSupportedMediaTypeByRel() { - List> links = jsonCollection.getList( "links" ); - List mediaTypes = Arrays.asList( "text/html", "application/json" ); - List> linksWithMediaTypes = findLinksWithSupportedMediaTypeByRel( links, mediaTypes, - "alternate" ); - - assertThat( linksWithMediaTypes.size(), is( 1 ) ); - } - - @Test - public void testHasProperty_true() { - boolean hasProperty = hasProperty( "links", jsonCollection ); - assertThat( hasProperty, is( true ) ); - } - - @Test - public void testHasProperty_false() { - boolean hasProperty = hasProperty( "doesNotExist", jsonCollection ); - assertThat( hasProperty, is( false ) ); - } - - @Test - public void testHasAtLeastOneSpatialFeatureCollection() { - boolean hasSpatialFeatureCollection = hasAtLeastOneSpatialFeatureCollection( jsonCollection ); - assertThat( hasSpatialFeatureCollection, is( true ) ); - } - - @Test - public void testFindFeaturesUrlForGeoJson() - throws Exception { - InputStream collectionJson = JsonUtilsTest.class.getResourceAsStream( "../conformance/core/collections/collection-flurstueck.json" ); - JsonPath flurstueckCollection = new JsonPath( collectionJson ); - URI rootUri = new URI( "http://localhost:8090/rest/services" ); - String featuresUrlForGeoJson = findFeaturesUrlForGeoJson( rootUri, flurstueckCollection ); - - assertThat( featuresUrlForGeoJson, - is( "http://localhost:8090/rest/services/kataster/collections/flurstueck/items?f=json" ) ); - } - - @Test - public void testFindFeatureUrlForGeoJson() - throws Exception { - Map link = createItemsLinks( "https://test.service.de/ogcapi/datasets/kitaeinrichtung/items" ); - JsonPath collection = Mockito.mock( JsonPath.class ); - when( collection.get( "links" ) ).thenReturn( Collections.singletonList( link ) ); - URI rootUri = new URI( "http://localhost:8090/rest/services" ); - String featuresUrlForGeoJson = findFeatureUrlForGeoJson( rootUri, collection, "testId" ); - - assertThat( featuresUrlForGeoJson, - is( "https://test.service.de/ogcapi/datasets/kitaeinrichtung/items/testId" ) ); - } - - @Test - public void testFindFeatureUrlForGeoJson_withParam() - throws Exception { - Map link = createItemsLinks( "https://test.service.de/ogcapi/datasets/kitaeinrichtung/items?f=json" ); - JsonPath collection = Mockito.mock( JsonPath.class ); - when( collection.get( "links" ) ).thenReturn( Collections.singletonList( link ) ); - URI rootUri = new URI( "http://localhost:8090/rest/services" ); - String featuresUrlForGeoJson = findFeatureUrlForGeoJson( rootUri, collection, "testId" ); - - assertThat( featuresUrlForGeoJson, - is( "https://test.service.de/ogcapi/datasets/kitaeinrichtung/items/testId" ) ); - } - - @Test - public void testFindFeatureUrlForGeoJson_withExtension() - throws Exception { - Map link = createItemsLinks( "https://test.service.de/ogcapi/datasets/kitaeinrichtung/items.json" ); - JsonPath collection = Mockito.mock( JsonPath.class ); - when( collection.get( "links" ) ).thenReturn( Collections.singletonList( link ) ); - URI rootUri = new URI( "http://localhost:8090/rest/services" ); - String featuresUrlForGeoJson = findFeatureUrlForGeoJson( rootUri, collection, "testId" ); - - assertThat( featuresUrlForGeoJson, - is( "https://test.service.de/ogcapi/datasets/kitaeinrichtung/items/testId.json" ) ); - } - - @Test - public void testCollectNumberOfAllReturnedFeatures() - throws Exception { - prepareJadler(); - URL json = new URL( "http://localhost:8090/collections/lakes/items" ); - JsonPath jsonPath = new JsonPath( json ); - - int numberOfAllFeatures = collectNumberOfAllReturnedFeatures( jsonPath, -1 ); - - assertThat( numberOfAllFeatures, is( 25 ) ); - } - - @Test - public void testParseFeatureGeometry() - throws Exception { - List> features = jsonCollectionItem.getList( "features" ); - Map firstFeature = features.get( 0 ); - Geometry geometry = parseFeatureGeometry( firstFeature, DEFAULT_CRS ); - assertThat( geometry, instanceOf( MultiPolygon.class ) ); - } - - private void prepareJadler() { - InputStream item1_10 = getClass().getResourceAsStream( "items_1-10.json" ); - onRequest().havingParameter( "startindex", nullValue() ).respond().withBody( item1_10 ); - - InputStream item11_20 = getClass().getResourceAsStream( "items_11-20.json" ); - onRequest().havingParameterEqualTo( "startindex", "10" ).respond().withBody( item11_20 ); - - InputStream item21_30 = getClass().getResourceAsStream( "items_21-30.json" ); - onRequest().havingParameterEqualTo( "startindex", "20" ).respond().withBody( item21_30 ); - - InputStream item31_40 = getClass().getResourceAsStream( "items_31-40.json" ); - onRequest().havingParameter( "startindex", allOf( notNullValue(), not( hasItems( "10" ) ), - not( hasItems( "20" ) ) ) ).respond().withBody( item31_40 ); - } - - private Map createItemsLinks( String href ) { - Map link = new HashMap<>(); - link.put( "rel", "items" ); - link.put( "type", GEOJSON_MIME_TYPE ); - link.put( "href", href ); - return link; - } + private static JsonPath jsonCollection; + + private static JsonPath jsonCollectionItem; + + @BeforeClass + public static void parseJson() { + InputStream collectionJson = JsonUtilsTest.class + .getResourceAsStream("../conformance/core/collections/collections.json"); + jsonCollection = new JsonPath(collectionJson); + InputStream collectionItemsJson = JsonUtilsTest.class + .getResourceAsStream("../conformance/core/collections/collectionItems-flurstueck.json"); + jsonCollectionItem = new JsonPath(collectionItemsJson); + } + + @Before + public void setUp() { + initJadlerListeningOn(8090); + } + + @After + public void tearDown() { + closeJadler(); + } + + @Test + public void testParseFeatureId() { + String featureId = parseFeatureId(jsonCollectionItem); + assertThat(featureId, is("DENW19AL0000geMFFL")); + } + + @Test + public void testParseAsDate() { + String timeStamp = "2017-03-04T01:02:33Z"; + ZonedDateTime dateTime = parseAsDate(timeStamp); + + assertThat(dateTime.getYear(), is(2017)); + assertThat(dateTime.getMonth(), is(Month.MARCH)); + assertThat(dateTime.getDayOfMonth(), is(4)); + assertThat(dateTime.getHour(), is(1)); + assertThat(dateTime.getMinute(), is(2)); + assertThat(dateTime.getSecond(), is(33)); + } + + @Test + public void testFormatDate() { + String dateTime = "2017-03-04T01:02:33Z"; + ZonedDateTime dateTimeAsZonedDateTime = parseAsDate(dateTime); + + String dateTimeAsString = formatDate(dateTimeAsZonedDateTime); + assertThat(dateTimeAsString, is(dateTime)); + + String dateAsString = formatDate(dateTimeAsZonedDateTime.toLocalDate()); + assertThat(dateAsString, is("2017-03-04")); + } + + @Test + public void testFormatDateRange() { + String beginDateTime = "2017-03-04T01:02:33Z"; + ZonedDateTime begin = parseAsDate(beginDateTime); + String endDateTime = "2018-03-04T01:02:33Z"; + ZonedDateTime end = parseAsDate(endDateTime); + + String asString = formatDateRange(begin, end); + assertThat(asString, is("2017-03-04T01:02:33Z/2018-03-04T01:02:33Z")); + } + + @Test + public void testFormatDateRangeWithDuration() { + String beginDate = "2017-03-04"; + LocalDate begin = LocalDate.parse(beginDate); + String endDate = "2017-04-06"; + LocalDate end = LocalDate.parse(endDate); + + String asString = formatDateRangeWithDuration(begin, end); + assertThat(asString, is("2017-03-04/P1M2D")); + } + + @Test + public void testTemporalExtent() { + List collections = jsonCollection.getList("collections"); + TemporalExtent extent = parseTemporalExtent((Map) collections.get(0)); + + ZonedDateTime begin = extent.getBegin(); + ZonedDateTime end = extent.getEnd(); + assertThat(begin, is(ZonedDateTime.parse("2017-01-01T00:00:00Z"))); + assertThat(end, is(ZonedDateTime.parse("2017-12-31T23:59:59Z"))); + } + + @Test + public void testParseSpatialExtent() { + List collections = jsonCollection.getList("collections"); + BBox extent = parseSpatialExtent((Map) collections.get(0)); + + String queryParam = extent.asQueryParameter(); + String[] queryParams = queryParam.split(","); + assertThat(queryParams.length, is(4)); + assertEquals(Double.parseDouble(queryParams[0]), 5.61272621360749, 0.00001); + assertEquals(Double.parseDouble(queryParams[1]), 50.2373512077239, 0.00001); + assertEquals(Double.parseDouble(queryParams[2]), 9.58963433710139, 0.00001); + assertEquals(Double.parseDouble(queryParams[3]), 52.5286304537795, 0.00001); + } + + @Test + public void testParseSpatialExtent_WithIntegerValues() { + List collections = jsonCollection.getList("collections"); + BBox extent = parseSpatialExtent((Map) collections.get(1)); + + String queryParam = extent.asQueryParameter(); + String[] queryParams = queryParam.split(","); + assertThat(queryParams.length, is(4)); + assertThat(Double.parseDouble(queryParams[0]), is(5d)); + assertThat(Double.parseDouble(queryParams[1]), is(50d)); + assertThat(Double.parseDouble(queryParams[2]), is(9d)); + assertThat(Double.parseDouble(queryParams[3]), is(52d)); + } + + @Test + public void testFindLinkToItself() { + List> links = jsonCollection.getList("links"); + Map linkToItself = findLinkByRel(links, "self"); + + assertThat(linkToItself.get("href"), is("http://localhost:8090/rest/services/kataster/collections/?f=json")); + assertThat(linkToItself.get("rel"), is("self")); + assertThat(linkToItself.get("type"), is("application/json")); + assertThat(linkToItself.get("title"), is("this document")); + } + + @Test + public void testLinkIncludesRelAndType() { + List> links = jsonCollection.getList("links"); + Map linkToItself = findLinkByRel(links, "self"); + boolean includesRelAndType = linkIncludesRelAndType(linkToItself); + + assertThat(includesRelAndType, is(true)); + } + + @Test + public void testFindLinksWithoutRelOrType() { + List> links = jsonCollection.getList("links"); + Set rels = new HashSet<>(); + rels.add("self"); + rels.add("alternate"); + List linksWithoutRelOrType = findLinksWithoutRelOrType(links, rels); + + assertThat(linksWithoutRelOrType.size(), is(0)); + } + + @Test + public void testFindLinksWithSupportedMediaTypeByRel() { + List> links = jsonCollection.getList("links"); + List mediaTypes = Arrays.asList("text/html", "application/json"); + List> linksWithMediaTypes = findLinksWithSupportedMediaTypeByRel(links, mediaTypes, + "alternate"); + + assertThat(linksWithMediaTypes.size(), is(1)); + } + + @Test + public void testHasProperty_true() { + boolean hasProperty = hasProperty("links", jsonCollection); + assertThat(hasProperty, is(true)); + } + + @Test + public void testHasProperty_false() { + boolean hasProperty = hasProperty("doesNotExist", jsonCollection); + assertThat(hasProperty, is(false)); + } + + @Test + public void testHasAtLeastOneSpatialFeatureCollection() { + boolean hasSpatialFeatureCollection = hasAtLeastOneSpatialFeatureCollection(jsonCollection); + assertThat(hasSpatialFeatureCollection, is(true)); + } + + @Test + public void testFindFeaturesUrlForGeoJson() throws Exception { + InputStream collectionJson = JsonUtilsTest.class + .getResourceAsStream("../conformance/core/collections/collection-flurstueck.json"); + JsonPath flurstueckCollection = new JsonPath(collectionJson); + URI rootUri = new URI("http://localhost:8090/rest/services"); + String featuresUrlForGeoJson = findFeaturesUrlForGeoJson(rootUri, flurstueckCollection); + + assertThat(featuresUrlForGeoJson, + is("http://localhost:8090/rest/services/kataster/collections/flurstueck/items?f=json")); + } + + @Test + public void testFindFeatureUrlForGeoJson() throws Exception { + Map link = createItemsLinks("https://test.service.de/ogcapi/datasets/kitaeinrichtung/items"); + JsonPath collection = Mockito.mock(JsonPath.class); + when(collection.get("links")).thenReturn(Collections.singletonList(link)); + URI rootUri = new URI("http://localhost:8090/rest/services"); + String featuresUrlForGeoJson = findFeatureUrlForGeoJson(rootUri, collection, "testId"); + + assertThat(featuresUrlForGeoJson, is("https://test.service.de/ogcapi/datasets/kitaeinrichtung/items/testId")); + } + + @Test + public void testFindFeatureUrlForGeoJson_withParam() throws Exception { + Map link = createItemsLinks( + "https://test.service.de/ogcapi/datasets/kitaeinrichtung/items?f=json"); + JsonPath collection = Mockito.mock(JsonPath.class); + when(collection.get("links")).thenReturn(Collections.singletonList(link)); + URI rootUri = new URI("http://localhost:8090/rest/services"); + String featuresUrlForGeoJson = findFeatureUrlForGeoJson(rootUri, collection, "testId"); + + assertThat(featuresUrlForGeoJson, is("https://test.service.de/ogcapi/datasets/kitaeinrichtung/items/testId")); + } + + @Test + public void testFindFeatureUrlForGeoJson_withExtension() throws Exception { + Map link = createItemsLinks( + "https://test.service.de/ogcapi/datasets/kitaeinrichtung/items.json"); + JsonPath collection = Mockito.mock(JsonPath.class); + when(collection.get("links")).thenReturn(Collections.singletonList(link)); + URI rootUri = new URI("http://localhost:8090/rest/services"); + String featuresUrlForGeoJson = findFeatureUrlForGeoJson(rootUri, collection, "testId"); + + assertThat(featuresUrlForGeoJson, + is("https://test.service.de/ogcapi/datasets/kitaeinrichtung/items/testId.json")); + } + + @Test + public void testCollectNumberOfAllReturnedFeatures() throws Exception { + prepareJadler(); + URL json = new URL("http://localhost:8090/collections/lakes/items"); + JsonPath jsonPath = new JsonPath(json); + + int numberOfAllFeatures = collectNumberOfAllReturnedFeatures(jsonPath, -1); + + assertThat(numberOfAllFeatures, is(25)); + } + + @Test + public void testParseFeatureGeometry() throws Exception { + List> features = jsonCollectionItem.getList("features"); + Map firstFeature = features.get(0); + Geometry geometry = parseFeatureGeometry(firstFeature, DEFAULT_CRS); + assertThat(geometry, instanceOf(MultiPolygon.class)); + } + + private void prepareJadler() { + InputStream item1_10 = getClass().getResourceAsStream("items_1-10.json"); + onRequest().havingParameter("startindex", nullValue()).respond().withBody(item1_10); + + InputStream item11_20 = getClass().getResourceAsStream("items_11-20.json"); + onRequest().havingParameterEqualTo("startindex", "10").respond().withBody(item11_20); + + InputStream item21_30 = getClass().getResourceAsStream("items_21-30.json"); + onRequest().havingParameterEqualTo("startindex", "20").respond().withBody(item21_30); + + InputStream item31_40 = getClass().getResourceAsStream("items_31-40.json"); + onRequest().havingParameter("startindex", allOf(notNullValue(), not(hasItems("10")), not(hasItems("20")))) + .respond() + .withBody(item31_40); + } + + private Map createItemsLinks(String href) { + Map link = new HashMap<>(); + link.put("rel", "items"); + link.put("type", GEOJSON_MIME_TYPE); + link.put("href", href); + return link; + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/util/OgcNameValidatorTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/util/OgcNameValidatorTest.java index a0708918..dca65db6 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/util/OgcNameValidatorTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/util/OgcNameValidatorTest.java @@ -10,40 +10,40 @@ */ public class OgcNameValidatorTest { - @Test - public void testIsValid_validUrn() { - OgcNameValidator ogcNameValidator = new OgcNameValidator(); - assertThat( ogcNameValidator.isValid( "urn:ogc:def:crs:EPSG::3163" ), is( true ) ); - } - - @Test - public void testIsValid_validUrnWitVersion() { - OgcNameValidator ogcNameValidator = new OgcNameValidator(); - assertThat( ogcNameValidator.isValid( "urn:ogc:def:crs:OGC:1.3:CRS84" ), is( true ) ); - } - - @Test - public void testIsValid_validHttp() { - OgcNameValidator ogcNameValidator = new OgcNameValidator(); - assertThat( ogcNameValidator.isValid( "http://www.opengis.net/def/crs/EPSG/0/3163" ), is( true ) ); - } - - @Test - public void testIsValid_invalidUrn() { - OgcNameValidator ogcNameValidator = new OgcNameValidator(); - assertThat( ogcNameValidator.isValid( "urn:example:1/406/47452/2" ), is( false ) ); - } - - @Test - public void testIsValid_null() { - OgcNameValidator ogcNameValidator = new OgcNameValidator(); - assertThat( ogcNameValidator.isValid( null ), is( false ) ); - } - - @Test - public void testIsValid_empty() { - OgcNameValidator ogcNameValidator = new OgcNameValidator(); - assertThat( ogcNameValidator.isValid( "" ), is( false ) ); - } + @Test + public void testIsValid_validUrn() { + OgcNameValidator ogcNameValidator = new OgcNameValidator(); + assertThat(ogcNameValidator.isValid("urn:ogc:def:crs:EPSG::3163"), is(true)); + } + + @Test + public void testIsValid_validUrnWitVersion() { + OgcNameValidator ogcNameValidator = new OgcNameValidator(); + assertThat(ogcNameValidator.isValid("urn:ogc:def:crs:OGC:1.3:CRS84"), is(true)); + } + + @Test + public void testIsValid_validHttp() { + OgcNameValidator ogcNameValidator = new OgcNameValidator(); + assertThat(ogcNameValidator.isValid("http://www.opengis.net/def/crs/EPSG/0/3163"), is(true)); + } + + @Test + public void testIsValid_invalidUrn() { + OgcNameValidator ogcNameValidator = new OgcNameValidator(); + assertThat(ogcNameValidator.isValid("urn:example:1/406/47452/2"), is(false)); + } + + @Test + public void testIsValid_null() { + OgcNameValidator ogcNameValidator = new OgcNameValidator(); + assertThat(ogcNameValidator.isValid(null), is(false)); + } + + @Test + public void testIsValid_empty() { + OgcNameValidator ogcNameValidator = new OgcNameValidator(); + assertThat(ogcNameValidator.isValid(""), is(false)); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/util/URIUtilsIT.java b/src/test/java/org/opengis/cite/ogcapifeatures10/util/URIUtilsIT.java index 4bbeb9cc..6410e790 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/util/URIUtilsIT.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/util/URIUtilsIT.java @@ -12,13 +12,12 @@ */ public class URIUtilsIT { - @Test - public void resolveHttpUriAsFile() - throws IOException { - URI uriRef = URI.create( "http://www.w3schools.com/xml/note.xml" ); - File file = URIUtils.dereferenceURI( uriRef ); - Assert.assertNotNull( file ); - Assert.assertTrue( "File should not be empty", file.length() > 0 ); - } + @Test + public void resolveHttpUriAsFile() throws IOException { + URI uriRef = URI.create("http://www.w3schools.com/xml/note.xml"); + File file = URIUtils.dereferenceURI(uriRef); + Assert.assertNotNull(file); + Assert.assertTrue("File should not be empty", file.length() > 0); + } } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/util/UrnValidatorTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/util/UrnValidatorTest.java index 57c8c3ce..be2a57d3 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/util/UrnValidatorTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/util/UrnValidatorTest.java @@ -10,27 +10,28 @@ */ public class UrnValidatorTest { - @Test - public void testIsValid_validUrn() { - UrnValidator urnValidator = new UrnValidator(); - assertThat( urnValidator.isValid( "urn:example:1/406/47452/2" ), is( true ) ); - } - - @Test - public void testIsValid_invalidUrn() { - UrnValidator urnValidator = new UrnValidator(); - assertThat( urnValidator.isValid( "urn" ), is( false ) ); - } - - @Test - public void testIsValid_null() { - UrnValidator urnValidator = new UrnValidator(); - assertThat( urnValidator.isValid( null ), is( false ) ); - } - - @Test - public void testIsValid_empty() { - UrnValidator urnValidator = new UrnValidator(); - assertThat( urnValidator.isValid( "" ), is( false ) ); - } + @Test + public void testIsValid_validUrn() { + UrnValidator urnValidator = new UrnValidator(); + assertThat(urnValidator.isValid("urn:example:1/406/47452/2"), is(true)); + } + + @Test + public void testIsValid_invalidUrn() { + UrnValidator urnValidator = new UrnValidator(); + assertThat(urnValidator.isValid("urn"), is(false)); + } + + @Test + public void testIsValid_null() { + UrnValidator urnValidator = new UrnValidator(); + assertThat(urnValidator.isValid(null), is(false)); + } + + @Test + public void testIsValid_empty() { + UrnValidator urnValidator = new UrnValidator(); + assertThat(urnValidator.isValid(""), is(false)); + } + } diff --git a/src/test/java/org/opengis/cite/ogcapifeatures10/util/XMLUtilsTest.java b/src/test/java/org/opengis/cite/ogcapifeatures10/util/XMLUtilsTest.java index d459775f..1a35f79d 100644 --- a/src/test/java/org/opengis/cite/ogcapifeatures10/util/XMLUtilsTest.java +++ b/src/test/java/org/opengis/cite/ogcapifeatures10/util/XMLUtilsTest.java @@ -17,22 +17,20 @@ */ public class XMLUtilsTest { - private static DocumentBuilder docBuilder; - - @BeforeClass - public static void setUpClass() - throws Exception { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware( true ); - docBuilder = dbf.newDocumentBuilder(); - } - - @Test - public void writeDocToString() - throws SAXException, IOException { - Document doc = docBuilder.parse( this.getClass().getResourceAsStream( "../landingPage.xml" ) ); - String content = XMLUtils.writeNodeToString( doc ); - assertTrue( "String should start with '