org.opengis.cite.ogcapitiles10.openapi3.OpenApiUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ets-ogcapi-tiles10 Show documentation
Show all versions of ets-ogcapi-tiles10 Show documentation
Describe purpose of test suite.
package org.opengis.cite.ogcapitiles10.openapi3;
import static org.opengis.cite.ogcapitiles10.openapi3.OpenApiUtils.PATH.COLLECTIONS;
import static org.opengis.cite.ogcapitiles10.openapi3.OpenApiUtils.PATH.CONFORMANCE;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import com.reprezen.kaizen.oasparser.model3.MediaType;
import com.reprezen.kaizen.oasparser.model3.OpenApi3;
import com.reprezen.kaizen.oasparser.model3.Operation;
import com.reprezen.kaizen.oasparser.model3.Parameter;
import com.reprezen.kaizen.oasparser.model3.Path;
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;
/**
* @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("/");
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("/");
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() <= 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(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("/");
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, String collectionName) {
String requestedPath = createCollectionPath(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, String collectionName,
String queryParam) {
String requestedPath = createCollectionPath(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(String collectionName) {
StringBuilder requestedPath = new StringBuilder();
requestedPath.append("/");
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 = "/" + 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
© 2015 - 2024 Weber Informatics LLC | Privacy Policy