Added monadic test containers for Certification. Cleaned up code.

This commit is contained in:
Joshua Darnell 2020-03-25 23:34:13 -07:00
parent 2a27c4ab0e
commit a598261d0d
13 changed files with 1046 additions and 730 deletions

Binary file not shown.

View File

@ -29,10 +29,10 @@ import java.util.List;
public class OAuth2HttpClientFactory extends AbstractHttpClientFactory { public class OAuth2HttpClientFactory extends AbstractHttpClientFactory {
final static String EXPIRES_IN = "expires_in";
final static String ACCESS_TOKEN = "access_token";
private static final Logger LOG = LogManager.getLogger(OAuth2HttpClientFactory.class); private static final Logger LOG = LogManager.getLogger(OAuth2HttpClientFactory.class);
HttpClientConnectionManager connectionManager = null; HttpClientConnectionManager connectionManager = null;
private String clientId; private String clientId;
private String clientSecret; private String clientSecret;
private String tokenUri; private String tokenUri;
@ -40,15 +40,13 @@ public class OAuth2HttpClientFactory extends AbstractHttpClientFactory {
private String accessToken; private String accessToken;
private Integer expiresIn; private Integer expiresIn;
final static String EXPIRES_IN = "expires_in";
final static String ACCESS_TOKEN = "access_token";
/** /**
* Creates an OAuth2 client for making HTTP requests using Client Credentials * Creates an OAuth2 client for making HTTP requests using Client Credentials
* @param clientId the client Id of the consumer *
* @param clientId the client Id of the consumer
* @param clientSecret the client secret of the consumer * @param clientSecret the client secret of the consumer
* @param tokenUri the token uri of the server to connect to * @param tokenUri the token uri of the server to connect to
* @param scope (optional) scope * @param scope (optional) scope
*/ */
public OAuth2HttpClientFactory(String clientId, String clientSecret, String tokenUri, String scope) { public OAuth2HttpClientFactory(String clientId, String clientSecret, String tokenUri, String scope) {
this.clientId = clientId; this.clientId = clientId;
@ -96,7 +94,7 @@ public class OAuth2HttpClientFactory extends AbstractHttpClientFactory {
if (responseData.get(ACCESS_TOKEN) != null) { if (responseData.get(ACCESS_TOKEN) != null) {
accessToken = responseData.get(ACCESS_TOKEN).asText(); accessToken = responseData.get(ACCESS_TOKEN).asText();
} }
assert(accessToken != null); assert (accessToken != null);
if (responseData.get(EXPIRES_IN) != null) { if (responseData.get(EXPIRES_IN) != null) {
expiresIn = responseData.get(EXPIRES_IN).asInt(); expiresIn = responseData.get(EXPIRES_IN).asInt();
@ -110,7 +108,7 @@ public class OAuth2HttpClientFactory extends AbstractHttpClientFactory {
@Override @Override
public CloseableHttpClient create(HttpMethod method, URI uri) { public CloseableHttpClient create(HttpMethod method, URI uri) {
assert(accessToken != null); assert (accessToken != null);
BasicHeader authHeader = new BasicHeader("Authorization", "Bearer " + accessToken); BasicHeader authHeader = new BasicHeader("Authorization", "Bearer " + accessToken);
List<Header> headers = new ArrayList<>(); List<Header> headers = new ArrayList<>();
@ -126,7 +124,7 @@ public class OAuth2HttpClientFactory extends AbstractHttpClientFactory {
@Override @Override
public void close(HttpClient httpClient) { public void close(HttpClient httpClient) {
try { try {
connectionManager.shutdown(); if (connectionManager != null) connectionManager.shutdown();
} catch (Exception ex) { } catch (Exception ex) {
LOG.error(ex.toString()); LOG.error(ex.toString());
} }

View File

@ -20,14 +20,13 @@ import java.util.List;
* Extends AbstractHttpClientFactory with one that can accept tokens passed in to make requests. * Extends AbstractHttpClientFactory with one that can accept tokens passed in to make requests.
*/ */
public class TokenHttpClientFactory extends AbstractHttpClientFactory { public class TokenHttpClientFactory extends AbstractHttpClientFactory {
String token;
private static final Logger LOG = LogManager.getLogger(TokenHttpClientFactory.class); private static final Logger LOG = LogManager.getLogger(TokenHttpClientFactory.class);
String token;
HttpClientConnectionManager connectionManager = null; HttpClientConnectionManager connectionManager = null;
/** /**
* Constructor for use with tokens. * Constructor for use with tokens.
*
* @param token the token to be used for server requests. * @param token the token to be used for server requests.
*/ */
public TokenHttpClientFactory(String token) { public TokenHttpClientFactory(String token) {

View File

@ -7,8 +7,8 @@ Feature: Web API Server 1.0.2 Certification
Background: Background:
Given a RESOScript file was provided Given a RESOScript file was provided
And Client Settings and Parameters were read from the file And Client Settings and Parameters were read from the file
And an OData client was successfully created from the given RESOScript And a test environment was successfully created from the given RESOScript
And the OData client uses authorization_code or client_credentials for authentication And the test environment uses an authorization_code or client_credentials for authentication
####################################### #######################################
@ -16,12 +16,13 @@ Feature: Web API Server 1.0.2 Certification
####################################### #######################################
@REQ-WA103-END3 @core @2.4.1 @core-endorsement @metadata @REQ-WA103-END3 @core @2.4.1 @core-endorsement @metadata
Scenario: REQ-WA103-END3 - Request and Validate Server Metadata Scenario: REQ-WA103-END3 - Request and Validate Server Metadata
When a GET request is made to the resolved Url in "REQ-WA103-END3" When XML Metadata are requested from the service root in "ClientSettings_WebAPIURI"
Then the server responds with a status code of 200 Then the server responds with a status code of 200
And the response is valid XML
And the XML metadata returned by the server are valid And the XML metadata returned by the server are valid
And a default entity container exists for the service root in "ClientSettings_WebAPIURI" And Edm metadata are requested from the service root in "ClientSettings_WebAPIURI"
Then the server responds with a status code of 200
And the Edm metadata returned by the server are valid And the Edm metadata returned by the server are valid
And the metadata contains a valid service document
And the metadata contains the "Parameter_EndpointResource" resource And the metadata contains the "Parameter_EndpointResource" resource
And the given "Parameter_EndpointResource" resource exists within "Parameter_DD17_WellKnownResourceList" And the given "Parameter_EndpointResource" resource exists within "Parameter_DD17_WellKnownResourceList"
And the metadata contains at least one resource from "Parameter_WebAPI102_RequiredResourceList" And the metadata contains at least one resource from "Parameter_WebAPI102_RequiredResourceList"

View File

@ -12,12 +12,9 @@ import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.olingo.client.api.communication.ODataClientErrorException; import org.apache.olingo.client.api.communication.ODataClientErrorException;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.client.api.data.ResWrap; import org.apache.olingo.client.api.data.ResWrap;
import org.apache.olingo.client.api.domain.ClientEntitySet; import org.apache.olingo.client.api.domain.ClientEntitySet;
import org.apache.olingo.client.api.edm.xml.XMLMetadata;
import org.apache.olingo.commons.api.data.EntityCollection; import org.apache.olingo.commons.api.data.EntityCollection;
import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer; import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer;
import org.apache.olingo.commons.api.edm.provider.CsdlNavigationProperty; import org.apache.olingo.commons.api.edm.provider.CsdlNavigationProperty;
@ -25,10 +22,9 @@ import org.apache.olingo.commons.api.edm.provider.CsdlProperty;
import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.format.ContentType;
import org.reso.commander.Commander; import org.reso.commander.Commander;
import org.reso.commander.TestUtils; import org.reso.commander.TestUtils;
import org.reso.models.ClientSettings; import org.reso.commander.certfication.containers.WebApiTestContainer;
import org.reso.models.Settings; import org.reso.models.Settings;
import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.sql.Time; import java.sql.Time;
@ -54,85 +50,49 @@ public class WebAPIServer_1_0_2 implements En {
private static final String SHOW_RESPONSES = "showResponses"; private static final String SHOW_RESPONSES = "showResponses";
private static final boolean showResponses = Boolean.parseBoolean(System.getProperty(SHOW_RESPONSES)); private static final boolean showResponses = Boolean.parseBoolean(System.getProperty(SHOW_RESPONSES));
private static Settings settings;
//container to hold retrieved metadata for later comparisons
private static AtomicReference<XMLMetadata> xmlMetadata = new AtomicReference<>();
private static AtomicReference<Edm> edm = new AtomicReference<>();
private String serviceRoot, bearerToken, clientId, clientSecret, authorizationUri, tokenUri, redirectUri, scope;
private String pathToRESOScript;
/* /*
* Used to store a static instance of the TestContainer class * Used to store a static instance of the WebApiTestContainer class
*/ */
private static AtomicReference<TestContainer> container = new AtomicReference<>(new TestContainer()); private static final AtomicReference<WebApiTestContainer> container = new AtomicReference<>(new WebApiTestContainer());
/** /**
* Entry point to the Web API Server tests * Entry point to the Web API Server tests
*/ */
public WebAPIServer_1_0_2() { public WebAPIServer_1_0_2() {
/* /*
* Background * Background
*/ */
Given("^a RESOScript file was provided$", () -> { Given("^a RESOScript file was provided$", () -> {
if (pathToRESOScript == null) { if (getTestContainer().getPathToRESOScript() == null) {
pathToRESOScript = System.getProperty("pathToRESOScript"); getTestContainer().setPathToRESOScript(System.getProperty("pathToRESOScript"));
} }
assertNotNull("ERROR: pathToRESOScript must be present in command arguments, see README", pathToRESOScript); assertNotNull("ERROR: pathToRESOScript must be present in command arguments, see README", getTestContainer().getPathToRESOScript());
LOG.info("Using RESOScript: " + pathToRESOScript); LOG.info("Using RESOScript: " + getTestContainer().getPathToRESOScript());
}); });
And("^Client Settings and Parameters were read from the file$", () -> { And("^Client Settings and Parameters were read from the file$", () -> {
if (settings == null) { if (getTestContainer().getSettings() == null) {
settings = Settings.loadFromRESOScript(new File(System.getProperty("pathToRESOScript"))); getTestContainer().setSettings(Settings.loadFromRESOScript(new File(System.getProperty("pathToRESOScript"))));
} }
assertNotNull("ERROR: Settings could not be loaded.", settings); assertNotNull("ERROR: Settings could not be loaded.", getTestContainer().getSettings());
LOG.info("RESOScript loaded successfully!"); LOG.info("RESOScript loaded successfully!");
}); });
Given("^an OData client was successfully created from the given RESOScript$", () -> {
serviceRoot = settings.getClientSettings().get(ClientSettings.WEB_API_URI);
//TODO: add base64 un-encode when applicable Given("^a test environment was successfully created from the given RESOScript$", () -> {
bearerToken = settings.getClientSettings().get(ClientSettings.BEARER_TOKEN); getTestContainer().initialize();
if (bearerToken != null && bearerToken.length() > 0) {
LOG.info("Bearer token loaded... first 4 characters: " + bearerToken.substring(0, 4));
}
clientId = settings.getClientSettings().get(ClientSettings.CLIENT_IDENTIFICATION);
clientSecret = settings.getClientSettings().get(ClientSettings.CLIENT_SECRET);
authorizationUri = settings.getClientSettings().get(ClientSettings.AUTHORIZATION_URI);
tokenUri = settings.getClientSettings().get(ClientSettings.TOKEN_URI);
redirectUri = settings.getClientSettings().get(ClientSettings.REDIRECT_URI);
scope = settings.getClientSettings().get(ClientSettings.CLIENT_SCOPE);
LOG.info("Service root is: " + serviceRoot);
if (container.get().commander.get() == null) {
//create Commander instance
container.get().commander.set(new Commander.Builder()
.clientId(clientId)
.clientSecret(clientSecret)
.tokenUri(tokenUri)
.scope(scope)
.serviceRoot(serviceRoot)
.bearerToken(bearerToken)
.useEdmEnabledClient(true)
.build());
}
}); });
/* /*
* Ensures that the client either uses Authorization Codes or Client Credentials * Ensures that the client either uses Authorization Codes or Client Credentials
*/ */
And("^the OData client uses authorization_code or client_credentials for authentication$", () -> { And("^the test environment uses an authorization_code or client_credentials for authentication$", () -> {
assertNotNull(container.get().commander.get()); assertNotNull(getTestContainer().getCommander());
assertTrue("ERROR: Commander must either have a valid Authorization Code or Client Credentials configuration.", assertTrue("ERROR: Commander must either have a valid Authorization Code or Client Credentials configuration.",
container.get().commander.get().isTokenClient() || (container.get().commander.get().isOAuthClient() && container.get().commander.get().hasValidAuthConfig())); getTestContainer().getCommander().isTokenClient() || (getTestContainer().getCommander().isOAuthClient() && getTestContainer().getCommander().hasValidAuthConfig()));
if (container.get().commander.get().isTokenClient()) { if (getTestContainer().getCommander().isTokenClient()) {
LOG.info("Authentication Type: authorization_code"); LOG.info("Authentication Type: authorization_code");
} else if (container.get().commander.get().isOAuthClient()) { } else if (getTestContainer().getCommander().isOAuthClient()) {
LOG.info("Authentication Type: client_credentials"); LOG.info("Authentication Type: client_credentials");
} }
}); });
@ -141,7 +101,7 @@ public class WebAPIServer_1_0_2 implements En {
* REQ-WA103-END2 - validate DataSystem endpoint, if present. * REQ-WA103-END2 - validate DataSystem endpoint, if present.
*/ */
And("^the results match the expected DataSystem JSON schema$", () -> { And("^the results match the expected DataSystem JSON schema$", () -> {
if (container.get().responseCode.get() == HttpStatus.SC_OK && container.get().responseData.get() != null) { if (getTestContainer().getResponseCode() == HttpStatus.SC_OK && getTestContainer().getResponseData() != null) {
try { try {
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(); JsonSchemaFactory factory = JsonSchemaFactory.getInstance();
InputStream is = Thread.currentThread().getContextClassLoader() InputStream is = Thread.currentThread().getContextClassLoader()
@ -149,7 +109,7 @@ public class WebAPIServer_1_0_2 implements En {
JsonSchema schema = factory.getSchema(is); JsonSchema schema = factory.getSchema(is);
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(container.get().responseData.get()); JsonNode node = mapper.readTree(getTestContainer().getResponseData());
if (node.findPath(JSON_VALUE_PATH).size() > 0) { if (node.findPath(JSON_VALUE_PATH).size() > 0) {
Set<ValidationMessage> errors = schema.validate(node); Set<ValidationMessage> errors = schema.validate(node);
@ -161,7 +121,7 @@ public class WebAPIServer_1_0_2 implements En {
LOG.info("DataSystem response matches reference schema!"); LOG.info("DataSystem response matches reference schema!");
} }
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
} }
}); });
@ -170,46 +130,60 @@ public class WebAPIServer_1_0_2 implements En {
* Edm Metadata Validator * Edm Metadata Validator
*/ */
And("^the Edm metadata returned by the server are valid$", () -> { And("^the Edm metadata returned by the server are valid$", () -> {
assertNotNull("ERROR: No Entity Data Model (Edm) Exists!", edm.get()); assertNotNull("ERROR: No Entity Data Model (Edm) Exists!", getTestContainer().getEdm());
try { try {
boolean isValid = container.get().commander.get().validateMetadata(edm.get()); boolean isValid = getTestContainer().getCommander().validateMetadata(getTestContainer().getEdm());
LOG.info("Edm Metadata is " + (isValid ? "valid" : "invalid") + "!"); LOG.info("Edm Metadata is " + (isValid ? "valid" : "invalid") + "!");
assertTrue("Edm Metadata at the given service root is not valid! " + serviceRoot, isValid); assertTrue("Edm Metadata at the given service root is not valid! " + getTestContainer().getServiceRoot(), isValid);
} catch (Exception ex) { } catch (Exception ex) {
fail("ERROR: could not validate Edm Metadata!\n" + ex.getMessage()); fail("ERROR: could not validate Edm Metadata!\n" + ex.toString());
} }
}); });
/* /*
* XMLMetadata Validator * XML Metadata Validator
*/ */
And("^the XML metadata returned by the server are valid$", () -> { And("^the XML metadata returned by the server are valid$", () -> {
assertNotNull("ERROR: No Response Data exists to convert to XML Metadata!", container.get().responseData.get()); assertNotNull("ERROR: XML Metadata (EDMX) Exists!", getTestContainer().getXMLMetadata());
try { try {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(container.get().responseData.get().getBytes()); boolean isValid = getTestContainer().getCommander().validateMetadata(getTestContainer().getXMLMetadata());
xmlMetadata.set(container.get().commander.get().getClient().getDeserializer(ContentType.APPLICATION_XML).toMetadata(byteArrayInputStream));
if (showResponses) LOG.info("XML Metadata is \n" + container.get().responseData.get());
boolean isValid = container.get().commander.get().validateMetadata(xmlMetadata.get());
LOG.info("XML Metadata is " + (isValid ? "valid" : "invalid") + "!"); LOG.info("XML Metadata is " + (isValid ? "valid" : "invalid") + "!");
assertTrue("ERROR: XML Metadata at the given service root is not valid! " + serviceRoot, isValid); assertTrue("XML Metadata at the given service root is not valid! " + getTestContainer().getServiceRoot(), isValid);
} catch (Exception ex) { } catch (Exception ex) {
fail("ERROR: could not validate XML Metadata!\n" + ex.getMessage()); fail("ERROR: could not validate XML Metadata!\n" + ex.toString());
} }
}); });
// /*
// * XMLMetadata Validator
// */
// And("^the XML metadata returned by the server are valid$", () -> {
// assertNotNull("ERROR: No Response Data exists to convert to XML Metadata!", getTestContainer().responseData.get());
//
// try {
// ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(getTestContainer().responseData.get().getBytes());
// xmlMetadata.set(getTestContainer().commander.get().getClient().getDeserializer(ContentType.APPLICATION_XML).toMetadata(byteArrayInputStream));
//
// if (showResponses) LOG.info("XML Metadata is: \n" + getTestContainer().responseData.get());
//
// boolean isValid = getTestContainer().commander.get().validateMetadata(getTestContainer().getXmlMetadata());
// LOG.info("XML Metadata is " + (isValid ? "valid" : "invalid") + "!");
// assertTrue("ERROR: XML Metadata at the given service root is not valid! " + serviceRoot, isValid);
// } catch (Exception ex) {
// fail("ERROR: could not validate XML Metadata!\n" + ex.toString());
// }
// });
/* /*
* REQ-WA103-QR1 * REQ-WA103-QR1
*/ */
And("^the provided \"([^\"]*)\" is returned in \"([^\"]*)\"$", (String parameterUniqueIdValue, String parameterUniqueId) -> { And("^the provided \"([^\"]*)\" is returned in \"([^\"]*)\"$", (String parameterUniqueIdValue, String parameterUniqueId) -> {
try { try {
String expectedValueAsString = Settings.resolveParametersString(parameterUniqueIdValue, settings), resolvedValueAsString = null; String expectedValueAsString = Settings.resolveParametersString(parameterUniqueIdValue, getTestContainer().getSettings());
Object resolvedValue = from(container.get().responseData.get()).get(Settings.resolveParametersString(parameterUniqueId, settings)); Object resolvedValue = from(getTestContainer().getResponseData()).get(Settings.resolveParametersString(parameterUniqueId, getTestContainer().getSettings()));
//both of the inputs should be present //both of the inputs should be present
assertNotNull(expectedValueAsString); assertNotNull(expectedValueAsString);
@ -228,7 +202,7 @@ public class WebAPIServer_1_0_2 implements En {
assertEquals("ERROR: the given String value is not equal to the value found on the server!", expectedValueAsString, resolvedValue.toString()); assertEquals("ERROR: the given String value is not equal to the value found on the server!", expectedValueAsString, resolvedValue.toString());
} }
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -238,11 +212,11 @@ public class WebAPIServer_1_0_2 implements En {
And("^data are present in fields contained within \"([^\"]*)\"$", (String parameterSelectList) -> { And("^data are present in fields contained within \"([^\"]*)\"$", (String parameterSelectList) -> {
try { try {
AtomicInteger numFieldsWithData = new AtomicInteger(); AtomicInteger numFieldsWithData = new AtomicInteger();
List<String> fieldList = new ArrayList<>(Arrays.asList(Settings.resolveParametersString(parameterSelectList, settings).split(FIELD_SEPARATOR))); List<String> fieldList = new ArrayList<>(Arrays.asList(Settings.resolveParametersString(parameterSelectList, getTestContainer().getSettings()).split(FIELD_SEPARATOR)));
AtomicInteger numResults = new AtomicInteger(); AtomicInteger numResults = new AtomicInteger();
//iterate over the items and count the number of fields with data to determine whether there are data present //iterate over the items and count the number of fields with data to determine whether there are data present
from(container.get().responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
if (item != null) { if (item != null) {
numResults.getAndIncrement(); numResults.getAndIncrement();
fieldList.forEach(field -> { fieldList.forEach(field -> {
@ -261,9 +235,9 @@ public class WebAPIServer_1_0_2 implements En {
} else { } else {
LOG.info("Percent Fill: 0% - no fields with data found!"); LOG.info("Percent Fill: 0% - no fields with data found!");
} }
assertTrue("ERROR: no fields with data could be found from the given $select list!",numFieldsWithData.get() > 0); assertTrue("ERROR: no fields with data could be found from the given $select list!", numFieldsWithData.get() > 0);
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -274,16 +248,16 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^the results contain at most \"([^\"]*)\" records$", (String parameterTopCount) -> { And("^the results contain at most \"([^\"]*)\" records$", (String parameterTopCount) -> {
try { try {
List<String> items = from(container.get().responseData.get()).getList(JSON_VALUE_PATH); List<String> items = from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH);
AtomicInteger numResults = new AtomicInteger(items.size()); AtomicInteger numResults = new AtomicInteger(items.size());
int topCount = Integer.parseInt(Settings.resolveParametersString(parameterTopCount, settings)); int topCount = Integer.parseInt(Settings.resolveParametersString(parameterTopCount, getTestContainer().getSettings()));
LOG.info("Number of values returned: " + numResults.get() + ", top count is: " + topCount); LOG.info("Number of values returned: " + numResults.get() + ", top count is: " + topCount);
assertTrue("ERROR: results count must be greater than zero and less than " + parameterTopCount + "!", assertTrue("ERROR: results count must be greater than zero and less than " + parameterTopCount + "!",
numResults.get() > 0 && numResults.get() <= topCount); numResults.get() > 0 && numResults.get() <= topCount);
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -294,24 +268,24 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^a GET request is made to the resolved Url in \"([^\"]*)\" with \\$skip=\"([^\"]*)\"$", (String requirementId, String parameterTopCount) -> { And("^a GET request is made to the resolved Url in \"([^\"]*)\" with \\$skip=\"([^\"]*)\"$", (String requirementId, String parameterTopCount) -> {
try { try {
int skipCount = Integer.parseInt(Settings.resolveParametersString(parameterTopCount, settings)); int skipCount = Integer.parseInt(Settings.resolveParametersString(parameterTopCount, getTestContainer().getSettings()));
LOG.info("Skip count is: " + skipCount); LOG.info("Skip count is: " + skipCount);
//preserve initial response data for later comparisons //preserve initial response data for later comparisons
container.get().initialResponseData.set(container.get().responseData.get()); getTestContainer().setInitialResponseData(getTestContainer().getResponseData());
//TODO: convert to OData filter factory //TODO: convert to OData filter factory
container.get().requestUri.set(Commander.prepareURI(Settings.resolveParameters(settings.getRequestById(requirementId), settings).getUrl() getTestContainer().setRequestUri(Commander.prepareURI(Settings.resolveParameters(getTestContainer().getSettings().getRequestById(requirementId), getTestContainer().getSettings()).getUrl()
+ "&" + Commander.ODATA_QUERY_OPTIONS.SKIP +"=" + skipCount)); + "&" + Commander.ODATA_QUERY_OPTIONS.SKIP + "=" + skipCount));
container.set(executeGetRequest(container.get().requestUri.get(), container.get())); getTestContainer().executePreparedGetRequest();
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
And("^data in the \"([^\"]*)\" fields are different in the second request than in the first$", (String parameterUniqueId) -> { And("^data in the \"([^\"]*)\" fields are different in the second request than in the first$", (String parameterUniqueId) -> {
try { try {
List<POJONode> l1 = from(container.get().initialResponseData.get()).getJsonObject(JSON_VALUE_PATH); List<POJONode> l1 = from(getTestContainer().getInitialResponseData()).getJsonObject(JSON_VALUE_PATH);
List<POJONode> l2 = from(container.get().responseData.get()).getJsonObject(JSON_VALUE_PATH); List<POJONode> l2 = from(getTestContainer().getResponseData()).getJsonObject(JSON_VALUE_PATH);
int combinedCount = l1.size() + l2.size(); int combinedCount = l1.size() + l2.size();
Set<POJONode> combined = new LinkedHashSet<>(l1); Set<POJONode> combined = new LinkedHashSet<>(l1);
@ -325,7 +299,7 @@ public class WebAPIServer_1_0_2 implements En {
assertEquals("ERROR: repeated data found, expected unique data on each page!", combinedCount, combined.size()); assertEquals("ERROR: repeated data found, expected unique data on each page!", combinedCount, combined.size());
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -339,11 +313,12 @@ public class WebAPIServer_1_0_2 implements En {
When("^a GET request is made to the resolved Url in \"([^\"]*)\"$", (String requestId) -> { When("^a GET request is made to the resolved Url in \"([^\"]*)\"$", (String requestId) -> {
try { try {
//reset local state each time a get request is run //reset local state each time a get request is run
container.get().resetState(); getTestContainer().resetState();
LOG.info("Request ID: " + requestId); LOG.info("Request ID: " + requestId);
container.get().requestUri.set(Commander.prepareURI(Settings.resolveParameters(settings.getRequestById(requestId), settings).getUrl())); getTestContainer().setRequestUri(Commander.prepareURI(Settings.resolveParameters(
container.set(executeGetRequest(container.get().requestUri.get(), container.get())); getTestContainer().getSettings().getRequestById(requestId), getTestContainer().getSettings()).getUrl()));
getTestContainer().executePreparedGetRequest();
} catch (Exception ex) { } catch (Exception ex) {
LOG.debug("Exception was thrown in " + this.getClass() + ": " + ex.toString()); LOG.debug("Exception was thrown in " + this.getClass() + ": " + ex.toString());
} }
@ -354,13 +329,13 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
Then("^the server responds with a status code of (\\d+)$", (Integer assertedResponseCode) -> { Then("^the server responds with a status code of (\\d+)$", (Integer assertedResponseCode) -> {
try { try {
LOG.info("Asserted Response Code: " + assertedResponseCode + ", Server Response Code: " + container.get().responseCode); LOG.info("Asserted Response Code: " + assertedResponseCode + ", Server Response Code: " + getTestContainer().getResponseCode());
assertTrue(container.get().responseCode.get() > 0 && assertedResponseCode > 0); assertTrue(getTestContainer().getResponseCode() > 0 && assertedResponseCode > 0);
assertEquals("ERROR: asserted response code does not match the one returned from the server!", assertEquals("ERROR: asserted response code does not match the one returned from the server!",
assertedResponseCode.intValue(), container.get().responseCode.get().intValue()); assertedResponseCode.intValue(), getTestContainer().getResponseCode().intValue());
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -369,10 +344,10 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^the response is valid XML$", () -> { And("^the response is valid XML$", () -> {
try { try {
assertTrue("ERROR: invalid XML response!", Commander.validateXML(container.get().responseData.get())); assertTrue("ERROR: invalid XML response!", Commander.validateXML(getTestContainer().getXMLMetadata()));
LOG.info("Response is valid XML!"); LOG.info("Response is valid XML!");
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -381,12 +356,13 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^the response is valid JSON$", () -> { And("^the response is valid JSON$", () -> {
try { try {
assertTrue("ERROR: invalid JSON response!", TestUtils.isValidJson(container.get().responseData.get())); assertTrue("ERROR: invalid JSON response!", TestUtils.isValidJson(getTestContainer().getResponseData()));
LOG.info("Response is valid JSON!"); LOG.info("Response is valid JSON!");
if (showResponses) LOG.info("Response: " + new ObjectMapper().readTree(container.get().responseData.get()).toPrettyString()); if (showResponses)
LOG.info("Response: " + new ObjectMapper().readTree(getTestContainer().getResponseData()).toPrettyString());
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -397,13 +373,13 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
Then("^the server responds with a status code of (\\d+) if the server headers report OData version \"([^\"]*)\"$", (Integer assertedHttpResponseCode, String assertedODataVersion) -> { Then("^the server responds with a status code of (\\d+) if the server headers report OData version \"([^\"]*)\"$", (Integer assertedHttpResponseCode, String assertedODataVersion) -> {
try { try {
boolean versionsMatch = container.get().serverODataHeaderVersion.get().equals(assertedODataVersion), boolean versionsMatch = getTestContainer().getServerODataHeaderVersion().equals(assertedODataVersion),
responseCodesMatch = container.get().responseCode.get().intValue() == assertedHttpResponseCode.intValue(); responseCodesMatch = getTestContainer().getResponseCode().intValue() == assertedHttpResponseCode.intValue();
LOG.info("Asserted OData Version: " + assertedODataVersion + ", Server Version: " + container.get().serverODataHeaderVersion.get()); LOG.info("Asserted OData Version: " + assertedODataVersion + ", Server Version: " + getTestContainer().getServerODataHeaderVersion());
if (versionsMatch) { if (versionsMatch) {
LOG.info("Asserted Response Code: " + assertedHttpResponseCode + ", Response code: " + container.get().responseCode.get()); LOG.info("Asserted Response Code: " + assertedHttpResponseCode + ", Response code: " + getTestContainer().getResponseCode());
assertTrue("ERROR: asserted response code does not match the one returned from the server!", responseCodesMatch); assertTrue("ERROR: asserted response code does not match the one returned from the server!", responseCodesMatch);
} }
} catch (Exception ex) { } catch (Exception ex) {
@ -419,25 +395,24 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^Integer data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> { And("^Integer data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> {
try { try {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); String fieldName = Settings.resolveParametersString(parameterFieldName, getTestContainer().getSettings());
int assertedValue = Integer.parseInt(Settings.resolveParametersString(parameterAssertedValue, settings)); int assertedValue = Integer.parseInt(Settings.resolveParametersString(parameterAssertedValue, getTestContainer().getSettings()));
LOG.info("fieldName: " + fieldName + ", op: " + op + ", assertedValue: " + assertedValue); LOG.info("fieldName: " + fieldName + ", op: " + op + ", assertedValue: " + assertedValue);
//subsequent value comparisons are and-ed together while iterating over the list of items, so init to true //subsequent value comparisons are and-ed together while iterating over the list of items, so init to true
AtomicBoolean result = new AtomicBoolean(true); AtomicBoolean result = new AtomicBoolean(true);
AtomicReference<Integer> fieldValue = new AtomicReference<>(); AtomicReference<Integer> fieldValue = new AtomicReference<>();
//iterate through response data and ensure that with data, the statement fieldName "op" assertValue is true //iterate through response data and ensure that with data, the statement fieldName "op" assertValue is true
from(container.get().responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
fieldValue.set(Integer.parseInt(item.get(fieldName).toString())); fieldValue.set(Integer.parseInt(item.get(fieldName).toString()));
result.set(result.get() && TestUtils.compare(fieldValue.get(), op, assertedValue)); result.set(result.get() && TestUtils.compare(fieldValue.get(), op, assertedValue));
}); });
assertTrue(result.get()); assertTrue(result.get());
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -446,11 +421,11 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^the response has results$", () -> { And("^the response has results$", () -> {
try { try {
int count = from(container.get().responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).size(); int count = from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).size();
LOG.info("Results count is: " + count); LOG.info("Results count is: " + count);
assertTrue("ERROR: no results returned from the server!", count > 0); assertTrue("ERROR: no results returned from the server!", count > 0);
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -459,13 +434,13 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^the response has singleton results in \"([^\"]*)\"", (String parameterFieldName) -> { And("^the response has singleton results in \"([^\"]*)\"", (String parameterFieldName) -> {
try { try {
String value = Settings.resolveParametersString(parameterFieldName, settings); String value = Settings.resolveParametersString(parameterFieldName, getTestContainer().getSettings());
boolean isPresent = from(container.get().responseData.get()).get() != null; boolean isPresent = from(getTestContainer().getResponseData()).get() != null;
LOG.info("Response value is: " + value);
LOG.info("IsPresent: " + isPresent);
assertTrue("ERROR: singleton results not found for '" + value + "'!", isPresent); assertTrue("ERROR: singleton results not found for '" + value + "'!", isPresent);
LOG.info("Response value is: " + value);
LOG.info("Is Present: " + isPresent);
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -474,12 +449,12 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^the number of results is less than or equal to \"([^\"]*)\"$", (String limitField) -> { And("^the number of results is less than or equal to \"([^\"]*)\"$", (String limitField) -> {
try { try {
int count = from(container.get().responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).size(), int count = from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).size(),
limit = Integer.parseInt(Settings.resolveParametersString(limitField, settings)); limit = Integer.parseInt(Settings.resolveParametersString(limitField, getTestContainer().getSettings()));
LOG.info("Results count is: " + count + ", Limit is: " + limit); LOG.info("Results count is: " + count + ", Limit is: " + limit);
assertTrue("ERROR: number of results exceeds that specified in '" + limitField + "'!", count <= limit); assertTrue("ERROR: number of results exceeds that specified in '" + limitField + "'!", count <= limit);
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -488,9 +463,9 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^Integer data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String opLhs, String parameterAssertedLhsValue, String andOrOp, String opRhs, String parameterAssertedRhsValue) -> { And("^Integer data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String opLhs, String parameterAssertedLhsValue, String andOrOp, String opRhs, String parameterAssertedRhsValue) -> {
try { try {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); String fieldName = Settings.resolveParametersString(parameterFieldName, getTestContainer().getSettings());
Integer assertedLhsValue = Integer.parseInt(Settings.resolveParametersString(parameterAssertedLhsValue, settings)), Integer assertedLhsValue = Integer.parseInt(Settings.resolveParametersString(parameterAssertedLhsValue, getTestContainer().getSettings())),
assertedRhsValue = Integer.parseInt(Settings.resolveParametersString(parameterAssertedRhsValue, settings)); assertedRhsValue = Integer.parseInt(Settings.resolveParametersString(parameterAssertedRhsValue, getTestContainer().getSettings()));
String op = andOrOp.toLowerCase(); String op = andOrOp.toLowerCase();
boolean isAndOp = op.contains(AND); boolean isAndOp = op.contains(AND);
@ -504,7 +479,7 @@ public class WebAPIServer_1_0_2 implements En {
rhsValue = new AtomicReference<>(); rhsValue = new AtomicReference<>();
//iterate through response data and ensure that with data, the statement fieldName "op" assertValue is true //iterate through response data and ensure that with data, the statement fieldName "op" assertValue is true
from(container.get().responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
lhsValue.set(Integer.parseInt(item.get(fieldName).toString())); lhsValue.set(Integer.parseInt(item.get(fieldName).toString()));
rhsValue.set(Integer.parseInt(item.get(fieldName).toString())); rhsValue.set(Integer.parseInt(item.get(fieldName).toString()));
@ -523,7 +498,7 @@ public class WebAPIServer_1_0_2 implements En {
} }
}); });
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -532,14 +507,14 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^Date data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> { And("^Date data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> {
try { try {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); String fieldName = Settings.resolveParametersString(parameterFieldName, getTestContainer().getSettings());
AtomicReference<Date> fieldValue = new AtomicReference<>(); AtomicReference<Date> fieldValue = new AtomicReference<>();
AtomicReference<Date> assertedValue = new AtomicReference<>(); AtomicReference<Date> assertedValue = new AtomicReference<>();
assertedValue.set(TestUtils.parseDateFromEdmDateString(Settings.resolveParametersString(parameterAssertedValue, settings))); assertedValue.set(TestUtils.parseDateFromEdmDateString(Settings.resolveParametersString(parameterAssertedValue, getTestContainer().getSettings())));
LOG.info("Asserted value is: " + assertedValue.get().toString()); LOG.info("Asserted value is: " + assertedValue.get().toString());
from(container.get().responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
try { try {
fieldValue.set(TestUtils.parseDateFromEdmDateTimeOffsetString(item.get(fieldName).toString())); fieldValue.set(TestUtils.parseDateFromEdmDateTimeOffsetString(item.get(fieldName).toString()));
assertTrue(TestUtils.compare(fieldValue.get(), op, assertedValue.get())); assertTrue(TestUtils.compare(fieldValue.get(), op, assertedValue.get()));
@ -548,7 +523,7 @@ public class WebAPIServer_1_0_2 implements En {
} }
}); });
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -557,23 +532,23 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^TimeOfDay data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> { And("^TimeOfDay data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> {
try { try {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); String fieldName = Settings.resolveParametersString(parameterFieldName, getTestContainer().getSettings());
AtomicReference<Time> fieldValue = new AtomicReference<>(); AtomicReference<Time> fieldValue = new AtomicReference<>();
AtomicReference<Time> assertedValue = new AtomicReference<>(); AtomicReference<Time> assertedValue = new AtomicReference<>();
assertedValue.set(TestUtils.parseTimeOfDayFromEdmTimeOfDayString(Settings.resolveParametersString(parameterAssertedValue, settings))); assertedValue.set(TestUtils.parseTimeOfDayFromEdmTimeOfDayString(Settings.resolveParametersString(parameterAssertedValue, getTestContainer().getSettings())));
LOG.info("Asserted value is: " + assertedValue.get().toString()); LOG.info("Asserted value is: " + assertedValue.get().toString());
from(container.get().responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
try { try {
fieldValue.set(TestUtils.parseTimeOfDayFromEdmDateTimeOffsetString(item.get(fieldName).toString())); fieldValue.set(TestUtils.parseTimeOfDayFromEdmDateTimeOffsetString(item.get(fieldName).toString()));
assertTrue(TestUtils.compare(fieldValue.get(), op, assertedValue.get())); assertTrue(TestUtils.compare(fieldValue.get(), op, assertedValue.get()));
} catch (Exception ex) { } catch (Exception ex) {
LOG.error(ex.getMessage()); LOG.error(ex.toString());
} }
}); });
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -582,9 +557,9 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^DateTimeOffset data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> { And("^DateTimeOffset data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> {
try { try {
TestUtils.assertDateTimeOffset(parameterFieldName, op, parameterAssertedValue, container.get().responseData.get(), settings); TestUtils.assertDateTimeOffset(parameterFieldName, op, parameterAssertedValue, getTestContainer().getResponseData(), getTestContainer().getSettings());
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -593,9 +568,9 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^DateTimeOffset data in \"([^\"]*)\" \"([^\"]*)\" now\\(\\)$", (String parameterFieldName, String op) -> { And("^DateTimeOffset data in \"([^\"]*)\" \"([^\"]*)\" now\\(\\)$", (String parameterFieldName, String op) -> {
try { try {
TestUtils.assertDateTimeOffset(parameterFieldName, op, Timestamp.from(Instant.now()), container.get().responseData.get(), settings); TestUtils.assertDateTimeOffset(parameterFieldName, op, Timestamp.from(Instant.now()), getTestContainer().getResponseData(), getTestContainer().getSettings());
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -604,23 +579,23 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^Single Valued Enumeration Data in \"([^\"]*)\" has \"([^\"]*)\"$", (String parameterFieldName, String parameterAssertedValue) -> { And("^Single Valued Enumeration Data in \"([^\"]*)\" has \"([^\"]*)\"$", (String parameterFieldName, String parameterAssertedValue) -> {
try { try {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); String fieldName = Settings.resolveParametersString(parameterFieldName, getTestContainer().getSettings());
AtomicReference<String> fieldValue = new AtomicReference<>(); AtomicReference<String> fieldValue = new AtomicReference<>();
AtomicReference<String> assertedValue = new AtomicReference<>(); AtomicReference<String> assertedValue = new AtomicReference<>();
AtomicBoolean result = new AtomicBoolean(false); AtomicBoolean result = new AtomicBoolean(false);
assertedValue.set(Settings.resolveParametersString(parameterAssertedValue, settings)); assertedValue.set(Settings.resolveParametersString(parameterAssertedValue, getTestContainer().getSettings()));
LOG.info("Asserted value is: " + assertedValue.get()); LOG.info("Asserted value is: " + assertedValue.get());
from(container.get().responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
fieldValue.set(item.get(fieldName).toString()); fieldValue.set(item.get(fieldName).toString());
result.set(fieldValue.get().contentEquals(assertedValue.get())); result.set(fieldValue.get().contentEquals(assertedValue.get()));
LOG.info("Assert True: " + fieldValue.get() + " equals " + assertedValue.get() + " ==> " + result.get()); LOG.info("Assert True: " + fieldValue.get() + " equals " + assertedValue.get() + " ==> " + result.get());
assertTrue(result.get()); assertTrue(result.get());
}); });
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -630,23 +605,23 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^Multiple Valued Enumeration Data in \"([^\"]*)\" has \"([^\"]*)\"$", (String parameterFieldName, String parameterAssertedValue) -> { And("^Multiple Valued Enumeration Data in \"([^\"]*)\" has \"([^\"]*)\"$", (String parameterFieldName, String parameterAssertedValue) -> {
try { try {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); String fieldName = Settings.resolveParametersString(parameterFieldName, getTestContainer().getSettings());
AtomicReference<String> fieldValue = new AtomicReference<>(); AtomicReference<String> fieldValue = new AtomicReference<>();
AtomicReference<String> assertedValue = new AtomicReference<>(); AtomicReference<String> assertedValue = new AtomicReference<>();
AtomicBoolean result = new AtomicBoolean(false); AtomicBoolean result = new AtomicBoolean(false);
assertedValue.set(Settings.resolveParametersString(parameterAssertedValue, settings)); assertedValue.set(Settings.resolveParametersString(parameterAssertedValue, getTestContainer().getSettings()));
LOG.info("Asserted value is: " + assertedValue.get()); LOG.info("Asserted value is: " + assertedValue.get());
from(container.get().responseData.get()).getList(JSON_VALUE_PATH, ObjectNode.class).forEach(item -> { from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, ObjectNode.class).forEach(item -> {
fieldValue.set(item.get(fieldName).toString()); fieldValue.set(item.get(fieldName).toString());
result.set(fieldValue.get().contains(assertedValue.get())); result.set(fieldValue.get().contains(assertedValue.get()));
LOG.info("Assert True: " + fieldValue.get() + " has " + assertedValue.get() + " ==> " + result.get()); LOG.info("Assert True: " + fieldValue.get() + " has " + assertedValue.get() + " ==> " + result.get());
assertTrue(result.get()); assertTrue(result.get());
}); });
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -655,7 +630,7 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^DateTimeOffset data in \"([^\"]*)\" is sorted in \"([^\"]*)\" order$", (String parameterFieldName, String parameterOrderByDirection) -> { And("^DateTimeOffset data in \"([^\"]*)\" is sorted in \"([^\"]*)\" order$", (String parameterFieldName, String parameterOrderByDirection) -> {
try { try {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); String fieldName = Settings.resolveParametersString(parameterFieldName, getTestContainer().getSettings());
final String ASC = "asc", DESC = "desc"; final String ASC = "asc", DESC = "desc";
AtomicReference<String> orderBy = new AtomicReference<>(parameterOrderByDirection.toLowerCase()); AtomicReference<String> orderBy = new AtomicReference<>(parameterOrderByDirection.toLowerCase());
@ -666,7 +641,7 @@ public class WebAPIServer_1_0_2 implements En {
AtomicReference<Timestamp> currentValue = new AtomicReference<>(); AtomicReference<Timestamp> currentValue = new AtomicReference<>();
AtomicInteger count = new AtomicInteger(0); AtomicInteger count = new AtomicInteger(0);
from(container.get().responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
try { try {
if (count.get() == 0) { if (count.get() == 0) {
initialValue.set(TestUtils.parseTimestampFromEdmDateTimeOffsetString(item.get(fieldName).toString())); initialValue.set(TestUtils.parseTimestampFromEdmDateTimeOffsetString(item.get(fieldName).toString()));
@ -681,11 +656,11 @@ public class WebAPIServer_1_0_2 implements En {
} }
count.getAndIncrement(); count.getAndIncrement();
} catch (EdmPrimitiveTypeException ptex) { } catch (EdmPrimitiveTypeException ptex) {
fail(ptex.getMessage()); fail(ptex.toString());
} }
}); });
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -693,26 +668,26 @@ public class WebAPIServer_1_0_2 implements En {
* Date Field comparisons * Date Field comparisons
*/ */
And("^\"([^\"]*)\" data in Date Field \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String stringDatePart, String parameterFieldName, String op, String parameterAssertedValue) -> { And("^\"([^\"]*)\" data in Date Field \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String stringDatePart, String parameterFieldName, String op, String parameterAssertedValue) -> {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); String fieldName = Settings.resolveParametersString(parameterFieldName, getTestContainer().getSettings());
AtomicReference<Integer> fieldValue = new AtomicReference<>(); AtomicReference<Integer> fieldValue = new AtomicReference<>();
AtomicInteger assertedValue = new AtomicInteger(); AtomicInteger assertedValue = new AtomicInteger();
AtomicReference<String> datePart = new AtomicReference<>(stringDatePart.toLowerCase()); AtomicReference<String> datePart = new AtomicReference<>(stringDatePart.toLowerCase());
AtomicReference<String> operator = new AtomicReference<>(op.toLowerCase()); AtomicReference<String> operator = new AtomicReference<>(op.toLowerCase());
try { try {
assertedValue.set(Integer.parseInt(Settings.resolveParametersString(parameterAssertedValue, settings))); assertedValue.set(Integer.parseInt(Settings.resolveParametersString(parameterAssertedValue, getTestContainer().getSettings())));
LOG.info("Asserted value is: " + assertedValue.get()); LOG.info("Asserted value is: " + assertedValue.get());
from(container.get().responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
try { try {
fieldValue.set(TestUtils.getDatePart(datePart.get(), item.get(fieldName))); fieldValue.set(TestUtils.getDatePart(datePart.get(), item.get(fieldName)));
assertTrue(TestUtils.compare(fieldValue.get(), operator.get(), assertedValue.get())); assertTrue(TestUtils.compare(fieldValue.get(), operator.get(), assertedValue.get()));
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -722,29 +697,29 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^\"([^\"]*)\" data in Timestamp Field \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String stringDatePart, String parameterFieldName, String op, String parameterAssertedValue) -> { And("^\"([^\"]*)\" data in Timestamp Field \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String stringDatePart, String parameterFieldName, String op, String parameterAssertedValue) -> {
try { try {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); String fieldName = Settings.resolveParametersString(parameterFieldName, getTestContainer().getSettings());
AtomicReference<Integer> fieldValue = new AtomicReference<>(); AtomicReference<Integer> fieldValue = new AtomicReference<>();
AtomicReference<Integer> assertedValue = new AtomicReference<>(); AtomicReference<Integer> assertedValue = new AtomicReference<>();
AtomicReference<String> datePart = new AtomicReference<>(stringDatePart.toLowerCase()); AtomicReference<String> datePart = new AtomicReference<>(stringDatePart.toLowerCase());
AtomicReference<String> operator = new AtomicReference<>(op.toLowerCase()); AtomicReference<String> operator = new AtomicReference<>(op.toLowerCase());
try { try {
assertedValue.set(Integer.parseInt(Settings.resolveParametersString(parameterAssertedValue, settings))); assertedValue.set(Integer.parseInt(Settings.resolveParametersString(parameterAssertedValue, getTestContainer().getSettings())));
LOG.info("Asserted value is: " + assertedValue.get().toString()); LOG.info("Asserted value is: " + assertedValue.get().toString());
from(container.get().responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
try { try {
fieldValue.set(TestUtils.getTimestampPart(datePart.get(), item.get(fieldName).toString())); fieldValue.set(TestUtils.getTimestampPart(datePart.get(), item.get(fieldName).toString()));
assertTrue(TestUtils.compare(fieldValue.get(), operator.get(), assertedValue.get())); assertTrue(TestUtils.compare(fieldValue.get(), operator.get(), assertedValue.get()));
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -753,15 +728,15 @@ public class WebAPIServer_1_0_2 implements En {
*/ */
And("^String data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> { And("^String data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> {
try { try {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); String fieldName = Settings.resolveParametersString(parameterFieldName, getTestContainer().getSettings());
AtomicReference<String> assertedValue = new AtomicReference<>(Settings.resolveParametersString(parameterAssertedValue, settings)); AtomicReference<String> assertedValue = new AtomicReference<>(Settings.resolveParametersString(parameterAssertedValue, getTestContainer().getSettings()));
AtomicReference<String> operator = new AtomicReference<>(op.toLowerCase()); AtomicReference<String> operator = new AtomicReference<>(op.toLowerCase());
from(container.get().responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
assertTrue(TestUtils.compare(item.get(fieldName).toString(), operator.get(), assertedValue.get())); assertTrue(TestUtils.compare(item.get(fieldName).toString(), operator.get(), assertedValue.get()));
}); });
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -774,11 +749,11 @@ public class WebAPIServer_1_0_2 implements En {
Checks that metadata are accessible and contain the resource name specified in generic.resoscript Checks that metadata are accessible and contain the resource name specified in generic.resoscript
*/ */
And("^the metadata contains the \"([^\"]*)\" resource$", (String parameterResourceName) -> { And("^the metadata contains the \"([^\"]*)\" resource$", (String parameterResourceName) -> {
final String resourceName = Settings.resolveParametersString(parameterResourceName, settings); final String resourceName = Settings.resolveParametersString(parameterResourceName, getTestContainer().getSettings());
AtomicReference<CsdlEntityContainer> entityContainer = new AtomicReference<>(); AtomicReference<CsdlEntityContainer> entityContainer = new AtomicReference<>();
try { try {
entityContainer.set(TestUtils.findDefaultEntityContainer(edm.get(), xmlMetadata.get())); entityContainer.set(TestUtils.findDefaultEntityContainer(getTestContainer().getEdm(), getTestContainer().getXMLMetadata()));
assertNotNull("ERROR: server metadata does not contain the given resource name: " + resourceName, assertNotNull("ERROR: server metadata does not contain the given resource name: " + resourceName,
entityContainer.get().getEntitySet(resourceName)); entityContainer.get().getEntitySet(resourceName));
@ -786,7 +761,7 @@ public class WebAPIServer_1_0_2 implements En {
LOG.info("Found EntityContainer for the given resource: '" + resourceName + "'"); LOG.info("Found EntityContainer for the given resource: '" + resourceName + "'");
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -795,15 +770,15 @@ public class WebAPIServer_1_0_2 implements En {
* all of the fields in the given parameterSelectList. * all of the fields in the given parameterSelectList.
*/ */
And("^resource metadata for \"([^\"]*)\" contains the fields in \"([^\"]*)\"$", (String parameterResourceName, String parameterSelectList) -> { And("^resource metadata for \"([^\"]*)\" contains the fields in \"([^\"]*)\"$", (String parameterResourceName, String parameterSelectList) -> {
final String selectList = Settings.resolveParametersString(parameterSelectList, settings); final String selectList = Settings.resolveParametersString(parameterSelectList, getTestContainer().getSettings());
try { try {
final String resourceName = Settings.resolveParametersString(parameterResourceName, settings); final String resourceName = Settings.resolveParametersString(parameterResourceName, getTestContainer().getSettings());
List<String> fieldNames = Arrays.asList(selectList.split(FIELD_SEPARATOR)); List<String> fieldNames = Arrays.asList(selectList.split(FIELD_SEPARATOR));
//create field lookup //create field lookup
Map<String, CsdlProperty> fieldMap = new HashMap<>(); Map<String, CsdlProperty> fieldMap = new HashMap<>();
TestUtils.findEntityTypesForEntityTypeName(edm.get(), xmlMetadata.get(), resourceName) TestUtils.findEntityTypesForEntityTypeName(getTestContainer().getEdm(), getTestContainer().getXMLMetadata(), resourceName)
.forEach(csdlProperty -> fieldMap.put(csdlProperty.getName(), csdlProperty)); .forEach(csdlProperty -> fieldMap.put(csdlProperty.getName(), csdlProperty));
LOG.info("Searching metadata for fields in given select list: " + selectList); LOG.info("Searching metadata for fields in given select list: " + selectList);
@ -813,7 +788,7 @@ public class WebAPIServer_1_0_2 implements En {
LOG.info("Found: '" + fieldName.trim() + "'"); LOG.info("Found: '" + fieldName.trim() + "'");
}); });
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -821,22 +796,16 @@ public class WebAPIServer_1_0_2 implements En {
* Finds default Edm entity container at the given Service Root. * Finds default Edm entity container at the given Service Root.
* Note that this assumes the server can process the Accept application/xml header! * Note that this assumes the server can process the Accept application/xml header!
*/ */
When("^a default entity container exists for the service root in \"([^\"]*)\"$", (String clientSettingsServiceRoot) -> { When("^the metadata contains a valid service document$", () -> {
final String serviceRoot = Settings.resolveParametersString(clientSettingsServiceRoot, settings);
assertEquals("ERROR: given service root doesn't match the one configured in the Commander", serviceRoot, container.get().commander.get().getServiceRoot());
try { try {
ODataRetrieveResponse<Edm> oDataRetrieveResponse = container.get().commander.get().getODataRetrieveEdmResponse(); assertNotNull("ERROR: could not find default entity container for given service root: " +
container.get().responseCode.set(oDataRetrieveResponse.getStatusCode()); getTestContainer().getServiceRoot(), getTestContainer().getEdm().getEntityContainer());
edm.set(oDataRetrieveResponse.getBody()); LOG.info("Found Default Entity Container: '" + getTestContainer().getEdm().getEntityContainer().getNamespace() + "'");
assertNotNull("ERROR: could not find default entity container for given service root: " + serviceRoot, edm.get().getEntityContainer());
LOG.info("Found Default Entity Container: '" + edm.get().getEntityContainer().getNamespace() + "'");
} catch (ODataClientErrorException cex) { } catch (ODataClientErrorException cex) {
container.get().responseCode.set(cex.getStatusLine().getStatusCode()); getTestContainer().setResponseCode(cex.getStatusLine().getStatusCode());
fail(cex.getMessage()); fail(cex.toString());
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
} }
}); });
@ -844,18 +813,33 @@ public class WebAPIServer_1_0_2 implements En {
* XML Metadata getter * XML Metadata getter
*/ */
And("^XML Metadata are requested from the service root in \"([^\"]*)\"$", (String clientSettingsServiceRoot) -> { And("^XML Metadata are requested from the service root in \"([^\"]*)\"$", (String clientSettingsServiceRoot) -> {
final String serviceRoot = Settings.resolveParametersString(clientSettingsServiceRoot, settings); final String serviceRoot = Settings.resolveParametersString(clientSettingsServiceRoot, getTestContainer().getSettings());
assertEquals("ERROR: given service root doesn't match the one configured in the Commander", serviceRoot, container.get().commander.get().getServiceRoot()); assertEquals("ERROR: given service root doesn't match the one configured in the Commander", serviceRoot, getTestContainer().getCommander().getServiceRoot());
try { try {
xmlMetadata.set(container.get().commander.get().getXMLMetadata()); assertNotNull("ERROR: could not find valid XML Metadata for given service root: " + serviceRoot, getTestContainer().getXMLMetadata());
assertNotNull("ERROR: could not find valid XML Metadata for given service root: " + serviceRoot, xmlMetadata.get());
LOG.info("XML Metadata retrieved from: " + serviceRoot);
} catch (ODataClientErrorException cex) { } catch (ODataClientErrorException cex) {
container.get().responseCode.set(cex.getStatusLine().getStatusCode()); getTestContainer().setResponseCode(cex.getStatusLine().getStatusCode());
fail(cex.getMessage()); fail(cex.toString());
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.getMessage()); fail(ex.toString());
}
});
/*
* Edm Metadata getter
*/
And("^Edm metadata are requested from the service root in \"([^\"]*)\"$", (String clientSettingsServiceRoot) -> {
final String serviceRoot = Settings.resolveParametersString(clientSettingsServiceRoot, getTestContainer().getSettings());
assertEquals("ERROR: given service root doesn't match the one configured in the Commander", serviceRoot, getTestContainer().getCommander().getServiceRoot());
try {
assertNotNull("ERROR: could not find valid Edm Metadata for given service root: " + serviceRoot, getTestContainer().getEdm());
} catch (ODataClientErrorException cex) {
getTestContainer().setResponseCode(cex.getStatusLine().getStatusCode());
fail(cex.toString());
} catch (Exception ex) {
fail(ex.toString());
} }
}); });
@ -863,10 +847,10 @@ public class WebAPIServer_1_0_2 implements En {
* Tests whether a navigation property can be found in the given resource name. * Tests whether a navigation property can be found in the given resource name.
*/ */
And("^an OData NavigationProperty exists for the given \"([^\"]*)\"$", (String parameterEndpointResource) -> { And("^an OData NavigationProperty exists for the given \"([^\"]*)\"$", (String parameterEndpointResource) -> {
String resourceName = Settings.resolveParametersString(parameterEndpointResource, settings); String resourceName = Settings.resolveParametersString(parameterEndpointResource, getTestContainer().getSettings());
List<CsdlNavigationProperty> navigationProperties List<CsdlNavigationProperty> navigationProperties
= TestUtils.findNavigationPropertiesForEntityTypeName(container.get().commander.get().getEdm(), container.get().commander.get().getXMLMetadata(), resourceName); = TestUtils.findNavigationPropertiesForEntityTypeName(getTestContainer().getEdm(), getTestContainer().getXMLMetadata(), resourceName);
assertTrue("ERROR: no navigation properties found for the given '" + resourceName + "' resource!", assertTrue("ERROR: no navigation properties found for the given '" + resourceName + "' resource!",
navigationProperties.size() > 0); navigationProperties.size() > 0);
@ -883,10 +867,10 @@ public class WebAPIServer_1_0_2 implements En {
* Checks to see whether the expanded field has data * Checks to see whether the expanded field has data
*/ */
And("^data are present within the expanded field \"([^\"]*)\"$", (String parameterExpandField) -> { And("^data are present within the expanded field \"([^\"]*)\"$", (String parameterExpandField) -> {
String expandField = Settings.resolveParametersString(parameterExpandField, settings); String expandField = Settings.resolveParametersString(parameterExpandField, getTestContainer().getSettings());
assertFalse("ERROR: no expand field found for " + parameterExpandField, expandField.isEmpty()); assertFalse("ERROR: no expand field found for " + parameterExpandField, expandField.isEmpty());
ClientEntitySet results = container.get().commander.get().getClient().getRetrieveRequestFactory().getEntitySetRequest(container.get().requestUri.get()).execute().getBody(); ClientEntitySet results = getTestContainer().getCommander().getClient().getRetrieveRequestFactory().getEntitySetRequest(getTestContainer().getRequestUri()).execute().getBody();
LOG.info("Results count is: " + results.getEntities().size()); LOG.info("Results count is: " + results.getEntities().size());
AtomicInteger counter = new AtomicInteger(); AtomicInteger counter = new AtomicInteger();
@ -920,14 +904,15 @@ public class WebAPIServer_1_0_2 implements En {
* Checks the Standard Resources requirement from Section 2.6 of the Web API specification * Checks the Standard Resources requirement from Section 2.6 of the Web API specification
*/ */
And("^the metadata contains at least one resource from \"([^\"]*)\"$", (String parameterRequiredResourceList) -> { And("^the metadata contains at least one resource from \"([^\"]*)\"$", (String parameterRequiredResourceList) -> {
String requiredResourceString = Settings.resolveParametersString(parameterRequiredResourceList, settings).replace(" ", ""); String requiredResourceString = Settings.resolveParametersString(parameterRequiredResourceList, getTestContainer().getSettings()).replace(" ", "");
List<String> requiredResources = Arrays.asList(requiredResourceString.split(",")); List<String> requiredResources = Arrays.asList(requiredResourceString.split(","));
LOG.info("Searching the default entity container for one of the following Standard Resources: " + requiredResourceString.replace(FIELD_SEPARATOR, PRETTY_FIELD_SEPARATOR)); LOG.info("Searching the default entity container for one of the following Standard Resources: " + requiredResourceString.replace(FIELD_SEPARATOR, PRETTY_FIELD_SEPARATOR));
AtomicBoolean found = new AtomicBoolean(false); AtomicBoolean found = new AtomicBoolean(false);
requiredResources.forEach(requiredResource -> { requiredResources.forEach(requiredResource -> {
if (!found.get()) found.set(found.get() || edm.get().getEntityContainer().getEntitySet(requiredResource) != null); if (!found.get())
found.set(found.get() || getTestContainer().getEdm().getEntityContainer().getEntitySet(requiredResource) != null);
}); });
assertTrue("ERROR: could not find one of the following Standard Resource Names in the default entity container: " + requiredResourceString.replace(FIELD_SEPARATOR, PRETTY_FIELD_SEPARATOR), assertTrue("ERROR: could not find one of the following Standard Resource Names in the default entity container: " + requiredResourceString.replace(FIELD_SEPARATOR, PRETTY_FIELD_SEPARATOR),
@ -941,8 +926,8 @@ public class WebAPIServer_1_0_2 implements En {
* latest version of the Data Dictionary, currently 1.7. * latest version of the Data Dictionary, currently 1.7.
*/ */
And("^the given \"([^\"]*)\" resource exists within \"([^\"]*)\"$", (String parameterResourceName, String parameterResourceList) -> { And("^the given \"([^\"]*)\" resource exists within \"([^\"]*)\"$", (String parameterResourceName, String parameterResourceList) -> {
String resourceName = Settings.resolveParametersString(parameterResourceName, settings), String resourceName = Settings.resolveParametersString(parameterResourceName, getTestContainer().getSettings()),
allowedResourceString = Settings.resolveParametersString(parameterResourceList, settings).replace(" ", ""); allowedResourceString = Settings.resolveParametersString(parameterResourceList, getTestContainer().getSettings()).replace(" ", "");
List<String> allowedResources = new ArrayList<>(Arrays.asList(allowedResourceString.split(FIELD_SEPARATOR))); List<String> allowedResources = new ArrayList<>(Arrays.asList(allowedResourceString.split(FIELD_SEPARATOR)));
LOG.info("Resource Name: " + resourceName); LOG.info("Resource Name: " + resourceName);
@ -954,23 +939,23 @@ public class WebAPIServer_1_0_2 implements En {
When("^a GET request is made to the resolved Url in \"([^\"]*)\" using the OData Client$", (String parameterRequestId) -> { When("^a GET request is made to the resolved Url in \"([^\"]*)\" using the OData Client$", (String parameterRequestId) -> {
String uriString = Settings.resolveParameters(settings.getRequestById(parameterRequestId), settings).getUrl(); String uriString = Settings.resolveParameters(getTestContainer().getSettings().getRequestById(parameterRequestId), getTestContainer().getSettings()).getUrl();
assertTrue("ERROR: the resolved Url in '" + parameterRequestId + "' was invalid!", uriString != null && uriString.length() > 0); assertTrue("ERROR: the resolved Url in '" + parameterRequestId + "' was invalid!", uriString != null && uriString.length() > 0);
LOG.info("Request Id: " + parameterRequestId); LOG.info("Request Id: " + parameterRequestId);
try { try {
container.get().requestUri.set(prepareUri(uriString)); getTestContainer().setRequestUri(prepareUri(uriString));
container.get().clientEntitySetRequest.set(container.get().commander.get().getClient().getRetrieveRequestFactory().getEntitySetRequest(container.get().requestUri.get())); getTestContainer().setClientEntitySetRequest(getTestContainer().getCommander().getClient().getRetrieveRequestFactory().getEntitySetRequest(getTestContainer().getRequestUri()));
LOG.info("OData Client Request being made to: " + uriString); LOG.info("OData Client Request being made to: " + uriString);
container.get().clientEntitySetResponse.set(container.get().clientEntitySetRequest.get().execute()); getTestContainer().setClientEntitySetRequest(getTestContainer().getClientEntitySetRequest());
getTestContainer().setClientEntitySetResponse(getTestContainer().getClientEntitySetRequest().execute());
getTestContainer().setResponseCode(getTestContainer().getClientEntitySetResponse().getStatusCode());
container.get().responseCode.set(container.get().clientEntitySetResponse.get().getStatusCode()); ResWrap<EntityCollection> coll = (getTestContainer().getCommander().getClient().getDeserializer(ContentType.JSON).toEntitySet(getTestContainer().getClientEntitySetResponse().getRawResponse()));
getTestContainer().setClientEntitySet(getTestContainer().getCommander().getClient().getBinder().getODataEntitySet(coll));
ResWrap<EntityCollection> coll = (container.get().commander.get().getClient().getDeserializer(ContentType.JSON).toEntitySet(container.get().clientEntitySetResponse.get().getRawResponse()));
container.get().clientEntitySet.set(container.get().commander.get().getClient().getBinder().getODataEntitySet(coll));
} catch (ODataClientErrorException cex) { } catch (ODataClientErrorException cex) {
container.get().oDataClientErrorException.set(cex); getTestContainer().setODataClientErrorException(cex);
container.get().responseCode.set(cex.getStatusLine().getStatusCode()); getTestContainer().setResponseCode(cex.getStatusLine().getStatusCode());
} catch (Exception ex) { } catch (Exception ex) {
fail(ex.toString()); fail(ex.toString());
} }
@ -980,28 +965,32 @@ public class WebAPIServer_1_0_2 implements En {
* Uses the OData ClientEntitySet rather than raw JSON responses for comparisons * Uses the OData ClientEntitySet rather than raw JSON responses for comparisons
*/ */
And("^client entity set Integer data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String operator, String parameterFieldValue) -> { And("^client entity set Integer data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String operator, String parameterFieldValue) -> {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings), String fieldName = Settings.resolveParametersString(parameterFieldName, getTestContainer().getSettings()),
op = operator.trim().toLowerCase(); op = operator.trim().toLowerCase();
Integer fieldValue = Integer.parseInt(Settings.resolveParametersString(parameterFieldValue, settings)); Integer fieldValue = Integer.parseInt(Settings.resolveParametersString(parameterFieldValue, getTestContainer().getSettings()));
assertNotNull(fieldValue); assertNotNull(fieldValue);
container.get().clientEntitySet.get().getEntities().forEach(entity -> { getTestContainer().getClientEntitySet().getEntities().forEach(entity -> {
assertTrue(compare((Integer)entity.getProperty(fieldName).getValue().asPrimitive().toValue(), op, fieldValue)); assertTrue(compare((Integer) entity.getProperty(fieldName).getValue().asPrimitive().toValue(), op, fieldValue));
}); });
}); });
And("^the OData client response has client entity set data$", () -> { And("^the OData client response has client entity set data$", () -> {
assertNotNull("ERROR: no entity collection returned in response!", container.get().clientEntitySet.get()); assertNotNull("ERROR: no entity collection returned in response!", getTestContainer().getClientEntitySet());
assertTrue("ERROR: no results returned!", container.get().clientEntitySet.get().getCount() > 0); assertTrue("ERROR: no results returned!", getTestContainer().getClientEntitySet().getCount() > 0);
if (showResponses) { if (showResponses) {
container.get().clientEntitySet.get().getEntities().forEach(entity -> { getTestContainer().getClientEntitySet().getEntities().forEach(entity -> {
LOG.info("Entity Type is: " + entity.getTypeName()); LOG.info("Entity Type is: " + entity.getTypeName());
entity.getProperties().forEach(property -> LOG.info("\tProperty: " + property.toString())); entity.getProperties().forEach(property -> LOG.info("\tProperty: " + property.toString()));
}); });
} }
}); });
} }
static WebApiTestContainer getTestContainer() {
return container.get();
}
} }

View File

@ -42,10 +42,6 @@ public class App {
private static final Logger LOG = LogManager.getLogger(App.class); private static final Logger LOG = LogManager.getLogger(App.class);
private static final String DIVIDER = "==============================================================";
private static final String SMALL_DIVIDER = "===========================";
private static final String RESOSCRIPT_EXTENSION = ".resoscript";
private static final String EDMX_EXTENSION = ".xml";
private static final String OUTPUT_DIR = "user.dir"; private static final String OUTPUT_DIR = "user.dir";
public static void main(String[] params) { public static void main(String[] params) {
@ -132,18 +128,18 @@ public class App {
if (cmd.hasOption(APP_OPTIONS.ACTIONS.RUN_RESOSCRIPT)) { if (cmd.hasOption(APP_OPTIONS.ACTIONS.RUN_RESOSCRIPT)) {
int numRequests = settings.getRequests().size(); int numRequests = settings.getRequests().size();
LOG.info(DIVIDER); LOG.info(REPORT_DIVIDER);
LOG.info("Web API Commander Starting... Press <ctrl+c> at any time to exit."); LOG.info("Web API Commander Starting... Press <ctrl+c> at any time to exit.");
LOG.info(DIVIDER); LOG.info(REPORT_DIVIDER);
LOG.info("Running " + numRequests + " Request(s)"); LOG.info("Running " + numRequests + " Request(s)");
LOG.info("RESOScript: " + inputFilename); LOG.info("RESOScript: " + inputFilename);
LOG.info(DIVIDER + "\n\n"); LOG.info(REPORT_DIVIDER + "\n\n");
//put in local directory rather than relative to where the input file is //put in local directory rather than relative to where the input file is
String directoryName = System.getProperty(OUTPUT_DIR), String directoryName = System.getProperty(OUTPUT_DIR),
outputPath = inputFilename outputPath = inputFilename
.substring(inputFilename.contains(File.separator) ? inputFilename.lastIndexOf(File.separator) : 0, inputFilename.length()) .substring(inputFilename.contains(File.separator) ? inputFilename.lastIndexOf(File.separator) : 0)
.replace(RESOSCRIPT_EXTENSION, "") + "-" + getTimestamp(new Date()); .replace(RESOSCRIPT_EXTENSION, "") + "-" + getTimestamp(new Date());
String resolvedUrl = null; String resolvedUrl = null;
@ -160,9 +156,9 @@ public class App {
request = settings.getRequestsAsList().get(i); request = settings.getRequestsAsList().get(i);
//TODO: create dynamic JUnit (or similar) test runner //TODO: create dynamic JUnit (or similar) test runner
LOG.info(SMALL_DIVIDER); LOG.info(REPORT_DIVIDER_SMALL);
LOG.info("Request: #" + (i + 1)); LOG.info("Request: #" + (i + 1));
LOG.info(SMALL_DIVIDER); LOG.info(REPORT_DIVIDER_SMALL);
if (request.getRequestId() != null && request.getRequestId().length() > 0) { if (request.getRequestId() != null && request.getRequestId().length() > 0) {
LOG.info("Request Id: " + request.getRequestId()); LOG.info("Request Id: " + request.getRequestId());
@ -193,9 +189,9 @@ public class App {
LOG.info("\n "); LOG.info("\n ");
} }
LOG.info(DIVIDER); LOG.info(REPORT_DIVIDER);
LOG.info("RESOScript Complete!"); LOG.info("RESOScript Complete!");
LOG.info(DIVIDER + "\n"); LOG.info(REPORT_DIVIDER + "\n");
System.exit(OK); //terminate the program after the batch completes System.exit(OK); //terminate the program after the batch completes
} }
@ -206,7 +202,7 @@ public class App {
if (cmd.hasOption(APP_OPTIONS.ACTIONS.GET_METADATA)) { if (cmd.hasOption(APP_OPTIONS.ACTIONS.GET_METADATA)) {
APP_OPTIONS.validateAction(cmd, APP_OPTIONS.ACTIONS.GET_METADATA); APP_OPTIONS.validateAction(cmd, APP_OPTIONS.ACTIONS.GET_METADATA);
metadata = commander.getEdm(); metadata = commander.prepareEdmMetadataRequest().execute().getBody();
getMetadataReport(metadata); getMetadataReport(metadata);
} else if (cmd.hasOption(APP_OPTIONS.ACTIONS.VALIDATE_METADATA)) { } else if (cmd.hasOption(APP_OPTIONS.ACTIONS.VALIDATE_METADATA)) {
@ -308,11 +304,12 @@ public class App {
/** /**
* Generates totals report from aggregates. * Generates totals report from aggregates.
*
* @param totalRequestCount total request count * @param totalRequestCount total request count
* @param numSucceeded num requests succeeded * @param numSucceeded num requests succeeded
* @param numFailed num requests failed * @param numFailed num requests failed
* @param numSkipped num requests skipped * @param numSkipped num requests skipped
* @param numIncomplete num requests incomplete * @param numIncomplete num requests incomplete
* @return a string containing the report. * @return a string containing the report.
*/ */
private static String generateTotalsReport(int totalRequestCount, int numSucceeded, int numFailed, int numSkipped, int numIncomplete) { private static String generateTotalsReport(int totalRequestCount, int numSucceeded, int numFailed, int numSkipped, int numIncomplete) {
@ -326,48 +323,14 @@ public class App {
} }
/** /**
* Metadata Pretty Printer * Gets a formatted date string for the given date.
* *
* @param metadata any metadata in Edm format * @param date the date to format
* @return date string in yyyyMMddHHMMssS format
*/ */
private static String getMetadataReport(Edm metadata) { private static String getTimestamp(Date date) {
StringBuilder reportBuilder = new StringBuilder(); DateFormat df = new SimpleDateFormat("yyyyMMddHHMMssS");
return df.format(date);
reportBuilder.append("\n\n" + DIVIDER);
reportBuilder.append("\nMetadata Report");
reportBuilder.append("\n" + DIVIDER);
//Note: other treatments may be added to this summary info
metadata.getSchemas().forEach(schema -> {
reportBuilder.append("\n\nNamespace: ").append(schema.getNamespace());
reportBuilder.append("\n" + SMALL_DIVIDER);
schema.getTypeDefinitions().forEach(a ->
reportBuilder.append("\n\n\tType Definition:").append(a.getName()));
schema.getEntityTypes().forEach(a -> {
reportBuilder.append("\n\n\tEntity Type: ").append(a.getName());
a.getKeyPropertyRefs().forEach(ref ->
reportBuilder.append("\n\t\tKey Field: ").append(ref.getName()));
a.getPropertyNames().forEach(n -> reportBuilder.append("\n\t\tName: ").append(n));
});
schema.getEnumTypes().forEach(a -> {
reportBuilder.append("\n\n\tEnum Type: ").append(a.getName());
a.getMemberNames().forEach(n -> reportBuilder.append("\n\t\tName: ").append(n));
});
schema.getComplexTypes().forEach(a ->
reportBuilder.append("\n\n\tComplex Entity Type: ").append(a.getFullQualifiedName().getFullQualifiedNameAsString()));
schema.getAnnotationGroups().forEach(a ->
reportBuilder.append("\n\n\tAnnotation: ").append(a.getQualifier()).append(", Target Path: ").append(a.getTargetPath()));
schema.getTerms().forEach(a ->
reportBuilder.append("\n\n\tTerm: ").append(a.getFullQualifiedName().getFullQualifiedNameAsString()));
});
return reportBuilder.toString();
} }
/** /**
@ -388,16 +351,6 @@ public class App {
static String CONTENT_TYPE = "contentType"; static String CONTENT_TYPE = "contentType";
static String HELP = "help"; static String HELP = "help";
static class ACTIONS {
//actions
static String RUN_RESOSCRIPT = "runRESOScript";
static String GET_METADATA = "getMetadata";
static String VALIDATE_METADATA = "validateMetadata";
static String GET_ENTITIES = "getEntities";
static String SAVE_RAW_GET_REQUEST = "saveRawGetRequest";
static String CONVERT_EDMX_TO_OPEN_API = "convertEDMXtoOpenAPI";
}
/** /**
* Validates options for the various actions exposed in App. * Validates options for the various actions exposed in App.
* <p> * <p>
@ -530,28 +483,28 @@ public class App {
.desc("Converts EDMX in <inputFile> to Open API, saving it in <inputFile>.swagger.json").build()); .desc("Converts EDMX in <inputFile> to Open API, saving it in <inputFile>.swagger.json").build());
return new Options() return new Options()
.addOption(helpOption) .addOption(helpOption)
.addOption(hostNameOption) .addOption(hostNameOption)
.addOption(bearerTokenOption) .addOption(bearerTokenOption)
.addOption(inputFileOption) .addOption(inputFileOption)
.addOption(outputFileOption) .addOption(outputFileOption)
.addOption(pageLimit) .addOption(pageLimit)
.addOption(pageSize) .addOption(pageSize)
.addOption(entityName) .addOption(entityName)
.addOption(useEdmEnabledClient) .addOption(useEdmEnabledClient)
.addOption(uriOption) .addOption(uriOption)
.addOption(contentType) .addOption(contentType)
.addOptionGroup(actions); .addOptionGroup(actions);
}
static class ACTIONS {
//actions
static String RUN_RESOSCRIPT = "runRESOScript";
static String GET_METADATA = "getMetadata";
static String VALIDATE_METADATA = "validateMetadata";
static String GET_ENTITIES = "getEntities";
static String SAVE_RAW_GET_REQUEST = "saveRawGetRequest";
static String CONVERT_EDMX_TO_OPEN_API = "convertEDMXtoOpenAPI";
} }
} }
/**
* Gets a formatted date string for the given date.
* @param date the date to format
* @return date string in yyyyMMddHHMMssS format
*/
private static String getTimestamp(Date date) {
DateFormat df = new SimpleDateFormat("yyyyMMddHHMMssS");
return df.format(date);
}
} }

View File

@ -1,6 +1,7 @@
package org.reso.commander; package org.reso.commander;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.apache.http.client.utils.URIBuilder; import org.apache.http.client.utils.URIBuilder;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@ -8,10 +9,12 @@ import org.apache.logging.log4j.Logger;
import org.apache.olingo.client.api.ODataClient; import org.apache.olingo.client.api.ODataClient;
import org.apache.olingo.client.api.communication.ODataClientErrorException; import org.apache.olingo.client.api.communication.ODataClientErrorException;
import org.apache.olingo.client.api.communication.request.retrieve.EdmMetadataRequest; import org.apache.olingo.client.api.communication.request.retrieve.EdmMetadataRequest;
import org.apache.olingo.client.api.communication.request.retrieve.XMLMetadataRequest;
import org.apache.olingo.client.api.communication.response.ODataRawResponse; import org.apache.olingo.client.api.communication.response.ODataRawResponse;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse; import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.client.api.domain.ClientEntitySet; import org.apache.olingo.client.api.domain.ClientEntitySet;
import org.apache.olingo.client.api.edm.xml.XMLMetadata; import org.apache.olingo.client.api.edm.xml.XMLMetadata;
import org.apache.olingo.client.api.serialization.ODataSerializerException;
import org.apache.olingo.client.core.ODataClientFactory; import org.apache.olingo.client.core.ODataClientFactory;
import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.format.ContentType;
@ -45,7 +48,13 @@ public class Commander {
public static final int NOT_OK = 1; public static final int NOT_OK = 1;
public static final Integer DEFAULT_PAGE_SIZE = 10; public static final Integer DEFAULT_PAGE_SIZE = 10;
public static final Integer DEFAULT_PAGE_LIMIT = 1; public static final Integer DEFAULT_PAGE_LIMIT = 1;
public static final String REPORT_DIVIDER = "==============================================================";
public static final String REPORT_DIVIDER_SMALL = "===========================";
public static final String RESOSCRIPT_EXTENSION = ".resoscript";
public static final String EDMX_EXTENSION = ".xml";
private static final Logger LOG = LogManager.getLogger(Commander.class); private static final Logger LOG = LogManager.getLogger(Commander.class);
private static final String EDM_4_0_3_XSD = "edm.4.0.3.xsd",
EDMX_4_0_3_XSD = "edmx.4.0.3.xsd";
private static String bearerToken; private static String bearerToken;
private static String clientId; private static String clientId;
private static String clientSecret; private static String clientSecret;
@ -54,20 +63,21 @@ public class Commander {
private static String redirectUri; private static String redirectUri;
private static String scope; private static String scope;
private static boolean isTokenClient, isOAuthClient; private static boolean isTokenClient, isOAuthClient;
//one instance of client per Commander. See Builder
private static ODataClient client; private static ODataClient client;
private static boolean useEdmEnabledClient; private static boolean useEdmEnabledClient;
private static String serviceRoot; private static String serviceRoot;
private static Edm edm; private static Edm edm;
private static XMLMetadata xmlMetadata; private static XMLMetadata xmlMetadata;
//private constructor for internal use, use Builder to construct instances //private constructor for internal use, use Builder to construct instances
private Commander() { private Commander() {
; //private constructor, should not be used. Use Builder instead. //private constructor, should not be used. Use Builder instead.
} }
/** /**
* Uses an XML validator to validate that the given string contains valid XML. * Uses an XML validator to validate that the given string contains valid XML.
*
* @param xmlString the string containing the XML to validate. * @param xmlString the string containing the XML to validate.
* @return true if the given xmlString is valid and false otherwise. * @return true if the given xmlString is valid and false otherwise.
*/ */
@ -75,8 +85,20 @@ public class Commander {
return validateXML(new ByteArrayInputStream(xmlString.getBytes())); return validateXML(new ByteArrayInputStream(xmlString.getBytes()));
} }
/**
* Validates XML for the given xmlMetadata item
*
* @param xmlMetadata the XML metadata to validate
* @return true if valid, false otherwise
* @throws ODataSerializerException if the given XML metadata could not be serialized
*/
public static boolean validateXML(XMLMetadata xmlMetadata) throws ODataSerializerException {
return validateXML(serializeXMLMetadataToXMLString(xmlMetadata));
}
/** /**
* Uses an XML validator to validate that the given inputStream contains valid XML. * Uses an XML validator to validate that the given inputStream contains valid XML.
*
* @param inputStream the input stream to check. * @param inputStream the input stream to check.
* @return true if the given inputStream has valid XML, false otherwise. * @return true if the given inputStream has valid XML, false otherwise.
*/ */
@ -87,8 +109,8 @@ public class Commander {
factory.setNamespaceAware(true); factory.setNamespaceAware(true);
factory.setSchema(SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(new StreamSource[]{ factory.setSchema(SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(new StreamSource[]{
new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream("edm.4.0.3.xsd")), new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(EDM_4_0_3_XSD)),
new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream("edmx.4.0.3.xsd")) new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream(EDMX_4_0_3_XSD))
})); }));
SAXParser parser = factory.newSAXParser(); SAXParser parser = factory.newSAXParser();
@ -110,6 +132,7 @@ public class Commander {
/** /**
* Prepares a URI for an OData request * Prepares a URI for an OData request
*
* @param uriString the uri string to use for the request * @param uriString the uri string to use for the request
* @return the prepared URI * @return the prepared URI
*/ */
@ -145,24 +168,18 @@ public class Commander {
JSON_FULL_METADATA = "JSON_FULL_METADATA", JSON_FULL_METADATA = "JSON_FULL_METADATA",
XML = "XML"; XML = "XML";
ContentType defaultType = ContentType.JSON; ContentType type = ContentType.JSON;
ContentType type;
if (contentType == null) { if (contentType.matches(JSON)) {
return defaultType; type = ContentType.JSON;
} else { } else if (contentType.matches(JSON_NO_METADATA)) {
if (contentType.matches(JSON)) { type = ContentType.JSON_NO_METADATA;
type = ContentType.JSON; } else if (contentType.matches(JSON_FULL_METADATA)) {
} else if (contentType.matches(JSON_NO_METADATA)) { type = ContentType.JSON_FULL_METADATA;
type = ContentType.JSON_NO_METADATA; } else if (contentType.matches(XML)) {
} else if (contentType.matches(JSON_FULL_METADATA)) { type = ContentType.APPLICATION_XML;
type = ContentType.JSON_FULL_METADATA;
} else if (contentType.matches(XML)) {
type = ContentType.APPLICATION_XML;
} else {
type = ContentType.JSON;
}
} }
return type; return type;
} }
@ -196,12 +213,70 @@ public class Commander {
return null; return null;
} }
/**
* Serializes XML Metadata to an XML string
*
* @param xmlMetadata the metadata to serialize
* @return a String containing the metadata
* @throws ODataSerializerException
*/
private static String serializeXMLMetadataToXMLString(XMLMetadata xmlMetadata) throws ODataSerializerException {
StringWriter writer = new StringWriter();
client.getSerializer(ContentType.APPLICATION_XML).write(writer, xmlMetadata);
return writer.getBuffer().toString();
}
/**
* Metadata Pretty Printer
*
* @param metadata any metadata in Edm format
*/
public static String getMetadataReport(Edm metadata) {
StringBuilder reportBuilder = new StringBuilder();
reportBuilder.append("\n\n" + REPORT_DIVIDER);
reportBuilder.append("\nMetadata Report");
reportBuilder.append("\n" + REPORT_DIVIDER);
//Note: other treatments may be added to this summary info
metadata.getSchemas().forEach(schema -> {
reportBuilder.append("\n\nNamespace: ").append(schema.getNamespace());
reportBuilder.append("\n" + REPORT_DIVIDER_SMALL);
schema.getTypeDefinitions().forEach(a ->
reportBuilder.append("\n\n\tType Definition:").append(a.getName()));
schema.getEntityTypes().forEach(a -> {
reportBuilder.append("\n\n\tEntity Type: ").append(a.getName());
a.getKeyPropertyRefs().forEach(ref ->
reportBuilder.append("\n\t\tKey Field: ").append(ref.getName()));
a.getPropertyNames().forEach(n -> reportBuilder.append("\n\t\tName: ").append(n));
});
schema.getEnumTypes().forEach(a -> {
reportBuilder.append("\n\n\tEnum Type: ").append(a.getName());
a.getMemberNames().forEach(n -> reportBuilder.append("\n\t\tName: ").append(n));
});
schema.getComplexTypes().forEach(a ->
reportBuilder.append("\n\n\tComplex Entity Type: ").append(a.getFullQualifiedName().getFullQualifiedNameAsString()));
schema.getAnnotationGroups().forEach(a ->
reportBuilder.append("\n\n\tAnnotation: ").append(a.getQualifier()).append(", Target Path: ").append(a.getTargetPath()));
schema.getTerms().forEach(a ->
reportBuilder.append("\n\n\tTerm: ").append(a.getFullQualifiedName().getFullQualifiedNameAsString()));
});
return reportBuilder.toString();
}
public ODataClient getClient() { public ODataClient getClient() {
return this.client; return client;
} }
public void setClient(ODataClient client) { public void setClient(ODataClient client) {
this.client = client; Commander.client = client;
} }
public String getTokenUri() { public String getTokenUri() {
@ -231,42 +306,22 @@ public class Commander {
} }
/** /**
* Gets server metadata in Edm format. * Prepares an Edm Metadata request
*
* @return
* @implNote the data in this item are cached in the commander once fetched
*/
public Edm getEdm() {
if (edm == null) {
edm = getODataRetrieveEdmResponse().getBody();
}
return edm;
}
/**
* Gets server metadata in XMLMetadata format.
*
* @return XMLMetadata representation of the server metadata.
* @implNote the data in this item are cached in the commander once fetched
*/
public XMLMetadata getXMLMetadata() {
if (xmlMetadata == null) {
EdmMetadataRequest metadataRequest = client.getRetrieveRequestFactory().getMetadataRequest(serviceRoot);
LOG.info("Fetching XMLMetadata with OData Client from: " + metadataRequest.getURI().toString());
xmlMetadata = metadataRequest.getXMLMetadata();
}
return xmlMetadata;
}
/**
* Used to contain the response for the request as well as get metadata.
* *
* @return the OData response retrieved from the server when making the request. * @return the OData response retrieved from the server when making the request.
*/ */
public ODataRetrieveResponse<Edm> getODataRetrieveEdmResponse() { public EdmMetadataRequest prepareEdmMetadataRequest() {
EdmMetadataRequest metadataRequest = client.getRetrieveRequestFactory().getMetadataRequest(serviceRoot); EdmMetadataRequest request = getClient().getRetrieveRequestFactory().getMetadataRequest(getServiceRoot());
LOG.info("Fetching Edm with OData Client from: " + metadataRequest.getURI().toString()); request.addCustomHeader(HttpHeaders.CONTENT_TYPE, null);
return metadataRequest.execute(); request.addCustomHeader(HttpHeaders.ACCEPT, null);
return request;
}
public XMLMetadataRequest prepareXMLMetadataRequest() {
XMLMetadataRequest request = getClient().getRetrieveRequestFactory().getXMLMetadataRequest(getServiceRoot());
request.addCustomHeader(HttpHeaders.CONTENT_TYPE, null);
request.addCustomHeader(HttpHeaders.ACCEPT, null);
return request;
} }
/** /**
@ -290,13 +345,9 @@ public class Commander {
* @param metadata the metadata to save. * @param metadata the metadata to save.
* @param outputFileName the file name to output the metadata to. * @param outputFileName the file name to output the metadata to.
*/ */
public void saveMetadata(Edm metadata, String outputFileName) { public void saveMetadata(Edm metadata, String outputFileName) throws IOException, ODataSerializerException {
try { FileWriter writer = new FileWriter(outputFileName);
FileWriter writer = new FileWriter(outputFileName); client.getSerializer(ContentType.APPLICATION_XML).write(writer, metadata);
client.getSerializer(ContentType.APPLICATION_XML).write(writer, metadata);
} catch (Exception ex) {
LOG.error(ex.getStackTrace());
}
} }
/** /**
@ -351,6 +402,7 @@ public class Commander {
/** /**
* Ensures that the input stream contains valid XMLMetadata. * Ensures that the input stream contains valid XMLMetadata.
*
* @param inputStream the input stream containing the metadata to validate. * @param inputStream the input stream containing the metadata to validate.
* @return true if the given input stream contains valid XML Metadata, false otherwise. * @return true if the given input stream contains valid XML Metadata, false otherwise.
*/ */
@ -384,6 +436,7 @@ public class Commander {
/** /**
* Boolean to determine whether this Commander instance is a token client. * Boolean to determine whether this Commander instance is a token client.
*
* @return true if the commander instance is a token client, false otherwise. * @return true if the commander instance is a token client, false otherwise.
*/ */
public boolean isTokenClient() { public boolean isTokenClient() {
@ -392,6 +445,7 @@ public class Commander {
/** /**
* Boolean to determine whether this Commander instance is an OAuth2 client. * Boolean to determine whether this Commander instance is an OAuth2 client.
*
* @return true if the commander instance is an OAuth2 client credentials client, false otherwise. * @return true if the commander instance is an OAuth2 client credentials client, false otherwise.
*/ */
public boolean isOAuthClient() { public boolean isOAuthClient() {
@ -641,8 +695,8 @@ public class Commander {
//items required for OAuth client //items required for OAuth client
isOAuthClient = isOAuthClient =
clientId != null && clientId.length() > 0 clientId != null && clientId.length() > 0
&& clientSecret != null && clientSecret.length() > 0 && clientSecret != null && clientSecret.length() > 0
&& tokenUri != null && tokenUri.length() > 0; && tokenUri != null && tokenUri.length() > 0;
//items required for token client //items required for token client
isTokenClient = bearerToken != null && bearerToken.length() > 0; isTokenClient = bearerToken != null && bearerToken.length() > 0;

View File

@ -2,16 +2,9 @@ package org.reso.commander;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.Header; import org.apache.http.Header;
import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.olingo.client.api.communication.ODataClientErrorException;
import org.apache.olingo.client.api.communication.ODataServerErrorException;
import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
import org.apache.olingo.client.api.communication.request.retrieve.ODataRawRequest;
import org.apache.olingo.client.api.communication.response.ODataRawResponse; import org.apache.olingo.client.api.communication.response.ODataRawResponse;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.client.api.domain.ClientEntitySet;
import org.apache.olingo.client.api.edm.xml.XMLMetadata; import org.apache.olingo.client.api.edm.xml.XMLMetadata;
import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.Edm;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
@ -22,7 +15,6 @@ import org.apache.olingo.commons.api.edm.provider.CsdlSchema;
import org.apache.olingo.commons.core.edm.primitivetype.EdmDate; import org.apache.olingo.commons.core.edm.primitivetype.EdmDate;
import org.apache.olingo.commons.core.edm.primitivetype.EdmDateTimeOffset; import org.apache.olingo.commons.core.edm.primitivetype.EdmDateTimeOffset;
import org.apache.olingo.commons.core.edm.primitivetype.EdmTimeOfDay; import org.apache.olingo.commons.core.edm.primitivetype.EdmTimeOfDay;
import org.reso.models.Request;
import org.reso.models.Settings; import org.reso.models.Settings;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -41,58 +33,18 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import static io.restassured.path.json.JsonPath.from; import static io.restassured.path.json.JsonPath.from;
import static org.junit.Assert.*; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public final class TestUtils { public final class TestUtils {
public static final String JSON_VALUE_PATH = "value"; public static final String JSON_VALUE_PATH = "value";
public static final String HEADER_ODATA_VERSION = "OData-Version"; public static final String HEADER_ODATA_VERSION = "OData-Version";
private static final Logger LOG = LogManager.getLogger(TestUtils.class); private static final Logger LOG = LogManager.getLogger(TestUtils.class);
/**
* Encapsulates Commander Requests and Responses during runtime
*/
public static final class TestContainer {
//TODO: Wrap in Commander Request/Response object
public AtomicReference<Commander> commander = new AtomicReference<>();
public AtomicReference<ODataRawResponse> oDataRawResponse = new AtomicReference<>();
public AtomicReference<Request> request = new AtomicReference<>();
public AtomicReference<URI> requestUri = new AtomicReference<>();
public AtomicReference<Integer> responseCode = new AtomicReference<>();
public AtomicReference<String> responseData = new AtomicReference<>();
public AtomicReference<String> initialResponseData = new AtomicReference<>(); //used if two result sets need to be compared
public AtomicReference<ODataRawRequest> rawRequest = new AtomicReference<>();
public AtomicReference<ODataClientErrorException> oDataClientErrorException = new AtomicReference<>();
public AtomicReference<ODataServerErrorException> oDataServerErrorException = new AtomicReference<>();
public AtomicReference<String> serverODataHeaderVersion = new AtomicReference<>();
public AtomicReference<Boolean> testAppliesToServerODataHeaderVersion = new AtomicReference<>();
public AtomicReference<ODataEntitySetRequest<ClientEntitySet>> clientEntitySetRequest = new AtomicReference<>();
public AtomicReference<ODataRetrieveResponse<ClientEntitySet>> clientEntitySetResponse = new AtomicReference<>();
public AtomicReference<ClientEntitySet> clientEntitySet = new AtomicReference<>();
/**
* Resets the state of the test container
*/
public void resetState() {
oDataRawResponse.set(null);
request.set(null);
responseCode.set(null);
responseData.set(null);
initialResponseData.set(null);
rawRequest.set(null);
oDataClientErrorException.set(null);
oDataServerErrorException.set(null);
serverODataHeaderVersion.set(null);
testAppliesToServerODataHeaderVersion.set(false);
}
}
/** /**
* Used to prepare URIs given that the input queryStrings can sometimes contain special characters * Used to prepare URIs given that the input queryStrings can sometimes contain special characters
* that need to be ensured that they be processed. * that need to be ensured that they be processed.
*
* @param queryString the queryString to prepare * @param queryString the queryString to prepare
* @return the prepared URI with special characters in the queryString processed. * @return the prepared URI with special characters in the queryString processed.
*/ */
@ -104,41 +56,6 @@ public final class TestUtils {
); );
} }
/**
* Executes HTTP GET request and sets the expected local variables in the given TestContainer
* Handles exceptions and sets response codes as well.
* @param uri the URI to make requests to
* @param container the TestContainer to execute the requests in
* @return a TestContainer containing the final state of the request.
*/
public static TestContainer executeGetRequest(final URI uri, TestContainer container) {
LOG.info("Request URI: " + uri);
try {
container.rawRequest.set(container.commander.get().getClient().getRetrieveRequestFactory().getRawRequest(uri));
container.oDataRawResponse.set(container.rawRequest.get().execute());
container.responseData.set(TestUtils.convertInputStreamToString(container.oDataRawResponse.get().getRawResponse()));
container.serverODataHeaderVersion.set(container.oDataRawResponse.get().getHeader(HEADER_ODATA_VERSION).toString());
container.responseCode.set(container.oDataRawResponse.get().getStatusCode());
LOG.info("Request succeeded..." + container.responseData.get().getBytes().length + " bytes received.");
} catch (ODataClientErrorException cex) {
LOG.debug("ODataClientErrorException caught. Check tests for asserted conditions...");
container.oDataClientErrorException.set(cex);
container.serverODataHeaderVersion.set(TestUtils.getHeaderData(HEADER_ODATA_VERSION, cex.getHeaderInfo()));
container.responseCode.set(cex.getStatusLine().getStatusCode());
} catch (ODataServerErrorException ode) {
LOG.debug("ODataServerErrorException thrown in executeGetRequest. Check tests for asserted conditions...");
//TODO: look for better ways to do this in Olingo or open PR
if (ode.getMessage().contains(Integer.toString(HttpStatus.SC_NOT_IMPLEMENTED))) {
container.responseCode.set(HttpStatus.SC_NOT_IMPLEMENTED);
}
container.oDataServerErrorException.set(ode);
} catch (Exception ex) {
fail("ERROR: unhandled Exception in executeGetRequest()!\n" + ex.toString());
//throw ex;
}
return container;
}
/** /**
* Finds the default entity container for the given configuration. * Finds the default entity container for the given configuration.
* *

View File

@ -0,0 +1,15 @@
package org.reso.commander.certfication.containers;
public interface TestContainer {
/**
* Used to initialize the container from the given RESOScript
*/
void initialize();
/**
* Used to reset the state of the given TestContainer.
*/
void resetState();
}

View File

@ -0,0 +1,369 @@
package org.reso.commander.certfication.containers;
import org.apache.http.HttpStatus;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.olingo.client.api.communication.ODataClientErrorException;
import org.apache.olingo.client.api.communication.ODataServerErrorException;
import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
import org.apache.olingo.client.api.communication.request.retrieve.ODataRawRequest;
import org.apache.olingo.client.api.communication.response.ODataRawResponse;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.client.api.domain.ClientEntitySet;
import org.apache.olingo.client.api.edm.xml.XMLMetadata;
import org.apache.olingo.commons.api.edm.Edm;
import org.reso.commander.Commander;
import org.reso.commander.TestUtils;
import org.reso.models.ClientSettings;
import org.reso.models.Request;
import org.reso.models.Settings;
import java.net.URI;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.fail;
import static org.reso.commander.TestUtils.HEADER_ODATA_VERSION;
/**
* Encapsulates Commander Requests and Responses during runtime
*/
public final class WebApiTestContainer implements TestContainer {
private static final Logger LOG = LogManager.getLogger(WebApiTestContainer.class);
private AtomicReference<Commander> commander = new AtomicReference<>();
private AtomicReference<ODataRawResponse> oDataRawResponse = new AtomicReference<>();
private AtomicReference<Request> request = new AtomicReference<>();
private AtomicReference<URI> requestUri = new AtomicReference<>();
private AtomicReference<Integer> responseCode = new AtomicReference<>();
private AtomicReference<String> responseData = new AtomicReference<>();
private AtomicReference<String> initialResponseData = new AtomicReference<>(); //used if two result sets need to be compared
private AtomicReference<ODataRawRequest> rawRequest = new AtomicReference<>();
private AtomicReference<ODataClientErrorException> oDataClientErrorException = new AtomicReference<>();
private AtomicReference<ODataServerErrorException> oDataServerErrorException = new AtomicReference<>();
private AtomicReference<String> serverODataHeaderVersion = new AtomicReference<>();
private AtomicReference<Boolean> testAppliesToServerODataHeaderVersion = new AtomicReference<>();
private AtomicReference<ODataEntitySetRequest<ClientEntitySet>> clientEntitySetRequest = new AtomicReference<>();
private AtomicReference<ODataRetrieveResponse<ClientEntitySet>> clientEntitySetResponse = new AtomicReference<>();
private AtomicReference<ClientEntitySet> clientEntitySet = new AtomicReference<>();
private AtomicReference<XMLMetadata> xmlMetadata = new AtomicReference<>();
private AtomicReference<Edm> edm = new AtomicReference<>();
private AtomicReference<Settings> settings = new AtomicReference<>();
private AtomicReference<String> serviceRoot = new AtomicReference<>();
private AtomicReference<String> bearerToken = new AtomicReference<>();
private AtomicReference<String> clientId = new AtomicReference<>();
private AtomicReference<String> clientSecret = new AtomicReference<>();
private AtomicReference<String> authorizationUri = new AtomicReference<>();
private AtomicReference<String> tokenUri = new AtomicReference<>();
private AtomicReference<String> redirectUri = new AtomicReference<>();
private AtomicReference<String> scope = new AtomicReference<>();
private AtomicReference<String> pathToRESOScript = new AtomicReference<>();
public void initialize() {
setServiceRoot(getSettings().getClientSettings().get(ClientSettings.WEB_API_URI));
//TODO: add base64 un-encode when applicable
setBearerToken(getSettings().getClientSettings().get(ClientSettings.BEARER_TOKEN));
if (getBearerToken() != null && getBearerToken().length() > 0) {
LOG.info("Bearer token loaded... first 4 characters: " + getBearerToken().substring(0, 4));
}
setClientId(getSettings().getClientSettings().get(ClientSettings.CLIENT_IDENTIFICATION));
setClientSecret(getSettings().getClientSettings().get(ClientSettings.CLIENT_SECRET));
setAuthorizationUri(getSettings().getClientSettings().get(ClientSettings.AUTHORIZATION_URI));
setTokenUri(getSettings().getClientSettings().get(ClientSettings.TOKEN_URI));
setRedirectUri(getSettings().getClientSettings().get(ClientSettings.REDIRECT_URI));
setScope(getSettings().getClientSettings().get(ClientSettings.CLIENT_SCOPE));
LOG.info("Service root is: " + getServiceRoot());
if (getCommander() == null) {
//create Commander instance
setCommander(new Commander.Builder()
.clientId(getClientId())
.clientSecret(getClientSecret())
.tokenUri(getTokenUri())
.scope(getScope())
.serviceRoot(getServiceRoot())
.bearerToken(getBearerToken())
.useEdmEnabledClient(true)
.build());
}
}
/**
* Resets the state of the test container
*/
public void resetState() {
oDataRawResponse.set(null);
request.set(null);
responseCode.set(null);
responseData.set(null);
initialResponseData.set(null);
rawRequest.set(null);
oDataClientErrorException.set(null);
oDataServerErrorException.set(null);
serverODataHeaderVersion.set(null);
testAppliesToServerODataHeaderVersion.set(false);
}
/**
* Executes HTTP GET request and sets the expected local variables in the WebApiTestContainer
* Handles exceptions and sets response codes as well.
*/
public void executePreparedGetRequest() {
try {
setRawRequest(getCommander().getClient().getRetrieveRequestFactory().getRawRequest(getRequestUri()));
setODataRawResponse(getRawRequest().execute());
setResponseData(TestUtils.convertInputStreamToString(getODataRawResponse().getRawResponse()));
setServerODataHeaderVersion(getODataRawResponse().getHeader(HEADER_ODATA_VERSION).toString());
setResponseCode(getODataRawResponse().getStatusCode());
LOG.info("Request succeeded..." + getResponseData().getBytes().length + " bytes received.");
} catch (ODataClientErrorException cex) {
LOG.debug("ODataClientErrorException caught. Check tests for asserted conditions...");
LOG.debug(cex);
setODataClientErrorException(cex);
setServerODataHeaderVersion(TestUtils.getHeaderData(HEADER_ODATA_VERSION, cex.getHeaderInfo()));
setResponseCode(cex.getStatusLine().getStatusCode());
} catch (ODataServerErrorException ode) {
LOG.debug("ODataServerErrorException thrown in executeGetRequest. Check tests for asserted conditions...");
//TODO: look for better ways to do this in Olingo or open PR
if (ode.getMessage().contains(Integer.toString(HttpStatus.SC_NOT_IMPLEMENTED))) {
setResponseCode(HttpStatus.SC_NOT_IMPLEMENTED);
}
setODataServerErrorException(ode);
} catch (Exception ex) {
fail("ERROR: unhandled Exception in executeGetRequest()!\n" + ex.toString());
}
}
public Settings getSettings() {
return settings.get();
}
public void setSettings(Settings settings) {
this.settings.set(settings);
}
/**
* Gets server metadata in Edm format.
*
* @return
* @implNote the data in this item are cached in the commander once fetched
*/
public Edm getEdm() {
if (edm.get() == null) {
ODataRetrieveResponse<Edm> response = getCommander().prepareEdmMetadataRequest().execute();
responseCode.set(response.getStatusCode());
edm.set(response.getBody());
}
return edm.get();
}
/**
* Gets server metadata in XMLMetadata format.
*
* @return XMLMetadata representation of the server metadata.
* @implNote the data in this item are cached in the commander once fetched
*/
public XMLMetadata getXMLMetadata() {
if (xmlMetadata.get() == null) {
ODataRetrieveResponse<XMLMetadata> response = getCommander().prepareXMLMetadataRequest().execute();
responseCode.set(response.getStatusCode());
xmlMetadata.set(response.getBody());
}
return xmlMetadata.get();
}
public Commander getCommander() {
return commander.get();
}
public void setCommander(Commander commander) {
this.commander.set(commander);
}
public ODataRawResponse getODataRawResponse() {
return oDataRawResponse.get();
}
public void setODataRawResponse(ODataRawResponse oDataRawResponse) {
this.oDataRawResponse.set(oDataRawResponse);
}
public Request getRequest() {
return request.get();
}
public void setRequest(Request request) {
this.request.set(request);
}
public URI getRequestUri() {
return requestUri.get();
}
public void setRequestUri(URI requestUri) {
this.requestUri.set(requestUri);
}
public Integer getResponseCode() {
return responseCode.get();
}
public void setResponseCode(Integer responseCode) {
this.responseCode.set(responseCode);
}
public String getResponseData() {
return responseData.get();
}
public void setResponseData(String responseData) {
this.responseData.set(responseData);
}
public String getInitialResponseData() {
return initialResponseData.get();
}
public void setInitialResponseData(String initialResponseData) {
this.initialResponseData.set(initialResponseData);
}
public ODataRawRequest getRawRequest() {
return rawRequest.get();
}
public void setRawRequest(ODataRawRequest oDataRawRequest) {
this.rawRequest.set(oDataRawRequest);
}
public ODataClientErrorException getODataClientErrorException() {
return oDataClientErrorException.get();
}
public void setODataClientErrorException(ODataClientErrorException oDataClientErrorException) {
this.oDataClientErrorException.set(oDataClientErrorException);
}
public ODataServerErrorException getODataServerErrorException() {
return oDataServerErrorException.get();
}
public void setODataServerErrorException(ODataServerErrorException oDataServerErrorException) {
this.oDataServerErrorException.set(oDataServerErrorException);
}
public String getServerODataHeaderVersion() {
return serverODataHeaderVersion.get();
}
public void setServerODataHeaderVersion(String serverODataHeaderVersion) {
this.serverODataHeaderVersion.set(serverODataHeaderVersion);
}
public Boolean getTestAppliesToServerODataHeaderVersion() {
return testAppliesToServerODataHeaderVersion.get();
}
public void setTestAppliesToServerODataHeaderVersion(Boolean testAppliesToServerODataHeaderVersion) {
this.testAppliesToServerODataHeaderVersion.set(testAppliesToServerODataHeaderVersion);
}
public ODataEntitySetRequest<ClientEntitySet> getClientEntitySetRequest() {
return clientEntitySetRequest.get();
}
public void setClientEntitySetRequest(ODataEntitySetRequest<ClientEntitySet> clientEntitySetRequest) {
this.clientEntitySetRequest.set(clientEntitySetRequest);
}
public ODataRetrieveResponse<ClientEntitySet> getClientEntitySetResponse() {
return clientEntitySetResponse.get();
}
public void setClientEntitySetResponse(ODataRetrieveResponse<ClientEntitySet> clientEntitySetResponse) {
this.clientEntitySetResponse.set(clientEntitySetResponse);
}
public ClientEntitySet getClientEntitySet() {
return clientEntitySet.get();
}
public void setClientEntitySet(ClientEntitySet clientEntitySet) {
this.clientEntitySet.set(clientEntitySet);
}
public String getServiceRoot() {
return serviceRoot.get();
}
public void setServiceRoot(String serviceRoot) {
this.serviceRoot.set(serviceRoot);
}
public String getBearerToken() {
return bearerToken.get();
}
public void setBearerToken(String bearerToken) {
this.bearerToken.set(bearerToken);
}
public String getClientId() {
return clientId.get();
}
public void setClientId(String clientId) {
this.clientId.set(clientId);
}
public String getClientSecret() {
return clientSecret.get();
}
public void setClientSecret(String clientSecret) {
this.clientSecret.set(clientSecret);
}
public String getAuthorizationUri() {
return authorizationUri.get();
}
public void setAuthorizationUri(String authorizationUri) {
this.authorizationUri.set(authorizationUri);
}
public String getTokenUri() {
return tokenUri.get();
}
public void setTokenUri(String tokenUri) {
this.tokenUri.set(tokenUri);
}
public String getRedirectUri() {
return redirectUri.get();
}
public void setRedirectUri(String redirectUri) {
this.redirectUri.set(redirectUri);
}
public String getScope() {
return scope.get();
}
public void setScope(String scope) {
this.scope.set(scope);
}
public String getPathToRESOScript() {
return pathToRESOScript.get();
}
public void setPathToRESOScript(String pathToRESOScript) {
this.pathToRESOScript.set(pathToRESOScript);
}
}

View File

@ -15,59 +15,59 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
public class Parameters { public class Parameters {
private final Map<String, String> parameters; private final Map<String, String> parameters;
public Parameters() { public Parameters() {
parameters = new LinkedHashMap<>(); parameters = new LinkedHashMap<>();
} }
public static Parameters loadFromRESOScript(File file) { public static Parameters loadFromRESOScript(File file) {
final String PARAMETERS_KEY = "Parameters"; final String PARAMETERS_KEY = "Parameters";
final String NAME_FIELD = "Name"; final String NAME_FIELD = "Name";
final String VALUE_FIELD = "Value"; final String VALUE_FIELD = "Value";
Map<String, String> settings = new LinkedHashMap<>(); Map<String, String> settings = new LinkedHashMap<>();
try { try {
FileInputStream fileIS = new FileInputStream(file); FileInputStream fileIS = new FileInputStream(file);
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder(); DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(fileIS); Document xmlDocument = builder.parse(fileIS);
XPath xPath = XPathFactory.newInstance().newXPath(); XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/OutputScript/" + PARAMETERS_KEY + "/node()"; String expression = "/OutputScript/" + PARAMETERS_KEY + "/node()";
NodeList nodes = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET); NodeList nodes = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
Node node; Node node;
String name, value; String name, value;
for (int i = 0; i < nodes.getLength(); i++) { for (int i = 0; i < nodes.getLength(); i++) {
node = nodes.item(i); node = nodes.item(i);
if (node != null && node.getNodeType() == Node.ELEMENT_NODE) { if (node != null && node.getNodeType() == Node.ELEMENT_NODE) {
name = node.getAttributes().getNamedItem(NAME_FIELD).getNodeValue(); name = node.getAttributes().getNamedItem(NAME_FIELD).getNodeValue();
value = node.getAttributes().getNamedItem(VALUE_FIELD).getNodeValue(); value = node.getAttributes().getNamedItem(VALUE_FIELD).getNodeValue();
settings.put(name, value); settings.put(name, value);
}
}
} catch (Exception e) {
e.printStackTrace();
} }
Parameters parameters = new Parameters(); }
parameters.getParameters().putAll(settings); } catch (Exception e) {
e.printStackTrace();
return parameters;
} }
Parameters parameters = new Parameters();
parameters.getParameters().putAll(settings);
public Map<String, String> getParameters() { return parameters;
return this.parameters; }
}
public String getValue(String name) { public Map<String, String> getParameters() {
return parameters.get(name); return this.parameters;
} }
public void putParameter(String name, String value) { public String getValue(String name) {
this.parameters.put(name, value); return parameters.get(name);
} }
public void putParameter(String name, String value) {
this.parameters.put(name, value);
}
} }

View File

@ -16,210 +16,225 @@ import java.util.Date;
import java.util.List; import java.util.List;
public class Request { public class Request {
private String requestId; private String requestId;
private String outputFile; private String outputFile;
private String url; private String url;
private Request request; private Request request;
private Status status; private Status status;
private Date startDate, endDate; private Date startDate, endDate;
private Integer httpResponseCode; private Integer httpResponseCode;
private Exception failedRequestException; private Exception failedRequestException;
/** /**
* Public constructor requires both outputFile and url. Remaining Request properties * Public constructor requires both outputFile and url. Remaining Request properties
* may be set individually after Request has been instantiated. * may be set individually after Request has been instantiated.
* *
* @param outputFile * @param outputFile
* @param url * @param url
*/ */
public Request(String url, String outputFile, String requestId) { public Request(String url, String outputFile, String requestId) {
setUrl(url); setUrl(url);
setOutputFile(outputFile); setOutputFile(outputFile);
setRequestId(requestId); setRequestId(requestId);
} }
/**
* Provides null handling for getting the requested item
*
* @param name the name of the item to get
* @param node the nod to get the named item from
* @return the named item, if present. Otherwise null
*/
private static String safeGetNamedItem(String name, Node node) {
Node named = name != null && node != null ? node.getAttributes().getNamedItem(name) : null;
return named != null ? named.getNodeValue() : null;
}
/** /**
* Gets the status of the given request * Loads the requests from the given File as an Observable List of Requests
* @return the status of the request *
*/ * @param file the file containing the requests
public Status getStatus() { * @return an Observable list of requests, or an exception is thrown
return status; */
} public static List<Request> loadFromRESOScript(File file) {
final String REQUESTS_KEY = "Requests";
ArrayList<Request> requests = new ArrayList<>();
/** try {
* Sets the status for the give request FileInputStream fileIS = new FileInputStream(file);
* @param status the status to set DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
* @return the current instance of the request DocumentBuilder builder = builderFactory.newDocumentBuilder();
*/ Document xmlDocument = builder.parse(fileIS);
public Request setStatus(Status status) { XPath xPath = XPathFactory.newInstance().newXPath();
this.status = status; String expression = "/OutputScript/" + REQUESTS_KEY + "/node()";
return this; NodeList nodes = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
} Node node;
String outputFile, url, requestId;
Request request;
/** for (int i = 0; i < nodes.getLength(); i++) {
* Starts request timer node = nodes.item(i);
* @return the current request
*/
public Request startTimer() {
startDate = new Date();
return this;
}
/** if (node.getNodeType() == Node.ELEMENT_NODE) {
* Stops request timer outputFile = safeGetNamedItem(FIELDS.OUTPUT_FILE, node);
* @return the current request url = safeGetNamedItem(FIELDS.URL, node);
*/ requestId = safeGetNamedItem(FIELDS.REQUEST_ID, node);
public Request stopTimer() {
endDate = new Date();
return this;
}
/** request = new Request(url, outputFile, requestId);
* Gets the elapsed time the request took to run requests.add(request);
* @return the elapsed time of the request in milliseconds
*/
public long getElapsedTimeMillis() {
return endDate != null && startDate != null ? endDate.getTime() - startDate.getTime() : 0L;
}
/**
* Sets the exception for a given request
* @param failedRequestException the exception that was thrown when the request was executed
*/
public void setFailedRequestException(Exception failedRequestException) {
this.failedRequestException = failedRequestException;
}
/**
* HTTP Response code getter
* @return an Integer representing the response code
*/
public Integer getHttpResponseCode() {
return httpResponseCode;
}
/**
* HTTP Response code setter
* @param httpResponseCode an Integer representing the HTTP Response code
*/
public void setHttpResponseCode(Integer httpResponseCode) {
this.httpResponseCode = httpResponseCode;
}
/**
* An enumeration of request status options
*/
public enum Status {
STARTED, SUCCEEDED, FAILED, SKIPPED
}
/**
* Provides null handling for getting the requested item
* @param name the name of the item to get
* @param node the nod to get the named item from
* @return the named item, if present. Otherwise null
*/
private static String safeGetNamedItem(String name, Node node) {
Node named = name != null && node != null ? node.getAttributes().getNamedItem(name) : null;
return named != null ? named.getNodeValue() : null;
}
/**
* Loads the requests from the given File as an Observable List of Requests
* @param file the file containing the requests
* @return an Observable list of requests, or an exception is thrown
*/
public static List<Request> loadFromRESOScript(File file) {
final String REQUESTS_KEY = "Requests";
ArrayList<Request> requests = new ArrayList<>();
try {
FileInputStream fileIS = new FileInputStream(file);
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(fileIS);
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/OutputScript/" + REQUESTS_KEY + "/node()";
NodeList nodes = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
Node node;
String outputFile, url, requestId;
Request request;
for (int i = 0; i < nodes.getLength(); i++) {
node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
outputFile = safeGetNamedItem(FIELDS.OUTPUT_FILE, node);
url = safeGetNamedItem(FIELDS.URL, node);
requestId = safeGetNamedItem(FIELDS.REQUEST_ID, node);
request = new Request(url, outputFile, requestId);
requests.add(request);
}
}
} catch (Exception e) {
e.printStackTrace();
} }
return requests; }
} catch (Exception e) {
e.printStackTrace();
} }
return requests;
}
/** /**
* Gets the given request by Id, if present. * Gets the status of the given request
* @return either the request Id or null if none was passed. May be null. *
*/ * @return the status of the request
public String getRequestId() { */
return requestId; public Status getStatus() {
} return status;
}
/** /**
* Sets the given request Id, if present. * Sets the status for the give request
* @param requestId the request Id to set. *
*/ * @param status the status to set
public void setRequestId(String requestId) { * @return the current instance of the request
this.requestId = requestId; */
} public Request setStatus(Status status) {
this.status = status;
return this;
}
/** /**
* Output file getter * Starts request timer
* @return the name of the output file for the request *
*/ * @return the current request
public String getOutputFile() { */
return outputFile; public Request startTimer() {
} startDate = new Date();
return this;
}
/** /**
* Output file setter * Stops request timer
* @param outputFile the name of the output file for the request (required, not null) *
*/ * @return the current request
private void setOutputFile(String outputFile) { */
this.outputFile = outputFile; public Request stopTimer() {
} endDate = new Date();
return this;
}
/** /**
* URL getter * Gets the elapsed time the request took to run
* @return the URL for the request, or null *
*/ * @return the elapsed time of the request in milliseconds
public String getUrl() { */
return url; public long getElapsedTimeMillis() {
} return endDate != null && startDate != null ? endDate.getTime() - startDate.getTime() : 0L;
}
/** /**
* URL setter * Sets the exception for a given request
* @param url the URL for the request, or null *
*/ * @param failedRequestException the exception that was thrown when the request was executed
private void setUrl(String url) { */
this.url = url; public void setFailedRequestException(Exception failedRequestException) {
} this.failedRequestException = failedRequestException;
}
/** /**
* Represents the known fields that can be in a serialized Request * HTTP Response code getter
*/ *
private static final class FIELDS { * @return an Integer representing the response code
static final String OUTPUT_FILE = "OutputFile"; */
static final String URL = "Url"; public Integer getHttpResponseCode() {
static final String REQUEST_ID = "RequestId"; return httpResponseCode;
} }
/**
* HTTP Response code setter
*
* @param httpResponseCode an Integer representing the HTTP Response code
*/
public void setHttpResponseCode(Integer httpResponseCode) {
this.httpResponseCode = httpResponseCode;
}
/**
* Gets the given request by Id, if present.
*
* @return either the request Id or null if none was passed. May be null.
*/
public String getRequestId() {
return requestId;
}
/**
* Sets the given request Id, if present.
*
* @param requestId the request Id to set.
*/
public void setRequestId(String requestId) {
this.requestId = requestId;
}
/**
* Output file getter
*
* @return the name of the output file for the request
*/
public String getOutputFile() {
return outputFile;
}
/**
* Output file setter
*
* @param outputFile the name of the output file for the request (required, not null)
*/
private void setOutputFile(String outputFile) {
this.outputFile = outputFile;
}
/**
* URL getter
*
* @return the URL for the request, or null
*/
public String getUrl() {
return url;
}
/**
* URL setter
*
* @param url the URL for the request, or null
*/
private void setUrl(String url) {
this.url = url;
}
/**
* An enumeration of request status options
*/
public enum Status {
STARTED, SUCCEEDED, FAILED, SKIPPED
}
/**
* Represents the known fields that can be in a serialized Request
*/
private static final class FIELDS {
static final String OUTPUT_FILE = "OutputFile";
static final String URL = "Url";
static final String REQUEST_ID = "RequestId";
}
} }

View File

@ -1,7 +1,10 @@
package org.reso.models; package org.reso.models;
import java.io.File; import java.io.File;
import java.util.*; import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/** /**
* The settings class contains all the settings a server can have, which currently means the following: * The settings class contains all the settings a server can have, which currently means the following:
@ -9,7 +12,9 @@ import java.util.*;
* * parameters - arbitrary collection of user-defined parameters * * parameters - arbitrary collection of user-defined parameters
* * requests - list of requests, one filter string per request, corresponding to a saved search * * requests - list of requests, one filter string per request, corresponding to a saved search
*/ */
public class Settings { public class Settings {
public static final String CLIENT_SETTING_PREFIX = "ClientSettings_";
public static final String PARAMETER_PREFIX = "Parameter_";
private ClientSettings clientSettings; private ClientSettings clientSettings;
private Parameters parameters; private Parameters parameters;
private Map<Request, Request> requests; private Map<Request, Request> requests;
@ -26,7 +31,8 @@ public class Settings {
* @param settings the settings to write. * @param settings the settings to write.
* @param filename the filename to save settings to. * @param filename the filename to save settings to.
*/ */
public static void saveToRESOScript(Settings settings, String filename) { /* TODO */ ; } public static void saveToRESOScript(Settings settings, String filename) { /* TODO */
}
/** /**
* Loads and returns settings from the given file. * Loads and returns settings from the given file.
@ -46,9 +52,6 @@ public class Settings {
return settings; return settings;
} }
public static final String CLIENT_SETTING_PREFIX = "ClientSettings_";
public static final String PARAMETER_PREFIX = "Parameter_";
/** /**
* Resolves the parameters in request with parameters. * Resolves the parameters in request with parameters.
* *
@ -62,8 +65,9 @@ public class Settings {
/** /**
* Resolves URIs containing special RESOScript parameters of the form *Parameter_X* and *ClientSettings_Y* * Resolves URIs containing special RESOScript parameters of the form *Parameter_X* and *ClientSettings_Y*
*
* @param parameterString the parameter string to resolve, possibly containing nested parameter settings * @param parameterString the parameter string to resolve, possibly containing nested parameter settings
* @param settings the settings to use to resolve the parameters * @param settings the settings to use to resolve the parameters
* @return the resolved parameter string * @return the resolved parameter string
*/ */
public static String resolveParametersString(String parameterString, Settings settings) { public static String resolveParametersString(String parameterString, Settings settings) {
@ -128,14 +132,26 @@ public class Settings {
/** /**
* Requests getter. * Requests getter.
*
* @return The request map that was loaded, indexed by request name. * @return The request map that was loaded, indexed by request name.
*/ */
public Map<Request, Request> getRequests() { public Map<Request, Request> getRequests() {
return requests; return requests;
} }
/**
* Requests setter.
*
* @param requests a list of requests to create the request map from
*/
private void setRequests(List<Request> requests) {
this.requests = new LinkedHashMap<Request, Request>();
requests.forEach(request -> this.requests.put(request, request));
}
/** /**
* Requests getter. * Requests getter.
*
* @return The request map that was loaded, indexed by request name. * @return The request map that was loaded, indexed by request name.
*/ */
public Request getRequestById(String requestId) { public Request getRequestById(String requestId) {
@ -159,14 +175,4 @@ public class Settings {
public List<Request> getRequestsAsList() { public List<Request> getRequestsAsList() {
return new ArrayList<>(requests.values()); return new ArrayList<>(requests.values());
} }
/**
* Requests setter.
*
* @param requests a list of requests to create the request map from
*/
private void setRequests(List<Request> requests) {
this.requests = new LinkedHashMap<Request, Request>();
requests.forEach(request -> this.requests.put(request, request));
}
} }