Added convenience methods for Gold and Platinum Web API Certs, Updated Docker Instructions and README

Tightened up metadata checking, including checking for given resource and select list. Added better debugging info. Updated README.
This commit is contained in:
Joshua Darnell 2020-03-05 21:15:43 -08:00
parent 82456bcf14
commit a3687b9f6a
8 changed files with 699 additions and 333 deletions

205
README.md
View File

@ -335,51 +335,99 @@ ability to run individual or multiple tests using tags.
### Web API Usage ### Web API Usage
The Commander may be run in automated testing mode for a Web API 1.0.2 Server Certification using a terminal. You do not need to use the Commander JAR file mentioned elsewhere in this step. Instead, you will run the tests using Gradle for automation against a clean copy of the latest Commander code. The Commander may be run in automated testing mode for a Web API 1.0.2 Server Certification using a terminal.
You do not need to use the Commander JAR file mentioned elsewhere in this step.
Instead, you will run the tests using Gradle for automation against a clean copy of the latest Commander code.
You will need to download the source code so you can run Gradle in the root of the directory. This assumes that you also have Java 8 (1.8.0) or above installed, as mentioned elsewhere in this [`README`](#getting-started). You will need to download the source code so you can run Gradle in the root of the directory.
This assumes that you also have Java 8 (1.8.0) or above installed, as mentioned elsewhere in this [`README`](#getting-started).
First, change into the directory you want to work in and clone the Commander repository. You will need to have Git installed. Chances are you already do, to check, open a command line and type `git` and if it's present, it will print some info about the app. If not, [there are instructions here](https://git-scm.com/downloads). First, change into the directory you want to work in and clone the Commander repository.
You will need to have Git installed.
Chances are you already do, to check, open a command line and type `git` and if it's present,
it will print some info about the app. If not, [there are instructions here](https://git-scm.com/downloads).
**MacOS or Linux** ##### MacOS or Linux
``` ```
$ git clone https://github.com/RESOStandards/web-api-commander.git $ git clone https://github.com/RESOStandards/web-api-commander.git
``` ```
**Windows** ##### Windows
``` ```
C:\> git clone https://github.com/RESOStandards/web-api-commander.git C:\> git clone https://github.com/RESOStandards/web-api-commander.git
``` ```
This will clone the repository into a directory called web-api-commander, which means you will have a fresh copy of the latest code to execute. To refresh the code after you have downloaded it, issue the command `$ git pull` in the root of the directory that was just created. This will clone the repository into a directory called web-api-commander relative to whatever directory you're currently in,
which also means you'll have a fresh copy of the latest code to execute.
To refresh the code after you have downloaded it, issue the command `$ git pull` in the root of the directory that was just created.
The Gradle wrapper provides a convenient way to automatically install Gradle when running tests. After you have cloned the repository, issuing the following command: #### Running with the Gradle Wrapper
The Gradle wrapper provides a convenient way to automatically install Gradle when running tests.
**MacOS or Linux** After you have cloned the repository, the task you run will depend on the level of Web API 1.0.2 Server Certification
you're interested in.
Before you do that, however, you'll want to make sure that you are running the 6.2.2 version of Gradle.
In the project directory, perform one of the following steps:
##### MacOS or Linux
```$ ./gradlew wrapper --gradle-version 6.2.2 --distribution-type all```
##### Windows
```C:\path\to\web-api-commander> gradlew wrapper --gradle-version 6.2.2 --distribution-type all```
You should see a success message. For more information, [see here](https://docs.gradle.org/current/userguide/gradle_wrapper.html).
### Convenience Methods for Web API 1.0.2 Gold and Platinum Certification (Recommended)
While you may use tags to filter tests as you choose, explained in the next section, it's convenient
to be able to run a predefined set of tests for Gold or Platinum certification.
These tasks will also produce reports in the local `build` directory, named according to which test you ran.
#### Gold Certification
This will run the Gold tests against the Web API 1.0.2 Server provided as `WebAPIURI` in `your.resoscript` file.
##### MacOS or Linux
``` ```
$ ./gradlew testWebAPIServer_1_0_2 -DpathToRESOScript=/path/to/your.resoscript $ ./gradlew testWebAPIServer_1_0_2_Gold -DpathToRESOScript=/path/to/your.resoscript -DshowResponses=true
``` ```
**Windows** ##### Windows
``` ```
C:\path\to\web-api-commander> gradlew.bat testWebAPIServer_1_0_2 -DpathToRESOScript=C:\path\to\your.resoscript C:\path\to\web-api-commander> gradlew testWebAPIServer_1_0_2_Gold -DpathToRESOScript=C:\path\to\your.resoscript -DshowResponses=true
``` ```
This will run the entirety of the tests against the Web API server provided as `WebAPIURI` in `your.resoscript` file. You can pass tags to filter on in order to run one or more tests matching the given tag. *Note: the first time you run these tasks, they will take some time as the environment is being configured behind the
scenes and the code is being compiled from the contents of the source directory you downloaded in the previous step.
Note that the first time you run this command, it will take some time to complete as Gradle will download all dependencies and compile the application before running the test suite. *Note: this step will be Dockerized so it can be run with a single command in a Docker container in upcoming versions of the Commander.* #### Platinum Certification
This will run the Platinum tests against the Web API 1.0.2 Server provided as `WebAPIURI` in `your.resoscript` file.
##### MacOS or Linux
To filter by tags, a command similar to the following would be used:
**MacOS or Linux**
``` ```
$ gradle testWebAPIServer_1_0_2 -DpathToRESOScript=/path/to/your.resoscript -Dcucumber.filter.tags="@core" $ ./gradlew testWebAPIServer_1_0_2_Platinum -DpathToRESOScript=/path/to/your.resoscript -DshowResponses=true
``` ```
**Windows** ##### Windows
``` ```
C:\path\to\web-api-commander> gradlew.bat testWebAPIServer_1_0_2 -DpathToRESOScript=C:\path\to\your.resoscript -Dcucumber.filter.tags="@core" C:\path\to\web-api-commander> gradlew testWebAPIServer_1_0_2_Platinum -DpathToRESOScript=C:\path\to\your.resoscript -DshowResponses=true
```
#### Advanced feature: Tag Filtering
You may also filter by tags. These are the items in the Cucumber .feature files prefixed by an `@` symbol. Expressions
may also be used with tags. See the [Cucumber Documentation](https://cucumber.io/docs/cucumber/api/#tags) for more information.
##### MacOS or Linux
```
$ gradle testWebAPIServer_1_0_2_Platinum -DpathToRESOScript=/path/to/your.resoscript -Dcucumber.filter.tags="@core"
```
##### Windows
```
C:\path\to\web-api-commander> gradlew.bat testWebAPIServer_1_0_2_Platinum -DpathToRESOScript=C:\path\to\your.resoscript -Dcucumber.filter.tags="@core"
``` ```
This would run only the tests marked as `@core` in the This would run only the tests marked as `@core` in the
@ -403,32 +451,48 @@ Please feel free to suggest additional tags that might be useful.
A sample of the runtime terminal output follows: A sample of the runtime terminal output follows:
``` ```gherkin
@REQ-WA103-END3 @core @x.y.z @core-support-endorsement > Task :testWebApiServer_1_0_2_Platinum
Scenario: REQ-WA103-END3 - CORE - Request and Validate Server Metadata
@REQ-WA103-END3 @core @x.y.z @core-endorsement @metadata
Scenario: Request and Validate Server Metadata
Using RESOScript: /path/to/your.resoscript Using RESOScript: /path/to/your.resoscript
Given a RESOScript file was provided Given a RESOScript file was provided
RESOScript loaded successfully! RESOScript loaded successfully!
And Client Settings and Parameters were read from the file And Client Settings and Parameters were read from the file
Bearer token loaded... first 4 characters: abcd Bearer token loaded... first 4 characters: abcd
Service root is: https://api.server.com/serviceRoot Service root is: https://api.server.com/
And an OData client was successfully created from the given RESOScript And an OData client was successfully created from the given RESOScript
Request URI: https://api.server.com/serviceRoot/$metadata?$format=application/xml Fetching XMLMetadata with OData Client from: https://api.server.com/$metadata
Request succeeded...185032 bytes received. When a successful metadata request is made to the service root in "ClientSettings_WebAPIURI"
When a GET request is made to the resolved Url in "REQ-WA103-END3"
Response code is: 200
Then the server responds with a status code of 200
Response is valid XML!
And the response is valid XML
Metadata is valid! Metadata is valid!
And the metadata returned is valid And the metadata returned is valid
Fetching Edm with OData Client from: https://api.server.com/$metadata
Found EntityContainer for the given resource: 'Property'
And the metadata contains the "Parameter_EndpointResource" resource
Searching metadata for fields in given select list: ListingKey,BedroomsTotal,StreetName,PropertyType,ListingContractDate,ModificationTimestamp,Latitude,Longitude
Found: 'ListingKey'
Found: 'BedroomsTotal'
Found: 'StreetName'
Found: 'PropertyType'
Found: 'ListingContractDate'
Found: 'ModificationTimestamp'
Found: 'Latitude'
Found: 'Longitude'
And resource metadata for "Parameter_EndpointResource" contains the fields in "Parameter_SelectList"
1 Scenarios (1 passed)
7 Steps (7 passed)
0m3.244s
``` ```
This shows configuration parameters, requests, and responses in a lightweight-manner. This shows configuration parameters, requests, and responses in a lightweight-manner.
@ -456,24 +520,73 @@ These commands should not be necessary for the normal use of the Commander. Ther
A [Dockerfile](./Dockerfile) has been provided to dockerize the application. A [Dockerfile](./Dockerfile) has been provided to dockerize the application.
This can be used for CI/CD environments such as Jenkins or TravisCI. The following command will build an image for you: This can be used for CI/CD environments such as Jenkins or TravisCI. The following command will build an image for you:
### Commander Features Other Than Automated Web API Testing
``` ```
$ docker build -t darnjo/web-api-command . $ docker build -t web-api-commander .
``` ```
The usage for the docker container is the same for `web-api-commander.jar` presented above. The usage for the docker container is the same for `web-api-commander.jar` presented above.
``` ```
$ docker run -it darnjo/web-api-commander --help $ docker run -it web-api-commander --help
``` ```
If you have input files you may need to mount your filesystem into the docker container If you have input files you may need to mount your filesystem into the docker container
``` ```
$ docker run -it -v $PWD:/app darnjo/web-api-commander --validateMetadata --inputFile <pathInContainer> $ docker run -it -v $PWD:/app web-api-commander --validateMetadata --inputFile <pathInContainer>
```
### Automated Web API Testing
You may also run the tests in a Docker container locally by issuing one of the following commands.
Docker must be running on your local machine.
#### MacOS or Linux All-In-One Commands
##### Gold
```
cd ~; \
rm -rf commander-tmp/; \
mkdir commander-tmp; \
cd commander-tmp; \
git clone https://github.com/RESOStandards/web-api-commander.git; \
cd web-api-commander; \
docker run --rm -u gradle -v "$PWD":/home/gradle/project -v /path/to/your/resoscripts:/home/gradle/project/resoscripts -w /home/gradle/project gradle gradle testWebAPIServer_1_0_2_Gold -DpathToRESOScript=/home/gradle/project/resoscripts/your.resoscript -DshowResponses=true
```
##### Platinum
```
cd ~; \
rm -rf commander-tmp/; \
mkdir commander-tmp; \
cd commander-tmp; \
git clone https://github.com/RESOStandards/web-api-commander.git; \
cd web-api-commander; \
docker run --rm -u gradle -v "$PWD":/home/gradle/project -v /path/to/your/resoscripts:/home/gradle/project/resoscripts -w /home/gradle/project gradle gradle testWebAPIServer_1_0_2_Platinum -DpathToRESOScript=/home/gradle/project/resoscripts/your.resoscript -DshowResponses=true
```
Note that this will create a directory in your home directory for the project, and build artifacts and the log will be placed in that directory,
which is also where you will end up after runtime.
#### Windows All-In-One WIP
##### Gold
```
cd C:\;mkdir commander-tmp;cd commander-tmp;git clone https://github.com/RESOStandards/web-api-commander.git;cd web-api-commander; docker run --rm -u gradle -v C:\current\path\web-api-commander:/home/gradle/project -v C:\path\to\your\resoscripts:/home/gradle/project/resoscripts -w /home/gradle/project gradle gradle testWebAPIServer_1_0_2_Gold -DpathToRESOScript=/home/gradle/project/resoscripts/your.resoscript -DshowResponses=true
```
##### Platinum
```
cd C:\;mkdir commander-tmp;cd commander-tmp;git clone https://github.com/RESOStandards/web-api-commander.git;cd web-api-commander;docker run --rm -u gradle -v C:\current\path\web-api-commander:/home/gradle/project -v C:\path\to\your\resoscripts:/home/gradle/project/resoscripts -w /home/gradle/project gradle gradle testWebAPIServer_1_0_2_Platinum -DpathToRESOScript=/home/gradle/project/resoscripts/your.resoscript -DshowResponses=true
``` ```
--- ---
## Logging ## Logging
In the current version of the Commander, two logs are produced. One is outputted in the terminal at `INFO` level during runtime through `stdout`. A detailed log called `commander.log` will be outputted at runtime and will contain details down to the wire requests. In the current version of the Commander, two logs are produced. One is outputted in the terminal at `INFO` level during runtime through `stdout`. A detailed log called `commander.log` will be outputted at runtime and will contain details down to the wire requests.
@ -491,4 +604,4 @@ Please contact [josh@reso.org](mailto:josh@reso.org) with any questions, bug rep
* Support for authentication options in addition to Bearer tokens (Client Credentials in beta, please email for more info). * Support for authentication options in addition to Bearer tokens (Client Credentials in beta, please email for more info).
* Parallel fetch for replication * Parallel fetch for replication
* Job Scheduling * Job Scheduling
* Excel export * Excel export

View File

@ -67,26 +67,54 @@ tasks.withType(JavaCompile) {
options.deprecation = true options.deprecation = true
} }
// task for Web API Server Testing - this is what should be run in the command line
task testWebApiServer_1_0_2() { // task for Web API Server 1.0.2 Gold Testing
task testWebApiServer_1_0_2_Gold() {
dependsOn jar dependsOn jar
doLast { doLast {
javaexec { javaexec {
main = "io.cucumber.core.cli.Main" main = "io.cucumber.core.cli.Main"
classpath = configurations.cucumberRuntime + sourceSets.main.output + sourceSets.test.output classpath = configurations.cucumberRuntime + sourceSets.main.output + sourceSets.test.output
systemProperties = System.getProperties()
args = [ args = [
'--strict', '--strict',
'--plugin', '--plugin',
'pretty', 'pretty',
'--plugin', '--plugin',
'json:build/web-api-server-1.0.2.json', 'json:build/web-api-server-1.0.2.gold.json',
'--plugin', '--plugin',
'html:build/web-api-server-1.0.2.html', 'html:build/web-api-server-1.0.2.gold.html',
'--glue',
'org.reso.certification.stepdefs#WebAPIServer_1_0_2',
'src/main/java/org/reso/certification/features',
'--tags',
'not @platinum'
+ (systemProperties.get('cucumber.filter.tags') != null ? ' and ' + systemProperties.get('cucumber.filter.tags') : '')
]
}
}
}
// task for Web API Server 1.0.2 Platinum Testing - currently equivalent to all, but generates a platinum-named report.
task testWebApiServer_1_0_2_Platinum() {
dependsOn jar
doLast {
javaexec {
main = "io.cucumber.core.cli.Main"
classpath = configurations.cucumberRuntime + sourceSets.main.output + sourceSets.test.output
systemProperties = System.getProperties()
args = [
'--strict',
'--plugin',
'pretty',
'--plugin',
'json:build/web-api-server-1.0.2.platinum.json',
'--plugin',
'html:build/web-api-server-1.0.2.platinum.html',
'--glue', '--glue',
'org.reso.certification.stepdefs#WebAPIServer_1_0_2', 'org.reso.certification.stepdefs#WebAPIServer_1_0_2',
'src/main/java/org/reso/certification/features' 'src/main/java/org/reso/certification/features'
] ]
systemProperties = System.getProperties()
} }
} }
} }

Binary file not shown.

View File

@ -7,5 +7,4 @@
* in the user manual at https://docs.gradle.org/5.2.1/userguide/multi_project_builds.html * in the user manual at https://docs.gradle.org/5.2.1/userguide/multi_project_builds.html
*/ */
rootProject.name = 'web-api-commander' rootProject.setName('web-api-commander')

View File

@ -6,12 +6,12 @@ Feature: Web API Server 1.0.2 Certification
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 an OData client was successfully created from the given RESOScript
@REQ-WA103-END3 @core @x.y.z @core-endorsement @REQ-WA103-END3 @core @x.y.z @core-endorsement @metadata
Scenario: Request and Validate Server Metadata Scenario: Request and Validate Server Metadata
When a GET request is made to the resolved Url in "REQ-WA103-END3" When a successful metadata request is made to the service root in "ClientSettings_WebAPIURI"
Then the server responds with a status code of 200
And the response is valid XML
And the metadata returned is valid And the metadata returned is valid
And the metadata contains the "Parameter_EndpointResource" resource
And resource metadata for "Parameter_EndpointResource" contains the fields in "Parameter_SelectList"
@REQ-WA103-END2 @core @x.y.z @core-endorsement @REQ-WA103-END2 @core @x.y.z @core-endorsement
Scenario: Data System Endpoint test Scenario: Data System Endpoint test

View File

@ -14,8 +14,11 @@ import org.apache.olingo.client.api.communication.ODataClientErrorException;
import org.apache.olingo.client.api.communication.request.retrieve.ODataRawRequest; 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.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.EdmPrimitiveTypeException; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer;
import org.apache.olingo.commons.api.edm.provider.CsdlProperty;
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;
@ -28,7 +31,10 @@ import java.io.*;
import java.net.URI; import java.net.URI;
import java.sql.Time; import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.*; import java.time.Instant;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.Year;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -116,6 +122,10 @@ public class WebAPIServer_1_0_2 implements En {
serverODataHeaderVersion.set(Utils.getHeaderData(HEADER_ODATA_VERSION, cex.getHeaderInfo())); serverODataHeaderVersion.set(Utils.getHeaderData(HEADER_ODATA_VERSION, cex.getHeaderInfo()));
responseCode.set(cex.getStatusLine().getStatusCode()); responseCode.set(cex.getStatusLine().getStatusCode());
oDataClientErrorExceptionHandled.set(true); oDataClientErrorExceptionHandled.set(true);
throw cex;
} catch (Exception ex) {
fail(ex.toString());
throw ex;
} }
return null; return null;
}; };
@ -127,12 +137,15 @@ public class WebAPIServer_1_0_2 implements En {
if (pathToRESOScript == null) { if (pathToRESOScript == null) {
pathToRESOScript = System.getProperty("pathToRESOScript"); pathToRESOScript = System.getProperty("pathToRESOScript");
} }
assertNotNull("ERROR: pathToRESOScript must be present in command arguments, see README", pathToRESOScript);
LOG.info("Using RESOScript: " + pathToRESOScript); LOG.info("Using RESOScript: " + pathToRESOScript);
}); });
And("^Client Settings and Parameters were read from the file$", () -> { And("^Client Settings and Parameters were read from the file$", () -> {
if (settings == null) { if (settings == null) {
settings = Settings.loadFromRESOScript(new File(System.getProperty("pathToRESOScript"))); settings = Settings.loadFromRESOScript(new File(System.getProperty("pathToRESOScript")));
} }
assertNotNull("ERROR: Settings could not be loaded.", settings);
LOG.info("RESOScript loaded successfully!"); LOG.info("RESOScript loaded successfully!");
}); });
Given("^an OData client was successfully created from the given RESOScript$", () -> { Given("^an OData client was successfully created from the given RESOScript$", () -> {
@ -165,6 +178,10 @@ public class WebAPIServer_1_0_2 implements En {
.bearerToken(bearerToken) .bearerToken(bearerToken)
.useEdmEnabledClient(true) .useEdmEnabledClient(true)
.build()); .build());
assertNotNull(commander.get());
assertTrue("ERROR: Commander must either have a valid bearer token or Client Credentials configuration.",
commander.get().isTokenClient() || (commander.get().isOAuthClient() && commander.get().getTokenUri() != null));
}); });
@ -180,13 +197,17 @@ public class WebAPIServer_1_0_2 implements En {
* REQ-WA103-END3 * REQ-WA103-END3
*/ */
And("^the metadata returned is valid$", () -> { And("^the metadata returned is valid$", () -> {
//store the metadata for later comparisons if (xmlMetadata.get() == null) {
xmlMetadata.set(commander.get().getClient().getDeserializer(ContentType.APPLICATION_XML) fail("ERROR: No XML Metadata Exists!");
.toMetadata(new ByteArrayInputStream(responseData.get().getBytes()))); }
boolean isValid = commander.get().validateMetadata(xmlMetadata.get()); try {
LOG.info("Metadata is " + (isValid ? "valid" : "invalid") + "!"); boolean isValid = commander.get().validateMetadata(xmlMetadata.get());
assertTrue(isValid); LOG.info("Metadata is " + (isValid ? "valid" : "invalid") + "!");
assertTrue(isValid);
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
@ -194,24 +215,28 @@ public class WebAPIServer_1_0_2 implements En {
* 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) -> {
String expectedValueAsString = Settings.resolveParametersString(parameterUniqueIdValue, settings), resolvedValueAsString = null; try {
Object resolvedValue = from(responseData.get()).get(Settings.resolveParametersString(parameterUniqueId, settings)); String expectedValueAsString = Settings.resolveParametersString(parameterUniqueIdValue, settings), resolvedValueAsString = null;
Object resolvedValue = from(responseData.get()).get(Settings.resolveParametersString(parameterUniqueId, settings));
//both of the inputs should be present //both of the inputs should be present
assertNotNull(expectedValueAsString); assertNotNull(expectedValueAsString);
assertNotNull(resolvedValue); assertNotNull(resolvedValue);
//quotes are passed for strings, let's strip them off //quotes are passed for strings, let's strip them off
expectedValueAsString = expectedValueAsString expectedValueAsString = expectedValueAsString
.replace("'", "").replace("\"", ""); .replace("'", "").replace("\"", "");
LOG.info("Expected Value is: " + expectedValueAsString); LOG.info("Expected Value is: " + expectedValueAsString);
LOG.info("Resolved value is: " + resolvedValue); LOG.info("Resolved value is: " + resolvedValue);
if (resolvedValue.getClass().isInstance(Integer.class)) { if (resolvedValue.getClass().isInstance(Integer.class)) {
assertEquals(Integer.parseInt(expectedValueAsString), resolvedValue); assertEquals(Integer.parseInt(expectedValueAsString), resolvedValue);
} else { } else {
assertEquals(expectedValueAsString, resolvedValue.toString()); assertEquals(expectedValueAsString, resolvedValue.toString());
}
} catch (Exception ex) {
fail(ex.getMessage());
} }
}); });
@ -220,32 +245,37 @@ public class WebAPIServer_1_0_2 implements En {
* REQ-WA103-QR3 - $select * REQ-WA103-QR3 - $select
*/ */
And("^data are present in fields contained within \"([^\"]*)\"$", (String parameterSelectList) -> { And("^data are present in fields contained within \"([^\"]*)\"$", (String parameterSelectList) -> {
AtomicInteger numFieldsWithData = new AtomicInteger(); try {
List<String> fieldList = new ArrayList<>(Arrays.asList(Settings.resolveParametersString(parameterSelectList, settings).split(","))); AtomicInteger numFieldsWithData = new AtomicInteger();
List<String> fieldList = new ArrayList<>(Arrays.asList(Settings.resolveParametersString(parameterSelectList, settings).split(",")));
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
from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { //iterate over the items and count the number of fields with data to determine whether there are data present
if (item != null) { from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
numResults.getAndIncrement(); if (item != null) {
fieldList.forEach(field -> { numResults.getAndIncrement();
if (item.get(field) != null) { fieldList.forEach(field -> {
numFieldsWithData.getAndIncrement(); if (item.get(field) != null) {
} numFieldsWithData.getAndIncrement();
}); }
});
}
});
LOG.info("Number of Results: " + numResults.get());
LOG.info("Number of Fields: " + fieldList.size());
LOG.info("Fields with Data: " + numFieldsWithData.get());
if (numFieldsWithData.get() > 0) {
LOG.info("Percent Fill: " + ((numResults.get() * fieldList.size()) / (1.0 * numFieldsWithData.get()) * 100) + "%");
} else {
LOG.info("Percent Fill: 0% - no fields with data found!");
} }
}); assertTrue(numFieldsWithData.get() > 0);
} catch (Exception ex) {
LOG.info("Number of Results: " + numResults.get()); fail(ex.getMessage());
LOG.info("Number of Fields: " + fieldList.size());
LOG.info("Fields with Data: " + numFieldsWithData.get());
if (numFieldsWithData.get() > 0) {
LOG.info("Percent Fill: " + ((numResults.get() * fieldList.size()) / (1.0 * numFieldsWithData.get()) * 100) + "%");
} else {
LOG.info("Percent Fill: 0% - no fields with data found!");
} }
assertTrue(numFieldsWithData.get() > 0);
}); });
@ -254,13 +284,17 @@ public class WebAPIServer_1_0_2 implements En {
* $top=*Parameter_TopCount* * $top=*Parameter_TopCount*
*/ */
And("^the results contain at most \"([^\"]*)\" records$", (String parameterTopCount) -> { And("^the results contain at most \"([^\"]*)\" records$", (String parameterTopCount) -> {
List<String> items = from(responseData.get()).getList(JSON_VALUE_PATH); try {
AtomicInteger numResults = new AtomicInteger(items.size()); List<String> items = from(responseData.get()).getList(JSON_VALUE_PATH);
AtomicInteger numResults = new AtomicInteger(items.size());
int topCount = Integer.parseInt(Settings.resolveParametersString(parameterTopCount, settings)); int topCount = Integer.parseInt(Settings.resolveParametersString(parameterTopCount, settings));
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(numResults.get() > 0 && numResults.get() <= topCount); assertTrue(numResults.get() > 0 && numResults.get() <= topCount);
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
@ -269,29 +303,37 @@ public class WebAPIServer_1_0_2 implements En {
* $skip=*Parameter_TopCount* * $skip=*Parameter_TopCount*
*/ */
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) -> {
int skipCount = Integer.parseInt(Settings.resolveParametersString(parameterTopCount, settings)); try {
LOG.info("Skip count is: " + skipCount); int skipCount = Integer.parseInt(Settings.resolveParametersString(parameterTopCount, settings));
LOG.info("Skip count is: " + skipCount);
//preserve initial response data for later comparisons //preserve initial response data for later comparisons
initialResponseData.set(responseData.get()); initialResponseData.set(responseData.get());
//TODO: convert to OData filter factory //TODO: convert to OData filter factory
URI requestUri = Commander.prepareURI(Settings.resolveParameters(settings.getRequests().get(requirementId), settings).getUrl() + "&$skip=" + skipCount); URI requestUri = Commander.prepareURI(Settings.resolveParameters(settings.getRequests().get(requirementId), settings).getUrl() + "&$skip=" + skipCount);
executeGetRequest.apply(requestUri); executeGetRequest.apply(requestUri);
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
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) -> {
List<POJONode> l1 = from(initialResponseData.get()).getJsonObject(JSON_VALUE_PATH); try {
List<POJONode> l2 = from(responseData.get()).getJsonObject(JSON_VALUE_PATH); List<POJONode> l1 = from(initialResponseData.get()).getJsonObject(JSON_VALUE_PATH);
List<POJONode> l2 = from(responseData.get()).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);
LOG.info("Response Page 1: " + new POJONode(l1)); LOG.info("Response Page 1: " + new POJONode(l1));
combined.addAll(l2); combined.addAll(l2);
LOG.info("Response Page 2: " + new POJONode(l2)); LOG.info("Response Page 2: " + new POJONode(l2));
assertEquals(combinedCount, combined.size()); assertEquals(combinedCount, combined.size());
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
//================================================================================================================== //==================================================================================================================
@ -302,65 +344,78 @@ public class WebAPIServer_1_0_2 implements En {
* GET request by requirementId (see generic.resoscript) * GET request by requirementId (see generic.resoscript)
*/ */
When("^a GET request is made to the resolved Url in \"([^\"]*)\"$", (String requirementId) -> { When("^a GET request is made to the resolved Url in \"([^\"]*)\"$", (String requirementId) -> {
//reset local state each time a get request is run try {
resetRequestState.run(); //reset local state each time a get request is run
resetRequestState.run();
URI requestUri = Commander.prepareURI(Settings.resolveParameters(settings.getRequests().get(requirementId), settings).getUrl()); URI requestUri = Commander.prepareURI(Settings.resolveParameters(settings.getRequests().get(requirementId), settings).getUrl());
executeGetRequest.apply(requestUri); executeGetRequest.apply(requestUri);
} catch (Exception ex) {
LOG.debug("Exception was thrown in " + this.getClass() + ": " + ex.toString());
}
}); });
/* /*
* Assert response code * Assert response code
*/ */
Then("^the server responds with a status code of (\\d+)$", (Integer assertedResponseCode) -> { Then("^the server responds with a status code of (\\d+)$", (Integer assertedResponseCode) -> {
LOG.info("Asserted Response Code: " + assertedResponseCode + ", Server Response Code: " + responseCode); try {
assertTrue(responseCode.get() > 0 && assertedResponseCode > 0); LOG.info("Asserted Response Code: " + assertedResponseCode + ", Server Response Code: " + responseCode);
assertEquals(assertedResponseCode.intValue(), responseCode.get().intValue()); assertTrue(responseCode.get() > 0 && assertedResponseCode > 0);
assertEquals(assertedResponseCode.intValue(), responseCode.get().intValue());
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
/* /*
* validate XML wrapper * validate XML wrapper
*/ */
And("^the response is valid XML$", () -> { And("^the response is valid XML$", () -> {
assertTrue(Commander.validateXML(responseData.get())); try {
LOG.info("Response is valid XML!"); assertTrue(Commander.validateXML(responseData.get()));
LOG.info("Response is valid XML!");
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
/* /*
* validate JSON wrapper * validate JSON wrapper
*/ */
And("^the response is valid JSON$", () -> { And("^the response is valid JSON$", () -> {
assertTrue(Utils.isValidJson(responseData.get())); try {
LOG.info("Response is valid JSON!"); assertTrue(Utils.isValidJson(responseData.get()));
LOG.info("Response is valid JSON!");
String showResponses = System.getProperty("showResponses"); String showResponses = System.getProperty("showResponses");
if (Boolean.parseBoolean(showResponses)) { if (Boolean.parseBoolean(showResponses)) {
LOG.info("Response: " + new ObjectMapper().readTree(responseData.get()).toPrettyString()); LOG.info("Response: " + new ObjectMapper().readTree(responseData.get()).toPrettyString());
}
} catch (Exception ex) {
fail(ex.getMessage());
} }
}); });
/*
* Assert OData version
*/
And("^the server reports OData version \"([^\"]*)\"$", (String assertODataVersion) -> {
LOG.info("Asserted version: " + assertODataVersion + ", Reported OData Version: " + serverODataHeaderVersion.get()); ;
assertEquals(serverODataHeaderVersion.get(), assertODataVersion);
});
/* /*
* Assert HTTP Response Code given asserted OData version * Assert HTTP Response Code given asserted OData version
* *
* TODO: make a general Header assertion function * TODO: make a general Header assertion function
*/ */
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) -> {
boolean versionsMatch = serverODataHeaderVersion.get().equals(assertedODataVersion), try {
responseCodesMatch = responseCode.get().intValue() == assertedHttpResponseCode.intValue(); boolean versionsMatch = serverODataHeaderVersion.get().equals(assertedODataVersion),
responseCodesMatch = responseCode.get().intValue() == assertedHttpResponseCode.intValue();
LOG.info("Asserted OData Version: " + assertedODataVersion + ", Server Version: " + serverODataHeaderVersion.get()); LOG.info("Asserted OData Version: " + assertedODataVersion + ", Server Version: " + serverODataHeaderVersion.get());
if (versionsMatch) { if (versionsMatch) {
LOG.info("Asserted Response Code: " + assertedHttpResponseCode + ", Response code: " + responseCode.get()); LOG.info("Asserted Response Code: " + assertedHttpResponseCode + ", Response code: " + responseCode.get());
assertTrue(responseCodesMatch); assertTrue(responseCodesMatch);
}
} catch (Exception ex) {
//DEBUG only in this case as we are expecting an error and don't want to throw or print it
LOG.debug(ex.toString());
} }
}); });
@ -369,59 +424,76 @@ public class WebAPIServer_1_0_2 implements En {
* and is used to select among the supported comparisons. * and is used to select among the supported comparisons.
*/ */
And("^Integer data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> { And("^Integer data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); try {
int assertedValue = Integer.parseInt(Settings.resolveParametersString(parameterAssertedValue, settings)); String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
int assertedValue = Integer.parseInt(Settings.resolveParametersString(parameterAssertedValue, settings));
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(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(responseData.get()).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() && Utils.compare(fieldValue.get(), op, assertedValue)); result.set(result.get() && Utils.compare(fieldValue.get(), op, assertedValue));
}); });
assertTrue(result.get()); assertTrue(result.get());
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
/* /*
* True if response has results, meaning value.length > 0 * True if response has results, meaning value.length > 0
*/ */
And("^the response has results$", () -> { And("^the response has results$", () -> {
int count = from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).size(); try {
LOG.info("Results count is: " + count); int count = from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).size();
assertTrue(count > 0); LOG.info("Results count is: " + count);
assertTrue(count > 0);
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
/* /*
* True if data are present in the response * True if data are present in the response
*/ */
And("^the response has singleton results in \"([^\"]*)\"", (String parameterFieldName) -> { And("^the response has singleton results in \"([^\"]*)\"", (String parameterFieldName) -> {
String value = Settings.resolveParametersString(parameterFieldName, settings); try {
boolean isPresent = from(responseData.get()).get() != null; String value = Settings.resolveParametersString(parameterFieldName, settings);
LOG.info("Response value is: " + value); boolean isPresent = from(responseData.get()).get() != null;
LOG.info("IsPresent: " + isPresent); LOG.info("Response value is: " + value);
assertTrue(isPresent); LOG.info("IsPresent: " + isPresent);
assertTrue(isPresent);
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
/* /*
* True if results count less than or equal to limit * True if results count less than or equal to limit
*/ */
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) -> {
int count = from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).size(), try {
limit = Integer.parseInt(Settings.resolveParametersString(limitField, settings)); int count = from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).size(),
LOG.info("Results count is: " + count + ", Limit is: " + limit); limit = Integer.parseInt(Settings.resolveParametersString(limitField, settings));
assertTrue(count <= limit); LOG.info("Results count is: " + count + ", Limit is: " + limit);
assertTrue(count <= limit);
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
/* /*
* True if data in the lhs expression and rhs expressions pass the AND or OR condition given in andOrOp * True if data in the lhs expression and rhs expressions pass the AND or OR condition given in andOrOp
*/ */
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 {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
Integer assertedLhsValue = Integer.parseInt(Settings.resolveParametersString(parameterAssertedLhsValue, settings)), Integer assertedLhsValue = Integer.parseInt(Settings.resolveParametersString(parameterAssertedLhsValue, settings)),
assertedRhsValue = Integer.parseInt(Settings.resolveParametersString(parameterAssertedRhsValue, settings)); assertedRhsValue = Integer.parseInt(Settings.resolveParametersString(parameterAssertedRhsValue, settings));
@ -456,88 +528,107 @@ public class WebAPIServer_1_0_2 implements En {
assertTrue(itemResult.get()); assertTrue(itemResult.get());
} }
}); });
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
/* /*
* Date Comparison glue * Date Comparison glue
*/ */
And("^Date data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> { And("^Date data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); try {
AtomicReference<Date> fieldValue = new AtomicReference<>(); String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
AtomicReference<Date> assertedValue = new AtomicReference<>(); AtomicReference<Date> fieldValue = new AtomicReference<>();
AtomicReference<Date> assertedValue = new AtomicReference<>();
assertedValue.set(Utils.parseDateFromEdmDateString(Settings.resolveParametersString(parameterAssertedValue, settings))); assertedValue.set(Utils.parseDateFromEdmDateString(Settings.resolveParametersString(parameterAssertedValue, settings)));
LOG.info("Asserted value is: " + assertedValue.get().toString()); LOG.info("Asserted value is: " + assertedValue.get().toString());
from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
try { try {
fieldValue.set(Utils.parseDateFromEdmDateTimeOffsetString(item.get(fieldName).toString())); fieldValue.set(Utils.parseDateFromEdmDateTimeOffsetString(item.get(fieldName).toString()));
assertTrue(Utils.compare(fieldValue.get(), op, assertedValue.get())); assertTrue(Utils.compare(fieldValue.get(), op, assertedValue.get()));
} catch (Exception ex){ } catch (Exception ex) {
LOG.error(ex.toString()); fail(ex.toString());
}
}); }
});
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
/* /*
* Time comparison glue * Time comparison glue
*/ */
And("^TimeOfDay data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> { And("^TimeOfDay data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); try {
AtomicReference<Time> fieldValue = new AtomicReference<>(); String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
AtomicReference<Time> assertedValue = new AtomicReference<>(); AtomicReference<Time> fieldValue = new AtomicReference<>();
AtomicReference<Time> assertedValue = new AtomicReference<>();
assertedValue.set(Utils.parseTimeOfDayFromEdmTimeOfDayString(Settings.resolveParametersString(parameterAssertedValue, settings))); assertedValue.set(Utils.parseTimeOfDayFromEdmTimeOfDayString(Settings.resolveParametersString(parameterAssertedValue, settings)));
LOG.info("Asserted value is: " + assertedValue.get().toString()); LOG.info("Asserted value is: " + assertedValue.get().toString());
from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
try { try {
fieldValue.set(Utils.parseTimeOfDayFromEdmDateTimeOffsetString(item.get(fieldName).toString())); fieldValue.set(Utils.parseTimeOfDayFromEdmDateTimeOffsetString(item.get(fieldName).toString()));
assertTrue(Utils.compare(fieldValue.get(), op, assertedValue.get())); assertTrue(Utils.compare(fieldValue.get(), op, assertedValue.get()));
} catch (Exception ex){ } catch (Exception ex) {
LOG.error(ex.toString()); LOG.error(ex.getMessage());
} }
}); });
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
/*
* Year comparison glue
*/
/* /*
* Timestamp comparison glue * Timestamp comparison glue
*/ */
And("^DateTimeOffset data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> { And("^DateTimeOffset data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> {
Utils.assertDateTimeOffset(parameterFieldName, op, parameterAssertedValue, responseData.get()); try {
Utils.assertDateTimeOffset(parameterFieldName, op, parameterAssertedValue, responseData.get());
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
/* /*
* Timestamp comparison to now() * Timestamp comparison to now()
*/ */
And("^DateTimeOffset data in \"([^\"]*)\" \"([^\"]*)\" now\\(\\)$", (String parameterFieldName, String op) -> { And("^DateTimeOffset data in \"([^\"]*)\" \"([^\"]*)\" now\\(\\)$", (String parameterFieldName, String op) -> {
Utils.assertDateTimeOffset(parameterFieldName, op, Timestamp.from(Instant.now()), responseData.get()); try {
Utils.assertDateTimeOffset(parameterFieldName, op, Timestamp.from(Instant.now()), responseData.get());
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
/* /*
* Single-Valued enumerations * Single-Valued enumerations
*/ */
And("^Single Valued Enumeration Data in \"([^\"]*)\" has \"([^\"]*)\"$", (String parameterFieldName, String parameterAssertedValue) -> { And("^Single Valued Enumeration Data in \"([^\"]*)\" has \"([^\"]*)\"$", (String parameterFieldName, String parameterAssertedValue) -> {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); try {
AtomicReference<String> fieldValue = new AtomicReference<>(); String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
AtomicReference<String> assertedValue = new AtomicReference<>(); AtomicReference<String> fieldValue = 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, settings));
LOG.info("Asserted value is: " + assertedValue.get()); LOG.info("Asserted value is: " + assertedValue.get());
from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(responseData.get()).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) {
fail(ex.getMessage());
}
}); });
/* /*
@ -545,57 +636,64 @@ public class WebAPIServer_1_0_2 implements En {
* TODO: turn array into JSON array and parse values from there * TODO: turn array into JSON array and parse values from there
*/ */
And("^Multiple Valued Enumeration Data in \"([^\"]*)\" has \"([^\"]*)\"$", (String parameterFieldName, String parameterAssertedValue) -> { And("^Multiple Valued Enumeration Data in \"([^\"]*)\" has \"([^\"]*)\"$", (String parameterFieldName, String parameterAssertedValue) -> {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); try {
AtomicReference<String> fieldValue = new AtomicReference<>(); String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
AtomicReference<String> assertedValue = new AtomicReference<>(); AtomicReference<String> fieldValue = 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, settings));
LOG.info("Asserted value is: " + assertedValue.get()); LOG.info("Asserted value is: " + assertedValue.get());
from(responseData.get()).getList(JSON_VALUE_PATH, ObjectNode.class).forEach(item -> { from(responseData.get()).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) {
fail(ex.getMessage());
}
}); });
/* /*
* Date comparison ordering (asc, desc). * Date comparison ordering (asc, desc).
*/ */
And("^DateTimeOffset data in \"([^\"]*)\" is sorted in \"([^\"]*)\" order$", (String parameterFieldName, String parameterOrderByDirection) -> { And("^DateTimeOffset data in \"([^\"]*)\" is sorted in \"([^\"]*)\" order$", (String parameterFieldName, String parameterOrderByDirection) -> {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); try {
final String ASC = "asc", DESC = "desc"; String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
AtomicReference<String> orderBy = new AtomicReference<>(parameterOrderByDirection.toLowerCase()); final String ASC = "asc", DESC = "desc";
AtomicReference<String> orderBy = new AtomicReference<>(parameterOrderByDirection.toLowerCase());
assertTrue(orderBy.get().equals(ASC) || orderBy.get().equals(DESC)); assertTrue(orderBy.get().equals(ASC) || orderBy.get().equals(DESC));
//used to store the last value for comparisons //used to store the last value for comparisons
AtomicReference<Timestamp> initialValue = new AtomicReference<>(); AtomicReference<Timestamp> initialValue = new AtomicReference<>();
AtomicReference<Timestamp> currentValue = new AtomicReference<>(); AtomicReference<Timestamp> currentValue = new AtomicReference<>();
AtomicInteger count = new AtomicInteger(0); AtomicInteger count = new AtomicInteger(0);
from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
try { try {
if (count.get() == 0) { if (count.get() == 0) {
initialValue.set(Utils.parseTimestampFromEdmDateTimeOffsetString(item.get(fieldName).toString())); initialValue.set(Utils.parseTimestampFromEdmDateTimeOffsetString(item.get(fieldName).toString()));
} else { } else {
currentValue.set(Utils.parseTimestampFromEdmDateTimeOffsetString(item.get(fieldName).toString())); currentValue.set(Utils.parseTimestampFromEdmDateTimeOffsetString(item.get(fieldName).toString()));
if (orderBy.get().equals(ASC)) { if (orderBy.get().equals(ASC)) {
assertTrue(Utils.compare(initialValue.get(), Operators.LESS_THAN_OR_EQUAL, currentValue.get())); assertTrue(Utils.compare(initialValue.get(), Operators.LESS_THAN_OR_EQUAL, currentValue.get()));
} else if (orderBy.get().equals(DESC)){ } else if (orderBy.get().equals(DESC)){
assertTrue(Utils.compare(initialValue.get(), Operators.GREATER_THAN_OR_EQUAL, currentValue.get())); assertTrue(Utils.compare(initialValue.get(), Operators.GREATER_THAN_OR_EQUAL, currentValue.get()));
}
initialValue.set(currentValue.get());
} }
initialValue.set(currentValue.get()); count.getAndIncrement();
} catch (EdmPrimitiveTypeException ptex) {
fail(ptex.getMessage());
} }
count.getAndIncrement(); });
} catch (EdmPrimitiveTypeException ptex) { } catch (Exception ex) {
LOG.error("ERROR: exception thrown parsing Timestamp from given string." + ptex); fail(ex.getMessage());
fail(); }
}
});
}); });
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) -> {
@ -614,13 +712,11 @@ public class WebAPIServer_1_0_2 implements En {
fieldValue.set(Utils.getDatePart(datePart.get(), item.get(fieldName))); fieldValue.set(Utils.getDatePart(datePart.get(), item.get(fieldName)));
assertTrue(Utils.compare(fieldValue.get(), operator.get(), assertedValue.get())); assertTrue(Utils.compare(fieldValue.get(), operator.get(), assertedValue.get()));
} catch (Exception ex){ } catch (Exception ex){
//fail(); fail(ex.getMessage());
LOG.error("ERROR: exception thrown." + ex);
} }
}); });
} catch (Exception ex) { } catch (Exception ex) {
fail(); fail(ex.getMessage());
LOG.error("ERROR: exception thrown." + ex);
} }
}); });
@ -629,28 +725,30 @@ public class WebAPIServer_1_0_2 implements En {
* TODO: consolidate with Year comparison with Date Field * TODO: consolidate with Year comparison with Date Field
*/ */
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) -> {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
AtomicReference<Integer> fieldValue = new AtomicReference<>();
AtomicReference<Integer> assertedValue = new AtomicReference<>();
AtomicReference<String> datePart = new AtomicReference<>(stringDatePart.toLowerCase());
AtomicReference<String> operator = new AtomicReference<>(op.toLowerCase());
try { try {
assertedValue.set(Integer.parseInt(Settings.resolveParametersString(parameterAssertedValue, settings))); String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
LOG.info("Asserted value is: " + assertedValue.get().toString()); AtomicReference<Integer> fieldValue = new AtomicReference<>();
AtomicReference<Integer> assertedValue = new AtomicReference<>();
AtomicReference<String> datePart = new AtomicReference<>(stringDatePart.toLowerCase());
AtomicReference<String> operator = new AtomicReference<>(op.toLowerCase());
from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> { try {
try { assertedValue.set(Integer.parseInt(Settings.resolveParametersString(parameterAssertedValue, settings)));
fieldValue.set(Utils.getTimestampPart(datePart.get(), item.get(fieldName).toString())); LOG.info("Asserted value is: " + assertedValue.get().toString());
assertTrue(Utils.compare(fieldValue.get(), operator.get(), assertedValue.get()));
} catch (Exception ex){ from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
fail(); try {
LOG.error("ERROR: exception thrown." + ex); fieldValue.set(Utils.getTimestampPart(datePart.get(), item.get(fieldName).toString()));
} assertTrue(Utils.compare(fieldValue.get(), operator.get(), assertedValue.get()));
}); } catch (Exception ex){
fail(ex.getMessage());
}
});
} catch (Exception ex) {
fail(ex.getMessage());
}
} catch (Exception ex) { } catch (Exception ex) {
fail(); fail(ex.getMessage());
LOG.error("ERROR: exception thrown." + ex);
} }
}); });
@ -658,15 +756,128 @@ public class WebAPIServer_1_0_2 implements En {
* String functions * String functions
*/ */
And("^String data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> { And("^String data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\"$", (String parameterFieldName, String op, String parameterAssertedValue) -> {
String fieldName = Settings.resolveParametersString(parameterFieldName, settings); try {
AtomicReference<String> assertedValue = new AtomicReference<>(Settings.resolveParametersString(parameterAssertedValue, settings)); String fieldName = Settings.resolveParametersString(parameterFieldName, settings);
AtomicReference<String> operator = new AtomicReference<>(op.toLowerCase()); AtomicReference<String> assertedValue = new AtomicReference<>(Settings.resolveParametersString(parameterAssertedValue, settings));
AtomicReference<String> operator = new AtomicReference<>(op.toLowerCase());
from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
assertTrue(Utils.compare(item.get(fieldName).toString(), operator.get(), assertedValue.get()));
});
from(responseData.get()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
assertTrue(Utils.compare(item.get(fieldName).toString(), operator.get(), assertedValue.get()));
});
} catch (Exception ex) {
fail(ex.getMessage());
}
}); });
/*
* Metadata validation methods
*/
/*
Checks that metadata are accessible and contain the resource name specified in generic.resoscript
*/
And("^the metadata contains the \"([^\"]*)\" resource$", (String parameterResourceName) -> {
final String resourceName = Settings.resolveParametersString(parameterResourceName, settings);
AtomicReference<CsdlEntityContainer> entityContainer = new AtomicReference<>();
try {
entityContainer.set(ODataHelper.findDefaultEntityContainer(commander.get(), xmlMetadata.get()));
assertNotNull("ERROR: server metadata does not contain the given resource name: " + resourceName,
entityContainer.get().getEntitySet(resourceName));
LOG.info("Found EntityContainer for the given resource: '" + resourceName + "'");
} catch (Exception ex) {
fail(ex.getMessage());
}
});
And("^resource metadata for \"([^\"]*)\" contains the fields in \"([^\"]*)\"$", (String parameterResourceName, String parameterSelectList) -> {
final String FIELD_SEPARATOR = ",";
final String selectList = Settings.resolveParametersString(parameterSelectList, settings);
try {
final String resourceName = Settings.resolveParametersString(parameterResourceName, settings);
List<String> fieldNames = Arrays.asList(selectList.split(FIELD_SEPARATOR));
//create field lookup
Map<String, CsdlProperty> fieldMap = new HashMap<>();
ODataHelper.findEntityTypesForEntityTypeName(commander.get(), xmlMetadata.get(), resourceName)
.forEach(csdlProperty -> fieldMap.put(csdlProperty.getName(), csdlProperty));
LOG.info("Searching metadata for fields in given select list: " + selectList);
fieldNames.forEach(fieldName -> {
//trim string just in case spaces were used after the commas
assertNotNull("ERROR: Field name '" + fieldName + "' is not present in server metadata!", fieldMap.get(fieldName.trim()));
LOG.info("Found: '" + fieldName.trim() + "'");
});
} catch (Exception ex) {
fail(ex.getMessage());
}
});
When("^a successful metadata request is made to the service root in \"([^\"]*)\"$", (String clientSettingsServiceRoot) -> {
final String serviceRoot = Settings.resolveParametersString(clientSettingsServiceRoot, settings);
assertEquals("ERROR: given service root doesn't match the one configured in the Commander", serviceRoot, commander.get().getServiceRoot());
try {
xmlMetadata.set(commander.get().getXMLMetadata());
} catch (ODataClientErrorException cex) {
responseCode.set(cex.getStatusLine().getStatusCode());
fail(cex.getMessage());
} catch (Exception ex) {
fail(ex.getMessage());
}
});
}
private static final class ODataHelper {
/**
* Finds the default entity container for the given configuration.
* @param commander a commander instance with a valid service root.
* @param xmlMetadata XML Metadata to search through
* @return the default CSDL Container for the given XMLMetadata
* @throws Exception if required metadata cannot be parsed, an exception will be thrown with an appropriate message.
*/
private static CsdlEntityContainer findDefaultEntityContainer(Commander commander, XMLMetadata xmlMetadata) throws Exception {
Edm edm = commander.getEdm();
if (edm == null)
throw new Exception("ERROR: Could not retrieve Edm from server using the given service root!");
if (xmlMetadata == null)
throw new Exception("ERROR: the provided XML metadata was null!");
if (edm.getEntityContainer() == null)
throw new Exception("ERROR: Could not find default EntityContainer for service root: " + commander.getServiceRoot());
String entityContainerNamespace = edm.getEntityContainer().getNamespace();
if (entityContainerNamespace == null)
throw new Exception("ERROR: no default EntityContainer namespace could be found");
return xmlMetadata.getSchema(entityContainerNamespace).getEntityContainer();
}
/**
* Gets a list of CsdlProperty items for the given entityTypeName.
* @param commander a Commander instance with a valid service root.
* @param xmlMetadata the metadata to search.
* @param entityTypeName the name of the entityType to search for. MUST be in the default EntityContainer.
* @return a list of CsdlProperty items for the given entityTypeName
* @throws Exception is thrown if the given metadata doesn't contain the given type name.
*/
private static List<CsdlProperty> findEntityTypesForEntityTypeName(Commander commander, XMLMetadata xmlMetadata, String entityTypeName) throws Exception {
CsdlEntityContainer entityContainer = findDefaultEntityContainer(commander, xmlMetadata);
CsdlSchema schemaForType = xmlMetadata.getSchema(entityContainer.getEntitySet(entityTypeName).getTypeFQN().getNamespace());
if (schemaForType == null)
throw new Exception("ERROR: could not find type corresponding to given type name: " + entityTypeName);
return schemaForType.getEntityType(entityTypeName).getProperties();
}
} }
/** /**
@ -766,7 +977,6 @@ public class WebAPIServer_1_0_2 implements En {
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) { } else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
result = lhs <= rhs; result = lhs <= rhs;
} }
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result); LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
return result; return result;
} }
@ -793,8 +1003,7 @@ public class WebAPIServer_1_0_2 implements En {
} else if (operator.contentEquals(Operators.TO_UPPER)) { } else if (operator.contentEquals(Operators.TO_UPPER)) {
result = lhs.toUpperCase().equals(rhs); result = lhs.toUpperCase().equals(rhs);
} }
LOG.info("Compare: \"" + lhs + "\" " + operator + " \"" + rhs + "\" ==> " + result);
LOG.info("Compare: " + operator + "(" + lhs + ") == " + rhs + " ==> " + result);
return result; return result;
} }

View File

@ -207,7 +207,7 @@ public class App {
if (request.getOutputFile().toLowerCase().contains(EDMX_EXTENSION.toLowerCase())) { if (request.getOutputFile().toLowerCase().contains(EDMX_EXTENSION.toLowerCase())) {
//Main.main(new String[]{"-g", "org.reso.certification.stepdefs#WebAPIServer_1_0_2", "/home/jdarnell/work/reso/github/web-api-commander/src/main/java/org/reso/certification/features/web-api-server-1.0.2.feature"}); //Main.main(new String[]{"-g", "org.reso.certification.stepdefs#WebAPIServer_1_0_2", "/home/jdarnell/work/reso/github/web-api-commander/src/main/java/org/reso/certification/features/web-api-server-1.0.2.feature"});
if (validateMetadata(commander, outputFilePath)) { if (validateMetadata(commander, outputFilePath)) {
metadata = commander.getMetadata(outputFilePath); metadata = commander.getEdm(outputFilePath);
} else { } else {
LOG.error("Error: Invalid metadata retrieved. Cannot continue!!"); LOG.error("Error: Invalid metadata retrieved. Cannot continue!!");
System.exit(NOT_OK); System.exit(NOT_OK);
@ -248,7 +248,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.getMetadata(); metadata = commander.getEdm();
getMetadataReport(metadata); getMetadataReport(metadata);
} else if (cmd.hasOption(APP_OPTIONS.ACTIONS.VALIDATE_METADATA)) { } else if (cmd.hasOption(APP_OPTIONS.ACTIONS.VALIDATE_METADATA)) {

View File

@ -1,25 +1,20 @@
package org.reso.commander; package org.reso.commander;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.commons.io.output.WriterOutputStream;
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;
import org.apache.logging.log4j.Logger; 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.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.ClientEntity; import org.apache.olingo.client.api.domain.ClientEntity;
import org.apache.olingo.client.api.domain.ClientEntitySet; import org.apache.olingo.client.api.domain.ClientEntitySet;
import org.apache.olingo.client.api.edm.xml.Edmx;
import org.apache.olingo.client.api.edm.xml.XMLMetadata; import org.apache.olingo.client.api.edm.xml.XMLMetadata;
import org.apache.olingo.client.core.ODataClientFactory; import org.apache.olingo.client.core.ODataClientFactory;
import org.apache.olingo.client.core.domain.ClientEntitySetImpl; import org.apache.olingo.client.core.domain.ClientEntitySetImpl;
import org.apache.olingo.client.core.edm.ClientCsdlXMLMetadata;
import org.apache.olingo.commons.api.data.Entity;
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;
import org.reso.auth.OAuth2HttpClientFactory; import org.reso.auth.OAuth2HttpClientFactory;
@ -52,7 +47,14 @@ public class Commander {
private ODataClient client; private ODataClient client;
private boolean useEdmEnabledClient; private boolean useEdmEnabledClient;
String serviceRoot, bearerToken, clientId, clientSecret, authorizationUri, tokenUri, redirectUri, scope; private String serviceRoot;
String bearerToken;
String clientId;
String clientSecret;
String authorizationUri;
String tokenUri;
String redirectUri;
String scope;
boolean isTokenClient, isOAuthClient; boolean isTokenClient, isOAuthClient;
private static final Logger LOG = LogManager.getLogger(Commander.class); private static final Logger LOG = LogManager.getLogger(Commander.class);
@ -69,6 +71,14 @@ public class Commander {
this.client = client; this.client = client;
} }
public String getTokenUri() {
return tokenUri;
}
public String getServiceRoot() {
return serviceRoot;
}
/** /**
* Builder pattern for creating Commander instances. * Builder pattern for creating Commander instances.
*/ */
@ -167,24 +177,50 @@ public class Commander {
//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 Edm edm;
private XMLMetadata xmlMetadata;
/** /**
* Gets server metadata in Edm format. * Gets server metadata in Edm format.
* <p> * @implNote the data in this item are cached in the commander once fetched
* @return XMLMetadata representation of the server metadata. * @return Edm representation of the server metadata.
*/ */
public Edm getMetadata() { public Edm getEdm() {
Edm metadata = null; if (edm == null) {
try { try {
LOG.info("Fetching Metadata from " + serviceRoot + "..."); EdmMetadataRequest metadataRequest = client.getRetrieveRequestFactory().getMetadataRequest(serviceRoot);
metadata = client.getRetrieveRequestFactory().getMetadataRequest(serviceRoot).execute().getBody(); LOG.info("Fetching Edm with OData Client from: " + metadataRequest.getURI().toString());
LOG.info("Transfer complete! KBytes received: " + (metadata.toString().getBytes().length / 1024)); edm = metadataRequest.execute().getBody();
} catch (ODataClientErrorException cex) { } catch (ODataClientErrorException cex) {
LOG.error(cex.getStackTrace()); LOG.error("ERROR: could not retrieve Metadata for the given service root!");
LOG.error(cex.getStatusLine().toString());
throw cex;
}
} }
return metadata; return edm;
} }
public Edm getMetadata(String pathToXmlMetadata) { /**
* Gets server metadata in XMLMetadata format.
* @implNote the data in this item are cached in the commander once fetched
* @return XMLMetadata representation of the server metadata.
*/
public XMLMetadata getXMLMetadata() {
if (xmlMetadata == null) {
try {
EdmMetadataRequest metadataRequest = client.getRetrieveRequestFactory().getMetadataRequest(serviceRoot);
LOG.info("Fetching XMLMetadata with OData Client from: " + metadataRequest.getURI().toString());
xmlMetadata = metadataRequest.getXMLMetadata();
} catch (ODataClientErrorException cex) {
LOG.error("ERROR: could not retrieve Metadata for the given service root!");
LOG.error(cex.getStatusLine().toString());
throw cex;
}
}
return xmlMetadata;
}
public Edm getEdm(String pathToXmlMetadata) {
try { try {
return client.getReader().readMetadata(new FileInputStream(pathToXmlMetadata)); return client.getReader().readMetadata(new FileInputStream(pathToXmlMetadata));
} catch (FileNotFoundException fex) { } catch (FileNotFoundException fex) {
@ -202,31 +238,6 @@ public class Commander {
} }
} }
/**
* Converts Edm to XMLMetadata
* @param edm
* @return the XMLMetadata representation of the given Edm
*/
private XMLMetadata convertEdmToXMLMetadata(Edm edm) {
XMLMetadata xmlMetadata = null;
try {
ByteArrayInputStream inputStream = new ByteArrayInputStream(edm.toString().getBytes());
xmlMetadata = client.getDeserializer(ContentType.APPLICATION_XML).toMetadata(inputStream);
} catch (Exception ex) {
LOG.error(ex.getStackTrace());
}
return xmlMetadata;
}
public boolean validateMetadata(Edm metadata) {
try {
return validateMetadata(convertEdmToXMLMetadata(metadata));
} catch (Exception ex) {
LOG.error(ex.getStackTrace());
}
return false;
}
/** /**
* Validates given XMLMetadata * Validates given XMLMetadata
* *
@ -256,10 +267,8 @@ public class Commander {
public boolean validateMetadata(InputStream inputStream) { public boolean validateMetadata(InputStream inputStream) {
try { try {
// deserialize metadata from given file // deserialize metadata from given file
XMLMetadata metadata = XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML).toMetadata(inputStream);
client.getDeserializer(ContentType.APPLICATION_XML).toMetadata(inputStream);
return validateMetadata(metadata); return validateMetadata(metadata);
} catch (Exception ex) { } catch (Exception ex) {
LOG.error("ERROR in validateMetadata! " + ex.toString() ); LOG.error("ERROR in validateMetadata! " + ex.toString() );
} }
@ -283,6 +292,14 @@ public class Commander {
return false; return false;
} }
public boolean isTokenClient() {
return isTokenClient;
}
public boolean isOAuthClient() {
return isOAuthClient;
}
public static boolean validateXML(String xmlString) { public static boolean validateXML(String xmlString) {
return validateXML(new ByteArrayInputStream(xmlString.getBytes(UTF_8))); return validateXML(new ByteArrayInputStream(xmlString.getBytes(UTF_8)));
} }