From 6be781fcb9c9597f494c2bf9fa8ed4846e014138 Mon Sep 17 00:00:00 2001 From: Jimmy Forsyth Date: Wed, 23 May 2018 12:24:34 -0400 Subject: [PATCH 01/16] Upversion for Casablanca Issue-ID: AAI-1169 Change-Id: I9ff388471e5ed1cb9980ac6eb95bce6e8bb75377 Signed-off-by: Jimmy Forsyth --- pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index ba84468..bcf3280 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ limitations under the License. org.onap.aai.gizmo gizmo - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT aai-gizmo @@ -186,17 +186,17 @@ limitations under the License. org.onap.aai.aai-common aai-schema - 1.2.4 + 1.3.0-SNAPSHOT org.onap.aai.aai-common aai-utils - 1.2.4 + 1.3.0-SNAPSHOT org.onap.aai.aai-common aai-core - 1.2.4 + 1.3.0-SNAPSHOT * @@ -207,7 +207,7 @@ limitations under the License. org.onap.aai.aai-common aai-auth - 1.2.4 + 1.3.0-SNAPSHOT org.eclipse.persistence -- 2.16.6 From dc0de42083f6a40586c39d897fd7e7cd3d02cee0 Mon Sep 17 00:00:00 2001 From: Jimmy Forsyth Date: Wed, 23 May 2018 13:18:55 -0400 Subject: [PATCH 02/16] Upversion for Casablanca Issue-ID: AAI-1169 Change-Id: I5f38cbc86210adc2e8b2c4e0d885ab83a4f03cde Signed-off-by: Jimmy Forsyth --- version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.properties b/version.properties index faf06bb..a254b21 100644 --- a/version.properties +++ b/version.properties @@ -3,7 +3,7 @@ # because they are used in Jenkins, whose plug-in doesn't support major=1 -minor=2 +minor=3 patch=0 base_version=${major}.${minor}.${patch} -- 2.16.6 From 64af7d23db52c696ee60a30c2f8f03e2df90c934 Mon Sep 17 00:00:00 2001 From: Mohammed Naser Date: Mon, 16 Apr 2018 13:35:21 -0700 Subject: [PATCH 03/16] Pin jnr-unixsocket for Docker plugin to 0.13 The current verison of jnr-unixsocket is 0.12 from the Docker plugin however in order to be able the images for ARM64, it needs the newer version which has support for it. There is work upstream to switch the version to 0.18[0] however it seems that this is still pending, so we can pin it for now until that merges. [0]: https://github.com/spotify/docker-maven-plugin/pull/379 Change-Id: Ic2559c8371b249f5a3f7de01d30d773d9b5d876f Issue-ID: CIMAN-154 Signed-off-by: Mohammed Naser --- pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pom.xml b/pom.xml index bcf3280..d4d63dd 100644 --- a/pom.xml +++ b/pom.xml @@ -340,6 +340,13 @@ limitations under the License. com.spotify docker-maven-plugin 0.4.11 + + + com.github.jnr + jnr-unixsocket + 0.13 + + true docker-hub -- 2.16.6 From 58377c868414816edae11ef24f6b8beee436ac1f Mon Sep 17 00:00:00 2001 From: Mohammed Naser Date: Mon, 16 Apr 2018 13:36:16 -0700 Subject: [PATCH 04/16] Dynamically determine image architecture The image architecture is currently hardcoded, this patch removes that hardcoded value to allow for ARM64 builds to go through. Change-Id: I50b7d3a270165852930c0ce5786121edbef61d08 Issue-ID: CIMAN-154 Signed-off-by: Mohammed Naser --- src/main/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/docker/Dockerfile b/src/main/docker/Dockerfile index 10c4dd0..b76edfe 100644 --- a/src/main/docker/Dockerfile +++ b/src/main/docker/Dockerfile @@ -10,7 +10,7 @@ RUN apt-get update && apt-get install -y software-properties-common ## sudo -E is required to preserve the environment. If you remove that line, it will most like freeze at this step RUN sudo -E add-apt-repository ppa:openjdk-r/ppa && apt-get update && apt-get install -y openjdk-8-jdk ## Setup JAVA_HOME, this is useful for docker commandline -ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64 +ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-$(dpkg --print-architecture) RUN export JAVA_HOME # Build up the deployment folder structure -- 2.16.6 From 9d48685b916536c5641b2f536e08edba0f9642c3 Mon Sep 17 00:00:00 2001 From: Daniel Silverthorn Date: Fri, 25 May 2018 10:37:42 -0400 Subject: [PATCH 05/16] Remove gizmo logback, use mounted one Change-Id: I256d2038c554aecc193b96661e080cd3bac82636 Issue-ID: AAI-1180 Signed-off-by: Daniel Silverthorn --- src/main/bin/start.sh | 3 +- src/main/resources/application.properties | 1 - src/main/resources/logback.xml | 214 ------------------------------ 3 files changed, 2 insertions(+), 216 deletions(-) delete mode 100644 src/main/resources/logback.xml diff --git a/src/main/bin/start.sh b/src/main/bin/start.sh index cbd37bc..f456ae6 100644 --- a/src/main/bin/start.sh +++ b/src/main/bin/start.sh @@ -1,6 +1,6 @@ #!/bin/bash -APP_HOME="/opt/app/crud-api/" +APP_HOME="/opt/app/crud-api" if [ -z "$CONFIG_HOME" ]; then echo "CONFIG_HOME must be set in order to start up process" @@ -19,6 +19,7 @@ fi PROPS="-DAPP_HOME=$APP_HOME" PROPS="$PROPS -DCONFIG_HOME=$CONFIG_HOME" +PROPS="$PROPS -Dlogging.config=$APP_HOME/bundleconfig/etc/logback.xml" PROPS="$PROPS -DKEY_STORE_PASSWORD=$KEY_STORE_PASSWORD" JVM_MAX_HEAP=${MAX_HEAP:-1024} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 2a65bc3..a21f3c5 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -7,4 +7,3 @@ server.ssl.enabled=true server.ssl.client-auth=need server.ssl.enabled-protocols=TLSv1.1,TLSv1.2 -logging.config=classpath:logback.xml \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml deleted file mode 100644 index 9a8d99a..0000000 --- a/src/main/resources/logback.xml +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - ${errorLogPattern} - - - - - - - - - - - ${logDirectory}/${generalLogName}.log - - ${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.log.zip - - 60 - - - ${errorLogPattern} - - - - - - INFO - - 256 - - - - - - - - ${logDirectory}/${auditLogName}.log - - ${logDirectory}/${auditLogName}.%d{yyyy-MM-dd}.log.zip - - 60 - - - ${auditMetricPattern} - - - - 256 - - - - - ${logDirectory}/${metricsLogName}.log - - ${logDirectory}/${metricsLogName}.%d{yyyy-MM-dd}.log.zip - - 60 - - - - ${auditMetricPattern} - - - - - - 256 - - - - - ${logDirectory}/${debugLogName}.log - - ${logDirectory}/${debugLogName}.%d{yyyy-MM-dd}.log.zip - - 60 - - - ${errorLogPattern} - - - - - 256 - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- 2.16.6 From 33bec1f4e3b0c824555e23b3681450709822ef76 Mon Sep 17 00:00:00 2001 From: Daniel Silverthorn Date: Wed, 30 May 2018 13:44:20 -0400 Subject: [PATCH 06/16] Add gizmo logback in local Change-Id: I024dd5aaba04f15169e19be008a6aa7c88fbc706 Issue-ID: AAI-1180 Signed-off-by: Daniel Silverthorn --- bundleconfig-local/etc/logback.xml | 179 +++++++++++++++++++++++++++++++++++++ pom.xml | 7 ++ src/main/docker/Dockerfile | 3 + 3 files changed, 189 insertions(+) create mode 100644 bundleconfig-local/etc/logback.xml diff --git a/bundleconfig-local/etc/logback.xml b/bundleconfig-local/etc/logback.xml new file mode 100644 index 0000000..a04d44c --- /dev/null +++ b/bundleconfig-local/etc/logback.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + ${errorLogPattern} + + + + + + + + + + + ${logDirectory}/${generalLogName}.log + + ${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + ${errorLogPattern} + + + + + + INFO + + 256 + + + + + + + + ${logDirectory}/${auditLogName}.log + + ${logDirectory}/${auditLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + ${auditMetricPattern} + + + + 256 + + + + + ${logDirectory}/${metricsLogName}.log + + ${logDirectory}/${metricsLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + + ${auditMetricPattern} + + + + + + 256 + + + + + ${logDirectory}/${debugLogName}.log + + ${logDirectory}/${debugLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + ${errorLogPattern} + + + + + 256 + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index d4d63dd..a6af37a 100644 --- a/pom.xml +++ b/pom.xml @@ -327,6 +327,13 @@ limitations under the License. **/* + + ${basedir} + true + + bundleconfig-local/** + + ${basedir}/src/main/bin/ diff --git a/src/main/docker/Dockerfile b/src/main/docker/Dockerfile index b76edfe..c643b2e 100644 --- a/src/main/docker/Dockerfile +++ b/src/main/docker/Dockerfile @@ -15,9 +15,12 @@ RUN export JAVA_HOME # Build up the deployment folder structure RUN mkdir -p $MICRO_HOME +RUN mkdir -p $MICRO_HOME/bundleconfig/etc COPY gizmo.jar $MICRO_HOME/ RUN mkdir -p $BIN_HOME COPY *.sh $BIN_HOME +COPY bundleconfig-local $MICRO_HOME/bundleconfig +COPY bundleconfig-local/etc/logback.xml $MICRO_HOME/bundleconfig/etc RUN chmod 755 $BIN_HOME/* RUN ln -s /logs $MICRO_HOME/logs -- 2.16.6 From d4e297058fbd58b7164a69f506a0c0af0274ed48 Mon Sep 17 00:00:00 2001 From: "Sanchez, Gabriel (gs882h)" Date: Mon, 4 Jun 2018 16:04:04 +0100 Subject: [PATCH 07/16] Fix logDir in logback.xml file Change logDir value to APP_HOME/logs Issue-ID: AAI-1199 Change-Id: I4fc10a6ab422be50aaf3333b67f404e2c1589f75 Signed-off-by: Sanchez, Gabriel (gs882h) --- bundleconfig-local/etc/logback.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bundleconfig-local/etc/logback.xml b/bundleconfig-local/etc/logback.xml index a04d44c..f49b222 100644 --- a/bundleconfig-local/etc/logback.xml +++ b/bundleconfig-local/etc/logback.xml @@ -2,7 +2,7 @@ - + - + + -- 2.16.6 From ca46bdfcfb109b856c293862f6ed77fe78eb510f Mon Sep 17 00:00:00 2001 From: Shwetank Dave Date: Mon, 4 Jun 2018 13:56:08 -0400 Subject: [PATCH 08/16] Adding "_reserved_" properties in the query params Adding "_reserved_version" and "_reserved_aai-type" to the query parameters when making downstream queries. Change-Id: Ibabf671618ac10813740d835d368ce30195f7937 Issue-ID: AAI-1202 Signed-off-by: Shwetank Dave --- .../org/onap/crud/service/CrudRestService.java | 45 +++++++++++----------- .../org/onap/crud/util/CrudServiceConstants.java | 2 + .../java/org/onap/schema/OxmModelValidator.java | 5 +++ 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/onap/crud/service/CrudRestService.java b/src/main/java/org/onap/crud/service/CrudRestService.java index b9062b0..5539374 100644 --- a/src/main/java/org/onap/crud/service/CrudRestService.java +++ b/src/main/java/org/onap/crud/service/CrudRestService.java @@ -98,10 +98,7 @@ public class CrudRestService { logger.debug("Incoming request..." + content); Response response = null; - Map params = new HashMap(); - for (Map.Entry> e : uriInfo.getQueryParameters().entrySet()) { - params.put(e.getKey(), e.getValue().get(0)); - } + Map params = addParams ( uriInfo, false, type, version ); try { if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) { @@ -136,14 +133,7 @@ public class CrudRestService { try { if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) { String propertiesKey = CrudProperties.get(CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY); - - Map filter = new HashMap(); - - for (Map.Entry> e : uriInfo.getQueryParameters().entrySet()) { - if (!e.getKey().equals(propertiesKey)) { - filter.put(e.getKey(), e.getValue().get(0)); - } - } + Map filter = addParams ( uriInfo, true, type, version ); HashSet properties; if (uriInfo.getQueryParameters().containsKey(propertiesKey)) { @@ -180,10 +170,7 @@ public class CrudRestService { logger.debug("Incoming request..." + content); Response response = null; - Map params = new HashMap(); - for (Map.Entry> e : uriInfo.getQueryParameters().entrySet()) { - params.put(e.getKey(), e.getValue().get(0)); - } + Map params = addParams ( uriInfo, false, type, version ); try { if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) { @@ -215,12 +202,7 @@ public class CrudRestService { logger.debug("Incoming request..." + content); Response response = null; - - - Map filter = new HashMap(); - for (Map.Entry> e : uriInfo.getQueryParameters().entrySet()) { - filter.put(e.getKey(), e.getValue().get(0)); - } + Map filter = addParams ( uriInfo, true, type, version ); try { if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) { @@ -828,4 +810,23 @@ public class CrudRestService { // uses our transaction id. MDC.clear(); } + + private Map addParams ( UriInfo info, boolean filter, String type, String version ) { + String propertiesKey = CrudProperties.get ( CrudServiceConstants.CRD_COLLECTION_PROPERTIES_KEY ); + Map params = new HashMap (); + params.put ( CrudServiceConstants.CRD_RESERVED_VERSION, version ); + params.put ( CrudServiceConstants.CRD_RESERVED_NODE_TYPE, type ); + if (filter) { + for (Map.Entry> e : info.getQueryParameters ().entrySet ()) { + if (!e.getKey ().equals ( propertiesKey )) { + params.put ( e.getKey (), e.getValue ().get ( 0 ) ); + } + } + } else { + for (Map.Entry> e : info.getQueryParameters ().entrySet ()) { + params.put ( e.getKey (), e.getValue ().get ( 0 ) ); + } + } + return params; + } } diff --git a/src/main/java/org/onap/crud/util/CrudServiceConstants.java b/src/main/java/org/onap/crud/util/CrudServiceConstants.java index 4b88353..3a02852 100644 --- a/src/main/java/org/onap/crud/util/CrudServiceConstants.java +++ b/src/main/java/org/onap/crud/util/CrudServiceConstants.java @@ -37,4 +37,6 @@ public class CrudServiceConstants { public static final String CRD_ASYNC_REQUEST_TIMEOUT = "crud.async.request.timeout"; public static final String CRD_ASYNC_RESPONSE_PROCESS_POLL_INTERVAL = "crud.async.response.process.poll.interval"; public static final String CRD_COLLECTION_PROPERTIES_KEY = "crud.collection.properties.key"; + public static final String CRD_RESERVED_VERSION = "_reserved_version"; + public static final String CRD_RESERVED_NODE_TYPE = "_reserved_aai-type"; } diff --git a/src/main/java/org/onap/schema/OxmModelValidator.java b/src/main/java/org/onap/schema/OxmModelValidator.java index dda4341..6bc8bcf 100644 --- a/src/main/java/org/onap/schema/OxmModelValidator.java +++ b/src/main/java/org/onap/schema/OxmModelValidator.java @@ -32,6 +32,7 @@ import org.eclipse.persistence.oxm.XMLField; import org.onap.aaiutils.oxm.OxmModelLoader; import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; +import org.onap.crud.util.CrudServiceConstants; import org.onap.crud.util.CrudServiceUtil; import java.util.HashMap; @@ -87,6 +88,10 @@ public class OxmModelValidator { final DynamicType reservedObjectType = jaxbContext.getDynamicType("ReservedPropNames"); for (String key : filter.keySet()) { + if ((key == CrudServiceConstants.CRD_RESERVED_VERSION ) || key == CrudServiceConstants.CRD_RESERVED_NODE_TYPE ) { + result.put ( key, filter.get ( key ) ); + continue; + } String keyJavaName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, key); DatabaseMapping mapping = modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName); -- 2.16.6 From c57a430c6dbd6951091978404a164000024fce20 Mon Sep 17 00:00:00 2001 From: "Sotiropoulos, Ioannis (is948x)" Date: Wed, 6 Jun 2018 10:56:36 +0100 Subject: [PATCH 09/16] Add validation for request header Add validation for inclusion of X-FromAppId and X-TransactionId in request header Issue-ID: AAI-1190 Change-Id: Ie1d2b64a7243c013982992196048e1d6635d5e66 Signed-off-by: Sotiropoulos, Ioannis (is948x) --- pom.xml | 10 ++++- .../org/onap/crud/service/CrudRestService.java | 29 ++++++++---- .../org/onap/crud/service/CrudRestServiceTest.java | 51 +++++++++++++++++++--- .../java/org/onap/crud/service/TestHeaders.java | 19 ++++++-- 4 files changed, 89 insertions(+), 20 deletions(-) diff --git a/pom.xml b/pom.xml index a6af37a..408a0cd 100644 --- a/pom.xml +++ b/pom.xml @@ -127,9 +127,15 @@ limitations under the License. org.mockito - mockito-all - 1.9.5 + mockito-core + 1.10.19 test + + + org.hamcrest + hamcrest-library + + dom4j diff --git a/src/main/java/org/onap/crud/service/CrudRestService.java b/src/main/java/org/onap/crud/service/CrudRestService.java index 5539374..2cbb87c 100644 --- a/src/main/java/org/onap/crud/service/CrudRestService.java +++ b/src/main/java/org/onap/crud/service/CrudRestService.java @@ -790,16 +790,29 @@ public class CrudRestService { return false; } - String sourceOfTruth = null; - if (headers.getRequestHeaders().containsKey("X-FromAppId")) { - sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); - } + validateRequestHeader(headers); + + return isValid; + } + + public void validateRequestHeader(HttpHeaders headers) throws CrudException { + String sourceOfTruth = null; + if (headers.getRequestHeaders().containsKey("X-FromAppId")) { + sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); + } - if (sourceOfTruth == null || sourceOfTruth.trim() == "") { - throw new CrudException("Invalid request, Missing X-FromAppId header", Status.BAD_REQUEST); - } + if (sourceOfTruth == null || sourceOfTruth.trim() == "") { + throw new CrudException("Invalid request, Missing X-FromAppId header", Status.BAD_REQUEST); + } + + String transId = null; + if (headers.getRequestHeaders().containsKey("X-TransactionId")) { + transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + } - return isValid; + if (transId == null || transId.trim() == "") { + throw new CrudException("Invalid request, Missing X-TransactionId header", Status.BAD_REQUEST); + } } void logResult(Action op, String uri, Exception e) { diff --git a/src/test/java/org/onap/crud/service/CrudRestServiceTest.java b/src/test/java/org/onap/crud/service/CrudRestServiceTest.java index 029fd52..b61f234 100644 --- a/src/test/java/org/onap/crud/service/CrudRestServiceTest.java +++ b/src/test/java/org/onap/crud/service/CrudRestServiceTest.java @@ -20,19 +20,19 @@ */ package org.onap.crud.service; -import static org.junit.Assert.*; - +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; - import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; - import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.mockito.Mockito; import org.onap.crud.exception.CrudException; import org.onap.schema.RelationshipSchemaLoader; @@ -69,6 +69,9 @@ public class CrudRestServiceTest { private CrudRestService mockService; + @Rule + public ExpectedException thrown = ExpectedException.none(); + @Before public void init() throws Exception { ClassLoader classLoader = getClass().getClassLoader(); @@ -141,7 +144,7 @@ public class CrudRestServiceTest { @Test public void testUpdateVertex() throws CrudException { Response response; - + // Test ID mismatch response = mockService.updateVertex(putVertexPayload, "v11", "pserver", "bad-id", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); @@ -202,6 +205,42 @@ public class CrudRestServiceTest { assertTrue(response.getStatus() == 200); } + @Test + public void testValidRequestHeader() throws CrudException { + TestHeaders testHeaders = new TestHeaders(); + mockService.validateRequestHeader(testHeaders); + } + + @Test + public void testInvalidRequestHeaderXTransactionId() throws CrudException { + thrown.expect(CrudException.class); + thrown.expectMessage("Invalid request, Missing X-TransactionId header"); + + TestHeaders testHeaders = new TestHeaders(); + testHeaders.clearRequestHeader("X-TransactionId"); + mockService.validateRequestHeader(testHeaders); + } + + @Test + public void testInvalidRequestHeaderXFromAppId() throws CrudException { + thrown.expect(CrudException.class); + thrown.expectMessage("Invalid request, Missing X-FromAppId header"); + + TestHeaders testHeaders = new TestHeaders(); + testHeaders.clearRequestHeader("X-FromAppId"); + mockService.validateRequestHeader(testHeaders); + } + + @Test + public void testEmptyRequestHeader() throws CrudException { + thrown.expect(CrudException.class); + thrown.expectMessage("Invalid request, Missing X-FromAppId header"); + + TestHeaders testHeaders = new TestHeaders(); + testHeaders.clearRequestHeader("X-TransactionId", "X-FromAppId"); + mockService.validateRequestHeader(testHeaders); + } + @Test public void testBulk() throws CrudException, IOException { Response response; @@ -238,4 +277,4 @@ public class CrudRestServiceTest { } } -} +} \ No newline at end of file diff --git a/src/test/java/org/onap/crud/service/TestHeaders.java b/src/test/java/org/onap/crud/service/TestHeaders.java index 6e30471..835840f 100644 --- a/src/test/java/org/onap/crud/service/TestHeaders.java +++ b/src/test/java/org/onap/crud/service/TestHeaders.java @@ -33,6 +33,14 @@ import javax.ws.rs.core.MultivaluedMap; public class TestHeaders implements HttpHeaders { + private MultivaluedMap headers; + + public TestHeaders() { + headers = new MultivaluedHashMap(); + headers.add("X-FromAppId", "test-app"); + headers.add("X-TransactionId", "65f7e29c-57fd-45b2-bfd5-19e25c59110e"); + } + @Override public List getAcceptableLanguages() { return null; @@ -82,10 +90,13 @@ public class TestHeaders implements HttpHeaders { @Override public MultivaluedMap getRequestHeaders() { - MultivaluedMap map = new MultivaluedHashMap(); - map.add("X-FromAppId", "test-app"); - map.add("X-TransactionId", "65f7e29c-57fd-45b2-bfd5-19e25c59110e"); - return map; + return headers; + } + + public void clearRequestHeader(String... keys) { + for (String key : keys) { + headers.remove(key); + } } } -- 2.16.6 From 36a7dbfd2672ee6629c4b375df2d6982d942fa43 Mon Sep 17 00:00:00 2001 From: "Sotiropoulos, Ioannis (is948x)" Date: Wed, 6 Jun 2018 15:37:35 +0100 Subject: [PATCH 10/16] Add tests for X-FromMsId Add tests for X-FromMsId header parameter changes Issue-ID: AAI-1198 Change-Id: I6342cf95e5c635b500245bfa90040376ffa1b992 Signed-off-by: Sotiropoulos, Ioannis (is948x) --- .../java/org/onap/crud/logging/LoggingUtil.java | 22 ++++++--- .../org/onap/crud/{service => dao}/TestDao.java | 2 +- .../onap/crud/event/GraphEventEnvelopeTest.java | 2 +- .../response/GraphEventResponseHandlerTest.java | 2 +- .../org/onap/crud/logging/LoggingUtilTest.java | 52 +++++++++++++++++++++ .../org/onap/crud/service/CrudRestServiceTest.java | 14 ++++++ .../onap/crud/service/{ => util}/TestHeaders.java | 7 +-- .../onap/crud/service/{ => util}/TestRequest.java | 2 +- .../onap/crud/service/{ => util}/TestUriInfo.java | 2 +- .../org/onap/crud/util/CrudServiceUtilTest.java | 54 ++++++++++++++++++++++ .../org/onap/crud/{test => }/util/TestUtil.java | 2 +- 11 files changed, 145 insertions(+), 16 deletions(-) rename src/test/java/org/onap/crud/{service => dao}/TestDao.java (99%) create mode 100644 src/test/java/org/onap/crud/logging/LoggingUtilTest.java rename src/test/java/org/onap/crud/service/{ => util}/TestHeaders.java (92%) rename src/test/java/org/onap/crud/service/{ => util}/TestRequest.java (99%) rename src/test/java/org/onap/crud/service/{ => util}/TestUriInfo.java (99%) create mode 100644 src/test/java/org/onap/crud/util/CrudServiceUtilTest.java rename src/test/java/org/onap/crud/{test => }/util/TestUtil.java (98%) diff --git a/src/main/java/org/onap/crud/logging/LoggingUtil.java b/src/main/java/org/onap/crud/logging/LoggingUtil.java index f9cb905..31c0c1f 100644 --- a/src/main/java/org/onap/crud/logging/LoggingUtil.java +++ b/src/main/java/org/onap/crud/logging/LoggingUtil.java @@ -37,21 +37,29 @@ public class LoggingUtil { */ public static void initMdcContext(HttpServletRequest httpReq, HttpHeaders headers) { String fromIp = httpReq.getRemoteAddr(); - String fromAppId = ""; - String transId = null; - if (headers.getRequestHeaders().getFirst("X-FromAppId") != null) { + MdcContext.initialize(getTransactionId(headers), CrudServiceConstants.CRD_SERVICE_NAME, "", getAppId(headers), fromIp); + } + + public static String getAppId(HttpHeaders headers) { + String fromAppId = ""; + if (headers.getRequestHeaders().getFirst("X-FromMsId") != null) { + fromAppId = headers.getRequestHeaders().getFirst("X-FromMsId"); + } else if (headers.getRequestHeaders().getFirst("X-FromAppId") != null) { fromAppId = headers.getRequestHeaders().getFirst("X-FromAppId"); } - + return fromAppId; + } + + public static String getTransactionId(HttpHeaders headers) { + String transId = null; if ((headers.getRequestHeaders().getFirst("X-TransactionId") == null) - || headers.getRequestHeaders().getFirst("X-TransactionId").isEmpty()) { + || headers.getRequestHeaders().getFirst("X-TransactionId").isEmpty()) { transId = java.util.UUID.randomUUID().toString(); } else { transId = headers.getRequestHeaders().getFirst("X-TransactionId"); } - - MdcContext.initialize(transId, CrudServiceConstants.CRD_SERVICE_NAME, "", fromAppId, fromIp); + return transId; } /** diff --git a/src/test/java/org/onap/crud/service/TestDao.java b/src/test/java/org/onap/crud/dao/TestDao.java similarity index 99% rename from src/test/java/org/onap/crud/service/TestDao.java rename to src/test/java/org/onap/crud/dao/TestDao.java index 5af85f0..69ce4a3 100644 --- a/src/test/java/org/onap/crud/service/TestDao.java +++ b/src/test/java/org/onap/crud/dao/TestDao.java @@ -18,7 +18,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.crud.service; +package org.onap.crud.dao; import java.util.ArrayList; import java.util.HashSet; diff --git a/src/test/java/org/onap/crud/event/GraphEventEnvelopeTest.java b/src/test/java/org/onap/crud/event/GraphEventEnvelopeTest.java index e280c95..de56992 100644 --- a/src/test/java/org/onap/crud/event/GraphEventEnvelopeTest.java +++ b/src/test/java/org/onap/crud/event/GraphEventEnvelopeTest.java @@ -26,7 +26,7 @@ import org.junit.Test; import org.onap.crud.entity.Vertex; import org.onap.crud.event.GraphEvent.GraphEventOperation; import org.onap.crud.event.envelope.GraphEventEnvelope; -import org.onap.crud.test.util.TestUtil; +import org.onap.crud.util.TestUtil; import org.skyscreamer.jsonassert.Customization; import org.skyscreamer.jsonassert.JSONAssert; import org.skyscreamer.jsonassert.JSONCompareMode; diff --git a/src/test/java/org/onap/crud/event/response/GraphEventResponseHandlerTest.java b/src/test/java/org/onap/crud/event/response/GraphEventResponseHandlerTest.java index 9330556..1829496 100644 --- a/src/test/java/org/onap/crud/event/response/GraphEventResponseHandlerTest.java +++ b/src/test/java/org/onap/crud/event/response/GraphEventResponseHandlerTest.java @@ -24,7 +24,7 @@ import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import org.junit.Test; import org.onap.crud.event.envelope.GraphEventEnvelope; -import org.onap.crud.test.util.TestUtil; +import org.onap.crud.util.TestUtil; import com.google.gson.Gson; public class GraphEventResponseHandlerTest { diff --git a/src/test/java/org/onap/crud/logging/LoggingUtilTest.java b/src/test/java/org/onap/crud/logging/LoggingUtilTest.java new file mode 100644 index 0000000..bc1c9bd --- /dev/null +++ b/src/test/java/org/onap/crud/logging/LoggingUtilTest.java @@ -0,0 +1,52 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.crud.logging; + +import org.junit.Assert; +import org.junit.Test; +import org.onap.crud.service.util.TestHeaders; + +public class LoggingUtilTest { + + @Test + public void testGetAppId() throws Exception { + // When both MsId and AppId headers populated, return MsId header to log + TestHeaders headers = new TestHeaders(); + Assert.assertEquals("sending-service", LoggingUtil.getAppId(headers)); + + // When AppId header populated, return AppId header to log + headers = new TestHeaders(); + headers.clearRequestHeader("X-FromMsId"); + Assert.assertEquals("source-of-truth", LoggingUtil.getAppId(headers)); + + // When no headers populated, return empty string + headers = new TestHeaders(); + headers.clearRequestHeader("X-FromMsId", "X-FromAppId"); + Assert.assertEquals("", LoggingUtil.getAppId(headers)); + } + + @Test + public void testGetTransactionId() throws Exception { + TestHeaders headers = new TestHeaders(); + Assert.assertEquals("1234567890", LoggingUtil.getTransactionId(headers)); + } + +} diff --git a/src/test/java/org/onap/crud/service/CrudRestServiceTest.java b/src/test/java/org/onap/crud/service/CrudRestServiceTest.java index b61f234..3d1ce12 100644 --- a/src/test/java/org/onap/crud/service/CrudRestServiceTest.java +++ b/src/test/java/org/onap/crud/service/CrudRestServiceTest.java @@ -34,7 +34,11 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mockito; +import org.onap.crud.dao.TestDao; import org.onap.crud.exception.CrudException; +import org.onap.crud.service.util.TestHeaders; +import org.onap.crud.service.util.TestRequest; +import org.onap.crud.service.util.TestUriInfo; import org.onap.schema.RelationshipSchemaLoader; @@ -231,6 +235,16 @@ public class CrudRestServiceTest { mockService.validateRequestHeader(testHeaders); } + @Test + public void testRequestHeaderWithMsId() throws CrudException { + thrown.expect(CrudException.class); + thrown.expectMessage("Invalid request, Missing X-FromAppId header"); + + TestHeaders testHeaders = new TestHeaders(); + testHeaders.clearRequestHeader("X-TransactionId", "X-FromAppId"); + mockService.validateRequestHeader(testHeaders); + } + @Test public void testEmptyRequestHeader() throws CrudException { thrown.expect(CrudException.class); diff --git a/src/test/java/org/onap/crud/service/TestHeaders.java b/src/test/java/org/onap/crud/service/util/TestHeaders.java similarity index 92% rename from src/test/java/org/onap/crud/service/TestHeaders.java rename to src/test/java/org/onap/crud/service/util/TestHeaders.java index 835840f..aca276c 100644 --- a/src/test/java/org/onap/crud/service/TestHeaders.java +++ b/src/test/java/org/onap/crud/service/util/TestHeaders.java @@ -18,7 +18,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.crud.service; +package org.onap.crud.service.util; import java.util.Date; import java.util.List; @@ -37,8 +37,9 @@ public class TestHeaders implements HttpHeaders { public TestHeaders() { headers = new MultivaluedHashMap(); - headers.add("X-FromAppId", "test-app"); - headers.add("X-TransactionId", "65f7e29c-57fd-45b2-bfd5-19e25c59110e"); + headers.add("X-FromMsId", "sending-service"); + headers.add("X-FromAppId", "source-of-truth"); + headers.add("X-TransactionId", "1234567890"); } @Override diff --git a/src/test/java/org/onap/crud/service/TestRequest.java b/src/test/java/org/onap/crud/service/util/TestRequest.java similarity index 99% rename from src/test/java/org/onap/crud/service/TestRequest.java rename to src/test/java/org/onap/crud/service/util/TestRequest.java index f5ee7d6..a0c9a2e 100644 --- a/src/test/java/org/onap/crud/service/TestRequest.java +++ b/src/test/java/org/onap/crud/service/util/TestRequest.java @@ -18,7 +18,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.crud.service; +package org.onap.crud.service.util; import java.io.BufferedReader; import java.io.IOException; diff --git a/src/test/java/org/onap/crud/service/TestUriInfo.java b/src/test/java/org/onap/crud/service/util/TestUriInfo.java similarity index 99% rename from src/test/java/org/onap/crud/service/TestUriInfo.java rename to src/test/java/org/onap/crud/service/util/TestUriInfo.java index 980f0da..f416d8b 100644 --- a/src/test/java/org/onap/crud/service/TestUriInfo.java +++ b/src/test/java/org/onap/crud/service/util/TestUriInfo.java @@ -18,7 +18,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.crud.service; +package org.onap.crud.service.util; import java.net.URI; import java.util.List; diff --git a/src/test/java/org/onap/crud/util/CrudServiceUtilTest.java b/src/test/java/org/onap/crud/util/CrudServiceUtilTest.java new file mode 100644 index 0000000..872586e --- /dev/null +++ b/src/test/java/org/onap/crud/util/CrudServiceUtilTest.java @@ -0,0 +1,54 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.crud.util; + +import org.junit.Assert; +import org.junit.Test; +import org.onap.crud.service.VertexPayload; +import org.onap.crud.service.util.TestHeaders; +import com.google.gson.JsonElement; + +public class CrudServiceUtilTest { + + private final String putVertexPayload = "{" + "\"id\": \"test-uuid\"," + "\"type\": \"pserver\"," + + "\"properties\": {" + "fqdn: myhost.onap.com," + "hostname: myhost } }"; + + @Test + public void testMergeHeaderInFoToPayload() throws Exception { + TestHeaders headers = new TestHeaders(); + // X-FromAppId is used to set the source of truth + VertexPayload payload = VertexPayload.fromJson(putVertexPayload); + + JsonElement properties = CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false); + Assert.assertEquals("myhost.onap.com", properties.getAsJsonObject().get("fqdn").getAsString()); + Assert.assertEquals("myhost", properties.getAsJsonObject().get("hostname").getAsString()); + Assert.assertEquals("source-of-truth", + properties.getAsJsonObject().get("last-mod-source-of-truth").getAsString()); + + properties = CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true); + Assert.assertEquals("myhost.onap.com", properties.getAsJsonObject().get("fqdn").getAsString()); + Assert.assertEquals("myhost", properties.getAsJsonObject().get("hostname").getAsString()); + Assert.assertEquals("source-of-truth", + properties.getAsJsonObject().get("last-mod-source-of-truth").getAsString()); + Assert.assertEquals("source-of-truth", properties.getAsJsonObject().get("source-of-truth").getAsString()); + } + +} diff --git a/src/test/java/org/onap/crud/test/util/TestUtil.java b/src/test/java/org/onap/crud/util/TestUtil.java similarity index 98% rename from src/test/java/org/onap/crud/test/util/TestUtil.java rename to src/test/java/org/onap/crud/util/TestUtil.java index 1fcb46e..bfbc91b 100644 --- a/src/test/java/org/onap/crud/test/util/TestUtil.java +++ b/src/test/java/org/onap/crud/util/TestUtil.java @@ -18,7 +18,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.crud.test.util; +package org.onap.crud.util; import java.io.File; import java.io.IOException; -- 2.16.6 From 28f9fa1399f5e513a3d5860c52cd51b615bc0a2c Mon Sep 17 00:00:00 2001 From: "Sotiropoulos, Ioannis (is948x)" Date: Mon, 11 Jun 2018 09:54:54 +0100 Subject: [PATCH 11/16] Process multi-OXM files Gizmo service uses common OXM consumer to process multi-OXM files Issue-ID: AAI-1196 Change-Id: If6dd50413a914984948272cd6bd98e2eeeaecedb Signed-off-by: Sotiropoulos, Ioannis (is948x) --- pom.xml | 30 + src/main/java/org/onap/crud/entity/Vertex.java | 32 +- .../org/onap/crud/exception/CrudException.java | 4 + .../org/onap/crud/logging/CrudServiceMsgs.java | 7 +- .../java/org/onap/crud/util/CrudServiceUtil.java | 8 +- .../org/onap/schema/OxmModelConfigTranslator.java | 100 + src/main/java/org/onap/schema/OxmModelLoader.java | 161 + .../java/org/onap/schema/OxmModelValidator.java | 41 +- .../org/onap/schema/RelationshipSchemaLoader.java | 12 +- .../schema/util/SchemaIngestPropertyReader.java | 91 + .../resources/logging/CrudServiceMsgs.properties | 5 +- .../org/onap/crud/service/CrudRestServiceTest.java | 57 +- .../java/org/onap/schema/OxmModelLoaderTest.java | 59 + .../onap/schema/RelationshipSchemaLoaderTest.java | 11 +- src/test/resources/oxm/aai_oxm_a_v13.xml | 2987 +++++++++ src/test/resources/oxm/aai_oxm_b_v13.xml | 3811 ++++++++++++ src/test/resources/oxm/aai_oxm_v11.xml | 6363 ++++++++++++++++++++ src/test/resources/schemaIngest.properties | 4 + 18 files changed, 13727 insertions(+), 56 deletions(-) create mode 100644 src/main/java/org/onap/schema/OxmModelConfigTranslator.java create mode 100644 src/main/java/org/onap/schema/OxmModelLoader.java create mode 100644 src/main/java/org/onap/schema/util/SchemaIngestPropertyReader.java create mode 100644 src/test/java/org/onap/schema/OxmModelLoaderTest.java create mode 100644 src/test/resources/oxm/aai_oxm_a_v13.xml create mode 100644 src/test/resources/oxm/aai_oxm_b_v13.xml create mode 100644 src/test/resources/oxm/aai_oxm_v11.xml create mode 100644 src/test/resources/schemaIngest.properties diff --git a/pom.xml b/pom.xml index 408a0cd..2276939 100644 --- a/pom.xml +++ b/pom.xml @@ -193,6 +193,11 @@ limitations under the License. org.onap.aai.aai-common aai-schema 1.3.0-SNAPSHOT + + + org.onap.aai.aai-common + aai-schema-ingest + 1.2.2 org.onap.aai.aai-common @@ -435,6 +440,31 @@ limitations under the License. + + + org.apache.maven.plugins + maven-dependency-plugin + + + unpack + prepare-package + + unpack + + + + + org.onap.aai.aai-common + aai-schema + 1.2.1 + jar + oxm/ + ${project.build.directory}/bundleconfig-local/etc + + + + + diff --git a/src/main/java/org/onap/crud/entity/Vertex.java b/src/main/java/org/onap/crud/entity/Vertex.java index efe2d5a..cffdcf1 100644 --- a/src/main/java/org/onap/crud/entity/Vertex.java +++ b/src/main/java/org/onap/crud/entity/Vertex.java @@ -20,30 +20,26 @@ */ package org.onap.crud.entity; -import net.dongliu.gson.GsonJava8TypeAdapterFactory; - -import com.google.common.base.CaseFormat; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.annotations.SerializedName; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; - import org.eclipse.persistence.dynamic.DynamicType; import org.eclipse.persistence.internal.helper.DatabaseField; import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; import org.eclipse.persistence.mappings.DatabaseMapping; import org.json.JSONArray; import org.json.JSONObject; -import org.onap.aaiutils.oxm.OxmModelLoader; import org.onap.crud.exception.CrudException; import org.onap.crud.util.CrudServiceUtil; +import org.onap.schema.OxmModelLoader; import org.onap.schema.OxmModelValidator; +import com.google.common.base.CaseFormat; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.annotations.SerializedName; +import net.dongliu.gson.GsonJava8TypeAdapterFactory; public class Vertex { private static final Gson gson = new GsonBuilder().registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory()) @@ -114,30 +110,30 @@ public class Vertex { try { String type = jsonObject.getString("type"); builder = new Builder(type).id(jsonObject.getString("key")); - + type = OxmModelValidator.resolveCollectionType(version, type); DynamicJAXBContext jaxbContext = OxmModelLoader.getContextForVersion(version); String modelObjectClass = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type)); final DynamicType modelObjectType = jaxbContext.getDynamicType(modelObjectClass); final DynamicType reservedType = jaxbContext.getDynamicType("ReservedPropNames"); - - + + if (modelObjectType == null) { throw new CrudException("Unable to load oxm version", javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); } if (jsonObject.has("properties")) { JSONObject jsonProps = jsonObject.getJSONObject("properties"); - for (String key : (Set)jsonProps.keySet()) { + for (String key : jsonProps.keySet()) { String keyJavaName = CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, key); DatabaseMapping mapping = modelObjectType.getDescriptor().getMappingForAttributeName(keyJavaName); - + if (mapping == null) { // This might be one of the reserved properties mapping = reservedType.getDescriptor().getMappingForAttributeName(keyJavaName); } - + if (mapping != null) { DatabaseField field = mapping.getField(); Object value = CrudServiceUtil.validateFieldType(jsonProps.get(key).toString(), field.getType()); @@ -149,8 +145,8 @@ public class Vertex { catch (Exception ex) { throw new CrudException("Unable to transform response: " + jsonObject.toString(), javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR); } - - return builder.build(); + + return builder.build(); } public static List collectionFromJson(String jsonString, String version) throws CrudException { diff --git a/src/main/java/org/onap/crud/exception/CrudException.java b/src/main/java/org/onap/crud/exception/CrudException.java index a4fb3d7..57d9858 100644 --- a/src/main/java/org/onap/crud/exception/CrudException.java +++ b/src/main/java/org/onap/crud/exception/CrudException.java @@ -30,6 +30,10 @@ public class CrudException extends Exception { public CrudException() {} + public CrudException(String message) { + super(message); + } + public CrudException(String message, Status httpStatus) { super(message); this.setHttpStatus(httpStatus); diff --git a/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java b/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java index 36cb3f5..72883a9 100644 --- a/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java +++ b/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java @@ -120,7 +120,12 @@ public enum CrudServiceMsgs implements LogMessageEnum { /** * Arguments: {0} Opertaion {1} URI {2} = Exception */ - EXCEPTION_DURING_METHOD_CALL; + EXCEPTION_DURING_METHOD_CALL, + + /** + * Schema Ingest properties file was not loaded properly + */ + SCHEMA_INGEST_LOAD_ERROR; /** * Static initializer to ensure the resource bundles for this class are diff --git a/src/main/java/org/onap/crud/util/CrudServiceUtil.java b/src/main/java/org/onap/crud/util/CrudServiceUtil.java index 7943218..4d108f2 100644 --- a/src/main/java/org/onap/crud/util/CrudServiceUtil.java +++ b/src/main/java/org/onap/crud/util/CrudServiceUtil.java @@ -21,8 +21,8 @@ package org.onap.crud.util; import org.onap.aai.db.props.AAIProperties; -import org.onap.aaiutils.oxm.OxmModelLoader; import org.onap.crud.exception.CrudException; +import org.onap.schema.OxmModelLoader; import org.onap.schema.RelationshipSchemaLoader; import com.google.gson.Gson; @@ -41,6 +41,8 @@ import javax.ws.rs.core.Response.Status; public class CrudServiceUtil { private static Gson gson = new Gson(); + + @SuppressWarnings({"unchecked", "rawtypes"}) public static Object validateFieldType(String value, Class clazz) throws CrudException { try { if (clazz.isAssignableFrom(Integer.class)) { @@ -88,7 +90,9 @@ public class CrudServiceUtil { * @param isAdd * @return */ - public static JsonElement mergeHeaderInFoToPayload(JsonElement propertiesFromRequest, HttpHeaders headers, boolean isAdd) { + @SuppressWarnings("unchecked") + public static JsonElement mergeHeaderInFoToPayload(JsonElement propertiesFromRequest, HttpHeaders headers, + boolean isAdd) { String sourceOfTruth = headers.getRequestHeaders().getFirst("X-FromAppId"); Set> properties = new HashSet>(); properties.addAll(propertiesFromRequest.getAsJsonObject().entrySet()); diff --git a/src/main/java/org/onap/schema/OxmModelConfigTranslator.java b/src/main/java/org/onap/schema/OxmModelConfigTranslator.java new file mode 100644 index 0000000..f6b9e70 --- /dev/null +++ b/src/main/java/org/onap/schema/OxmModelConfigTranslator.java @@ -0,0 +1,100 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.schema; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.nio.file.Paths; +import java.util.List; +import java.util.Map; +import java.util.ServiceConfigurationError; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.onap.aai.setup.ConfigTranslator; +import org.onap.aai.setup.SchemaLocationsBean; +import org.onap.aai.setup.Version; + +public class OxmModelConfigTranslator extends ConfigTranslator { + + public OxmModelConfigTranslator(SchemaLocationsBean bean) { + super(bean); + } + + @Override + public Map> getNodeFiles() { + String nodeDirectory = bean.getNodeDirectory(); + if (nodeDirectory == null) { + throw new ServiceConfigurationError( + "Node(s) directory is empty in the schema location bean (" + bean.getSchemaConfigLocation() + ")"); + } + try { + return getVersionMap(Paths.get(nodeDirectory), "*_v*.xml"); + } catch (IOException e) { + throw new ServiceConfigurationError("Failed to read node(s) directory " + getPath(nodeDirectory), e); + } + } + + @Override + public Map> getEdgeFiles() { + String edgeDirectory = bean.getEdgeDirectory(); + if (edgeDirectory == null) { + throw new ServiceConfigurationError( + "Edge(s) directory is empty in the schema location bean (" + bean.getSchemaConfigLocation() + ")"); + } + try { + return getVersionMap(Paths.get(edgeDirectory), "*_v*.json"); + } catch (IOException e) { + throw new ServiceConfigurationError("Failed to read edge(s) directory " + getPath(edgeDirectory), e); + } + } + + private String getPath(String nodeDirectory) { + return Paths.get(nodeDirectory).toAbsolutePath().toString(); + } + + /** + * Creates a map containing each OXM Version and the matching OXM file path(s) + * + * @param folderPath the folder/directory containing the OXM files + * @param fileSuffix + * @return a new Map object (may be empty) + * @throws IOException if there is a problem reading the specified directory path + */ + private Map> getVersionMap(Path folderPath, String globPattern) throws IOException { + final PathMatcher filter = folderPath.getFileSystem().getPathMatcher("glob:**/" + globPattern); + try (final Stream stream = Files.list(folderPath)) { + return stream.filter(filter::matches).map(Path::toString).filter(p -> getVersionFromPath(p) != null) + .collect(Collectors.groupingBy(this::getVersionFromPath)); + } + } + + private Version getVersionFromPath(String pathName) { + String version = "V" + pathName.replaceAll("^.*\\/", "").replaceAll("\\D+", ""); + try { + return Version.valueOf(version); + } catch (IllegalArgumentException e) { + return null; + } + } + +} diff --git a/src/main/java/org/onap/schema/OxmModelLoader.java b/src/main/java/org/onap/schema/OxmModelLoader.java new file mode 100644 index 0000000..869df8f --- /dev/null +++ b/src/main/java/org/onap/schema/OxmModelLoader.java @@ -0,0 +1,161 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.schema; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.ws.rs.core.Response.Status; +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.nodes.NodeIngestor; +import org.onap.aai.setup.ConfigTranslator; +import org.onap.aai.setup.SchemaLocationsBean; +import org.onap.aai.setup.Version; +import org.onap.crud.exception.CrudException; +import org.onap.crud.logging.CrudServiceMsgs; +import org.onap.schema.util.SchemaIngestPropertyReader; + +public class OxmModelLoader { + + private static Map versionContextMap = + new ConcurrentHashMap<>(); + + static final Pattern p = Pattern.compile("aai_oxm_(.*).xml"); + static final Pattern versionPattern = Pattern.compile("V(\\d*)"); + + private static org.onap.aai.cl.api.Logger logger = + LoggerFactory.getInstance().getLogger(OxmModelLoader.class.getName()); + + private OxmModelLoader() { + } + + /** + * Finds all OXM model files + * + * @throws SpikeException + * @throws IOException + * + */ + public static synchronized void loadModels() throws CrudException { + SchemaIngestPropertyReader schemaIngestPropertyReader = new SchemaIngestPropertyReader(); + + SchemaLocationsBean schemaLocationsBean = new SchemaLocationsBean(); + schemaLocationsBean.setNodeDirectory(schemaIngestPropertyReader.getNodeDir()); + ConfigTranslator configTranslator = new OxmModelConfigTranslator(schemaLocationsBean); + NodeIngestor nodeIngestor = new NodeIngestor(configTranslator); + + if (logger.isDebugEnabled()) { + logger.debug("Loading OXM Models"); + } + + for (Version oxmVersion : Version.values()) { + DynamicJAXBContext jaxbContext = nodeIngestor.getContextForVersion(oxmVersion); + if (jaxbContext != null) { + loadModel(oxmVersion.toString().toLowerCase(), jaxbContext); + } + } + } + + + private static synchronized void loadModel(String oxmVersion, DynamicJAXBContext jaxbContext) { + versionContextMap.put(oxmVersion, jaxbContext); + logger.info(CrudServiceMsgs.LOADED_OXM_FILE, oxmVersion); + } + + /** + * Retrieves the JAXB context for the specified OXM model version. + * + * @param version - The OXM version that we want the JAXB context for. + * + * @return - A JAXB context derived from the OXM model schema. + * + * @throws SpikeException + */ + public static DynamicJAXBContext getContextForVersion(String version) throws CrudException { + + // If we haven't already loaded in the available OXM models, then do so now. + if (versionContextMap == null || versionContextMap.isEmpty()) { + loadModels(); + } else if (!versionContextMap.containsKey(version)) { + logger.error(CrudServiceMsgs.OXM_LOAD_ERROR, "Error loading oxm model: " + version); + throw new CrudException("Error loading oxm model: " + version, Status.INTERNAL_SERVER_ERROR); + } + + return versionContextMap.get(version); + } + + public static String getLatestVersion() throws CrudException { + + // If we haven't already loaded in the available OXM models, then do so now. + if (versionContextMap == null || versionContextMap.isEmpty()) { + loadModels(); + } + + // If there are still no models available, then there's not much we can do... + if (versionContextMap.isEmpty()) { + logger.error(CrudServiceMsgs.OXM_LOAD_ERROR, "No available OXM schemas to get latest version for."); + throw new CrudException("No available OXM schemas to get latest version for.", + Status.INTERNAL_SERVER_ERROR); + } + + // Iterate over the available model versions to determine which is the most + // recent. + Integer latestVersion = null; + String latestVersionStr = null; + for (String versionKey : versionContextMap.keySet()) { + + Matcher matcher = versionPattern.matcher(versionKey.toUpperCase()); + if (matcher.find()) { + + int currentVersion = Integer.parseInt(matcher.group(1)); + + if ((latestVersion == null) || (currentVersion > latestVersion)) { + latestVersion = currentVersion; + latestVersionStr = versionKey; + } + } + } + + return latestVersionStr; + } + + /** + * Retrieves the map of all JAXB context objects that have been created by importing the + * available OXM model schemas. + * + * @return - Map of JAXB context objects. + */ + public static Map getVersionContextMap() { + return versionContextMap; + } + + /** + * Assigns the map of all JAXB context objects. + * + * @param versionContextMap + */ + public static void setVersionContextMap(Map versionContextMap) { + OxmModelLoader.versionContextMap = versionContextMap; + } +} diff --git a/src/main/java/org/onap/schema/OxmModelValidator.java b/src/main/java/org/onap/schema/OxmModelValidator.java index 6bc8bcf..24d4a8c 100644 --- a/src/main/java/org/onap/schema/OxmModelValidator.java +++ b/src/main/java/org/onap/schema/OxmModelValidator.java @@ -20,27 +20,29 @@ */ package org.onap.schema; -import com.google.common.base.CaseFormat; -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; - +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import javax.ws.rs.core.Response.Status; import org.eclipse.persistence.dynamic.DynamicType; import org.eclipse.persistence.internal.helper.DatabaseField; import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; import org.eclipse.persistence.mappings.DatabaseMapping; import org.eclipse.persistence.oxm.XMLField; -import org.onap.aaiutils.oxm.OxmModelLoader; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; +import org.onap.crud.logging.CrudServiceMsgs; import org.onap.crud.util.CrudServiceConstants; import org.onap.crud.util.CrudServiceUtil; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import javax.ws.rs.core.Response.Status; +import com.google.common.base.CaseFormat; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; public class OxmModelValidator { + private static Logger logger = LoggerFactory.getInstance().getLogger(OxmModelValidator.class.getName()); + public enum Metadata { NODE_TYPE("aai-node-type"), URI("aai-uri"), @@ -81,7 +83,8 @@ public class OxmModelValidator { Map result = new HashMap(); if (jaxbContext == null) { - throw new CrudException("", Status.NOT_FOUND); + logger.error(CrudServiceMsgs.OXM_LOAD_ERROR, "Error loading oxm model: " + version); + throw new CrudException("Error loading oxm model: " + version, Status.NOT_FOUND); } final DynamicType modelObjectType = jaxbContext.getDynamicType( CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type))); @@ -120,12 +123,15 @@ public class OxmModelValidator { DynamicJAXBContext jaxbContext = null; try { jaxbContext = OxmModelLoader.getContextForVersion(version); + } catch (CrudException ce) { + throw new CrudException(ce.getMessage(), ce.getHttpStatus()); } catch (Exception e) { throw new CrudException(e); } if (jaxbContext == null) { - throw new CrudException("", Status.NOT_FOUND); + logger.error(CrudServiceMsgs.OXM_LOAD_ERROR, "Error loading oxm model: " + version); + throw new CrudException("Error loading oxm model: " + version, Status.NOT_FOUND); } // Determine if the Object part is a collection type in the model // definition @@ -133,7 +139,8 @@ public class OxmModelValidator { CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_CAMEL, type))); if (modelObjectType == null) { - throw new CrudException("", Status.NOT_FOUND); + logger.error(CrudServiceMsgs.INVALID_OXM_FILE, "Object of collection type not found: " + type); + throw new CrudException("Object of collection type not found: " + type, Status.NOT_FOUND); } if (modelObjectType.getDescriptor().getMappings().size() == 1 @@ -142,9 +149,9 @@ public class OxmModelValidator { childJavaObjectName = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, childJavaObjectName); final DynamicType childObjectType = jaxbContext.getDynamicType(childJavaObjectName); if (childObjectType == null) { - // Should not happen as child object is defined in oxm model - // itself - throw new CrudException("", Status.NOT_FOUND); + // Should not happen as child object is defined in oxm model itself + logger.error(CrudServiceMsgs.INVALID_OXM_FILE, "Child Object Type for Java Object not found: " + childJavaObjectName); + throw new CrudException("Child Object Type for Java Object not found: " + childJavaObjectName, Status.NOT_FOUND); } return childObjectType.getDescriptor().getTableName(); } else { @@ -231,6 +238,8 @@ public class OxmModelValidator { } return modelVertexBuilder.build(); + } catch (CrudException ce) { + throw new CrudException(ce.getMessage(), ce.getHttpStatus()); } catch (Exception e) { throw new CrudException(e.getMessage(), Status.BAD_REQUEST); } diff --git a/src/main/java/org/onap/schema/RelationshipSchemaLoader.java b/src/main/java/org/onap/schema/RelationshipSchemaLoader.java index 0e10fc3..9a9a37c 100644 --- a/src/main/java/org/onap/schema/RelationshipSchemaLoader.java +++ b/src/main/java/org/onap/schema/RelationshipSchemaLoader.java @@ -41,9 +41,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; - import javax.ws.rs.core.Response.Status; - import org.apache.commons.io.IOUtils; import org.onap.aai.cl.eelf.LoggerFactory; import org.onap.crud.exception.CrudException; @@ -125,8 +123,8 @@ public class RelationshipSchemaLoader { rulesFiles.add(file); existingFiles.add(filename(file)); } - - // Get DBEdgeRules from the jar on the classpath. Don't include any that conflict with files which + + // Get DBEdgeRules from the jar on the classpath. Don't include any that conflict with files which // were dropped manually. Resource[] rawResourceList = rulesResolver.getResources("classpath*:/dbedgerules/DbEdgeRules*" + fileExt); List prunedResourceList = new ArrayList(); @@ -135,10 +133,10 @@ public class RelationshipSchemaLoader { prunedResourceList.add(resource); } } - + rulesFiles.addAll(Arrays.stream(prunedResourceList.toArray(new Resource[prunedResourceList.size()])) .filter(r -> !myMatcher(rulesPattern, r.getFilename()).isEmpty()).collect(Collectors.toList())); - + // This gets all the objects of type "File" from external directory (not // on the classpath) // 1. From an external directory (one not on the classpath) we get all the @@ -271,4 +269,4 @@ public class RelationshipSchemaLoader { Matcher m = p.matcher(s); return m.matches() ? m.group(1) : ""; } -} +} \ No newline at end of file diff --git a/src/main/java/org/onap/schema/util/SchemaIngestPropertyReader.java b/src/main/java/org/onap/schema/util/SchemaIngestPropertyReader.java new file mode 100644 index 0000000..71ea47e --- /dev/null +++ b/src/main/java/org/onap/schema/util/SchemaIngestPropertyReader.java @@ -0,0 +1,91 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.schema.util; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.crud.exception.CrudException; +import org.onap.crud.logging.CrudServiceMsgs; + +public class SchemaIngestPropertyReader { + + private static final String SCHEMA_INGEST_PROPERTIES_FILE = "schemaIngest.properties"; + + private static final String SCHEMA_INGEST_PROPERTIES_LOCATION = + System.getProperty("CONFIG_HOME") + "/" + SCHEMA_INGEST_PROPERTIES_FILE; + + private static org.onap.aai.cl.api.Logger logger = + LoggerFactory.getInstance().getLogger(SchemaIngestPropertyReader.class.getName()); + + /** + * Gets the location of the OXM + * + * @return + * @throws SpikeException + * @throws IOException + */ + public String getNodeDir() throws CrudException { + + Properties prop = new Properties(); + try { + prop = loadFromFile(SCHEMA_INGEST_PROPERTIES_LOCATION); + } catch (NoSuchFileException e) { + // if file not found, try via classpath + try { + prop = loadFromClasspath(SCHEMA_INGEST_PROPERTIES_FILE); + } catch (URISyntaxException | IOException e1) { + logger.error(CrudServiceMsgs.SCHEMA_INGEST_LOAD_ERROR, e1.getMessage()); + throw new CrudException("Failed to load schemaIngest.properties", e1); + } + } catch (IOException e) { + logger.error(CrudServiceMsgs.SCHEMA_INGEST_LOAD_ERROR, e.getMessage()); + throw new CrudException("Failed to load schemaIngest.properties", e); + } + return prop.getProperty("nodeDir"); + } + + private Properties loadFromFile(String filename) throws IOException { + Path configLocation = Paths.get(filename); + try (InputStream stream = Files.newInputStream(configLocation)) { + return loadProperties(stream); + } + } + + private Properties loadFromClasspath(String resourceName) throws URISyntaxException, IOException { + Path path = Paths.get(ClassLoader.getSystemResource(resourceName).toURI()); + try (InputStream stream = Files.newInputStream(path)) { + return loadProperties(stream); + } + } + + private Properties loadProperties(InputStream stream) throws IOException { + Properties config = new Properties(); + config.load(stream); + return config; + } +} \ No newline at end of file diff --git a/src/main/resources/logging/CrudServiceMsgs.properties b/src/main/resources/logging/CrudServiceMsgs.properties index 165b892..5ae6ca6 100644 --- a/src/main/resources/logging/CrudServiceMsgs.properties +++ b/src/main/resources/logging/CrudServiceMsgs.properties @@ -78,4 +78,7 @@ ASYNC_RESPONSE_CONSUMER_INFO=\ AsyncResponseConsumer: {0} ASYNC_RESPONSE_CONSUMER_ERROR=\ CRD0514E|\ - AsyncResponseConsumer Error: {0} \ No newline at end of file + AsyncResponseConsumer Error: {0} +SCHEMA_INGEST_LOAD_ERROR=\ + CRD0900E|\ + Unable to load schema ingest properties file due to : {0} \ No newline at end of file diff --git a/src/test/java/org/onap/crud/service/CrudRestServiceTest.java b/src/test/java/org/onap/crud/service/CrudRestServiceTest.java index 3d1ce12..a4b4305 100644 --- a/src/test/java/org/onap/crud/service/CrudRestServiceTest.java +++ b/src/test/java/org/onap/crud/service/CrudRestServiceTest.java @@ -26,9 +26,12 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; +import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -78,9 +81,10 @@ public class CrudRestServiceTest { @Before public void init() throws Exception { - ClassLoader classLoader = getClass().getClassLoader(); - File dir = new File(classLoader.getResource("model").getFile()); - System.setProperty("CONFIG_HOME", dir.getParent()); + Path resourcePath = Paths.get(ClassLoader.getSystemResource("model").toURI()); + Path parentPath = resourcePath.getParent(); + + System.setProperty("CONFIG_HOME", parentPath.toString()); RelationshipSchemaLoader.resetVersionContextMap(); CrudGraphDataService service = new CrudGraphDataService(new TestDao()); @@ -100,7 +104,8 @@ public class CrudRestServiceTest { "services/inventory/v11", new TestHeaders(), null, new TestRequest()); assertTrue(response.getStatus() == 200); - response = mockService.deleteEdge("", "v11", "tosca.relationships.HostedOn", "872dd5df-0be9-4167-95e9-2cf4b21165ed", + response = mockService.deleteEdge("", "v11", "tosca.relationships.HostedOn", + "872dd5df-0be9-4167-95e9-2cf4b21165ed", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); assertTrue(response.getStatus() == 200); } @@ -109,6 +114,13 @@ public class CrudRestServiceTest { public void testAddVertex() throws CrudException { Response response; + // Cannot find OXM version + response = mockService.addVertex(postVertexPayload, "v8", "services/inventory/v8", + new TestHeaders(), null, new TestRequest()); + System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); + assertTrue(response.getStatus() == 500); + Assert.assertNull(response.getEntityTag()); + response = mockService.addVertex(postMissingPropVertexPayload, "v11", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); @@ -149,6 +161,13 @@ public class CrudRestServiceTest { public void testUpdateVertex() throws CrudException { Response response; + // Cannot find OXM version + response = mockService.updateVertex(putVertexPayload, "v8", "pserver", "test-uuid", "services/inventory/v8", + new TestHeaders(), null, new TestRequest()); + System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); + assertTrue(response.getStatus() == 500); + Assert.assertNull(response.getEntityTag()); + // Test ID mismatch response = mockService.updateVertex(putVertexPayload, "v11", "pserver", "bad-id", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); @@ -156,8 +175,8 @@ public class CrudRestServiceTest { assertTrue(response.getStatus() == 400); // Success case - response = mockService.updateVertex(putVertexPayload, "v11", "pserver", "test-uuid", - "services/inventory/v11", new TestHeaders(), null, new TestRequest()); + response = mockService.updateVertex(putVertexPayload, "v11", "pserver", "test-uuid", "services/inventory/v11", + new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 200); @@ -255,6 +274,32 @@ public class CrudRestServiceTest { mockService.validateRequestHeader(testHeaders); } + @Test + public void testGetMultiOxm() throws CrudException { + Response response; + + response = mockService.getVertex("", "v13", "pserver", "872dd5df-0be9-4167-95e9-2cf4b21165ed", + "services/inventory/v11", new TestHeaders(), new TestUriInfo(), new TestRequest()); + System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); + assertTrue(response.getStatus() == 200); + + response = + mockService.getEdge("", "v11", "tosca.relationships.HostedOn", "872dd5df-0be9-4167-95e9-2cf4b21165ed", + "services/inventory/v11", new TestHeaders(), new TestUriInfo(), new TestRequest()); + System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); + assertTrue(response.getStatus() == 200); + + response = mockService.getVertices("", "v13", "pserver", "services/inventory/v11", new TestHeaders(), + new TestUriInfo(), new TestRequest()); + System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); + assertTrue(response.getStatus() == 200); + + response = mockService.getEdges("", "v11", "tosca.relationships.HostedOn", "services/inventory/v11", + new TestHeaders(), new TestUriInfo(), new TestRequest()); + System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); + assertTrue(response.getStatus() == 200); + } + @Test public void testBulk() throws CrudException, IOException { Response response; diff --git a/src/test/java/org/onap/schema/OxmModelLoaderTest.java b/src/test/java/org/onap/schema/OxmModelLoaderTest.java new file mode 100644 index 0000000..c4437fa --- /dev/null +++ b/src/test/java/org/onap/schema/OxmModelLoaderTest.java @@ -0,0 +1,59 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.schema; + +import org.eclipse.persistence.dynamic.DynamicType; +import org.eclipse.persistence.internal.helper.DatabaseField; +import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; +import org.eclipse.persistence.mappings.DatabaseMapping; +import org.junit.Assert; +import org.junit.Test; + +public class OxmModelLoaderTest { + + @Test + public void testLoadingMultipleOxmFiles() throws Exception { + OxmModelLoader.loadModels(); + + DynamicJAXBContext jaxbContext = OxmModelLoader.getContextForVersion(OxmModelLoader.getLatestVersion()); + + DynamicType pserver = jaxbContext.getDynamicType("Pserver"); + DynamicType genericVnf = jaxbContext.getDynamicType("GenericVnf"); + + Assert.assertNotNull(pserver); + Assert.assertNotNull(genericVnf); + + DatabaseMapping mapping = pserver.getDescriptor().getMappings().firstElement(); + if (mapping.isAbstractDirectMapping()) { + DatabaseField f = mapping.getField(); + String keyName = f.getName().substring(0, f.getName().indexOf("/")); + Assert.assertEquals(keyName, "hostname"); + } + + mapping = genericVnf.getDescriptor().getMappings().firstElement(); + if (mapping.isAbstractDirectMapping()) { + DatabaseField f = mapping.getField(); + String keyName = f.getName().substring(0, f.getName().indexOf("/")); + Assert.assertEquals(keyName, "vnf-id"); + } + + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/schema/RelationshipSchemaLoaderTest.java b/src/test/java/org/onap/schema/RelationshipSchemaLoaderTest.java index 4e6590d..feeb1c4 100644 --- a/src/test/java/org/onap/schema/RelationshipSchemaLoaderTest.java +++ b/src/test/java/org/onap/schema/RelationshipSchemaLoaderTest.java @@ -23,7 +23,8 @@ package org.onap.schema; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; @@ -34,10 +35,10 @@ import org.onap.crud.exception.CrudException; public class RelationshipSchemaLoaderTest { @Before - public void init() { - ClassLoader classLoader = getClass().getClassLoader(); - File dir = new File(classLoader.getResource( "model").getFile()); - System.setProperty("CONFIG_HOME", dir.getParent()); + public void init() throws Exception { + Path resourcePath = Paths.get(ClassLoader.getSystemResource("model").toURI()); + Path parentPath = resourcePath.getParent(); + System.setProperty("CONFIG_HOME", parentPath.toString()); RelationshipSchemaLoader.resetVersionContextMap(); } diff --git a/src/test/resources/oxm/aai_oxm_a_v13.xml b/src/test/resources/oxm/aai_oxm_a_v13.xml new file mode 100644 index 0000000..ab7c586 --- /dev/null +++ b/src/test/resources/oxm/aai_oxm_a_v13.xml @@ -0,0 +1,2987 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/oxm/aai_oxm_b_v13.xml b/src/test/resources/oxm/aai_oxm_b_v13.xml new file mode 100644 index 0000000..fa36065 --- /dev/null +++ b/src/test/resources/oxm/aai_oxm_b_v13.xml @@ -0,0 +1,3811 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/oxm/aai_oxm_v11.xml b/src/test/resources/oxm/aai_oxm_v11.xml new file mode 100644 index 0000000..5c3d450 --- /dev/null +++ b/src/test/resources/oxm/aai_oxm_v11.xml @@ -0,0 +1,6363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/schemaIngest.properties b/src/test/resources/schemaIngest.properties new file mode 100644 index 0000000..2aa388e --- /dev/null +++ b/src/test/resources/schemaIngest.properties @@ -0,0 +1,4 @@ +# Properties for the SchemaLocationsBean +schemaConfig=NA +nodeDir=src/test/resources/oxm/ +edgeDir= \ No newline at end of file -- 2.16.6 From 414eaef56d9f9427712448c22a0c7eec02007ba4 Mon Sep 17 00:00:00 2001 From: Ravi Geda Date: Tue, 12 Jun 2018 14:54:41 +0100 Subject: [PATCH 12/16] Fix GET ALL for vertices created asynchronously Vertices created asynchronously are not being returned in the GET ALL vertices. This commit addresses this problem Change-Id: I83ee7a59dc2005447706fa0a43ba2c9d2f0e4592 Issue-ID: AAI-1223 Signed-off-by: Ravi Geda --- src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java b/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java index dc30a4e..5d37acb 100644 --- a/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java +++ b/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java @@ -202,6 +202,7 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService { public String addVertex(String version, String type, VertexPayload payload) throws CrudException { // Validate the incoming payload Vertex vertex = OxmModelValidator.validateIncomingUpsertPayload(null, version, type, payload.getProperties()); + vertex.getProperties().put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); // Create graph request event GraphEvent event = GraphEvent.builder(GraphEventOperation.CREATE) .vertex(GraphEventVertex.fromVertex(vertex, version)).build(); -- 2.16.6 From 00832f054dd0c21492af531548e321ea25cdb8b4 Mon Sep 17 00:00:00 2001 From: Shwetank Dave Date: Wed, 13 Jun 2018 08:40:26 -0400 Subject: [PATCH 13/16] Gizmo to load multiple Db Edge Rules files There is an Edge Rule file for each OXM file. For every OXM version that is loaded, an edge rule file should also be loaded. Issue-ID: AAI-1201 Change-Id: I728e577ea8152623d3c5e2f0e8edf677f0eb9ef4 Signed-off-by: Shwetank Dave --- pom.xml | 9 + .../org/onap/crud/logging/CrudServiceMsgs.java | 8 + .../org/onap/crud/parser/CrudResponseBuilder.java | 6 +- .../org/onap/crud/service/AaiResourceService.java | 12 +- .../java/org/onap/crud/util/CrudServiceUtil.java | 4 +- src/main/java/org/onap/schema/EdgeRulesLoader.java | 231 ++ src/main/java/org/onap/schema/OxmModelLoader.java | 34 + .../java/org/onap/schema/RelationshipSchema.java | 24 +- .../org/onap/schema/RelationshipSchemaLoader.java | 272 -- .../onap/schema/RelationshipSchemaValidator.java | 12 +- .../schema/util/SchemaIngestPropertyReader.java | 32 +- .../resources/logging/CrudServiceMsgs.properties | 4 + .../org/onap/crud/service/CrudRestServiceTest.java | 6 +- .../java/org/onap/schema/EdgeRulesLoaderTest.java | 69 + .../onap/schema/RelationshipSchemaLoaderTest.java | 124 - .../org/onap/schema/RelationshipSchemaTest.java | 148 +- .../resources/edgeProps/edge_properties_v11.json | 6 + .../resources/edgeProps/edge_properties_v13.json | 6 + .../resources/rules/DbEdgeRules_test_one_v11.json | 26 + .../resources/rules/DbEdgeRules_test_one_v13.json | 26 + .../resources/rules/DbEdgeRules_test_two_v11.json | 26 + .../resources/rules/DbEdgeRules_test_two_v13.json | 26 + src/test/resources/rules/DbEdgeRules_v11.json | 2416 +++++++++++++++++ src/test/resources/rules/DbEdgeRules_v13.json | 2836 ++++++++++++++++++++ src/test/resources/schemaIngest.properties | 3 +- 25 files changed, 5832 insertions(+), 534 deletions(-) create mode 100644 src/main/java/org/onap/schema/EdgeRulesLoader.java delete mode 100644 src/main/java/org/onap/schema/RelationshipSchemaLoader.java create mode 100644 src/test/java/org/onap/schema/EdgeRulesLoaderTest.java delete mode 100644 src/test/java/org/onap/schema/RelationshipSchemaLoaderTest.java create mode 100644 src/test/resources/edgeProps/edge_properties_v11.json create mode 100644 src/test/resources/edgeProps/edge_properties_v13.json create mode 100644 src/test/resources/rules/DbEdgeRules_test_one_v11.json create mode 100644 src/test/resources/rules/DbEdgeRules_test_one_v13.json create mode 100644 src/test/resources/rules/DbEdgeRules_test_two_v11.json create mode 100644 src/test/resources/rules/DbEdgeRules_test_two_v13.json create mode 100644 src/test/resources/rules/DbEdgeRules_v11.json create mode 100644 src/test/resources/rules/DbEdgeRules_v13.json diff --git a/pom.xml b/pom.xml index 2276939..50c6c88 100644 --- a/pom.xml +++ b/pom.xml @@ -461,6 +461,15 @@ limitations under the License. oxm/ ${project.build.directory}/bundleconfig-local/etc + + org.onap.aai.aai-common + aai-core + 1.2.1 + jar + dbedgerules/ + **/*.ftlh + ${project.build.directory}/bundleconfig-local/etc + diff --git a/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java b/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java index 72883a9..2b669ae 100644 --- a/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java +++ b/src/main/java/org/onap/crud/logging/CrudServiceMsgs.java @@ -45,6 +45,14 @@ public enum CrudServiceMsgs implements LogMessageEnum { */ LOADED_OXM_FILE, + /** + * Successfully loaded Edge Properties Files: {0} + * + *

+ * Arguments: {0} = oxm filename + */ + LOADED_DB_RULE_FILE, + /** * Unable to load OXM schema: {0} * diff --git a/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java b/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java index e28f7a7..0c66d81 100644 --- a/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java +++ b/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java @@ -34,7 +34,7 @@ import org.onap.crud.exception.CrudException; import org.onap.crud.service.BulkPayload; import org.onap.crud.service.EdgePayload; import org.onap.crud.service.VertexPayload; -import org.onap.schema.RelationshipSchemaLoader; +import org.onap.schema.EdgeRulesLoader; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -120,7 +120,7 @@ public class CrudResponseBuilder { EdgePayload inEdge = new EdgePayload(); inEdge.setId(e.getId().get()); inEdge.setType(e.getType()); - inEdge.setUrl(URL_BASE + "relationships/" + RelationshipSchemaLoader.getLatestSchemaVersion() + "/" + inEdge.setUrl(URL_BASE + "relationships/" + EdgeRulesLoader.getLatestSchemaVersion() + "/" + e.getType() + "/" + e.getId().get()); inEdge.setSource(URL_BASE + version + "/" + e.getSource().getType() + "/" + e.getSource().getId().get()); @@ -129,7 +129,7 @@ public class CrudResponseBuilder { EdgePayload outEdge = new EdgePayload(); outEdge.setId(e.getId().get()); outEdge.setType(e.getType()); - outEdge.setUrl(URL_BASE + "relationships/" + RelationshipSchemaLoader.getLatestSchemaVersion() + "/" + outEdge.setUrl(URL_BASE + "relationships/" + EdgeRulesLoader.getLatestSchemaVersion() + "/" + e.getType() + "/" + e.getId().get()); outEdge.setTarget(URL_BASE + version + "/" + e.getTarget().getType() + "/" + e.getTarget().getId().get()); outEdges.add(outEdge); diff --git a/src/main/java/org/onap/crud/service/AaiResourceService.java b/src/main/java/org/onap/crud/service/AaiResourceService.java index 6dfbab7..c9a5805 100644 --- a/src/main/java/org/onap/crud/service/AaiResourceService.java +++ b/src/main/java/org/onap/crud/service/AaiResourceService.java @@ -56,7 +56,7 @@ import org.onap.crud.logging.CrudServiceMsgs; import org.onap.crud.logging.LoggingUtil; import org.onap.crud.service.CrudRestService.Action; import org.onap.crud.util.CrudServiceConstants; -import org.onap.schema.RelationshipSchemaLoader; +import org.onap.schema.EdgeRulesLoader; import org.onap.schema.RelationshipSchemaValidator; import org.slf4j.MDC; @@ -161,11 +161,11 @@ public class AaiResourceService { payload = applyEdgeRulesToPayload(payload); if(logger.isDebugEnabled()) { - logger.debug("Creating AAI edge using version " + RelationshipSchemaLoader.getLatestSchemaVersion() ); + logger.debug("Creating AAI edge using version " + EdgeRulesLoader.getLatestSchemaVersion() ); } // Now, create our edge in the graph store. - String result = graphDataService.addEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), type, payload); + String result = graphDataService.addEdge(EdgeRulesLoader.getLatestSchemaVersion(), type, payload); response = Response.status(Status.CREATED).entity(result).type(mediaType).build(); } catch (CrudException e) { @@ -229,7 +229,7 @@ public class AaiResourceService { payload = applyEdgeRulesToPayload(payload); // Now, create our edge in the graph store. - String result = graphDataService.addEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), payload.getType(), payload); + String result = graphDataService.addEdge(EdgeRulesLoader.getLatestSchemaVersion(), payload.getType(), payload); response = Response.status(Status.CREATED).entity(result).type(mediaType).build(); } catch (CrudException ce) { @@ -304,10 +304,10 @@ public class AaiResourceService { String result; if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) { - result = graphDataService.patchEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), id, type, payload); + result = graphDataService.patchEdge(EdgeRulesLoader.getLatestSchemaVersion(), id, type, payload); } else { - result = graphDataService.updateEdge(RelationshipSchemaLoader.getLatestSchemaVersion(), id, type, payload); + result = graphDataService.updateEdge(EdgeRulesLoader.getLatestSchemaVersion(), id, type, payload); } response = Response.status(Status.OK).entity(result).type(mediaType).build(); diff --git a/src/main/java/org/onap/crud/util/CrudServiceUtil.java b/src/main/java/org/onap/crud/util/CrudServiceUtil.java index 4d108f2..6c251bc 100644 --- a/src/main/java/org/onap/crud/util/CrudServiceUtil.java +++ b/src/main/java/org/onap/crud/util/CrudServiceUtil.java @@ -23,7 +23,7 @@ package org.onap.crud.util; import org.onap.aai.db.props.AAIProperties; import org.onap.crud.exception.CrudException; import org.onap.schema.OxmModelLoader; -import org.onap.schema.RelationshipSchemaLoader; +import org.onap.schema.EdgeRulesLoader; import com.google.gson.Gson; import com.google.gson.JsonElement; @@ -77,10 +77,10 @@ public class CrudServiceUtil { // load the schemas try { OxmModelLoader.loadModels(); + EdgeRulesLoader.loadModels (); } catch (Exception e) { throw new CrudException(e); } - RelationshipSchemaLoader.loadModels(); } /** diff --git a/src/main/java/org/onap/schema/EdgeRulesLoader.java b/src/main/java/org/onap/schema/EdgeRulesLoader.java new file mode 100644 index 0000000..a990ae5 --- /dev/null +++ b/src/main/java/org/onap/schema/EdgeRulesLoader.java @@ -0,0 +1,231 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.schema; + +import com.google.common.collect.Multimap; +import org.apache.commons.io.IOUtils; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.edges.EdgeRule; +import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException; +import org.onap.aai.edges.EdgeIngestor; +import org.onap.aai.setup.ConfigTranslator; +import org.onap.aai.setup.SchemaLocationsBean; +import org.onap.aai.setup.Version; +import org.onap.crud.exception.CrudException; +import org.onap.crud.logging.CrudServiceMsgs; +import org.onap.schema.util.SchemaIngestPropertyReader; +import org.springframework.core.io.UrlResource; + +import javax.ws.rs.core.Response.Status; +import java.io.*; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +public class EdgeRulesLoader { + + private static Map versionContextMap = + new ConcurrentHashMap<> (); + + static final Pattern versionPattern = Pattern.compile ( "V(\\d*)" ); + static final String propsPrefix = "edge_properties_"; + static final String propsSuffix = ".json"; + final static Pattern propsFilePattern = Pattern.compile ( propsPrefix + "(.*)" + propsSuffix ); + final static Pattern propsVersionPattern = Pattern.compile ( "v\\d*" ); + + private static org.onap.aai.cl.api.Logger logger = + LoggerFactory.getInstance ().getLogger ( EdgeRulesLoader.class.getName () ); + + private EdgeRulesLoader () { + } + + /** + * Finds all DB Edge Rules and Edge Properties files for all OXM models. + * + * @throws CrudException + */ + public static synchronized void loadModels () throws CrudException { + SchemaIngestPropertyReader schemaIngestPropertyReader = new SchemaIngestPropertyReader (); + SchemaLocationsBean schemaLocationsBean = new SchemaLocationsBean (); + schemaLocationsBean.setEdgeDirectory ( schemaIngestPropertyReader.getEdgeDir () ); + ConfigTranslator configTranslator = new OxmModelConfigTranslator ( schemaLocationsBean ); + EdgeIngestor edgeIngestor = new EdgeIngestor ( configTranslator ); + Map propFiles = edgePropertyFiles(schemaIngestPropertyReader); + + if (logger.isDebugEnabled ()) { + logger.debug ( "Loading DB Edge Rules" ); + } + + for (String version : OxmModelLoader.getLoadedOXMVersions ()) { + try { + loadModel ( Version.valueOf ( version ), edgeIngestor, propFiles ); + } catch (IOException | EdgeRuleNotFoundException e) { + throw new CrudException(e.getMessage (), e); + } + } + } + + /** + * Loads DB Edge Rules and Edge Properties for a given version. + * + * @throws CrudException + */ + + public static synchronized void loadModels ( String v ) throws CrudException { + SchemaIngestPropertyReader schemaIngestPropertyReader = new SchemaIngestPropertyReader (); + SchemaLocationsBean schemaLocationsBean = new SchemaLocationsBean (); + schemaLocationsBean.setEdgeDirectory ( schemaIngestPropertyReader.getEdgeDir () ); + ConfigTranslator configTranslator = new OxmModelConfigTranslator ( schemaLocationsBean ); + EdgeIngestor edgeIngestor = new EdgeIngestor ( configTranslator ); + String version = v.toUpperCase (); + Map propFiles = edgePropertyFiles(schemaIngestPropertyReader); + + if (logger.isDebugEnabled ()) { + logger.debug ( "Loading DB Edge Rules " ); + } + + try { + loadModel ( Version.valueOf ( version ), edgeIngestor, propFiles ); + } catch (IOException | EdgeRuleNotFoundException e) { + throw new CrudException(e.getMessage (), Status.INTERNAL_SERVER_ERROR); + } + } + + /** + * Retrieves the DB Edge Rule relationship schema for a given version. + * + * @param version - The OXM version that we want the DB Edge Rule for. + * @return - A RelationshipSchema of the DB Edge Rule for the OXM version. + * @throws CrudException + */ + public static RelationshipSchema getSchemaForVersion ( String version ) throws CrudException { + + // If we haven't already loaded in the available OXM models, then do so now. + if (versionContextMap == null || versionContextMap.isEmpty ()) { + loadModels (); + } else if (!versionContextMap.containsKey ( version )) { + logger.error ( CrudServiceMsgs.OXM_LOAD_ERROR, "Error loading DB Edge Rules for: " + version ); + throw new CrudException ( "Error loading DB Edge Rules for: " + version, Status.NOT_FOUND ); + } + + return versionContextMap.get ( version ); + } + + /** + * Retrieves the DB Edge Rule relationship schema for all loaded OXM versions. + * + * @return - A Map of the OXM version and it's corresponding RelationshipSchema of the DB Edge Rule. + * @throws CrudException + */ + public static Map getSchemas () throws CrudException { + + // If we haven't already loaded in the available OXM models, then do so now. + if (versionContextMap == null || versionContextMap.isEmpty ()) { + loadModels (); + } + return versionContextMap; + } + + /** + * Returns the latest available DB Edge Rule version. + * + * @return - A Map of the OXM version and it's corresponding RelationshipSchema of the DB Edge Rule. + * @throws CrudException + */ + public static String getLatestSchemaVersion () throws CrudException { + + // If we haven't already loaded in the available OXM models, then do so now. + if (versionContextMap == null || versionContextMap.isEmpty ()) { + loadModels (); + } + + // If there are still no models available, then there's not much we can do... + if (versionContextMap.isEmpty ()) { + logger.error ( CrudServiceMsgs.OXM_LOAD_ERROR, "No available DB Edge Rules to get latest version for." ); + throw new CrudException ( "No available DB Edge Rules to get latest version for.", + Status.INTERNAL_SERVER_ERROR ); + } + + // Iterate over the available model versions to determine which is the most + // recent. + Integer latestVersion = null; + String latestVersionStr = null; + for (String versionKey : versionContextMap.keySet ()) { + + Matcher matcher = versionPattern.matcher ( versionKey.toUpperCase () ); + if (matcher.find ()) { + + int currentVersion = Integer.parseInt ( matcher.group ( 1 ) ); + + if ((latestVersion == null) || (currentVersion > latestVersion)) { + latestVersion = currentVersion; + latestVersionStr = versionKey; + } + } + } + + return latestVersionStr; + } + + /** + * Reset the loaded DB Edge Rule schemas + * + */ + + public static void resetSchemaVersionContext () { + versionContextMap = new ConcurrentHashMap<> (); + } + + private static synchronized void loadModel ( Version version, EdgeIngestor edgeIngestor, Map props) + throws IOException, CrudException, EdgeRuleNotFoundException { + + Multimap edges = edgeIngestor.getAllRules ( version ); + String edgeProps; + if (props.get ( version.toString().toLowerCase () ) != null) { + edgeProps = IOUtils.toString ( new FileInputStream ( props.get ( version.toString().toLowerCase () ) ), "UTF-8" ); + } else { + throw new FileNotFoundException ( "The Edge Properties file for OXM version " + version + "was not found." ); + } + if (edges != null) { + RelationshipSchema rs = new RelationshipSchema ( edges, edgeProps ); + versionContextMap.put ( version.toString ().toLowerCase (), rs ); + logger.info ( CrudServiceMsgs.LOADED_DB_RULE_FILE, version.toString () ); + } + } + + private static Map edgePropertyFiles ( SchemaIngestPropertyReader dir ) throws CrudException { + Map propsFiles = Arrays.stream ( new File ( dir.getEdgePropsDir () ) + .listFiles ( ( d, name ) -> propsFilePattern.matcher ( name ).matches () ) ) + .collect ( Collectors.toMap ( new Function () { + public String apply ( File f ) { + Matcher m1 = propsVersionPattern.matcher ( f.getName () ); + m1.find (); + return m1.group ( 0 ); + } + }, f -> f ) ); + return propsFiles; + } + +} diff --git a/src/main/java/org/onap/schema/OxmModelLoader.java b/src/main/java/org/onap/schema/OxmModelLoader.java index 869df8f..8f55602 100644 --- a/src/main/java/org/onap/schema/OxmModelLoader.java +++ b/src/main/java/org/onap/schema/OxmModelLoader.java @@ -21,6 +21,8 @@ package org.onap.schema; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; @@ -140,6 +142,38 @@ public class OxmModelLoader { return latestVersionStr; } + /** + * Retrieves the list of all Loaded OXM versions. + * + * @return - A List of Strings of all loaded OXM versions. + * + * @throws CrudException + */ + public static List getLoadedOXMVersions() throws CrudException { + + // If we haven't already loaded in the available OXM models, then do so now. + if (versionContextMap == null || versionContextMap.isEmpty()) { + loadModels(); + } + + // If there are still no models available, then there's not much we can do... + if (versionContextMap.isEmpty()) { + logger.error(CrudServiceMsgs.OXM_LOAD_ERROR, "No available OXM schemas to get versions for."); + throw new CrudException("No available OXM schemas to get versions for.", + Status.INTERNAL_SERVER_ERROR); + } + + List versions = new ArrayList (); + for (String versionKey : versionContextMap.keySet()) { + + Matcher matcher = versionPattern.matcher(versionKey.toUpperCase()); + if (matcher.find()) { + versions.add ( "V" + matcher.group ( 1 ) ); + } + } + return versions; + } + /** * Retrieves the map of all JAXB context objects that have been created by importing the * available OXM model schemas. diff --git a/src/main/java/org/onap/schema/RelationshipSchema.java b/src/main/java/org/onap/schema/RelationshipSchema.java index 557c374..fc91662 100644 --- a/src/main/java/org/onap/schema/RelationshipSchema.java +++ b/src/main/java/org/onap/schema/RelationshipSchema.java @@ -20,10 +20,9 @@ */ package org.onap.schema; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - +import com.google.common.collect.Multimap; import org.codehaus.jackson.map.ObjectMapper; +import org.onap.aai.edges.EdgeRule; import org.onap.crud.exception.CrudException; import java.io.IOException; @@ -33,12 +32,8 @@ import javax.ws.rs.core.Response.Status; public class RelationshipSchema { - private static final Gson gson = new GsonBuilder().create(); - public static final String SCHEMA_SOURCE_NODE_TYPE = "from"; - public static final String SCHEMA_TARGET_NODE_TYPE = "to"; public static final String SCHEMA_RELATIONSHIP_TYPE = "label"; - public static final String SCHEMA_RULES_ARRAY = "rules"; private Map>> relations = new HashMap<>(); @@ -47,12 +42,7 @@ public class RelationshipSchema { */ private Map>> relationTypes = new HashMap<>(); - - public RelationshipSchema(List jsonStrings) throws CrudException, IOException { - String edgeRules = jsonStrings.get(0); - String props = jsonStrings.get(1); - - HashMap>> rules = new ObjectMapper().readValue(edgeRules, HashMap.class); + public RelationshipSchema( Multimap rules, String props) throws CrudException, IOException { HashMap properties = new ObjectMapper().readValue(props, HashMap.class); Map> edgeProps = properties.entrySet().stream().collect(Collectors.toMap(p -> p.getKey(), p -> { try { @@ -63,14 +53,12 @@ public class RelationshipSchema { return null; })); - rules.get(SCHEMA_RULES_ARRAY).forEach(l -> { - relationTypes.put(l.get(SCHEMA_RELATIONSHIP_TYPE), edgeProps); - relations.put(buildRelation(l.get(SCHEMA_SOURCE_NODE_TYPE), l.get(SCHEMA_TARGET_NODE_TYPE), l.get(SCHEMA_RELATIONSHIP_TYPE)), edgeProps); + rules.entries ().forEach ( (kv) -> { + relationTypes.put(kv.getValue ().getLabel (), edgeProps); + relations.put (buildRelation ( kv.getValue ().getFrom (), kv.getValue ().getTo (), kv.getValue ().getLabel ()), edgeProps); }); } - - public Map> lookupRelation(String key) { return this.relations.get(key); } diff --git a/src/main/java/org/onap/schema/RelationshipSchemaLoader.java b/src/main/java/org/onap/schema/RelationshipSchemaLoader.java deleted file mode 100644 index 9a9a37c..0000000 --- a/src/main/java/org/onap/schema/RelationshipSchemaLoader.java +++ /dev/null @@ -1,272 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 Amdocs - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.schema; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; -import java.util.Timer; -import java.util.TimerTask; -import java.util.TreeSet; -import java.util.concurrent.ConcurrentHashMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import javax.ws.rs.core.Response.Status; -import org.apache.commons.io.IOUtils; -import org.onap.aai.cl.eelf.LoggerFactory; -import org.onap.crud.exception.CrudException; -import org.onap.crud.logging.CrudServiceMsgs; -import org.onap.crud.util.CrudServiceConstants; -import org.onap.crud.util.FileWatcher; -import org.springframework.core.io.Resource; -import org.springframework.core.io.UrlResource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternResolver; - -public class RelationshipSchemaLoader { - - private static Map versionContextMap = new ConcurrentHashMap<>(); - private static SortedSet versions = new TreeSet(); - private static Map timers = new ConcurrentHashMap(); - final static String edgePropsFiles = "edge_properties_"; - final static String fileExt = ".json"; - final static Pattern rulesFilePattern = Pattern.compile("DbEdgeRules(.*)" + fileExt); - final static Pattern propsFilePattern = Pattern.compile(edgePropsFiles + "(.*)" + fileExt); - final static Pattern versionPattern = Pattern.compile(".*(v\\d+)" + fileExt); - - private static org.onap.aai.cl.api.Logger logger = LoggerFactory.getInstance() - .getLogger(RelationshipSchemaLoader.class.getName()); - - public synchronized static void loadModels() throws CrudException { - load(rulesFilePattern, propsFilePattern); - } - - public synchronized static void loadModels(String version) throws CrudException { - String pattern = String.format("DbEdgeRules.*(%s)" + fileExt, version); - load(Pattern.compile(pattern), Pattern.compile(edgePropsFiles + version + fileExt)); - } - - public static RelationshipSchema getSchemaForVersion(String version) throws CrudException { - if (versionContextMap == null || versionContextMap.isEmpty()) { - loadModels(); - } else if (!versionContextMap.containsKey(version)) { - try { - loadModels(version); - } catch (Exception e) { - throw new CrudException("", Status.NOT_FOUND); - } - } - RelationshipSchema schema = versionContextMap.get(version); - if (schema == null) { - throw new CrudException("", Status.NOT_FOUND); - } else - return schema; - } - - public static String getLatestSchemaVersion() throws CrudException { - return "v" + versions.last(); - } - - public static Map getVersionContextMap() { - return versionContextMap; - } - - public static void setVersionContextMap(Map versionContextMap) { - RelationshipSchemaLoader.versionContextMap = versionContextMap; - } - - public static void resetVersionContextMap() { - RelationshipSchemaLoader.versionContextMap = new ConcurrentHashMap<>(); - } - - private static void load(Pattern rulesPattern, Pattern edgePropsPattern) throws CrudException { - ClassLoader cl = RelationshipSchemaLoader.class.getClassLoader(); - ResourcePatternResolver rulesResolver = new PathMatchingResourcePatternResolver(cl); - List rulesFiles = new ArrayList(); - Set existingFiles = new HashSet(); - String rulesDir = CrudServiceConstants.CRD_HOME_MODEL; - try { - - // Allow additional DBEdgeRule files to be dropped in manually (in addition to those found on the classpath) - File[] edgeRuleFileList = new File(rulesDir).listFiles((d, name) -> rulesPattern.matcher(name).matches()); - for (File file : edgeRuleFileList) { - rulesFiles.add(file); - existingFiles.add(filename(file)); - } - - // Get DBEdgeRules from the jar on the classpath. Don't include any that conflict with files which - // were dropped manually. - Resource[] rawResourceList = rulesResolver.getResources("classpath*:/dbedgerules/DbEdgeRules*" + fileExt); - List prunedResourceList = new ArrayList(); - for (Resource resource : rawResourceList) { - if (!existingFiles.contains(filename(resource))) { - prunedResourceList.add(resource); - } - } - - rulesFiles.addAll(Arrays.stream(prunedResourceList.toArray(new Resource[prunedResourceList.size()])) - .filter(r -> !myMatcher(rulesPattern, r.getFilename()).isEmpty()).collect(Collectors.toList())); - - // This gets all the objects of type "File" from external directory (not - // on the classpath) - // 1. From an external directory (one not on the classpath) we get all the - // objects of type "File" - // 2. We only return the files whose names matched the supplied pattern - // "p2". - // 3. We then collect all the objects in a list and add the contents of - // this list - // to the previous collection (rulesFiles) - rulesFiles - .addAll(Arrays.stream(new File(rulesDir).listFiles( (d, name) -> edgePropsPattern.matcher(name).matches() )) - .collect(Collectors.toList())); - - if (rulesFiles.isEmpty()) { - logger.error(CrudServiceMsgs.INVALID_OXM_DIR, rulesDir); - throw new FileNotFoundException("DbEdgeRules and edge_properties files were not found."); - } - - // Sort and then group the files with their versions, convert them to the - // schema, and add them to versionContextMap - // 1. Sort the files. We need the DbEdgeRules files to be before the - // edgeProperties files. - // 2. Group the files with their versions. ie. v11 -> - // ["DbEdgeRule_v11.json", "edgeProperties_v11.json"]. - // The "group method" returns a HashMap whose key is the version and the - // value is a list of objects. - // 3. Go through each version and map the files into one schema using the - // "jsonFilesLoader" method. - // Also update the "versionContextMap" with the version and it's schema. - rulesFiles.stream().sorted(Comparator.comparing(RelationshipSchemaLoader::filename)) - .collect(Collectors.groupingBy(f -> myMatcher(versionPattern, filename(f)))) - .forEach((version, resourceAndFile) -> { - if (resourceAndFile.size() == 2) { - versionContextMap.put(version, jsonFilesLoader(version, resourceAndFile)); - } else { - String filenames = resourceAndFile.stream().map(f -> filename(f)).collect(Collectors.toList()).toString(); - String errorMsg = "Expecting a rules and a edge_properties files for " + version + ". Found: " - + filenames; - logger.warn(CrudServiceMsgs.INVALID_OXM_FILE, errorMsg); - } - }); - logger.info(CrudServiceMsgs.LOADED_OXM_FILE, "Relationship Schema and Properties files: " - + rulesFiles.stream().map(f -> filename(f)).collect(Collectors.toList())); - } catch (IOException e) { - logger.error(CrudServiceMsgs.INVALID_OXM_DIR, rulesDir); - throw new CrudException("DbEdgeRules or edge_properties files were not found.", new FileNotFoundException()); - } - } - - private static String filename(Object k) throws ClassCastException { - if (k instanceof UrlResource) { - return ((UrlResource) k).getFilename(); - } else if (k instanceof File) { - return ((File) k).getName(); - } else { - throw new ClassCastException(); - } - } - - private static RelationshipSchema jsonFilesLoader(String version, List files) { - List fileContents = new ArrayList<>(); - RelationshipSchema rsSchema = null; - if (files.size() == 2) { - for (Object file : files) { - fileContents.add(jsonToRelationSchema(version, file)); - versions.add(Integer.parseInt(version.substring(1))); - } - - try { - rsSchema = new RelationshipSchema(fileContents); - } catch (CrudException | IOException e) { - e.printStackTrace(); - logger.error(CrudServiceMsgs.INVALID_OXM_FILE, - files.stream().map(f -> filename(f)).collect(Collectors.toList()).toString(), e.getMessage()); - } - return rsSchema; - } - return rsSchema; - } - - private synchronized static void updateVersionContext(String version, RelationshipSchema rs) { - versionContextMap.put(version, rs); - } - - private synchronized static String jsonToRelationSchema(String version, Object file) { - InputStream inputStream = null; - String content = null; - - try { - if (file instanceof UrlResource) { - inputStream = ((UrlResource) file).getInputStream(); - } else { - inputStream = new FileInputStream((File) file); - addtimer(version, file); - } - content = IOUtils.toString(inputStream, "UTF-8"); - } catch (IOException e) { - e.printStackTrace(); - } - return content; - } - - private static void addtimer(String version, Object file) { - TimerTask task = null; - task = new FileWatcher((File) file) { - protected void onChange(File file) { - // here we implement the onChange - logger.info(CrudServiceMsgs.OXM_FILE_CHANGED, file.getName()); - - try { - // Cannot use the file object here because we also have to get the - // edge properties associated with that version. - // The properties are stored in a different file. - RelationshipSchemaLoader.loadModels(version); - } catch (Exception e) { - e.printStackTrace(); - } - } - }; - - if (!timers.containsKey(version)) { - Timer timer = new Timer("db_edge_rules_" + version); - timer.schedule(task, new Date(), 10000); - timers.put(version, timer); - - } - } - - private static String myMatcher(Pattern p, String s) { - Matcher m = p.matcher(s); - return m.matches() ? m.group(1) : ""; - } -} \ No newline at end of file diff --git a/src/main/java/org/onap/schema/RelationshipSchemaValidator.java b/src/main/java/org/onap/schema/RelationshipSchemaValidator.java index 4b05c6f..15b1762 100644 --- a/src/main/java/org/onap/schema/RelationshipSchemaValidator.java +++ b/src/main/java/org/onap/schema/RelationshipSchemaValidator.java @@ -49,7 +49,7 @@ public class RelationshipSchemaValidator { Map filter) throws CrudException { - RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); + RelationshipSchema schema = EdgeRulesLoader.getSchemaForVersion(version); if (schema == null) { throw new CrudException("", Status.NOT_FOUND); } @@ -77,7 +77,7 @@ public class RelationshipSchemaValidator { public static void validateType(String version, String type) throws CrudException { - RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); + RelationshipSchema schema = EdgeRulesLoader.getSchemaForVersion(version); if (!schema.isValidType(type)) { throw new CrudException("Invalid " + RelationshipSchema.SCHEMA_RELATIONSHIP_TYPE + ": " + type, @@ -101,7 +101,7 @@ public class RelationshipSchemaValidator { public static Edge validateIncomingAddPayload(String version, String type, EdgePayload payload) throws CrudException { - RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); + RelationshipSchema schema = EdgeRulesLoader.getSchemaForVersion(version); try { @@ -151,7 +151,7 @@ public class RelationshipSchemaValidator { public static Edge validateIncomingPatchPayload(Edge edge, String version, EdgePayload payload) throws CrudException { - RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); + RelationshipSchema schema = EdgeRulesLoader.getSchemaForVersion(version); try { if (payload.getSource() != null) { @@ -243,7 +243,7 @@ public class RelationshipSchemaValidator { public static Edge validateIncomingUpdatePayload(Edge edge, String version, EdgePayload payload) throws CrudException { - RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); + RelationshipSchema schema = EdgeRulesLoader.getSchemaForVersion(version); try { @@ -328,7 +328,7 @@ public class RelationshipSchemaValidator { .get()).source(edge.getSource()) .target(edge.getTarget()); - RelationshipSchema schema = RelationshipSchemaLoader.getSchemaForVersion(version); + RelationshipSchema schema = EdgeRulesLoader.getSchemaForVersion(version); String key = edge.getSource().getType() + ":" + edge.getTarget().getType() + ":" + edge.getType(); diff --git a/src/main/java/org/onap/schema/util/SchemaIngestPropertyReader.java b/src/main/java/org/onap/schema/util/SchemaIngestPropertyReader.java index 71ea47e..ca5fa6b 100644 --- a/src/main/java/org/onap/schema/util/SchemaIngestPropertyReader.java +++ b/src/main/java/org/onap/schema/util/SchemaIngestPropertyReader.java @@ -46,11 +46,37 @@ public class SchemaIngestPropertyReader { * Gets the location of the OXM * * @return - * @throws SpikeException - * @throws IOException + * @throws CrudException */ public String getNodeDir() throws CrudException { + return getProps ().getProperty("nodeDir"); + } + + /** + * Gets the location of the Edge Rules + * + * @return + * @throws CrudException + */ + public String getEdgeDir() throws CrudException { + + return getProps ().getProperty("edgeDir"); + } + + /** + * Gets the location of the Edge Properties + * + * @return + * @throws CrudException + */ + public String getEdgePropsDir() throws CrudException { + + return getProps ().getProperty("edgePropsDir"); + } + + private Properties getProps() throws CrudException { + Properties prop = new Properties(); try { prop = loadFromFile(SCHEMA_INGEST_PROPERTIES_LOCATION); @@ -66,7 +92,7 @@ public class SchemaIngestPropertyReader { logger.error(CrudServiceMsgs.SCHEMA_INGEST_LOAD_ERROR, e.getMessage()); throw new CrudException("Failed to load schemaIngest.properties", e); } - return prop.getProperty("nodeDir"); + return prop; } private Properties loadFromFile(String filename) throws IOException { diff --git a/src/main/resources/logging/CrudServiceMsgs.properties b/src/main/resources/logging/CrudServiceMsgs.properties index 5ae6ca6..3d81571 100644 --- a/src/main/resources/logging/CrudServiceMsgs.properties +++ b/src/main/resources/logging/CrudServiceMsgs.properties @@ -46,6 +46,10 @@ LOADED_OXM_FILE=\ CRD0007I|\ Successfully loaded schema: {0} +LOADED_DB_RULE_FILE=\ + CRD00014I|\ + Successfully loaded DB Edge Rule and Edge Properties for: {0} + EXCEPTION_DURING_METHOD_CALL=\ CRD0502E|\ Failed to {0} request for {1} due to: {2}|\ diff --git a/src/test/java/org/onap/crud/service/CrudRestServiceTest.java b/src/test/java/org/onap/crud/service/CrudRestServiceTest.java index a4b4305..13cba11 100644 --- a/src/test/java/org/onap/crud/service/CrudRestServiceTest.java +++ b/src/test/java/org/onap/crud/service/CrudRestServiceTest.java @@ -42,8 +42,7 @@ import org.onap.crud.exception.CrudException; import org.onap.crud.service.util.TestHeaders; import org.onap.crud.service.util.TestRequest; import org.onap.crud.service.util.TestUriInfo; -import org.onap.schema.RelationshipSchemaLoader; - +import org.onap.schema.EdgeRulesLoader; public class CrudRestServiceTest { @@ -85,8 +84,7 @@ public class CrudRestServiceTest { Path parentPath = resourcePath.getParent(); System.setProperty("CONFIG_HOME", parentPath.toString()); - RelationshipSchemaLoader.resetVersionContextMap(); - + EdgeRulesLoader.resetSchemaVersionContext (); CrudGraphDataService service = new CrudGraphDataService(new TestDao()); CrudRestService restService = new CrudRestService(service, null); mockService = Mockito.spy(restService); diff --git a/src/test/java/org/onap/schema/EdgeRulesLoaderTest.java b/src/test/java/org/onap/schema/EdgeRulesLoaderTest.java new file mode 100644 index 0000000..073e1d3 --- /dev/null +++ b/src/test/java/org/onap/schema/EdgeRulesLoaderTest.java @@ -0,0 +1,69 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.schema; + +import org.junit.Test; +import org.onap.crud.exception.CrudException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +public class EdgeRulesLoaderTest { + + @Test + public void loadModels() throws Exception { + EdgeRulesLoader.loadModels(); + assertTrue(EdgeRulesLoader.getSchemaForVersion ( "v11" ).isValidType ( "org.onap.relationships.inventory.groupsResourcesIn" )); + } + + @Test + public void loadModelsWithAVersion() throws Exception { + EdgeRulesLoader.resetSchemaVersionContext (); + EdgeRulesLoader.loadModels("V11"); + assertEquals(1, EdgeRulesLoader.getSchemas ().size ()); + assertEquals("v11", EdgeRulesLoader.getLatestSchemaVersion ()); + } + + @Test + public void getSchemaForVersion() throws Exception { + EdgeRulesLoader.resetSchemaVersionContext (); + EdgeRulesLoader.loadModels("v11"); + String version = EdgeRulesLoader.getLatestSchemaVersion(); + RelationshipSchema g = EdgeRulesLoader.getSchemaForVersion(version); + assertNotNull(g.lookupRelationType("org.onap.relationships.inventory.groupsResourcesIn")); + assertNotNull(g.lookupRelation("U:V:org.onap.relationships.inventory.groupsResourcesIn")); + assertNull(g.lookupRelation("U:W:org.onap.relationships.inventory.groupsResourcesIn")); + } + + + @Test + public void getSchemaForVersionFail() throws Exception { + EdgeRulesLoader.loadModels(); + try { + EdgeRulesLoader.getSchemaForVersion("v1"); + } catch (CrudException e) { + assertEquals(404, e.getHttpStatus().getStatusCode()); + } + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/schema/RelationshipSchemaLoaderTest.java b/src/test/java/org/onap/schema/RelationshipSchemaLoaderTest.java deleted file mode 100644 index feeb1c4..0000000 --- a/src/test/java/org/onap/schema/RelationshipSchemaLoaderTest.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 Amdocs - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.schema; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import org.junit.Before; -import org.junit.Test; -import org.onap.crud.exception.CrudException; - -public class RelationshipSchemaLoaderTest { - - @Before - public void init() throws Exception { - Path resourcePath = Paths.get(ClassLoader.getSystemResource("model").toURI()); - Path parentPath = resourcePath.getParent(); - System.setProperty("CONFIG_HOME", parentPath.toString()); - RelationshipSchemaLoader.resetVersionContextMap(); - } - - @Test - public void loadModels() throws Exception { - RelationshipSchemaLoader.resetVersionContextMap(); - RelationshipSchemaLoader.loadModels(); - assertFalse( RelationshipSchemaLoader.getVersionContextMap().keySet().isEmpty()); - } - - @Test - public void loadModelsWithAVersion() throws Exception { - RelationshipSchemaLoader.resetVersionContextMap(); - RelationshipSchemaLoader.loadModels("v11"); - assertEquals(1, RelationshipSchemaLoader.getVersionContextMap().keySet().size()); - assertEquals("v11", RelationshipSchemaLoader.getLatestSchemaVersion()); - } - - @Test - public void getSchemaForVersion() throws Exception { - RelationshipSchemaLoader.resetVersionContextMap(); - RelationshipSchemaLoader.loadModels("v11"); - String version = RelationshipSchemaLoader.getLatestSchemaVersion(); - RelationshipSchema g = RelationshipSchemaLoader.getSchemaForVersion(version); - assertNotNull(g.lookupRelationType("org.onap.relationships.inventory.BelongsTo")); - } - - public void getSchemaForVersionManualFile() throws Exception { - RelationshipSchemaLoader.resetVersionContextMap(); - RelationshipSchemaLoader.loadModels("v10"); - String version = RelationshipSchemaLoader.getLatestSchemaVersion(); - RelationshipSchema g = RelationshipSchemaLoader.getSchemaForVersion(version); - assertNotNull(g.lookupRelationType("locatedIn")); - } - - - @Test - public void getSchemaForVersionFail() throws Exception { - RelationshipSchemaLoader.resetVersionContextMap(); - RelationshipSchemaLoader.loadModels(); - try { - RelationshipSchemaLoader.getSchemaForVersion("v1"); - } catch (CrudException e) { - assertEquals(404, e.getHttpStatus().getStatusCode()); - } - } - - @Test - public void setVersionContextMap() throws Exception { - RelationshipSchemaLoader.resetVersionContextMap(); - ArrayList jsonString = new ArrayList(); - String rules = "{" + - "\"rules\": [" + - "{" + - "\"from\": \"availability-zone\"," + - "\"to\": \"complex\"," + - "\"label\": \"groupsResourcesIn\"," + - "\"direction\": \"OUT\"," + - "\"multiplicity\": \"Many2Many\"," + - "\"contains-other-v\": \"NONE\"," + - "\"delete-other-v\": \"NONE\"," + - "\"SVC-INFRA\": \"NONE\"," + - "\"prevent-delete\": \"!${direction}\"" + - "}]}"; - String props = "{" + - " \"isParent\":\"java.lang.Boolean\"," + - " \"isParent-REV\":\"java.lang.Boolean\"," + - " \"usesResource\":\"java.lang.Boolean\"," + - " \"usesResource-REV\":\"java.lang.Boolean\"," + - " \"SVC-INFRA\":\"java.lang.Boolean\"," + - " \"SVC-INFRA-REV\":\"java.lang.Boolean\"," + - " \"hasDelTarget\":\"java.lang.Boolean\"," + - " \"hasDelTarget-REV\":\"java.lang.Boolean\"" + - "}"; - jsonString.add(rules); - jsonString.add(props); - RelationshipSchema nRs = new RelationshipSchema(jsonString); - Map versionMap = new HashMap<>(); - versionMap.put("v1", nRs); - RelationshipSchemaLoader.setVersionContextMap(versionMap); - assertNotNull(RelationshipSchemaLoader.getSchemaForVersion("v1").lookupRelationType("groupsResourcesIn")); - } -} diff --git a/src/test/java/org/onap/schema/RelationshipSchemaTest.java b/src/test/java/org/onap/schema/RelationshipSchemaTest.java index ce8559a..9467f41 100644 --- a/src/test/java/org/onap/schema/RelationshipSchemaTest.java +++ b/src/test/java/org/onap/schema/RelationshipSchemaTest.java @@ -20,128 +20,86 @@ */ package org.onap.schema; -import org.apache.commons.io.IOUtils; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; import org.junit.Test; +import org.onap.aai.edges.EdgeRule; +import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException; import org.onap.crud.exception.CrudException; -import com.att.aft.dme2.internal.apache.commons.lang.ArrayUtils; - -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Comparator; -import java.util.concurrent.ConcurrentHashMap; import java.util.HashMap; import java.util.Map; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; import static org.junit.Assert.*; public class RelationshipSchemaTest { - final static Pattern rulesFilePattern = Pattern.compile("DbEdgeRules(.*).json"); - final static Pattern propsFilePattern = Pattern.compile("edge_properties_(.*).json"); - final static Pattern versionPattern = Pattern.compile(".*(v\\d+).json"); - - @Test public void shouldLoadAllTheVersionsInDirectory() throws Exception { - Map versionContextMap = new ConcurrentHashMap<>(); - loadRelations(versionContextMap); - assertTrue(versionContextMap.keySet().size() >= 0); + RelationshipSchema rs = loadRelations(); + assertTrue(!rs.lookupRelationType ("org.onap.some-relation" ).isEmpty ()); } @Test public void shouldContainValidTypes() throws Exception { - Map versionContextMap = new ConcurrentHashMap<>(); - loadRelations(versionContextMap); - assertTrue(versionContextMap.get("v10").isValidType("groupsResourcesIn")); - assertTrue(versionContextMap.get("v10").isValidType("uses")); - assertFalse(versionContextMap.get("v10").isValidType("notValidType")); + RelationshipSchema rs = loadRelations(); + assertTrue(rs.lookupRelationType ("org.onap.some-relation") != null); + assertTrue(rs.lookupRelationType("notValidType") == null); } @Test public void shouldLookUpByRelation() throws Exception { - Map versionContextMap = new ConcurrentHashMap<>(); - loadRelations(versionContextMap); - assertNotNull(versionContextMap.get("v10").lookupRelation("availability-zone:complex:groupsResourcesIn")); - assertTrue(versionContextMap.get("v10") - .lookupRelation("availability-zone:complex:groupsResourcesIn").containsKey("prevent-delete")); + RelationshipSchema rs = loadRelations(); + assertNotNull(rs.lookupRelation("service-instance:customer:org.onap.some-relation")); } @Test public void shouldLookUpByRelationType() throws Exception { - Map versionContextMap = new ConcurrentHashMap<>(); - loadRelations(versionContextMap); - assertNotNull(versionContextMap.get("v10").lookupRelationType("groupsResourcesIn")); - assertTrue(versionContextMap.get("v10") - .lookupRelation("availability-zone:complex:groupsResourcesIn").containsKey("prevent-delete")); - } - - private void loadRelations(Map map){ - ClassLoader classLoader = getClass().getClassLoader(); - File dir = new File(classLoader.getResource("model").getFile()); - File[] allFiles = dir.listFiles((d, name) -> - (propsFilePattern.matcher(name).matches() || rulesFilePattern.matcher(name).matches())); - - // Special handling for the v12 file, as it is used for a special test - for (File f : allFiles) { - if (f.getName().equals("edge_properties_v11.json")) { - allFiles = (File[]) ArrayUtils.removeElement(allFiles, f); - } - } - - Arrays.stream(allFiles).sorted(Comparator.comparing(File::getName)) - .collect(Collectors.groupingBy(f -> myMatcher(versionPattern, f.getName()))) - .forEach((e, f) -> map.put(e, jsonFilesLoader(f))); - - } - - - private RelationshipSchema jsonFilesLoader (List files) { - List fileContents = new ArrayList<>(); - RelationshipSchema rsSchema = null; - for (File f : files) { - fileContents.add(jsonToString(f)); - } - - try { - if (fileContents.size() == 2) { - rsSchema = new RelationshipSchema(fileContents); - } - } catch (CrudException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - return rsSchema; + RelationshipSchema rs = loadRelations(); + assertNotNull(rs.lookupRelationType("org.onap.groupsResourcesIn")); + assertTrue(rs.lookupRelation("availability-zone:complex:org.onap.groupsResourcesIn").containsKey("prevent-delete")); } - private String jsonToString (File file) { - InputStream inputStream = null; - String content = null; - HashMap result = null; - - try { - inputStream = new FileInputStream(file); - content = IOUtils.toString(inputStream, "UTF-8"); - } catch (IOException e) { - e.printStackTrace(); - } - - return content; - } + private RelationshipSchema loadRelations() throws CrudException, EdgeRuleNotFoundException, IOException { + String defaultEdgeProps = "{" + + "\"contains-other-v\": \"java.lang.String\"," + + "\"delete-other-v\": \"java.lang.String\"," + + "\"SVC-INFRA\": \"java.lang.String\"," + + "\"prevent-delete\": \"java.lang.String\"" + + "}"; + + Map ruleOne = new HashMap<> ( ); + Map ruleTwo = new HashMap<> ( ); + + ruleOne.put("label", "org.onap.some-relation"); + ruleOne.put("direction", "OUT"); + ruleOne.put("contains-other-v", "NONE"); + ruleOne.put("delete-other-v", "NONE"); + ruleOne.put("prevent-delete", "NONE"); + ruleOne.put("from", "service-instance"); + ruleOne.put("to", "customer"); + ruleOne.put("multiplicity", "MANY2MANY"); + ruleOne.put("default", "true"); + ruleOne.put("description", ""); + + ruleTwo.put("label", "org.onap.groupsResourcesIn"); + ruleTwo.put("direction", "OUT"); + ruleTwo.put("contains-other-v", "NONE"); + ruleTwo.put("delete-other-v", "NONE"); + ruleTwo.put("prevent-delete", "NONE"); + ruleTwo.put("from", "availability-zone"); + ruleTwo.put("to", "complex"); + ruleTwo.put("multiplicity", "MANY2MANY"); + ruleTwo.put("default", "true"); + ruleTwo.put("description", ""); + + EdgeRule erOne = new EdgeRule ( ruleOne ); + EdgeRule erTwo = new EdgeRule ( ruleTwo ); + Multimap relationship = ArrayListMultimap.create(); + relationship.put ( "customer|service-instane", erOne ); + relationship.put ( "availability-zone|complex", erTwo ); + return new RelationshipSchema ( relationship, defaultEdgeProps ); - private String myMatcher (Pattern p, String s) { - Matcher m = p.matcher(s); - return m.matches() ? m.group(1) : ""; } } \ No newline at end of file diff --git a/src/test/resources/edgeProps/edge_properties_v11.json b/src/test/resources/edgeProps/edge_properties_v11.json new file mode 100644 index 0000000..8d00636 --- /dev/null +++ b/src/test/resources/edgeProps/edge_properties_v11.json @@ -0,0 +1,6 @@ +{ + "contains-other-v": "java.lang.String", + "delete-other-v": "java.lang.String", + "SVC-INFRA": "java.lang.String", + "prevent-delete": "java.lang.String" +} \ No newline at end of file diff --git a/src/test/resources/edgeProps/edge_properties_v13.json b/src/test/resources/edgeProps/edge_properties_v13.json new file mode 100644 index 0000000..8d00636 --- /dev/null +++ b/src/test/resources/edgeProps/edge_properties_v13.json @@ -0,0 +1,6 @@ +{ + "contains-other-v": "java.lang.String", + "delete-other-v": "java.lang.String", + "SVC-INFRA": "java.lang.String", + "prevent-delete": "java.lang.String" +} \ No newline at end of file diff --git a/src/test/resources/rules/DbEdgeRules_test_one_v11.json b/src/test/resources/rules/DbEdgeRules_test_one_v11.json new file mode 100644 index 0000000..61eed72 --- /dev/null +++ b/src/test/resources/rules/DbEdgeRules_test_one_v11.json @@ -0,0 +1,26 @@ +{ + "rules": [ + { + "from": "U", + "to": "V", + "label": "org.onap.relationships.inventory.groupsResourcesIn", + "direction": "IN", + "multiplicity": "Many2Many", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}" + }, + { + "from": "W", + "to": "X", + "label": "org.onap.relationships.inventory.groupsResourcesIn", + "direction": "OUT", + "multiplicity": "Many2Many", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}" + } + ] +} diff --git a/src/test/resources/rules/DbEdgeRules_test_one_v13.json b/src/test/resources/rules/DbEdgeRules_test_one_v13.json new file mode 100644 index 0000000..6611750 --- /dev/null +++ b/src/test/resources/rules/DbEdgeRules_test_one_v13.json @@ -0,0 +1,26 @@ +{ + "rules": [ + { + "from": “A”, + "to": “B”, + "label": “A-To-B”, + "direction": "OUT", + "multiplicity": "Many2Many", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}" + }, + { + "from": “B”, + "to": “c”, + "label": “B-To-C”, + "direction": "OUT", + "multiplicity": "Many2Many", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}" + } + ] +} diff --git a/src/test/resources/rules/DbEdgeRules_test_two_v11.json b/src/test/resources/rules/DbEdgeRules_test_two_v11.json new file mode 100644 index 0000000..f38bd2c --- /dev/null +++ b/src/test/resources/rules/DbEdgeRules_test_two_v11.json @@ -0,0 +1,26 @@ +{ + "rules": [ + { + "from": "U", + "to": "V", + "label": "org.onap.relationships.inventory.groupsResourcesIn", + "direction": "BOTH", + "multiplicity": "Many2Many", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}" + }, + { + "from": "Y", + "to": "X", + "label": "org.onap.relationships.inventory.groupsResourcesIn", + "direction": "OUT", + "multiplicity": "Many2Many", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}" + } + ] +} diff --git a/src/test/resources/rules/DbEdgeRules_test_two_v13.json b/src/test/resources/rules/DbEdgeRules_test_two_v13.json new file mode 100644 index 0000000..d1995d2 --- /dev/null +++ b/src/test/resources/rules/DbEdgeRules_test_two_v13.json @@ -0,0 +1,26 @@ +{ + "rules": [ + { + "from": “C”, + "to": “D”, + "label": “C-To-D”, + "direction": "OUT", + "multiplicity": "Many2Many", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}" + }, + { + "from": “D”, + "to": “E”, + "label": “D-To-E”, + "direction": "OUT", + "multiplicity": "Many2Many", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}" + } + ] +} diff --git a/src/test/resources/rules/DbEdgeRules_v11.json b/src/test/resources/rules/DbEdgeRules_v11.json new file mode 100644 index 0000000..a32ba86 --- /dev/null +++ b/src/test/resources/rules/DbEdgeRules_v11.json @@ -0,0 +1,2416 @@ +{ + "rules": [ + { + "from": "esr-ems", + "to": "esr-system-info", + "label": "has", + "direction": "OUT", + "multiplicity": "One2Many", + "contains-other-v": "${direction}", + "delete-other-v": "${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "esr-vnfm", + "to": "esr-system-info", + "label": "has", + "direction": "OUT", + "multiplicity": "One2One", + "contains-other-v": "${direction}", + "delete-other-v": "${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "esr-thirdparty-sdnc", + "to": "esr-system-info", + "label": "has", + "direction": "OUT", + "multiplicity": "One2One", + "contains-other-v": "${direction}", + "delete-other-v": "${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "esr-thirdparty-sdnc", + "to": "pnf", + "label": "has", + "direction": "OUT", + "multiplicity": "One2Many", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "cloud-region", + "to": "esr-system-info", + "label": "has", + "direction": "OUT", + "multiplicity": "One2Many", + "contains-other-v": "${direction}", + "delete-other-v": "${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "allotted-resource", + "to": "allotted-resource", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "allotted-resource", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.PartOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "allotted-resource", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "allotted-resource", + "to": "l3-network", + "label": "org.onap.relationships.inventory.PartOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "allotted-resource", + "to": "l-interface", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "allotted-resource", + "to": "network-policy", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "allotted-resource", + "to": "vlan", + "label": "org.onap.relationships.inventory.PartOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "allotted-resource", + "to": "vpn-binding", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "tunnel-xconnect", + "to": "allotted-resource", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "availability-zone", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "availability-zone", + "to": "service-capability", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "availability-zone", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "cloud-region", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "cloud-region", + "to": "l3-network", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "cloud-region", + "to": "zone", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "dvs-switch", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "flavor", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "group-assignment", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "image", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "oam-network", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "snapshot", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "tenant", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "vip-ipv4-address-list", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "vip-ipv6-address-list", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "volume-group", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "complex", + "to": "l3-network", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "ctag-pool", + "to": "complex", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "configuration", + "to": "allotted-resource", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "configuration", + "to": "logical-link", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "metadatum", + "to": "configuration", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "connector", + "to": "virtual-data-center", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "metadatum", + "to": "connector", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "element-choice-set", + "to": "constrained-element-set", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "ctag-pool", + "to": "availability-zone", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "service-subscription", + "to": "customer", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "dvs-switch", + "to": "availability-zone", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "model-element", + "to": "element-choice-set", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "entitlement", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "availability-zone", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "configuration", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "ctag-pool", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "ipsec-configuration", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "l3-network", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "license-key-resource", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "pnf", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "pserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "vnfc", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "vnf-image", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "volume-group", + "label": "org.onap.relationships.inventory.DependsOn", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "vserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "lag-interface", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "license", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l-interface", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "network-profile", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "site-pair-set", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vf-module", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "pserver", + "to": "group-assignment", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "${direction}", + "default": "true" + }, + { + "from": "tenant", + "to": "group-assignment", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "metadatum", + "to": "image", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "instance-group", + "to": "model", + "label": "org.onap.relationships.inventory.Targets", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "vig-server", + "to": "ipsec-configuration", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-interface-ipv4-address-list", + "to": "instance-group", + "label": "org.onap.relationships.inventory.network.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-interface-ipv4-address-list", + "to": "l3-network", + "label": "org.onap.relationships.inventory.network.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-interface-ipv4-address-list", + "to": "subnet", + "label": "org.onap.relationships.inventory.network.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "l3-interface-ipv6-address-list", + "to": "instance-group", + "label": "org.onap.relationships.inventory.network.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-interface-ipv6-address-list", + "to": "l3-network", + "label": "org.onap.relationships.inventory.network.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-interface-ipv6-address-list", + "to": "subnet", + "label": "org.onap.relationships.inventory.network.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "ctag-assignment", + "to": "l3-network", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-network", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-network", + "to": "network-policy", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-network", + "to": "route-table-reference", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-network", + "to": "vpn-binding", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "segmentation-assignment", + "to": "l3-network", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "l3-network", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "subnet", + "to": "l3-network", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "lag-interface", + "to": "lag-link", + "label": "tosca.relationships.network.LinksTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "lag-interface", + "to": "logical-link", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "lag-interface", + "to": "p-interface", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l-interface", + "to": "lag-interface", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "line-of-business", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-interface-ipv4-address-list", + "to": "l-interface", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-interface-ipv6-address-list", + "to": "l-interface", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l-interface", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l-interface", + "to": "l-interface", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l-interface", + "to": "logical-link", + "label": "tosca.relationships.network.LinksTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "sriov-vf", + "to": "l-interface", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vlan", + "to": "l-interface", + "label": "tosca.relationships.network.LinksTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "logical-link", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "logical-link", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BridgedTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "logical-link", + "to": "lag-link", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "logical-link", + "to": "logical-link", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "logical-link", + "to": "pnf", + "label": "org.onap.relationships.inventory.BridgedTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "logical-link", + "to": "pserver", + "label": "org.onap.relationships.inventory.BridgedTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "logical-link", + "to": "vpn-binding", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "model-ver", + "to": "model", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "constrained-element-set", + "to": "model-constraint", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "constrained-element-set", + "to": "model-element", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "model-constraint", + "to": "model-element", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "model-element", + "to": "model-element", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "model-element", + "to": "model-ver", + "label": "org.onap.relationships.inventory.IsA", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "model-element", + "to": "model-ver", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "named-query", + "to": "model", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "named-query-element", + "to": "named-query", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "named-query-element", + "to": "model", + "label": "org.onap.relationships.inventory.IsA", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "named-query-element", + "to": "named-query-element", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "property-constraint", + "to": "named-query-element", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "related-lookup", + "to": "named-query-element", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l-interface", + "to": "newvce", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "oam-network", + "to": "complex", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "oam-network", + "to": "service-capability", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "service-instance", + "to": "owning-entity", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l-interface", + "to": "p-interface", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "p-interface", + "to": "logical-link", + "label": "tosca.relationships.network.LinksTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "p-interface", + "to": "physical-link", + "label": "tosca.relationships.network.LinksTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "sriov-pf", + "to": "p-interface", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "platform", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "lag-interface", + "to": "pnf", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "p-interface", + "to": "pnf", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "pnf", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "pnf", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "pnf", + "to": "zone", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "cvlan-tag", + "to": "port-group", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "project", + "to": "service-instance", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "lag-interface", + "to": "pserver", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "p-interface", + "to": "pserver", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "pserver", + "to": "availability-zone", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "pserver", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "pserver", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "pserver", + "to": "zone", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "site-pair", + "to": "routing-instance", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "allotted-resource", + "to": "service-instance", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "metadatum", + "to": "service-instance", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "allotted-resource", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "configuration", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "connector", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "ctag-assignment", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "cvlan-tag", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "logical-link", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "pnf", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "service-instance", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "vlan", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "zone", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "service-subscription", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "class-of-service", + "to": "site-pair", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "routing-instance", + "to": "site-pair-set", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "sriov-vf", + "to": "sriov-pf", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "host-route", + "to": "subnet", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-subscription", + "to": "tenant", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "tenant", + "to": "l3-network", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vserver", + "to": "tenant", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "entitlement", + "to": "vce", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "license", + "to": "vce", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "port-group", + "to": "vce", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "service-instance", + "to": "vce", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vce", + "to": "availability-zone", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "vce", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "vce", + "to": "vserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vf-module", + "to": "l3-network", + "label": "org.onap.relationships.inventory.DependsOn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vf-module", + "to": "vnfc", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "${direction}", + "default": "true" + }, + { + "from": "vf-module", + "to": "volume-group", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vip-ipv4-address-list", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vip-ipv4-address-list", + "to": "subnet", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "vip-ipv6-address-list", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vip-ipv6-address-list", + "to": "subnet", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "generic-vnf", + "to": "virtual-data-center", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "logical-link", + "to": "virtual-data-center", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-interface-ipv4-address-list", + "to": "vlan", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-interface-ipv6-address-list", + "to": "vlan", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vlan", + "to": "logical-link", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vlan", + "to": "multicast-configuration", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-interface-ipv4-address-list", + "to": "vnfc", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l3-interface-ipv6-address-list", + "to": "vnfc", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vnfc", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vnfc", + "to": "vip-ipv4-address-list", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vnfc", + "to": "vip-ipv6-address-list", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "tenant", + "to": "volume-group", + "label": "org.onap.relationships.inventory.DependsOn", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "volume-group", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "lag-interface", + "to": "vpls-pe", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "p-interface", + "to": "vpls-pe", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vpls-pe", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "vpls-pe", + "to": "ctag-pool", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "route-target", + "to": "vpn-binding", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "l-interface", + "to": "vserver", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vf-module", + "to": "vserver", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vnfc", + "to": "vserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "!${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vserver", + "to": "flavor", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "vserver", + "to": "image", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "vserver", + "to": "pserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}", + "default": "true" + }, + { + "from": "vserver", + "to": "snapshot", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "vserver", + "to": "volume", + "label": "tosca.relationships.AttachesTo", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "${direction}", + "delete-other-v": "${direction}", + "SVC-INFRA": "${direction}", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "metadatum", + "to": "model-ver", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "SVC-INFRA": "NONE", + "prevent-delete": "NONE", + "default": "true" + }, + { + "from": "zone", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "NONE", + "prevent-delete": "!${direction}", + "default": "true" + } + ] +} diff --git a/src/test/resources/rules/DbEdgeRules_v13.json b/src/test/resources/rules/DbEdgeRules_v13.json new file mode 100644 index 0000000..fd45c9b --- /dev/null +++ b/src/test/resources/rules/DbEdgeRules_v13.json @@ -0,0 +1,2836 @@ +{ + "rules": [ + { + "from": "service-instance", + "to": "customer", + "label": "ncso.related-to", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" +}, +{ + "from": "generic-vnf", + "to": "vnfc", + "label": "ncso.related-to", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" +}, +{ + "from": "vnfc", + "to": "vnfc", + "label": "ncso.related-to", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" +}, +{ + "from": "vnfc", + "to": "vserver", + "label": "ncso.related-to", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" +}, +{ + "from": "generic-vnf", + "to": "service-instance", + "label": "ncso.related-to", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" +}, +{ + "from": "generic-vnf", + "to": "generic-vnf", + "label": "ncso.related-to", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, +{ + "from": "service-instance", + "to": "generic-vnf", + "label": "ncso.related-to", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" +}, +{ + "from": "generic-vnf", + "to": "vserver", + "label": "ncso.related-to", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" +}, + { + "from": "allotted-resource", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.PartOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "allotted-resource", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "allotted-resource", + "to": "l3-network", + "label": "org.onap.relationships.inventory.PartOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "allotted-resource", + "to": "l-interface", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "allotted-resource", + "to": "network-policy", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "allotted-resource", + "to": "vlan", + "label": "org.onap.relationships.inventory.PartOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "allotted-resource", + "to": "vpn-binding", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "tunnel-xconnect", + "to": "allotted-resource", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "availability-zone", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "availability-zone", + "to": "service-capability", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "availability-zone", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "cloud-region", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "cloud-region", + "to": "l3-network", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "cloud-region", + "to": "zone", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "dvs-switch", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "flavor", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "group-assignment", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "image", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "oam-network", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "snapshot", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "tenant", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "vip-ipv4-address-list", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "vip-ipv6-address-list", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "volume-group", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "complex", + "to": "l3-network", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "ctag-pool", + "to": "complex", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "configuration", + "to": "allotted-resource", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "configuration", + "to": "logical-link", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "metadatum", + "to": "configuration", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "connector", + "to": "virtual-data-center", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "metadatum", + "to": "connector", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "element-choice-set", + "to": "constrained-element-set", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "ctag-pool", + "to": "availability-zone", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "service-subscription", + "to": "customer", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "dvs-switch", + "to": "availability-zone", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "model-element", + "to": "element-choice-set", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "entitlement", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "availability-zone", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "configuration", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "ctag-pool", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "ipsec-configuration", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "l3-network", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "pnf", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "pserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "vnfc", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "vnf-image", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "volume-group", + "label": "org.onap.relationships.inventory.DependsOn", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "vserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "lag-interface", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "license", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l-interface", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "network-profile", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "site-pair-set", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vf-module", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "pserver", + "to": "group-assignment", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "${direction}", + "default": "true", + "description":"" + }, + { + "from": "tenant", + "to": "group-assignment", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "metadatum", + "to": "image", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "instance-group", + "to": "model", + "label": "org.onap.relationships.inventory.Targets", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "vig-server", + "to": "ipsec-configuration", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-interface-ipv4-address-list", + "to": "instance-group", + "label": "org.onap.relationships.inventory.network.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-interface-ipv4-address-list", + "to": "l3-network", + "label": "org.onap.relationships.inventory.network.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-interface-ipv4-address-list", + "to": "subnet", + "label": "org.onap.relationships.inventory.network.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "l3-interface-ipv6-address-list", + "to": "instance-group", + "label": "org.onap.relationships.inventory.network.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-interface-ipv6-address-list", + "to": "l3-network", + "label": "org.onap.relationships.inventory.network.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-interface-ipv6-address-list", + "to": "subnet", + "label": "org.onap.relationships.inventory.network.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "ctag-assignment", + "to": "l3-network", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-network", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-network", + "to": "network-policy", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-network", + "to": "route-table-reference", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-network", + "to": "vpn-binding", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "segmentation-assignment", + "to": "l3-network", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "l3-network", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "subnet", + "to": "l3-network", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "lag-interface", + "to": "lag-link", + "label": "tosca.relationships.network.LinksTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "lag-interface", + "to": "logical-link", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "lag-interface", + "to": "p-interface", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l-interface", + "to": "lag-interface", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "lag-interface", + "to": "l-interface", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "false", + "description":"" + }, + { + "from": "line-of-business", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-interface-ipv4-address-list", + "to": "l-interface", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-interface-ipv6-address-list", + "to": "l-interface", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l-interface", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l-interface", + "to": "l-interface", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l-interface", + "to": "logical-link", + "label": "tosca.relationships.network.LinksTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "logical-link", + "to": "l-interface", + "label": "org.onap.relationships.inventory.Source", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "false", + "description":"" + }, + { + "from": "logical-link", + "to": "l-interface", + "label": "org.onap.relationships.inventory.Destination", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "false", + "description":"" + }, + { + "from": "sriov-vf", + "to": "l-interface", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vlan", + "to": "l-interface", + "label": "tosca.relationships.network.LinksTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "logical-link", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "logical-link", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.BridgedTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "logical-link", + "to": "lag-link", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "logical-link", + "to": "logical-link", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "logical-link", + "to": "pnf", + "label": "org.onap.relationships.inventory.BridgedTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "logical-link", + "to": "pserver", + "label": "org.onap.relationships.inventory.BridgedTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "logical-link", + "to": "vpn-binding", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "model-ver", + "to": "model", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "constrained-element-set", + "to": "model-constraint", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "constrained-element-set", + "to": "model-element", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "model-constraint", + "to": "model-element", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "model-element", + "to": "model-element", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "model-element", + "to": "model-ver", + "label": "org.onap.relationships.inventory.IsA", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "metadatum", + "to": "model-ver", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "model-element", + "to": "model-ver", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "named-query", + "to": "model", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "named-query-element", + "to": "named-query", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "named-query-element", + "to": "model", + "label": "org.onap.relationships.inventory.IsA", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "named-query-element", + "to": "named-query-element", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "property-constraint", + "to": "named-query-element", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "related-lookup", + "to": "named-query-element", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l-interface", + "to": "newvce", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "oam-network", + "to": "complex", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "oam-network", + "to": "service-capability", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "operational-environment", + "to": "operational-environment", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "owning-entity", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l-interface", + "to": "p-interface", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "p-interface", + "to": "logical-link", + "label": "tosca.relationships.network.LinksTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "p-interface", + "to": "physical-link", + "label": "tosca.relationships.network.LinksTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "sriov-pf", + "to": "p-interface", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "platform", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "lag-interface", + "to": "pnf", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "p-interface", + "to": "pnf", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "pnf", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "pnf", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "pnf", + "to": "zone", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "cvlan-tag", + "to": "port-group", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "project", + "to": "service-instance", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "lag-interface", + "to": "pserver", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "p-interface", + "to": "pserver", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "pserver", + "to": "availability-zone", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "pserver", + "to": "cloud-region", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "pserver", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "pserver", + "to": "zone", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "site-pair", + "to": "routing-instance", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "allotted-resource", + "to": "service-instance", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "metadatum", + "to": "service-instance", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "allotted-resource", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "configuration", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "connector", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "ctag-assignment", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "cvlan-tag", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "logical-link", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "pnf", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "service-instance", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "vlan", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "zone", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "service-subscription", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "class-of-service", + "to": "site-pair", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "routing-instance", + "to": "site-pair-set", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "sriov-vf", + "to": "sriov-pf", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "host-route", + "to": "subnet", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-subscription", + "to": "tenant", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "tenant", + "to": "l3-network", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vserver", + "to": "tenant", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "entitlement", + "to": "vce", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "license", + "to": "vce", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "port-group", + "to": "vce", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "vce", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vce", + "to": "availability-zone", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "vce", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "vce", + "to": "vserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vf-module", + "to": "l3-network", + "label": "org.onap.relationships.inventory.DependsOn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vf-module", + "to": "vnfc", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "${direction}", + "default": "true", + "description":"" + }, + { + "from": "vf-module", + "to": "volume-group", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vip-ipv4-address-list", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vip-ipv4-address-list", + "to": "subnet", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "vip-ipv6-address-list", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vip-ipv6-address-list", + "to": "subnet", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "virtual-data-center", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "logical-link", + "to": "virtual-data-center", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-interface-ipv4-address-list", + "to": "vlan", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-interface-ipv6-address-list", + "to": "vlan", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vlan", + "to": "logical-link", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vlan", + "to": "multicast-configuration", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-interface-ipv4-address-list", + "to": "vnfc", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-interface-ipv6-address-list", + "to": "vnfc", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vnfc", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vnfc", + "to": "vip-ipv4-address-list", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vnfc", + "to": "vip-ipv6-address-list", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "tenant", + "to": "volume-group", + "label": "org.onap.relationships.inventory.DependsOn", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "volume-group", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "lag-interface", + "to": "vpls-pe", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "p-interface", + "to": "vpls-pe", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vpls-pe", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "vpls-pe", + "to": "ctag-pool", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "route-target", + "to": "vpn-binding", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l-interface", + "to": "vserver", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vf-module", + "to": "vserver", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vnfc", + "to": "vserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vserver", + "to": "flavor", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "vserver", + "to": "image", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "vserver", + "to": "pserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "vserver", + "to": "snapshot", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vserver", + "to": "volume", + "label": "tosca.relationships.AttachesTo", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "${direction}", + "delete-other-v": "${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "zone", + "to": "complex", + "label": "org.onap.relationships.inventory.LocatedIn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "allotted-resource", + "to": "model-ver", + "label": "org.onap.relationships.inventory.IsA", + "direction": "OUT", + "multiplicity": "Many2One", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "model-ver", + "label": "org.onap.relationships.inventory.IsA", + "direction": "OUT", + "multiplicity": "Many2One", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "l3-network", + "to": "model-ver", + "label": "org.onap.relationships.inventory.IsA", + "direction": "OUT", + "multiplicity": "Many2One", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "logical-link", + "to": "model-ver", + "label": "org.onap.relationships.inventory.IsA", + "direction": "OUT", + "multiplicity": "Many2One", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "model-ver", + "label": "org.onap.relationships.inventory.IsA", + "direction": "OUT", + "multiplicity": "Many2One", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vf-module", + "to": "model-ver", + "label": "org.onap.relationships.inventory.IsA", + "direction": "OUT", + "multiplicity": "Many2One", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "configuration", + "to": "l-interface", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "configuration", + "to": "pnf", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "forwarder", + "to": "forwarding-path", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "forwarding-path", + "to": "service-instance", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "forwarder", + "to": "l-interface", + "label": "org.onap.relationships.inventory.ForwardsTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "forwarder", + "to": "configuration", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "forwarding-path", + "to": "configuration", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "forwarder", + "to": "lag-interface", + "label": "org.onap.relationships.inventory.ForwardsTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "evc", + "to": "configuration", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "forwarder-evc", + "to": "configuration", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "forwarder", + "to": "p-interface", + "label": "org.onap.relationships.inventory.ForwardsTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "generic-vnf", + "to": "nos-server", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "nos-server", + "to": "pserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "nos-server", + "to": "tenant", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "NONE", + "prevent-delete": "!${direction}", + "default": "true", + "description":"" + }, + { + "from": "configuration", + "to": "configuration", + "label": "tosca.relationships.network.BindsTo", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "configuration", + "to": "vpn-binding", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "configuration", + "to": "l3-network", + "label": "org.onap.relationships.inventory.PartOf", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "vpn-binding", + "to": "customer", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description":"" + }, + { + "from": "service-instance", + "to": "configuration", + "label": "org.onap.relationships.inventory.ComposedOf", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "false", + "description":"" + }, + { + "from": "forwarder", + "to": "generic-vnf", + "label": "org.onap.relationships.inventory.AppliesTo", + "direction": "OUT", + "multiplicity": "MANY2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description": "Points to the generic-vnf(s) involved in this forwarding step." + }, + { + "from": "cloud-region", + "to": "instance-group", + "label": "org.onap.relationships.inventory.Uses", + "direction": "OUT", + "multiplicity": "ONE2MANY", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description": "" + }, + { + "from": "collection", + "to": "instance-group", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description": "" + }, + { + "from": "service-instance", + "to": "collection", + "label": "org.onap.relationships.inventory.MemberOf", + "direction": "OUT", + "multiplicity": "ONE2ONE", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "prevent-delete": "NONE", + "default": "true", + "description": "" + }, + { + "from": "vlan-mapping", + "to": "forwarder-evc", + "label": "org.onap.relationships.inventory.BelongsTo", + "direction": "OUT", + "multiplicity": "MANY2ONE", + "contains-other-v": "!${direction}", + "delete-other-v": "!${direction}", + "prevent-delete": "NONE", + "default": "true", + "description": "" + } + ] +} \ No newline at end of file diff --git a/src/test/resources/schemaIngest.properties b/src/test/resources/schemaIngest.properties index 2aa388e..2fa77aa 100644 --- a/src/test/resources/schemaIngest.properties +++ b/src/test/resources/schemaIngest.properties @@ -1,4 +1,5 @@ # Properties for the SchemaLocationsBean schemaConfig=NA nodeDir=src/test/resources/oxm/ -edgeDir= \ No newline at end of file +edgeDir=src/test/resources/rules/ +edgePropsDir=src/test/resources/edgeProps/ \ No newline at end of file -- 2.16.6 From b348af8ed2c4192f88169b37bf53fa25b8a7a681 Mon Sep 17 00:00:00 2001 From: "Sotiropoulos, Ioannis (is948x)" Date: Fri, 15 Jun 2018 15:32:01 +0100 Subject: [PATCH 14/16] ETags on resources An etag should be generated (by Champ) when creating a resource (edge or vertex). The Champ microservice should return this etag in the response header. Gizmo should also return the etag in it's response header (Gizmo will receive the etag from Champ). Issue-ID: AAI-1196 Change-Id: Ie16f871eccbceeccde037e73e0de0d96eeba18bd Signed-off-by: Sotiropoulos, Ioannis (is948x) --- .gitignore | 4 + src/main/java/org/onap/crud/dao/GraphDao.java | 47 ++-- .../java/org/onap/crud/dao/champ/ChampDao.java | 112 +++++---- src/main/java/org/onap/crud/event/GraphEvent.java | 14 +- .../onap/crud/event/envelope/GraphEventHeader.java | 2 +- .../org/onap/crud/parser/CrudResponseBuilder.java | 4 - .../org/onap/crud/service/AaiResourceService.java | 249 ++++++++++----------- .../crud/service/AbstractGraphDataService.java | 141 +++++++----- .../crud/service/CrudAsyncGraphDataService.java | 107 +++++++-- .../onap/crud/service/CrudGraphDataService.java | 117 +++++++--- .../org/onap/crud/service/CrudRestService.java | 61 +++-- .../java/org/onap/crud/service/EdgePayload.java | 6 +- .../java/org/onap/crud/service/VertexPayload.java | 10 +- .../org/onap/crud/util/CrudServiceConstants.java | 1 + .../java/org/onap/crud/util/CrudServiceUtil.java | 42 ++-- .../java/org/onap/crud/util/HashGenerator.java | 65 ++++++ .../org/onap/crud/util/etag/EtagGenerator.java | 92 ++++++++ .../org/onap/crud/service/CrudRestServiceTest.java | 45 ++-- .../org/onap/crud/{dao => service}/TestDao.java | 101 ++++++--- .../org/onap/crud/util/etag/EtagGeneratorTest.java | 168 ++++++++++++++ 20 files changed, 953 insertions(+), 435 deletions(-) create mode 100644 src/main/java/org/onap/crud/util/HashGenerator.java create mode 100644 src/main/java/org/onap/crud/util/etag/EtagGenerator.java rename src/test/java/org/onap/crud/{dao => service}/TestDao.java (56%) create mode 100644 src/test/java/org/onap/crud/util/etag/EtagGeneratorTest.java diff --git a/.gitignore b/.gitignore index 88cf0cb..3615915 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,7 @@ target/ # IntelliJ .idea/ *.iml + +# Misc +.checkstyle + diff --git a/src/main/java/org/onap/crud/dao/GraphDao.java b/src/main/java/org/onap/crud/dao/GraphDao.java index 29ea6da..fe638ce 100644 --- a/src/main/java/org/onap/crud/dao/GraphDao.java +++ b/src/main/java/org/onap/crud/dao/GraphDao.java @@ -23,9 +23,8 @@ package org.onap.crud.dao; import java.util.HashSet; import java.util.List; import java.util.Map; - +import org.onap.aai.restclient.client.OperationResult; import org.onap.crud.entity.Edge; - import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; @@ -33,7 +32,7 @@ public interface GraphDao { public Vertex getVertex(String id, String version) throws CrudException; - public Vertex getVertex(String id, String type, String version, Map queryParams) throws CrudException; + public OperationResult getVertex(String id, String type, String version, Map queryParams) throws CrudException; /** * Retrieve all of the edges which are incident to the vertex with the @@ -42,7 +41,7 @@ public interface GraphDao { * @param id * - The unique identifier of the vertex to retrieve the edges for. * @param queryParams - * - query parameters to be passed + * - query parameters to be passed * @return - A collection of edges. * @throws CrudException */ @@ -56,10 +55,10 @@ public interface GraphDao { * - The vertex type that we want to retrieve. * @param filter * - The parameters to filter our results by. - * @return - A collection of vertices. + * @return - The {@link OperationResult} OperationResult * @throws CrudException */ - public List getVertices(String type, Map filter, String version) throws CrudException; + public OperationResult getVertices(String type, Map filter, String version) throws CrudException; /** * Retrieve a collection of {@link Vertex} objects which match the supplied @@ -71,10 +70,10 @@ public interface GraphDao { * - The parameters to filter our results by. * @param properties * - The properties to retrieve with the vertex - * @return - A collection of vertices. + * @return - The {@link OperationResult} OperationResult * @throws CrudException */ - public List getVertices(String type, Map filter, HashSet properties, String version) throws CrudException; + public OperationResult getVertices(String type, Map filter, HashSet properties, String version) throws CrudException; /** * Retrieve an {@link Edge} from the graph database by specifying its unique @@ -85,11 +84,11 @@ public interface GraphDao { * @param type * - The type that we want to retrieve. * @param queryParams - * - query parameters to be passed - * @return - The Edge corresponding to the specified identifier. + * - query parameters to be passed + * @return - The {@link OperationResult} OperationResult corresponding to the specified identifier. * @throws CrudException */ - public Edge getEdge(String id, String type, Map queryParams) throws CrudException; + public OperationResult getEdge(String id, String type, Map queryParams) throws CrudException; /** * Retrieve a collection of {@link Edge} objects with a given type and which @@ -99,10 +98,10 @@ public interface GraphDao { * - The type of edges that we are interested in. * @param filter * - The parameters that we want to filter our edges by. - * @return - A collection of edges which match the supplied filter parameters. + * @return - The {@link OperationResult} OperationResult * @throws CrudException */ - public List getEdges(String type, Map filter) throws CrudException; + public OperationResult getEdges(String type, Map filter) throws CrudException; /** * Insert a new {@link Vertex} into the graph data store. @@ -111,10 +110,10 @@ public interface GraphDao { * - The type label to assign to the vertex. * @param properties * - The properties to associated with this vertex. - * @return - The {@link Vertex} object that was created. + * @return - The result of the Vertex creation. * @throws CrudException */ - public Vertex addVertex(String type, Map properties, String version) throws CrudException; + public OperationResult addVertex(String type, Map properties, String version) throws CrudException; /** * Updates an existing {@link Vertex}. @@ -123,10 +122,10 @@ public interface GraphDao { * - The unique identifier of the vertex to be updated. * @param properties * - The properties to associate with the vertex. - * @return - The udpated vertex. + * @return - The result of the update OperationResult. * @throws CrudException */ - public Vertex updateVertex(String id, String type, Map properties, String version) throws CrudException; + public OperationResult updateVertex(String id, String type, Map properties, String version) throws CrudException; /** * Removes the specified vertex from the graph data base. @@ -151,22 +150,20 @@ public interface GraphDao { * - The target vertex for this edge. * @param properties * - The properties map to associate with this edge. - * @return - The {@link Edge} object that was created. + * @return - The {@link OperationResult} OperationResult containing the Edge that was created. * @throws CrudException */ - public Edge addEdge(String type, Vertex source, Vertex target, Map properties, String version) throws CrudException; + public OperationResult addEdge(String type, Vertex source, Vertex target, Map properties, String version) throws CrudException; /** * Updates an existing {@link Edge}. * - * @param id - * - The unique identifier of the edge to be updated. - * @param properties - * - The properties to associate with the edge. - * @return - The update edge. + * @param edge + * - The edge to be updated. + * @return - The result of the update OperationResult. * @throws CrudException */ - public Edge updateEdge(Edge edge) throws CrudException; + public OperationResult updateEdge(Edge edge) throws CrudException; /** * Remove the specified edge from the graph data base. diff --git a/src/main/java/org/onap/crud/dao/champ/ChampDao.java b/src/main/java/org/onap/crud/dao/champ/ChampDao.java index 344d797..c8488ba 100644 --- a/src/main/java/org/onap/crud/dao/champ/ChampDao.java +++ b/src/main/java/org/onap/crud/dao/champ/ChampDao.java @@ -20,39 +20,36 @@ */ package org.onap.crud.dao.champ; -import net.dongliu.gson.GsonJava8TypeAdapterFactory; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; - +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.message.BasicNameValuePair; import org.eclipse.jetty.util.security.Password; -import org.onap.aai.cl.mdc.MdcContext; -import org.onap.aai.logging.LoggingContext; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.cl.mdc.MdcContext; +import org.onap.aai.logging.LoggingContext; +import org.onap.aai.restclient.client.OperationResult; +import org.onap.aai.restclient.client.RestClient; +import org.onap.aai.restclient.enums.RestAuthenticationMode; import org.onap.crud.dao.GraphDao; import org.onap.crud.entity.Edge; import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; import org.onap.crud.util.CrudServiceConstants; -import org.onap.aai.restclient.client.OperationResult; -import org.onap.aai.restclient.client.RestClient; -import org.onap.aai.restclient.enums.RestAuthenticationMode; import org.slf4j.MDC; - -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import net.dongliu.gson.GsonJava8TypeAdapterFactory; public class ChampDao implements GraphDao { protected RestClient client; @@ -75,7 +72,7 @@ public class ChampDao implements GraphDao { .registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory()) .registerTypeAdapter(Vertex.class, new ChampVertexSerializer()) .registerTypeAdapter(Edge.class, new ChampEdgeSerializer()).create(); - + public ChampDao() { } @@ -112,12 +109,12 @@ public class ChampDao implements GraphDao { } else { // We didn't find a vertex with the supplied id, so just throw an // exception. - throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph"); + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph"); } } @Override - public Vertex getVertex(String id, String type, String version, Map queryParams) throws CrudException { + public OperationResult getVertex(String id, String type, String version, Map queryParams) throws CrudException { StringBuilder strBuild = new StringBuilder(baseObjectUrl); strBuild.append("/"); strBuild.append(id); @@ -138,11 +135,11 @@ public class ChampDao implements GraphDao { throw new CrudException("No vertex with id " + id + "and type " + type + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND); } - return vert; + return getResult; } else { // We didn't find a vertex with the supplied id, so just throw an // exception. - throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph"); + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph"); } } @@ -158,24 +155,24 @@ public class ChampDao implements GraphDao { } OperationResult getResult = client.get(strBuild.toString(), createHeader(), MediaType.APPLICATION_JSON_TYPE); - + if (getResult.getResultCode() == 200) { return champGson.fromJson(getResult.getResult(), new TypeToken>() { }.getType()); } else { // We didn't find a vertex with the supplied id, so just throw an // exception. - throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph"); + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph"); } } @Override - public List getVertices(String type, Map filter, String version) throws CrudException { + public OperationResult getVertices(String type, Map filter, String version) throws CrudException { return getVertices(type, filter, new HashSet(), version); } @Override - public List getVertices(String type, Map filter, HashSet properties, String version) throws CrudException { + public OperationResult getVertices(String type, Map filter, HashSet properties, String version) throws CrudException { filter.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); List queryParams = convertToNameValuePair(filter); @@ -186,16 +183,16 @@ public class ChampDao implements GraphDao { OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE); if (getResult.getResultCode() == 200) { - return Vertex.collectionFromJson(getResult.getResult(), version); + return getResult; } else { // We didn't find a vertex with the supplied id, so just throw an // exception. - throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertices found in graph for given filters"); + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertices found in graph for given filters"); } } @Override - public Edge getEdge(String id, String type, Map queryParams) throws CrudException { + public OperationResult getEdge(String id, String type, Map queryParams) throws CrudException { StringBuilder strBuild = new StringBuilder(baseRelationshipUrl); strBuild.append("/"); strBuild.append(id); @@ -205,7 +202,7 @@ public class ChampDao implements GraphDao { strBuild.append(URLEncodedUtils.format(convertToNameValuePair(queryParams), Charset.defaultCharset())); } OperationResult getResult = client.get(strBuild.toString(), createHeader(), MediaType.APPLICATION_JSON_TYPE); - + if (getResult.getResultCode() == 200) { Edge edge = Edge.fromJson(getResult.getResult()); @@ -215,33 +212,32 @@ public class ChampDao implements GraphDao { throw new CrudException("No edge with id " + id + "and type " + type + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND); } - return edge; + return getResult; } else { // We didn't find a edge with the supplied type, so just throw an // exception. - throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); } } @Override - public List getEdges(String type, Map filter) throws CrudException { + public OperationResult getEdges(String type, Map filter) throws CrudException { String url = baseRelationshipUrl + "/filter" + "?" + URLEncodedUtils.format(convertToNameValuePair(filter), Charset.defaultCharset()); OperationResult getResult = client.get(url, createHeader(), MediaType.APPLICATION_JSON_TYPE); if (getResult.getResultCode() == 200) { - return champGson.fromJson(getResult.getResult(), new TypeToken>() { - }.getType()); + return getResult; } else { // We didn't find a vertex with the supplied id, so just throw an // exception. - throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edges found in graph for given filters"); + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edges found in graph for given filters"); } } @Override - public Vertex addVertex(String type, Map properties, String version) throws CrudException { + public OperationResult addVertex(String type, Map properties, String version) throws CrudException { String url = baseObjectUrl; // Add the aai_node_type so that AAI can read the data created by gizmo @@ -256,7 +252,7 @@ public class ChampDao implements GraphDao { MediaType.APPLICATION_JSON_TYPE); if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) { - return Vertex.fromJson(getResult.getResult(), version); + return getResult; } else { // We didn't create a vertex with the supplied type, so just throw an // exception. @@ -265,7 +261,7 @@ public class ChampDao implements GraphDao { } @Override - public Vertex updateVertex(String id, String type, Map properties, String version) throws CrudException { + public OperationResult updateVertex(String id, String type, Map properties, String version) throws CrudException { String url = baseObjectUrl + "/" + id; // Add the aai_node_type so that AAI can read the data created by gizmo @@ -282,7 +278,7 @@ public class ChampDao implements GraphDao { MediaType.APPLICATION_JSON_TYPE); if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) { - return Vertex.fromJson(getResult.getResult(), version); + return getResult; } else { // We didn't create a vertex with the supplied type, so just throw an // exception. @@ -303,12 +299,14 @@ public class ChampDao implements GraphDao { } @Override - public Edge addEdge(String type, Vertex source, Vertex target, Map properties, String version) throws CrudException { + public OperationResult addEdge(String type, Vertex source, Vertex target, Map properties, String version) throws CrudException { String url = baseRelationshipUrl; // Try requests to ensure source and target exist in Champ - Vertex dbSource = getVertex(source.getId().get(), source.getType(), version, new HashMap()); - Vertex dbTarget = getVertex(target.getId().get(), target.getType(), version, new HashMap()); + OperationResult dbSourceOpResult = getVertex(source.getId().get(), source.getType(), version, new HashMap()); + Vertex dbSource = Vertex.fromJson(dbSourceOpResult.getResult(), version); + OperationResult dbTargetOpResult = getVertex(target.getId().get(), target.getType(), version, new HashMap()); + Vertex dbTarget = Vertex.fromJson(dbTargetOpResult.getResult(), version); Edge.Builder insertEdgeBuilder = new Edge.Builder(type).source(dbSource).target(dbTarget); properties.forEach(insertEdgeBuilder::property); @@ -319,7 +317,7 @@ public class ChampDao implements GraphDao { MediaType.APPLICATION_JSON_TYPE); if (getResult.getResultCode() == Response.Status.CREATED.getStatusCode()) { - return Edge.fromJson(getResult.getResult()); + return getResult; } else { // We didn't create an edge with the supplied type, so just throw an // exception. @@ -328,7 +326,7 @@ public class ChampDao implements GraphDao { } @Override - public Edge updateEdge(Edge edge) throws CrudException { + public OperationResult updateEdge(Edge edge) throws CrudException { if (!edge.getId().isPresent()) { throw new CrudException("Unable to identify edge: " + edge.toString(), Response.Status.BAD_REQUEST); } @@ -339,7 +337,7 @@ public class ChampDao implements GraphDao { MediaType.APPLICATION_JSON_TYPE); if (getResult.getResultCode() == Response.Status.OK.getStatusCode()) { - return Edge.fromJson(getResult.getResult()); + return getResult; } else { // We didn't create an edge with the supplied type, so just throw an // exception. @@ -355,7 +353,7 @@ public class ChampDao implements GraphDao { if (getResult.getResultCode() != 200) { // We didn't find an edge with the supplied type, so just throw an // exception. - throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); } } @@ -524,7 +522,7 @@ public class ChampDao implements GraphDao { if (getResult.getResultCode() != 200) { // We didn't find an edge with the supplied type, so just throw an // exception. - throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); } } @@ -546,7 +544,7 @@ public class ChampDao implements GraphDao { } else { // We didn't find an edge with the supplied id, so just throw an // exception. - throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No edge with id " + id + " found in graph"); } } @@ -567,7 +565,7 @@ public class ChampDao implements GraphDao { } else { // We didn't find a vertex with the supplied id, so just throw an // exception. - throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph"); + throw createErrorException(getResult, javax.ws.rs.core.Response.Status.NOT_FOUND, "No vertex with id " + id + " found in graph"); } } @@ -588,15 +586,15 @@ public class ChampDao implements GraphDao { return nvpList; } - + private Map> createHeader() { Map> headers = new HashMap<>(); headers.put(HEADER_FROM_APP, Arrays.asList(FROM_APP_NAME)); headers.put(HEADER_TRANS_ID, Arrays.asList(MDC.get(MdcContext.MDC_REQUEST_ID))); return headers; } - - private CrudException createErrorException(OperationResult result, javax.ws.rs.core.Response.Status defaultErrorCode , String defaultErrorMsg) + + private CrudException createErrorException(OperationResult result, javax.ws.rs.core.Response.Status defaultErrorCode , String defaultErrorMsg) { CrudException ce = null; if(result != null) diff --git a/src/main/java/org/onap/crud/event/GraphEvent.java b/src/main/java/org/onap/crud/event/GraphEvent.java index 63b84fd..958c227 100644 --- a/src/main/java/org/onap/crud/event/GraphEvent.java +++ b/src/main/java/org/onap/crud/event/GraphEvent.java @@ -20,14 +20,13 @@ */ package org.onap.crud.event; +import java.util.Objects; +import javax.ws.rs.core.Response.Status; +import org.onap.crud.exception.CrudException; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.annotations.SerializedName; -import org.onap.crud.exception.CrudException; - -import javax.ws.rs.core.Response.Status; - public class GraphEvent { public enum GraphEventOperation { @@ -171,9 +170,14 @@ public class GraphEvent { @Override public String toString() { - return toJson(); } + + @Override + public int hashCode() { + return Objects.hash(this.dbTransactionId, this.timestamp, this.edge, this.vertex, this.operation, + this.result); + } public String getObjectKey() { if (this.getVertex() != null) { diff --git a/src/main/java/org/onap/crud/event/envelope/GraphEventHeader.java b/src/main/java/org/onap/crud/event/envelope/GraphEventHeader.java index 4f914cf..81613dd 100644 --- a/src/main/java/org/onap/crud/event/envelope/GraphEventHeader.java +++ b/src/main/java/org/onap/crud/event/envelope/GraphEventHeader.java @@ -173,7 +173,7 @@ public class GraphEventHeader { .append(requestId, rhs.requestId) .append(timestamp, rhs.timestamp) .append(sourceName, rhs.sourceName) - .append(eventType, rhs.sourceName) + .append(eventType, rhs.eventType) .append(validationEntityType, rhs.validationEntityType) .append(validationTopEntityType, rhs.validationTopEntityType) .append(entityLink, rhs.entityLink) diff --git a/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java b/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java index 0c66d81..0a81884 100644 --- a/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java +++ b/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java @@ -24,10 +24,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; - -import javax.ws.rs.core.Response.Status; - import org.onap.crud.entity.Edge; import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; diff --git a/src/main/java/org/onap/crud/service/AaiResourceService.java b/src/main/java/org/onap/crud/service/AaiResourceService.java index c9a5805..afabe7e 100644 --- a/src/main/java/org/onap/crud/service/AaiResourceService.java +++ b/src/main/java/org/onap/crud/service/AaiResourceService.java @@ -26,7 +26,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; - import javax.security.auth.x500.X500Principal; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; @@ -37,20 +36,21 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; +import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.Response.Status; - +import javax.ws.rs.core.UriInfo; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; import org.onap.aai.exceptions.AAIException; import org.onap.aai.serialization.db.EdgeProperty; import org.onap.aai.serialization.db.EdgeRule; import org.onap.aai.serialization.db.EdgeRules; import org.onap.aai.serialization.db.EdgeType; import org.onap.aaiauth.auth.Auth; -import org.onap.aai.cl.api.Logger; -import org.onap.aai.cl.eelf.LoggerFactory; import org.onap.crud.exception.CrudException; import org.onap.crud.logging.CrudServiceMsgs; import org.onap.crud.logging.LoggingUtil; @@ -59,7 +59,6 @@ import org.onap.crud.util.CrudServiceConstants; import org.onap.schema.EdgeRulesLoader; import org.onap.schema.RelationshipSchemaValidator; import org.slf4j.MDC; - import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; @@ -74,78 +73,78 @@ public class AaiResourceService { private String mediaType = MediaType.APPLICATION_JSON; public static final String HTTP_PATCH_METHOD_OVERRIDE = "X-HTTP-Method-Override"; - + private Auth auth; AbstractGraphDataService graphDataService; Gson gson = new Gson(); - + private Logger logger = LoggerFactory.getInstance().getLogger(AaiResourceService.class.getName()); private Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(AaiResourceService.class.getName()); - + public AaiResourceService() {} - + /** * Creates a new instance of the AaiResourceService. - * + * * @param crudGraphDataService - Service used for interacting with the graph. - * + * * @throws Exception */ public AaiResourceService(AbstractGraphDataService graphDataService) throws Exception { this.graphDataService = graphDataService; this.auth = new Auth(CrudServiceConstants.CRD_AUTH_FILE); } - + /** * Perform any one-time initialization required when starting the service. */ public void startup() { - + if(logger.isDebugEnabled()) { logger.debug("AaiResourceService started!"); } } - - + + /** * Creates a new relationship in the graph, automatically populating the edge * properties based on the A&AI edge rules. - * + * * @param content - Json structure describing the relationship to create. * @param type - Relationship type supplied as a URI parameter. * @param uri - Http request uri * @param headers - Http request headers * @param uriInfo - Http URI info field * @param req - Http request structure. - * + * * @return - Standard HTTP response. */ @POST @Path("/relationships/{type}/") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - public Response createRelationship(String content, - @PathParam("type") String type, + public Response createRelationship(String content, + @PathParam("type") String type, @PathParam("uri") @Encoded String uri, - @Context HttpHeaders headers, + @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) { - + LoggingUtil.initMdcContext(req, headers); if(logger.isDebugEnabled()) { logger.debug("Incoming request..." + content); } - + Response response = null; if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - + try { - + // Extract the edge payload from the request. - EdgePayload payload = EdgePayload.fromJson(content); - + EdgePayload payload = EdgePayload.fromJson(content); + // Do some basic validation on the payload. if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); @@ -156,50 +155,50 @@ public class AaiResourceService { if (payload.getType() != null && !payload.getType().equals(type)) { throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST); } - + // Apply the edge rules to our edge. payload = applyEdgeRulesToPayload(payload); - + if(logger.isDebugEnabled()) { logger.debug("Creating AAI edge using version " + EdgeRulesLoader.getLatestSchemaVersion() ); } - + // Now, create our edge in the graph store. - String result = graphDataService.addEdge(EdgeRulesLoader.getLatestSchemaVersion(), type, payload); - response = Response.status(Status.CREATED).entity(result).type(mediaType).build(); - + ImmutablePair result = graphDataService.addEdge(EdgeRulesLoader.getLatestSchemaVersion(), type, payload); + response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build(); + } catch (CrudException e) { response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); - } + } } - + LoggingUtil.logRestRequest(logger, auditLogger, req, response); return response; } - - + + /** * Creates a new relationship in the graph, automatically populating the edge * properties based on the A&AI edge rules. - * + * * @param content - Json structure describing the relationship to create. * @param uri - Http request uri * @param headers - Http request headers * @param uriInfo - Http URI info field * @param req - Http request structure. - * + * * @return - Standard HTTP response. - * + * */ @POST @Path("/relationships/") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - public Response createRelationship(String content, - @PathParam("uri") @Encoded String uri, + public Response createRelationship(String content, + @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, - @Context UriInfo uriInfo, + @Context UriInfo uriInfo, @Context HttpServletRequest req) { LoggingUtil.initMdcContext(req, headers); @@ -210,10 +209,10 @@ public class AaiResourceService { if (validateRequest(req, uri, content, Action.POST, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { try { - + // Extract the edge payload from the request. EdgePayload payload = EdgePayload.fromJson(content); - + // Do some basic validation on the payload. if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); @@ -224,14 +223,14 @@ public class AaiResourceService { if (payload.getType() == null || payload.getType().isEmpty()) { throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST); } - + // Apply the edge rules to our edge. payload = applyEdgeRulesToPayload(payload); - + // Now, create our edge in the graph store. - String result = graphDataService.addEdge(EdgeRulesLoader.getLatestSchemaVersion(), payload.getType(), payload); - response = Response.status(Status.CREATED).entity(result).type(mediaType).build(); - + ImmutablePair result = graphDataService.addEdge(EdgeRulesLoader.getLatestSchemaVersion(), payload.getType(), payload); + response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build(); + } catch (CrudException ce) { response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); } catch (Exception e) { @@ -246,17 +245,17 @@ public class AaiResourceService { return response; } - - + + /** * Upserts a relationship into the graph, automatically populating the edge properties * based on the A&AI edge rules. The behaviour is as follows: *

- *

  • If no relationship with the supplied identifier already exists, then a new relationship + *
  • If no relationship with the supplied identifier already exists, then a new relationship * is created with that id.
    - *
  • If a relationship with the supplied id DOES exist, then it is replaced with the supplied + *
  • If a relationship with the supplied id DOES exist, then it is replaced with the supplied * content. - * + * * @param content - Json structure describing the relationship to create. * @param type - Relationship type supplied as a URI parameter. * @param id - Edge identifier. @@ -264,19 +263,19 @@ public class AaiResourceService { * @param headers - Http request headers * @param uriInfo - Http URI info field * @param req - Http request structure. - * + * * @return - Standard HTTP response. */ @PUT @Path("/relationships/{type}/{id}") @Consumes({MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_JSON}) - public Response upsertEdge(String content, - @PathParam("type") String type, + public Response upsertEdge(String content, + @PathParam("type") String type, @PathParam("id") String id, - @PathParam("uri") @Encoded String uri, + @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, - @Context UriInfo uriInfo, + @Context UriInfo uriInfo, @Context HttpServletRequest req) { LoggingUtil.initMdcContext(req, headers); @@ -284,12 +283,12 @@ public class AaiResourceService { Response response = null; if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME)) { - + try { - + // Extract the edge payload from the request. EdgePayload payload = EdgePayload.fromJson(content); - + // Do some basic validation on the payload. if (payload.getProperties() == null || payload.getProperties().isJsonNull()) { throw new CrudException("Invalid request Payload", Status.BAD_REQUEST); @@ -297,47 +296,45 @@ public class AaiResourceService { if (payload.getId() != null && !payload.getId().equals(id)) { throw new CrudException("ID Mismatch", Status.BAD_REQUEST); } - + // Apply the edge rules to our edge. payload = applyEdgeRulesToPayload(payload); - - String result; + ImmutablePair result; if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) { result = graphDataService.patchEdge(EdgeRulesLoader.getLatestSchemaVersion(), id, type, payload); + response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build(); } else { - result = graphDataService.updateEdge(EdgeRulesLoader.getLatestSchemaVersion(), id, type, payload); + response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build(); } - response = Response.status(Status.OK).entity(result).type(mediaType).build(); - } catch (CrudException ce) { response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); } catch (Exception e) { response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); } - + } else { - + response = Response.status(Status.FORBIDDEN).entity(content) .type(MediaType.APPLICATION_JSON).build(); } - + LoggingUtil.logRestRequest(logger, auditLogger, req, response); return response; } - - + + /** - * Retrieves the properties defined in the edge rules for a relationship between the + * Retrieves the properties defined in the edge rules for a relationship between the * supplied vertex types. - * + * * @param sourceVertexType - Type of source vertex for the relationship. * @param targetVertexType - Type of target vertex for the relationship. - * + * * @return - The defined properties for the relationship type. - * + * * @throws CrudException */ private Map getEdgeRuleProperties(String sourceVertexType, String targetVertexType) throws CrudException { @@ -345,119 +342,119 @@ public class AaiResourceService { if(logger.isDebugEnabled()) { logger.debug("Lookup db edge rules for " + sourceVertexType + " -> " + targetVertexType); } - + EdgeRules rules = EdgeRules.getInstance(); EdgeRule rule; try { - + if(logger.isDebugEnabled()) { logger.debug("Lookup by edge type TREE"); } - + // We have no way of knowing in advance whether our relationship is considered to // be a tree or cousing relationship, so try looking it up as a tree type first. rule = rules.getEdgeRule(EdgeType.TREE, sourceVertexType, targetVertexType); - + } catch (AAIException e) { try { - + if(logger.isDebugEnabled()) { logger.debug("Lookup by edge type COUSIN"); } - + // If we are here, then our lookup by 'tree' type failed, so try looking it up // as a 'cousin' relationship. rule = rules.getEdgeRule(EdgeType.COUSIN, sourceVertexType, targetVertexType); - + } catch (AAIException e1) { - + // If we're here then we failed to find edge rules for this relationship. Time to // give up... throw new CrudException("No edge rules for " + sourceVertexType + " -> " + targetVertexType, Status.NOT_FOUND); } } catch (Exception e) { - - throw new CrudException("General failure getting edge rule properties - " + + + throw new CrudException("General failure getting edge rule properties - " + e.getMessage(), Status.INTERNAL_SERVER_ERROR); } - + return rule.getEdgeProperties(); } - - + + /** * This method takes an inbound edge request payload, looks up the edge rules for the * sort of relationship defined in the payload, and automatically applies the defined * edge properties to it. - * + * * @param payload - The original edge request payload - * + * * @return - An updated edge request payload, with the properties defined in the edge * rules automatically populated. - * + * * @throws CrudException */ public EdgePayload applyEdgeRulesToPayload(EdgePayload payload) throws CrudException { - + // Extract the types for both the source and target vertices. String srcType = RelationshipSchemaValidator.vertexTypeFromUri(payload.getSource()); String tgtType = RelationshipSchemaValidator.vertexTypeFromUri(payload.getTarget()); // Now, get the default properties for this edge based on the edge rules definition... Map props = getEdgeRuleProperties(srcType, tgtType); - + // ...and merge them with any custom properties provided in the request. JsonElement mergedProperties = mergeProperties(payload.getProperties(), props); payload.setProperties(mergedProperties); - - + + if(logger.isDebugEnabled()) { logger.debug("Edge properties after applying rules for '" + srcType + " -> " + tgtType + "': " + mergedProperties); } - + return payload; } - - + + /** * Given a set of edge properties extracted from an edge request payload and a set of properties * taken from the db edge rules, this method merges them into one set of properties. *

    * If the client has attempted to override the defined value for a property in the db edge rules * then the request will be rejected as invalid. - * + * * @param propertiesFromRequest - Set of properties from the edge request. * @param propertyDefaults - Set of properties from the db edge rules. - * + * * @return - A merged set of properties. - * + * * @throws CrudException */ public JsonElement mergeProperties(JsonElement propertiesFromRequest, Map propertyDefaults) throws CrudException { - + // Convert the properties from the edge payload into something we can // manipulate. Set> properties = new HashSet>(); properties.addAll(propertiesFromRequest.getAsJsonObject().entrySet()); - + Set propertyKeys = new HashSet(); for(Map.Entry property : properties) { propertyKeys.add(property.getKey()); } - + // Now, merge in the properties specified in the Db Edge Rules. for(EdgeProperty defProperty : propertyDefaults.keySet()) { - + // If the edge rules property was explicitly specified by the // client then we will reject the request... if(!propertyKeys.contains(defProperty.toString())) { properties.add(new AbstractMap.SimpleEntry(defProperty.toString(), - (JsonElement)(new JsonPrimitive(propertyDefaults.get(defProperty))))); - + (new JsonPrimitive(propertyDefaults.get(defProperty))))); + } else { - throw new CrudException("Property " + defProperty + " defined in db edge rules can not be overriden by the client.", + throw new CrudException("Property " + defProperty + " defined in db edge rules can not be overriden by the client.", Status.BAD_REQUEST); - } + } } Object[] propArray = properties.toArray(); @@ -465,7 +462,7 @@ public class AaiResourceService { sb.append("{"); boolean first=true; for(int i=0; i entry = (Entry) propArray[i]; if(!first) { sb.append(","); @@ -474,7 +471,7 @@ public class AaiResourceService { first=false; } sb.append("}"); - + // We're done. Return the result as a JsonElement. return gson.fromJson(sb.toString(), JsonElement.class); } @@ -482,45 +479,45 @@ public class AaiResourceService { /** * Invokes authentication validation on an incoming HTTP request. - * + * * @param req - The HTTP request. * @param uri - HTTP URI * @param content - Payload of the HTTP request. * @param action - What HTTP action is being performed (GET/PUT/POST/PATCH/DELETE) * @param authPolicyFunctionName - Policy function being invoked. - * + * * @return true - if the request passes validation, * false - otherwise. */ - protected boolean validateRequest(HttpServletRequest req, - String uri, + protected boolean validateRequest(HttpServletRequest req, + String uri, String content, - Action action, + Action action, String authPolicyFunctionName) { try { String cipherSuite = (String) req.getAttribute("javax.servlet.request.cipher_suite"); String authUser = null; if (cipherSuite != null) { - + X509Certificate[] certChain = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate"); X509Certificate clientCert = certChain[0]; X500Principal subjectDn = clientCert.getSubjectX500Principal(); authUser = subjectDn.toString(); } - + return this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName); - + } catch (Exception e) { logResult(action, uri, e); return false; } } - + protected void logResult(Action op, String uri, Exception e) { - logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, - op.toString(), - uri, + logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, + op.toString(), + uri, e.getStackTrace().toString()); // Clear the MDC context so that no other transaction inadvertently diff --git a/src/main/java/org/onap/crud/service/AbstractGraphDataService.java b/src/main/java/org/onap/crud/service/AbstractGraphDataService.java index 9c7e0d4..7c1168e 100644 --- a/src/main/java/org/onap/crud/service/AbstractGraphDataService.java +++ b/src/main/java/org/onap/crud/service/AbstractGraphDataService.java @@ -25,11 +25,14 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; - +import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response.Status; - +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.onap.aai.restclient.client.OperationResult; import org.onap.crud.dao.GraphDao; +import org.onap.crud.dao.champ.ChampEdgeSerializer; +import org.onap.crud.dao.champ.ChampVertexSerializer; import org.onap.crud.entity.Edge; import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; @@ -37,50 +40,65 @@ import org.onap.crud.parser.CrudResponseBuilder; import org.onap.crud.util.CrudServiceUtil; import org.onap.schema.OxmModelValidator; import org.onap.schema.RelationshipSchemaValidator; - +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; +import com.google.gson.reflect.TypeToken; +import net.dongliu.gson.GsonJava8TypeAdapterFactory; public abstract class AbstractGraphDataService { protected GraphDao daoForGet; protected GraphDao dao; - + public AbstractGraphDataService() throws CrudException { CrudServiceUtil.loadModels(); } - public String getEdge(String version, String id, String type, Map queryParams) throws CrudException { + public ImmutablePair getEdge(String version, String id, String type, Map queryParams) throws CrudException { RelationshipSchemaValidator.validateType(version, type); - Edge edge = daoForGet.getEdge(id, type, queryParams); - - return CrudResponseBuilder.buildGetEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, edge), version); + OperationResult operationResult = daoForGet.getEdge(id, type, queryParams); + EntityTag entityTag = CrudServiceUtil.getETagFromHeader(operationResult.getHeaders()); + Edge edge = Edge.fromJson(operationResult.getResult()); + return new ImmutablePair<>(entityTag, CrudResponseBuilder.buildGetEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, edge), version)); } - - public String getEdges(String version, String type, Map filter) throws CrudException { + + public ImmutablePair getEdges(String version, String type, Map filter) throws CrudException { + Gson champGson = new GsonBuilder() + .registerTypeAdapterFactory(new GsonJava8TypeAdapterFactory()) + .registerTypeAdapter(Vertex.class, new ChampVertexSerializer()) + .registerTypeAdapter(Edge.class, new ChampEdgeSerializer()).create(); RelationshipSchemaValidator.validateType(version, type); - List items = daoForGet.getEdges(type, RelationshipSchemaValidator.resolveCollectionfilter(version, type, filter)); - return CrudResponseBuilder.buildGetEdgesResponse(items, version); + OperationResult operationResult = daoForGet.getEdges(type, RelationshipSchemaValidator.resolveCollectionfilter(version, type, filter)); + List items = champGson.fromJson(operationResult.getResult(), new TypeToken>() { + }.getType()); + EntityTag entityTag = CrudServiceUtil.getETagFromHeader(operationResult.getHeaders()); + return new ImmutablePair<>(entityTag, CrudResponseBuilder.buildGetEdgesResponse(items, version)); } - - public String getVertex(String version, String id, String type, Map queryParams) throws CrudException { + + public ImmutablePair getVertex(String version, String id, String type, Map queryParams) throws CrudException { type = OxmModelValidator.resolveCollectionType(version, type); - Vertex vertex = daoForGet.getVertex(id, type, version, queryParams); + OperationResult vertexOpResult = daoForGet.getVertex(id, type, version, queryParams); + Vertex vertex = Vertex.fromJson(vertexOpResult.getResult(), version); List edges = daoForGet.getVertexEdges(id, queryParams); - return CrudResponseBuilder.buildGetVertexResponse(OxmModelValidator.validateOutgoingPayload(version, vertex), edges, - version); + EntityTag entityTag = CrudServiceUtil.getETagFromHeader(vertexOpResult.getHeaders()); + return new ImmutablePair<>(entityTag, CrudResponseBuilder.buildGetVertexResponse(OxmModelValidator.validateOutgoingPayload(version, vertex), edges, + version)); } - public String getVertices(String version, String type, Map filter, HashSet properties) throws CrudException { + public ImmutablePair getVertices(String version, String type, Map filter, HashSet properties) throws CrudException { type = OxmModelValidator.resolveCollectionType(version, type); - List items = daoForGet.getVertices(type, OxmModelValidator.resolveCollectionfilter(version, type, filter), properties, version); - return CrudResponseBuilder.buildGetVerticesResponse(items, version); + OperationResult operationResult = daoForGet.getVertices(type, OxmModelValidator.resolveCollectionfilter(version, type, filter), properties, version); + List vertices = Vertex.collectionFromJson(operationResult.getResult(), version); + EntityTag entityTag = CrudServiceUtil.getETagFromHeader(operationResult.getHeaders()); + return new ImmutablePair<>(entityTag, CrudResponseBuilder.buildGetVerticesResponse(vertices, version)); } - + public String addBulk(String version, BulkPayload payload, HttpHeaders headers) throws CrudException { - HashMap vertices = new HashMap(); - HashMap edges = new HashMap(); - - String txId = dao.openTransaction(); - + HashMap vertices = new HashMap<>(); + HashMap edges = new HashMap<>(); + + String txId = dao.openTransaction(); + try { // Step 1. Handle edge deletes (must happen before vertex deletes) for (JsonElement v : payload.getRelationships()) { @@ -98,8 +116,8 @@ public abstract class AbstractGraphDataService { RelationshipSchemaValidator.validateType(version, edgePayload.getType()); deleteBulkEdge(edgePayload.getId(), version, edgePayload.getType(), txId); } - } - + } + // Step 2: Handle vertex deletes for (JsonElement v : payload.getObjects()) { List> entries = new ArrayList>( @@ -118,7 +136,7 @@ public abstract class AbstractGraphDataService { deleteBulkVertex(vertexPayload.getId(), version, type, txId); } } - + // Step 3: Handle vertex add/modify (must happen before edge adds) for (JsonElement v : payload.getObjects()) { List> entries = new ArrayList>( @@ -130,21 +148,21 @@ public abstract class AbstractGraphDataService { Map.Entry opr = entries.get(0); Map.Entry item = entries.get(1); VertexPayload vertexPayload = VertexPayload.fromJson(item.getValue().getAsJsonObject().toString()); - + // Add vertex if (opr.getValue().getAsString().equalsIgnoreCase("add")) { - vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(), - headers, true)); + vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(), + headers, true)); Vertex validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(null, version, vertexPayload.getType(), vertexPayload.getProperties()); Vertex persistedVertex = addBulkVertex(validatedVertex, version, txId); Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex); vertices.put(item.getKey(), outgoingVertex); } - - // Update vertex + + // Update vertex else if (opr.getValue().getAsString().equalsIgnoreCase("modify")) { - vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(), + vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(), headers, false)); Vertex validatedVertex = OxmModelValidator.validateIncomingUpsertPayload(vertexPayload.getId(), version, vertexPayload.getType(), vertexPayload.getProperties()); @@ -152,18 +170,19 @@ public abstract class AbstractGraphDataService { Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex); vertices.put(item.getKey(), outgoingVertex); } - - // Patch vertex + + // Patch vertex else if (opr.getValue().getAsString().equalsIgnoreCase("patch")) { if ( (vertexPayload.getId() == null) || (vertexPayload.getType() == null) ) { throw new CrudException("id and type must be specified for patch request", Status.BAD_REQUEST); } - - vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(), + + vertexPayload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(vertexPayload.getProperties(), headers, false)); - - Vertex existingVertex = dao.getVertex(vertexPayload.getId(), OxmModelValidator.resolveCollectionType(version, vertexPayload.getType()), version, new HashMap()); - Vertex validatedVertex = OxmModelValidator.validateIncomingPatchPayload(vertexPayload.getId(), + + OperationResult existingVertexOpResult = dao.getVertex(vertexPayload.getId(), OxmModelValidator.resolveCollectionType(version, vertexPayload.getType()), version, new HashMap()); + Vertex existingVertex = Vertex.fromJson(existingVertexOpResult.getResult(), version); + Vertex validatedVertex = OxmModelValidator.validateIncomingPatchPayload(vertexPayload.getId(), version, vertexPayload.getType(), vertexPayload.getProperties(), existingVertex); Vertex persistedVertex = updateBulkVertex(validatedVertex, vertexPayload.getId(), version, txId); Vertex outgoingVertex = OxmModelValidator.validateOutgoingPayload(version, persistedVertex); @@ -171,7 +190,7 @@ public abstract class AbstractGraphDataService { } } - // Step 4: Handle edge add/modify + // Step 4: Handle edge add/modify for (JsonElement v : payload.getRelationships()) { List> entries = new ArrayList>( v.getAsJsonObject().entrySet()); @@ -185,7 +204,7 @@ public abstract class AbstractGraphDataService { // Add/Update edge if (opr.getValue().getAsString().equalsIgnoreCase("add") - || opr.getValue().getAsString().equalsIgnoreCase("modify") + || opr.getValue().getAsString().equalsIgnoreCase("modify") || opr.getValue().getAsString().equalsIgnoreCase("patch")) { Edge validatedEdge; Edge persistedEdge; @@ -224,13 +243,13 @@ public abstract class AbstractGraphDataService { Edge patchedEdge = RelationshipSchemaValidator.validateIncomingPatchPayload(existingEdge, version, edgePayload); persistedEdge = updateBulkEdge(patchedEdge, version, txId); } - + Edge outgoingEdge = RelationshipSchemaValidator.validateOutgoingPayload(version, persistedEdge); edges.put(item.getKey(), outgoingEdge); - } - } - + } + } + // commit transaction dao.commitTransaction(txId); } catch (CrudException ex) { @@ -244,26 +263,32 @@ public abstract class AbstractGraphDataService { dao.rollbackTransaction(txId); } } - + return CrudResponseBuilder.buildUpsertBulkResponse(vertices, edges, version, payload); } - public abstract String addVertex(String version, String type, VertexPayload payload) throws CrudException; - public abstract String updateVertex(String version, String id, String type, VertexPayload payload) throws CrudException; - public abstract String patchVertex(String version, String id, String type, VertexPayload payload) throws CrudException; + public abstract ImmutablePair addVertex(String version, String type, VertexPayload payload) + throws CrudException; + public abstract ImmutablePair updateVertex(String version, String id, String type, + VertexPayload payload) throws CrudException; + public abstract ImmutablePair patchVertex(String version, String id, String type, + VertexPayload payload) throws CrudException; public abstract String deleteVertex(String version, String id, String type) throws CrudException; - public abstract String addEdge(String version, String type, EdgePayload payload) throws CrudException; + public abstract ImmutablePair addEdge(String version, String type, EdgePayload payload) + throws CrudException; public abstract String deleteEdge(String version, String id, String type) throws CrudException; - public abstract String updateEdge(String version, String id, String type, EdgePayload payload) throws CrudException; - public abstract String patchEdge(String version, String id, String type, EdgePayload payload) throws CrudException; - + public abstract ImmutablePair updateEdge(String version, String id, String type, + EdgePayload payload) throws CrudException; + public abstract ImmutablePair patchEdge(String version, String id, String type, + EdgePayload payload) throws CrudException; + protected abstract Vertex addBulkVertex(Vertex vertex, String version, String dbTransId) throws CrudException; protected abstract Vertex updateBulkVertex(Vertex vertex, String id, String version, String dbTransId) throws CrudException; protected abstract void deleteBulkVertex(String id, String version, String type, String dbTransId) throws CrudException; - + protected abstract Edge addBulkEdge(Edge edge, String version, String dbTransId) throws CrudException; protected abstract Edge updateBulkEdge(Edge edge, String version, String dbTransId) throws CrudException; protected abstract void deleteBulkEdge(String id, String version, String type, String dbTransId) throws CrudException; - + } diff --git a/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java b/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java index 5d37acb..6b447a1 100644 --- a/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java +++ b/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java @@ -20,6 +20,8 @@ */ package org.onap.crud.service; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; import java.text.SimpleDateFormat; import java.util.HashMap; import java.util.Timer; @@ -32,7 +34,9 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import javax.annotation.PreDestroy; +import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.Response.Status; +import org.apache.commons.lang3.tuple.ImmutablePair; import org.onap.aai.cl.api.LogFields; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; @@ -40,6 +44,7 @@ import org.onap.aai.cl.mdc.MdcContext; import org.onap.aai.cl.mdc.MdcOverride; import org.onap.aai.event.api.EventConsumer; import org.onap.aai.event.api.EventPublisher; +import org.onap.aai.restclient.client.OperationResult; import org.onap.crud.dao.GraphDao; import org.onap.crud.entity.Edge; import org.onap.crud.entity.Vertex; @@ -53,6 +58,7 @@ import org.onap.crud.exception.CrudException; import org.onap.crud.logging.CrudServiceMsgs; import org.onap.crud.util.CrudProperties; import org.onap.crud.util.CrudServiceConstants; +import org.onap.crud.util.etag.EtagGenerator; import org.onap.schema.OxmModelValidator; import org.onap.schema.RelationshipSchemaValidator; @@ -71,6 +77,7 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService { private static Logger metricsLogger = LoggerFactory.getInstance().getMetricsLogger(CrudAsyncGraphDataService.class.getName()); private static LogFields okFields = new LogFields(); + private EtagGenerator etagGenerator; static { okFields.setField(Status.OK, Status.OK.toString()); @@ -83,12 +90,12 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService { } public CrudAsyncGraphDataService(GraphDao dao, EventPublisher asyncRequestPublisher, - EventConsumer asyncResponseConsumer) throws CrudException { + EventConsumer asyncResponseConsumer) throws CrudException, NoSuchAlgorithmException { this(dao, dao, asyncRequestPublisher, asyncResponseConsumer); } public CrudAsyncGraphDataService(GraphDao dao, GraphDao daoForGet, EventPublisher asyncRequestPublisher, - EventConsumer asyncResponseConsumer) throws CrudException { + EventConsumer asyncResponseConsumer) throws CrudException, NoSuchAlgorithmException { super(); this.dao = dao; @@ -116,6 +123,7 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService { timer.schedule(crudAsyncResponseConsumer, responsePollInterval, responsePollInterval); this.asyncRequestPublisher = asyncRequestPublisher; + this.etagGenerator = new EtagGenerator(); logger.info(CrudServiceMsgs.ASYNC_DATA_SERVICE_INFO, "CrudAsyncGraphDataService initialized SUCCESSFULLY!"); } @@ -199,7 +207,8 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService { } @Override - public String addVertex(String version, String type, VertexPayload payload) throws CrudException { + public ImmutablePair addVertex(String version, String type, VertexPayload payload) + throws CrudException { // Validate the incoming payload Vertex vertex = OxmModelValidator.validateIncomingUpsertPayload(null, version, type, payload.getProperties()); vertex.getProperties().put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); @@ -208,41 +217,81 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService { .vertex(GraphEventVertex.fromVertex(vertex, version)).build(); GraphEventEnvelope response = sendAndWait(event); - return responseHandler.handleVertexResponse(version, event, response); + + EntityTag entityTag; + try { + entityTag = new EntityTag(etagGenerator.computeHashForVertex(response.getBody().getVertex())); + } catch (IOException e) { + throw new CrudException(e); + } + String responsePayload = responseHandler.handleVertexResponse(version, event, response); + + return new ImmutablePair(entityTag, responsePayload); } @Override - public String addEdge(String version, String type, EdgePayload payload) throws CrudException { + public ImmutablePair addEdge(String version, String type, EdgePayload payload) + throws CrudException { Edge edge = RelationshipSchemaValidator.validateIncomingAddPayload(version, type, payload); // Create graph request event GraphEvent event = GraphEvent.builder(GraphEventOperation.CREATE).edge(GraphEventEdge.fromEdge(edge, version)).build(); GraphEventEnvelope response = sendAndWait(event); - return responseHandler.handleEdgeResponse(version, event, response); + + EntityTag entityTag; + try { + entityTag = new EntityTag(etagGenerator.computeHashForEdge(response.getBody().getEdge())); + } catch (IOException e) { + throw new CrudException(e); + } + String responsePayload = responseHandler.handleEdgeResponse(version, event, response); + + return new ImmutablePair(entityTag, responsePayload); } @Override - public String updateVertex(String version, String id, String type, VertexPayload payload) throws CrudException { + public ImmutablePair updateVertex(String version, String id, String type, VertexPayload payload) + throws CrudException { Vertex vertex = OxmModelValidator.validateIncomingUpsertPayload(id, version, type, payload.getProperties()); GraphEvent event = GraphEvent.builder(GraphEventOperation.UPDATE) .vertex(GraphEventVertex.fromVertex(vertex, version)).build(); GraphEventEnvelope response = sendAndWait(event); - return responseHandler.handleVertexResponse(version, event, response); + + EntityTag entityTag; + try { + entityTag = new EntityTag(etagGenerator.computeHashForVertex(response.getBody().getVertex())); + } catch (IOException e) { + throw new CrudException(e); + } + String responsePayload = responseHandler.handleVertexResponse(version, event, response); + + return new ImmutablePair(entityTag, responsePayload); } @Override - public String patchVertex(String version, String id, String type, VertexPayload payload) throws CrudException { - Vertex existingVertex = dao.getVertex(id, OxmModelValidator.resolveCollectionType(version, type), version, + public ImmutablePair patchVertex(String version, String id, String type, VertexPayload payload) + throws CrudException { + OperationResult existingVertexOpResult = dao.getVertex(id, OxmModelValidator.resolveCollectionType(version, type), version, new HashMap()); + Vertex existingVertex = Vertex.fromJson(existingVertexOpResult.getResult(), version); Vertex patchedVertex = OxmModelValidator.validateIncomingPatchPayload(id, version, type, payload.getProperties(), existingVertex); GraphEvent event = GraphEvent.builder(GraphEventOperation.UPDATE) .vertex(GraphEventVertex.fromVertex(patchedVertex, version)).build(); GraphEventEnvelope response = sendAndWait(event); - return responseHandler.handleVertexResponse(version, event, response); + + EntityTag entityTag; + try { + entityTag = new EntityTag(etagGenerator.computeHashForVertex(response.getBody().getVertex())); + } catch (IOException e) { + throw new CrudException(e); + } + String responsePayload = responseHandler.handleVertexResponse(version, event, response); + + return new ImmutablePair(entityTag, responsePayload); } @Override @@ -266,25 +315,47 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService { } @Override - public String updateEdge(String version, String id, String type, EdgePayload payload) throws CrudException { - Edge edge = dao.getEdge(id, type, new HashMap()); + public ImmutablePair updateEdge(String version, String id, String type, EdgePayload payload) + throws CrudException { + OperationResult operationResult = dao.getEdge(id, type, new HashMap()); + Edge edge = Edge.fromJson(operationResult.getResult()); Edge validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, payload); GraphEvent event = GraphEvent.builder(GraphEventOperation.UPDATE) .edge(GraphEventEdge.fromEdge(validatedEdge, version)).build(); GraphEventEnvelope response = sendAndWait(event); - return responseHandler.handleEdgeResponse(version, event, response); + + EntityTag entityTag; + try { + entityTag = new EntityTag(etagGenerator.computeHashForEdge(response.getBody().getEdge())); + } catch (IOException e) { + throw new CrudException(e); + } + String responsePayload = responseHandler.handleEdgeResponse(version, event, response); + + return new ImmutablePair(entityTag, responsePayload); } @Override - public String patchEdge(String version, String id, String type, EdgePayload payload) throws CrudException { - Edge edge = dao.getEdge(id, type, new HashMap()); + public ImmutablePair patchEdge(String version, String id, String type, EdgePayload payload) + throws CrudException { + OperationResult operationResult = dao.getEdge(id, type, new HashMap()); + Edge edge = Edge.fromJson(operationResult.getResult()); Edge patchedEdge = RelationshipSchemaValidator.validateIncomingPatchPayload(edge, version, payload); GraphEvent event = GraphEvent.builder(GraphEventOperation.UPDATE) .edge(GraphEventEdge.fromEdge(patchedEdge, version)).build(); GraphEventEnvelope response = sendAndWait(event); - return responseHandler.handleEdgeResponse(version, event, response); + + EntityTag entityTag; + try { + entityTag = new EntityTag(etagGenerator.computeHashForEdge(response.getBody().getEdge())); + } catch (IOException e) { + throw new CrudException(e); + } + String responsePayload = responseHandler.handleEdgeResponse(version, event, response); + + return new ImmutablePair(entityTag, responsePayload); } @PreDestroy @@ -349,4 +420,4 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService { responseHandler.handleBulkEventResponse(event, response); return response.getBody(); } -} +} \ No newline at end of file diff --git a/src/main/java/org/onap/crud/service/CrudGraphDataService.java b/src/main/java/org/onap/crud/service/CrudGraphDataService.java index 5a2710d..5b1c2dd 100644 --- a/src/main/java/org/onap/crud/service/CrudGraphDataService.java +++ b/src/main/java/org/onap/crud/service/CrudGraphDataService.java @@ -22,20 +22,22 @@ package org.onap.crud.service; import java.util.HashMap; - +import javax.ws.rs.core.EntityTag; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.onap.aai.restclient.client.OperationResult; import org.onap.crud.dao.GraphDao; import org.onap.crud.entity.Edge; - import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; import org.onap.crud.parser.CrudResponseBuilder; +import org.onap.crud.util.CrudServiceUtil; import org.onap.schema.OxmModelValidator; import org.onap.schema.RelationshipSchemaValidator; public class CrudGraphDataService extends AbstractGraphDataService { - - + + public CrudGraphDataService(GraphDao dao) throws CrudException { super(); this.dao = dao; @@ -48,103 +50,146 @@ public class CrudGraphDataService extends AbstractGraphDataService { this.daoForGet = daoForGet; } - public String addVertex(String version, String type, VertexPayload payload) throws CrudException { + @Override + public ImmutablePair addVertex(String version, String type, VertexPayload payload) + throws CrudException { Vertex vertex = OxmModelValidator.validateIncomingUpsertPayload(null, version, type, payload.getProperties()); return addVertex(version, vertex); } - private String addVertex(String version, Vertex vertex) throws CrudException { - Vertex addedVertex = dao.addVertex(vertex.getType(), vertex.getProperties(), version); - return CrudResponseBuilder + private ImmutablePair addVertex(String version, Vertex vertex) throws CrudException { + OperationResult addedVertexResult = dao.addVertex(vertex.getType(), vertex.getProperties(), version); + EntityTag entityTag = CrudServiceUtil.getETagFromHeader(addedVertexResult.getHeaders()); + Vertex addedVertex = Vertex.fromJson(addedVertexResult.getResult(), version); + String payload = CrudResponseBuilder .buildUpsertVertexResponse(OxmModelValidator.validateOutgoingPayload(version, addedVertex), version); + + return new ImmutablePair(entityTag, payload); } - public String addEdge(String version, String type, EdgePayload payload) throws CrudException { + @Override + public ImmutablePair addEdge(String version, String type, EdgePayload payload) + throws CrudException { Edge edge = RelationshipSchemaValidator.validateIncomingAddPayload(version, type, payload); return addEdge(version, edge); } - private String addEdge(String version, Edge edge) throws CrudException { - Edge addedEdge = dao.addEdge(edge.getType(), edge.getSource(), edge.getTarget(), edge.getProperties(), version); - return CrudResponseBuilder - .buildUpsertEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, addedEdge), version); + private ImmutablePair addEdge(String version, Edge edge) throws CrudException { + OperationResult addedEdgeResult = dao.addEdge(edge.getType(), edge.getSource(), edge.getTarget(), edge.getProperties(), version); + EntityTag entityTag = CrudServiceUtil.getETagFromHeader(addedEdgeResult.getHeaders()); + Edge addedEdge = Edge.fromJson(addedEdgeResult.getResult()); + String payload = CrudResponseBuilder + .buildUpsertEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, addedEdge), version); + + return new ImmutablePair(entityTag, payload); } - public String updateVertex(String version, String id, String type, VertexPayload payload) throws CrudException { + @Override + public ImmutablePair updateVertex(String version, String id, String type, VertexPayload payload) + throws CrudException { Vertex vertex = OxmModelValidator.validateIncomingUpsertPayload(id, version, type, payload.getProperties()); return updateVertex(version, vertex); + } + private ImmutablePair updateVertex(String version, Vertex vertex) throws CrudException { + OperationResult updatedVertexResult = dao.updateVertex(vertex.getId().get(), vertex.getType(), vertex.getProperties(), version); + String payload = getUpdatedVertexPayload(version, updatedVertexResult); + EntityTag entityTag = CrudServiceUtil.getETagFromHeader(updatedVertexResult.getHeaders()); + + return new ImmutablePair(entityTag, payload); } - private String updateVertex(String version, Vertex vertex) throws CrudException { - Vertex updatedVertex = dao.updateVertex(vertex.getId().get(), vertex.getType(), vertex.getProperties(), version); + private String getUpdatedVertexPayload(String version, OperationResult updatedVertexResult) throws CrudException { + Vertex updatedVertex = Vertex.fromJson(updatedVertexResult.getResult(), version); + return CrudResponseBuilder - .buildUpsertVertexResponse(OxmModelValidator.validateOutgoingPayload(version, updatedVertex), version); + .buildUpsertVertexResponse(OxmModelValidator.validateOutgoingPayload(version, updatedVertex), version); } - public String patchVertex(String version, String id, String type, VertexPayload payload) throws CrudException { - Vertex existingVertex = dao.getVertex(id, OxmModelValidator.resolveCollectionType(version, type), version, new HashMap()); + @Override + public ImmutablePair patchVertex(String version, String id, String type, VertexPayload payload) + throws CrudException { + OperationResult existingVertexOpResult = dao.getVertex(id, OxmModelValidator.resolveCollectionType(version, type), version, new HashMap()); + Vertex existingVertex = Vertex.fromJson(existingVertexOpResult.getResult(), version); Vertex vertex = OxmModelValidator.validateIncomingPatchPayload(id, version, type, payload.getProperties(), - existingVertex); + existingVertex); return updateVertex(version, vertex); } + @Override public String deleteVertex(String version, String id, String type) throws CrudException { type = OxmModelValidator.resolveCollectionType(version, type); dao.deleteVertex(id, type); return ""; } + @Override public String deleteEdge(String version, String id, String type) throws CrudException { RelationshipSchemaValidator.validateType(version, type); dao.deleteEdge(id, type); return ""; } - public String updateEdge(String version, String id, String type, EdgePayload payload) throws CrudException { - Edge edge = dao.getEdge(id, type, new HashMap()); - Edge validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, payload); + @Override + public ImmutablePair updateEdge(String version, String id, String type, EdgePayload payload) + throws CrudException { + Edge validatedEdge = getValidatedEdge(version, id, type, payload); return updateEdge(version, validatedEdge); } - private String updateEdge(String version, Edge edge) throws CrudException { - Edge updatedEdge = dao.updateEdge(edge); + private ImmutablePair updateEdge(String version, Edge edge) throws CrudException { + OperationResult updatedEdgeResult = dao.updateEdge(edge); + String payload = getUpdatedEdgePayload(version, updatedEdgeResult); + EntityTag entityTag = CrudServiceUtil.getETagFromHeader(updatedEdgeResult.getHeaders()); + + return new ImmutablePair(entityTag, payload); + } + + private String getUpdatedEdgePayload(String version, OperationResult updatedEdgeResult) throws CrudException { + Edge updatedEdge = Edge.fromJson(updatedEdgeResult.getResult()); + return CrudResponseBuilder - .buildUpsertEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, updatedEdge), version); + .buildUpsertEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, updatedEdge), version); + } + + private Edge getValidatedEdge(String version, String id, String type, EdgePayload payload) throws CrudException { + OperationResult operationResult = dao.getEdge(id, type, new HashMap()); + return RelationshipSchemaValidator.validateIncomingUpdatePayload(Edge.fromJson(operationResult.getResult()), version, payload); } - - public String patchEdge(String version, String id, String type, EdgePayload payload) throws CrudException { - Edge edge = dao.getEdge(id, type, new HashMap()); - Edge patchedEdge = RelationshipSchemaValidator.validateIncomingPatchPayload(edge, version, payload); - return updateEdge(version, patchedEdge); + @Override + public ImmutablePair patchEdge(String version, String id, String type, EdgePayload payload) + throws CrudException { + OperationResult operationResult = dao.getEdge(id, type, new HashMap()); + Edge patchedEdge = RelationshipSchemaValidator.validateIncomingPatchPayload(Edge.fromJson(operationResult.getResult()), version, payload); + return updateEdge(version, patchedEdge); } @Override protected Vertex addBulkVertex(Vertex vertex, String version, String dbTransId) throws CrudException { return dao.addVertex(vertex.getType(), vertex.getProperties(), version, dbTransId); } - + @Override protected Vertex updateBulkVertex(Vertex vertex, String id, String version, String dbTransId) throws CrudException { return dao.updateVertex(id, vertex.getType(), vertex.getProperties(), version, dbTransId); } - + @Override protected void deleteBulkVertex(String id, String version, String type, String dbTransId) throws CrudException { dao.deleteVertex(id, type, dbTransId); } - + @Override protected Edge addBulkEdge(Edge edge, String version, String dbTransId) throws CrudException { return dao.addEdge(edge.getType(), edge.getSource(), edge.getTarget(), edge.getProperties(), version, dbTransId); } - + @Override protected Edge updateBulkEdge(Edge edge, String version, String dbTransId) throws CrudException { return dao.updateEdge(edge, dbTransId); } - + @Override protected void deleteBulkEdge(String id, String version, String type, String dbTransId) throws CrudException { dao.deleteEdge(id, type, dbTransId); diff --git a/src/main/java/org/onap/crud/service/CrudRestService.java b/src/main/java/org/onap/crud/service/CrudRestService.java index 2cbb87c..583fee6 100644 --- a/src/main/java/org/onap/crud/service/CrudRestService.java +++ b/src/main/java/org/onap/crud/service/CrudRestService.java @@ -38,11 +38,13 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; +import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriInfo; +import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.cxf.jaxrs.ext.PATCH; import org.onap.aai.cl.api.Logger; import org.onap.aai.cl.eelf.LoggerFactory; @@ -102,8 +104,8 @@ public class CrudRestService { try { if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) { - String result = graphDataService.getVertex(version, id, type, params); - response = Response.status(Status.OK).entity(result).type(mediaType).build(); + ImmutablePair result = graphDataService.getVertex(version, id, type, params); + response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build(); } else { response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build(); } @@ -142,8 +144,8 @@ public class CrudRestService { properties = new HashSet<>(); } - String result = graphDataService.getVertices(version, type, filter, properties); - response = Response.status(Status.OK).entity(result).type(mediaType).build(); + ImmutablePair result = graphDataService.getVertices(version, type, filter, properties); + response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build(); } else { response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build(); } @@ -175,8 +177,8 @@ public class CrudRestService { try { if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) { - String result = graphDataService.getEdge(version, id, type, params); - response = Response.status(Status.OK).entity(result).type(mediaType).build(); + ImmutablePair result = graphDataService.getEdge(version, id, type, params); + response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build(); } else { response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build(); } @@ -206,8 +208,8 @@ public class CrudRestService { try { if (validateRequest(req, uri, content, Action.GET, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) { - String result = graphDataService.getEdges(version, type, filter); - response = Response.status(Status.OK).entity(result).type(mediaType).build(); + ImmutablePair result = graphDataService.getEdges(version, type, filter); + response = Response.status(Status.OK).entity(result.getValue()).tag(result.getKey()).type(mediaType).build(); } else { response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build(); } @@ -244,17 +246,16 @@ public class CrudRestService { if (payload.getId() != null && !payload.getId().equals(id)) { throw new CrudException("ID Mismatch", Status.BAD_REQUEST); } - String result; - + ImmutablePair result; if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) { result = graphDataService.patchEdge(version, id, type, payload); + response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build(); } else { - result = graphDataService.updateEdge(version, id, type, payload); + response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build(); } - - response = Response.status(Status.OK).entity(result).type(mediaType).build(); + } else { response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build(); } @@ -291,8 +292,8 @@ public class CrudRestService { throw new CrudException("ID Mismatch", Status.BAD_REQUEST); } - String result = graphDataService.patchEdge(version, id, type, payload); - response = Response.status(Status.OK).entity(result).type(mediaType).build(); + ImmutablePair result = graphDataService.patchEdge(version, id, type, payload); + response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build(); } else { response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build(); } @@ -319,7 +320,6 @@ public class CrudRestService { logger.debug("Incoming request..." + content); Response response = null; - try { if (validateRequest(req, uri, content, Action.PUT, CrudServiceConstants.CRD_AUTH_POLICY_NAME, headers)) { VertexPayload payload = VertexPayload.fromJson(content); @@ -330,18 +330,18 @@ public class CrudRestService { throw new CrudException("ID Mismatch", Status.BAD_REQUEST); } - String result; - payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false)); + ImmutablePair result; if (headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE) != null && headers.getRequestHeaders().getFirst(HTTP_PATCH_METHOD_OVERRIDE).equalsIgnoreCase("PATCH")) { result = graphDataService.patchVertex(version, id, type, payload); + response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build(); } else { - result = graphDataService.updateVertex(version, id, type, payload); + response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build(); } - response = Response.status(Status.OK).entity(result).type(mediaType).build(); + } else { response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build(); } @@ -380,8 +380,8 @@ public class CrudRestService { payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, false)); - String result = graphDataService.patchVertex(version, id, type, payload); - response = Response.status(Status.OK).entity(result).type(mediaType).build(); + ImmutablePair result = graphDataService.patchVertex(version, id, type, payload); + response = Response.status(Status.OK).entity(result.getValue()).type(mediaType).tag(result.getKey()).build(); } else { response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build(); } @@ -425,8 +425,8 @@ public class CrudRestService { payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true)); - String result = graphDataService.addVertex(version, type, payload); - response = Response.status(Status.CREATED).entity(result).type(mediaType).build(); + ImmutablePair result = graphDataService.addVertex(version, type, payload); + response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build(); } else { response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build(); } @@ -612,8 +612,8 @@ public class CrudRestService { payload.setProperties(CrudServiceUtil.mergeHeaderInFoToPayload(payload.getProperties(), headers, true)); - String result = graphDataService.addVertex(version, payload.getType(), payload); - response = Response.status(Status.CREATED).entity(result).type(mediaType).build(); + ImmutablePair result = graphDataService.addVertex(version, payload.getType(), payload); + response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build(); } else { response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build(); } @@ -654,8 +654,8 @@ public class CrudRestService { if (payload.getType() != null && !payload.getType().equals(type)) { throw new CrudException("Edge Type mismatch", Status.BAD_REQUEST); } - String result = graphDataService.addEdge(version, type, payload); - response = Response.status(Status.CREATED).entity(result).type(mediaType).build(); + ImmutablePair result = graphDataService.addEdge(version, type, payload); + response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build(); } else { response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build(); } @@ -695,9 +695,8 @@ public class CrudRestService { if (payload.getType() == null || payload.getType().isEmpty()) { throw new CrudException("Missing Edge Type ", Status.BAD_REQUEST); } - String result = graphDataService.addEdge(version, payload.getType(), payload); - - response = Response.status(Status.CREATED).entity(result).type(mediaType).build(); + ImmutablePair result = graphDataService.addEdge(version, payload.getType(), payload); + response = Response.status(Status.CREATED).entity(result.getValue()).tag(result.getKey()).type(mediaType).build(); } else { response = Response.status(Status.FORBIDDEN).entity(content).type(MediaType.APPLICATION_JSON).build(); } diff --git a/src/main/java/org/onap/crud/service/EdgePayload.java b/src/main/java/org/onap/crud/service/EdgePayload.java index 630ec02..a670b54 100644 --- a/src/main/java/org/onap/crud/service/EdgePayload.java +++ b/src/main/java/org/onap/crud/service/EdgePayload.java @@ -20,14 +20,12 @@ */ package org.onap.crud.service; +import javax.ws.rs.core.Response.Status; +import org.onap.crud.exception.CrudException; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; -import org.onap.crud.exception.CrudException; - -import javax.ws.rs.core.Response.Status; - public class EdgePayload { private String id; diff --git a/src/main/java/org/onap/crud/service/VertexPayload.java b/src/main/java/org/onap/crud/service/VertexPayload.java index 594dc1a..172d03b 100644 --- a/src/main/java/org/onap/crud/service/VertexPayload.java +++ b/src/main/java/org/onap/crud/service/VertexPayload.java @@ -20,15 +20,13 @@ */ package org.onap.crud.service; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; - -import org.onap.crud.exception.CrudException; - import java.util.ArrayList; import java.util.List; import javax.ws.rs.core.Response.Status; +import org.onap.crud.exception.CrudException; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; public class VertexPayload { diff --git a/src/main/java/org/onap/crud/util/CrudServiceConstants.java b/src/main/java/org/onap/crud/util/CrudServiceConstants.java index 3a02852..ae5b464 100644 --- a/src/main/java/org/onap/crud/util/CrudServiceConstants.java +++ b/src/main/java/org/onap/crud/util/CrudServiceConstants.java @@ -39,4 +39,5 @@ public class CrudServiceConstants { public static final String CRD_COLLECTION_PROPERTIES_KEY = "crud.collection.properties.key"; public static final String CRD_RESERVED_VERSION = "_reserved_version"; public static final String CRD_RESERVED_NODE_TYPE = "_reserved_aai-type"; + public static final String CRD_HEADER_ETAG = "etag"; } diff --git a/src/main/java/org/onap/crud/util/CrudServiceUtil.java b/src/main/java/org/onap/crud/util/CrudServiceUtil.java index 6c251bc..6b5cdcd 100644 --- a/src/main/java/org/onap/crud/util/CrudServiceUtil.java +++ b/src/main/java/org/onap/crud/util/CrudServiceUtil.java @@ -20,6 +20,15 @@ */ package org.onap.crud.util; +import java.util.AbstractMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import javax.ws.rs.core.EntityTag; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response.Status; import org.onap.aai.db.props.AAIProperties; import org.onap.crud.exception.CrudException; import org.onap.schema.OxmModelLoader; @@ -29,15 +38,6 @@ import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; -import java.util.AbstractMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; - -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response.Status; - public class CrudServiceUtil { private static Gson gson = new Gson(); @@ -54,13 +54,13 @@ public class CrudServiceUtil { } else if (clazz.isAssignableFrom(Double.class)) { return Double.parseDouble(value); } else if (clazz.isAssignableFrom(Boolean.class)) { - + // If the value is an IN/OUT direction, this gets seen as a boolean, so // check for that first. if (value.equals("OUT") || value.equals("IN")) { return value; } - + if (!value.equals("true") && !value.equals("false")) { throw new CrudException("Invalid propertry value: " + value, Status.BAD_REQUEST); } @@ -82,7 +82,7 @@ public class CrudServiceUtil { throw new CrudException(e); } } - + /** * This method will merge header property from app id in request payload if not already populated * @param propertiesFromRequest @@ -104,12 +104,12 @@ public class CrudServiceUtil { if(!propertyKeys.contains(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH)) { properties.add(new AbstractMap.SimpleEntry(AAIProperties.LAST_MOD_SOURCE_OF_TRUTH, - (JsonElement)(new JsonPrimitive(sourceOfTruth)))); + (new JsonPrimitive(sourceOfTruth)))); } if(isAdd && !propertyKeys.contains(AAIProperties.SOURCE_OF_TRUTH)) { properties.add(new AbstractMap.SimpleEntry(AAIProperties.SOURCE_OF_TRUTH, - (JsonElement)(new JsonPrimitive(sourceOfTruth)))); + (new JsonPrimitive(sourceOfTruth)))); } Object[] propArray = properties.toArray(); @@ -117,7 +117,7 @@ public class CrudServiceUtil { sb.append("{"); boolean first=true; for(int i=0; i entry = (Entry) propArray[i]; if(!first) { sb.append(","); @@ -126,7 +126,17 @@ public class CrudServiceUtil { first=false; } sb.append("}"); - + return gson.fromJson(sb.toString(), JsonElement.class); } + + public static EntityTag getETagFromHeader(MultivaluedMap headers) { + EntityTag entityTag = null; + if (headers != null && headers.containsKey(CrudServiceConstants.CRD_HEADER_ETAG)) { + String value = headers.getFirst(CrudServiceConstants.CRD_HEADER_ETAG); + entityTag = new EntityTag(value.replace("\"", "")); + } + return entityTag; + } + } diff --git a/src/main/java/org/onap/crud/util/HashGenerator.java b/src/main/java/org/onap/crud/util/HashGenerator.java new file mode 100644 index 0000000..02558fa --- /dev/null +++ b/src/main/java/org/onap/crud/util/HashGenerator.java @@ -0,0 +1,65 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.crud.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +/** + * Generates a sha 256 hash + */ +public class HashGenerator { + + private MessageDigest messageDigest; + + public HashGenerator() throws NoSuchAlgorithmException { + this.messageDigest = MessageDigest.getInstance("SHA-256"); + } + + /** + * Generates a SHA 256 hash as a hexadecimal string for the inputs. + * Calls toString on the input objects to convert into a byte stream. + * @param values + * @return SHA 256 hash of the inputs as a hexadecimal string. + * @throws IOException + */ + public String generateSHA256AsHex(Object... values) throws IOException { + byte[] bytes = convertToBytes(values); + byte[] digest = messageDigest.digest(bytes); + StringBuilder result = new StringBuilder(); + for (byte byt : digest) result.append(Integer.toString((byt & 0xff) + 0x100, 16).substring(1)); + return result.toString(); + } + + private byte[] convertToBytes(Object... values) throws IOException { + try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutput out = new ObjectOutputStream(bos)) { + for (Object object : values) { + out.writeObject(object.toString()); + } + return bos.toByteArray(); + } + } + +} \ No newline at end of file diff --git a/src/main/java/org/onap/crud/util/etag/EtagGenerator.java b/src/main/java/org/onap/crud/util/etag/EtagGenerator.java new file mode 100644 index 0000000..b288b78 --- /dev/null +++ b/src/main/java/org/onap/crud/util/etag/EtagGenerator.java @@ -0,0 +1,92 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.crud.util.etag; + +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import org.onap.crud.event.GraphEventEdge; +import org.onap.crud.event.GraphEventVertex; +import org.onap.crud.util.HashGenerator; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +/** + * Computes hash for GraphEventVertex and GraphEventEdge + */ +public class EtagGenerator { + + private static final String AAI_LAST_MOD_TS = "aai-last-mod-ts"; + private final HashGenerator hashGenerator; + + public EtagGenerator() throws NoSuchAlgorithmException { + this.hashGenerator = new HashGenerator(); + } + + /** + * Takes in the GraphEventVertex for which the hash is to be computed. + * @param GraphEventVertex + * @return hash for the GraphEventVertex + * @throws IOException + */ + public String computeHashForVertex(GraphEventVertex graphEventVertex) throws IOException { + return hashGenerator.generateSHA256AsHex(graphEventVertex.getId(), graphEventVertex.getType(), convertPropertiesToMap(graphEventVertex.getProperties())); + } + + /** + * Takes in the GraphEventEdge for which the hash is to be computed. + * @param GraphEventEdge + * @return hash for the GraphEventEdge + * @throws IOException + */ + public String computeHashForEdge(GraphEventEdge graphEventEdge) throws IOException { + return hashGenerator.generateSHA256AsHex(graphEventEdge.getId(), graphEventEdge.getType(), + convertPropertiesToMap(graphEventEdge.getProperties()), + computeHashForVertex(graphEventEdge.getSource()), computeHashForVertex(graphEventEdge.getTarget())); + } + + private Map convertPropertiesToMap(JsonElement properties) { + Map propertiesMap = new HashMap<>(); + if (null != properties) { + JsonObject propsObject = properties.getAsJsonObject(); + for (Entry props : propsObject.entrySet()) { + String key = props.getKey(); + String value = props.getValue().getAsString(); + propertiesMap.put(key, value); + } + } + return filterAndSortProperties(propertiesMap); + } + + private Map filterAndSortProperties(Map properties) { + return properties + .entrySet() + .stream() + .filter(x -> !x.getKey().equals(AAI_LAST_MOD_TS)) + .sorted((x, y) -> x.getKey().compareTo(y.getKey())) + .collect(LinkedHashMap::new, + (m, e) -> m.put(e.getKey(), e.getValue()), + Map::putAll); + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/crud/service/CrudRestServiceTest.java b/src/test/java/org/onap/crud/service/CrudRestServiceTest.java index 13cba11..68c876c 100644 --- a/src/test/java/org/onap/crud/service/CrudRestServiceTest.java +++ b/src/test/java/org/onap/crud/service/CrudRestServiceTest.java @@ -26,8 +26,6 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; @@ -37,8 +35,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mockito; -import org.onap.crud.dao.TestDao; import org.onap.crud.exception.CrudException; +import org.onap.crud.service.TestDao; import org.onap.crud.service.util.TestHeaders; import org.onap.crud.service.util.TestRequest; import org.onap.crud.service.util.TestUriInfo; @@ -80,18 +78,18 @@ public class CrudRestServiceTest { @Before public void init() throws Exception { - Path resourcePath = Paths.get(ClassLoader.getSystemResource("model").toURI()); - Path parentPath = resourcePath.getParent(); + ClassLoader classLoader = getClass().getClassLoader(); + File dir = new File(classLoader.getResource("model").getFile()); + System.setProperty("CONFIG_HOME", dir.getParent()); + EdgeRulesLoader.resetSchemaVersionContext(); - System.setProperty("CONFIG_HOME", parentPath.toString()); - EdgeRulesLoader.resetSchemaVersionContext (); - CrudGraphDataService service = new CrudGraphDataService(new TestDao()); - CrudRestService restService = new CrudRestService(service, null); - mockService = Mockito.spy(restService); - - Mockito.doReturn(true).when(mockService).validateRequest(Mockito.any(HttpServletRequest.class), - Mockito.anyString(), Mockito.anyString(), Mockito.any(CrudRestService.Action.class), Mockito.anyString(), - Mockito.any(HttpHeaders.class)); + CrudGraphDataService service = new CrudGraphDataService(new TestDao()); + CrudRestService restService = new CrudRestService(service, null); + mockService = Mockito.spy(restService); + + Mockito.doReturn(true).when(mockService).validateRequest(Mockito.any(HttpServletRequest.class), + Mockito.anyString(), Mockito.anyString(), Mockito.any(CrudRestService.Action.class), Mockito.anyString(), + Mockito.any(HttpHeaders.class)); } @Test @@ -123,21 +121,25 @@ public class CrudRestServiceTest { new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 400); + Assert.assertNull(response.getEntityTag()); response = mockService.addVertex(postVertexPayload, "v11", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 201); + Assert.assertEquals(response.getEntityTag().getValue(), "test123"); response = mockService.addVertex(postMissingPropVertexPayload, "v11", "pserver", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); - assertTrue(response.getStatus() == 400); + assertTrue(response.getStatus() == 400); + Assert.assertNull(response.getEntityTag()); response = mockService.addVertex(postVertexPayload, "v11", "pserver", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); - assertTrue(response.getStatus() == 201); + assertTrue(response.getStatus() == 201); + Assert.assertEquals(response.getEntityTag().getValue(), "test123"); } @Test @@ -148,11 +150,13 @@ public class CrudRestServiceTest { new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 201); + Assert.assertEquals(response.getEntityTag().getValue(), "test123"); response = mockService.addEdge(postEdgePayload, "v11", "tosca.relationships.HostedOn", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); - assertTrue(response.getStatus() == 201); + assertTrue(response.getStatus() == 201); + Assert.assertEquals(response.getEntityTag().getValue(), "test123"); } @Test @@ -170,19 +174,22 @@ public class CrudRestServiceTest { response = mockService.updateVertex(putVertexPayload, "v11", "pserver", "bad-id", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); - assertTrue(response.getStatus() == 400); + assertTrue(response.getStatus() == 400); + Assert.assertNull(response.getEntityTag()); // Success case response = mockService.updateVertex(putVertexPayload, "v11", "pserver", "test-uuid", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 200); + Assert.assertEquals(response.getEntityTag().getValue(), "test123"); // Patch response = mockService.patchVertex(putVertexPayload, "v11", "pserver", "test-uuid", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 200); + Assert.assertEquals(response.getEntityTag().getValue(), "test123"); } @Test @@ -193,12 +200,14 @@ public class CrudRestServiceTest { "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 200); + Assert.assertEquals(response.getEntityTag().getValue(), "test123"); // Patch response = mockService.patchEdge(postEdgePayload, "v11", "tosca.relationships.HostedOn", "my-uuid", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 200); + Assert.assertEquals(response.getEntityTag().getValue(), "test123"); } @Test diff --git a/src/test/java/org/onap/crud/dao/TestDao.java b/src/test/java/org/onap/crud/service/TestDao.java similarity index 56% rename from src/test/java/org/onap/crud/dao/TestDao.java rename to src/test/java/org/onap/crud/service/TestDao.java index 69ce4a3..d412163 100644 --- a/src/test/java/org/onap/crud/dao/TestDao.java +++ b/src/test/java/org/onap/crud/service/TestDao.java @@ -18,27 +18,36 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.crud.dao; +package org.onap.crud.service; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; - +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; +import org.onap.aai.restclient.client.OperationResult; import org.onap.crud.dao.GraphDao; import org.onap.crud.entity.Edge; import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; public class TestDao implements GraphDao { - + private final String champVertex = "{" + "\"key\": \"test-uuid\"," + "\"type\": \"pserver\"," + "\"properties\": {" + "\"fqdn\": \"myhost.onap.com\"," + "\"hostname\": \"myhost\" } }"; - + + private final String champVertices = "[ {" + + "\"key\": \"test-uuid\"," + + "\"type\": \"pserver\"," + + "\"properties\": {" + + "\"fqdn\": \"myhost.onap.com\"," + + "\"hostname\": \"myhost\" } } ]"; + private final String champEdge = "{" + "\"key\": \"test-uuid\"," + "\"type\": \"tosca.relationships.HostedOn\"," + @@ -50,15 +59,28 @@ public class TestDao implements GraphDao { "\"key\": \"1d326bc7-b985-492b-9604-0d5d1f06f908\", \"type\": \"pserver\"}" + " }"; + private final String champEdges = "[ {" + + "\"key\": \"test-uuid\"," + + "\"type\": \"tosca.relationships.HostedOn\"," + + "\"properties\": {" + + "\"prevent-delete\": \"NONE\" }," + + "\"source\": {" + + "\"key\": \"50bdab41-ad1c-4d00-952c-a0aa5d827811\", \"type\": \"vserver\"}," + + "\"target\": {" + + "\"key\": \"1d326bc7-b985-492b-9604-0d5d1f06f908\", \"type\": \"pserver\"}" + + " } ]"; + @Override public Vertex getVertex(String id, String version) throws CrudException { return Vertex.fromJson(champVertex, "v11"); } @Override - public Vertex getVertex(String id, String type, String version, Map queryParams) + public OperationResult getVertex(String id, String type, String version, Map queryParams) throws CrudException { - return Vertex.fromJson(champVertex, "v11"); + OperationResult operationResult = new OperationResult(); + operationResult.setResult(champVertex); + return operationResult; } @Override @@ -69,41 +91,49 @@ public class TestDao implements GraphDao { } @Override - public List getVertices(String type, Map filter, String version) throws CrudException { - List list = new ArrayList(); - list.add(Vertex.fromJson(champVertex, "v11")); - return list; + public OperationResult getVertices(String type, Map filter, String version) throws CrudException { + OperationResult operationResult = new OperationResult(); + operationResult.setResult(champVertices); + return operationResult; } @Override - public List getVertices(String type, Map filter, HashSet properties, String version) + public OperationResult getVertices(String type, Map filter, HashSet properties, String version) throws CrudException { - List list = new ArrayList(); - list.add(Vertex.fromJson(champVertex, "v11")); - return list; + OperationResult operationResult = new OperationResult(); + operationResult.setResult(champVertices); + return operationResult; } @Override - public Edge getEdge(String id, String type, Map queryParams) throws CrudException { - return Edge.fromJson(champEdge); + public OperationResult getEdge(String id, String type, Map queryParams) throws CrudException { + OperationResult operationResult = new OperationResult(); + operationResult.setResult(champEdge); + return operationResult; } @Override - public List getEdges(String type, Map filter) throws CrudException { - List list = new ArrayList(); - list.add(Edge.fromJson(champEdge)); - return list; + public OperationResult getEdges(String type, Map filter) throws CrudException { + OperationResult operationResult = new OperationResult(); + operationResult.setResult(champEdges); + return operationResult; } @Override - public Vertex addVertex(String type, Map properties, String version) throws CrudException { - return Vertex.fromJson(champVertex, "v11"); + public OperationResult addVertex(String type, Map properties, String version) throws CrudException { + OperationResult operationResult = new OperationResult(); + operationResult.setHeaders(addReponseHeader()); + operationResult.setResult(champVertex); + return operationResult; } @Override - public Vertex updateVertex(String id, String type, Map properties, String version) + public OperationResult updateVertex(String id, String type, Map properties, String version) throws CrudException { - return Vertex.fromJson(champVertex, "v11"); + OperationResult operationResult = new OperationResult(); + operationResult.setHeaders(addReponseHeader()); + operationResult.setResult(champVertex); + return operationResult; } @Override @@ -112,14 +142,20 @@ public class TestDao implements GraphDao { } @Override - public Edge addEdge(String type, Vertex source, Vertex target, Map properties, String version) + public OperationResult addEdge(String type, Vertex source, Vertex target, Map properties, String version) throws CrudException { - return Edge.fromJson(champEdge); + OperationResult operationResult = new OperationResult(); + operationResult.setHeaders(addReponseHeader()); + operationResult.setResult(champEdge); + return operationResult; } @Override - public Edge updateEdge(Edge edge) throws CrudException { - return Edge.fromJson(champEdge); + public OperationResult updateEdge(Edge edge) throws CrudException { + OperationResult operationResult = new OperationResult(); + operationResult.setHeaders(addReponseHeader()); + operationResult.setResult(champEdge); + return operationResult; } @Override @@ -190,5 +226,10 @@ public class TestDao implements GraphDao { public Edge getEdge(String id, String type, String txId) throws CrudException { return Edge.fromJson(champEdge); } - -} + + private MultivaluedMap addReponseHeader() { + MultivaluedMap headers = new MultivaluedHashMap(); + headers.add("etag", "test123"); + return headers; + } +} \ No newline at end of file diff --git a/src/test/java/org/onap/crud/util/etag/EtagGeneratorTest.java b/src/test/java/org/onap/crud/util/etag/EtagGeneratorTest.java new file mode 100644 index 0000000..c4f7c38 --- /dev/null +++ b/src/test/java/org/onap/crud/util/etag/EtagGeneratorTest.java @@ -0,0 +1,168 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.crud.util.etag; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.assertThat; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import org.junit.Before; +import org.junit.Test; +import org.onap.crud.event.GraphEventEdge; +import org.onap.crud.event.GraphEventVertex; +import org.onap.crud.util.etag.EtagGenerator; +import com.google.gson.JsonObject; + +public class EtagGeneratorTest { + + private EtagGenerator etagGenerator; + + @Before + public void init() throws NoSuchAlgorithmException { + etagGenerator = new EtagGenerator(); + } + + private GraphEventVertex createVertex(String propKey, String propValue) { + JsonObject properties = new JsonObject(); + properties.addProperty(propKey, propValue); + GraphEventVertex vertex = new GraphEventVertex("vertex1", "v11", "pserver", properties); + return vertex; + } + + private GraphEventEdge createEdge(String id, GraphEventVertex source, GraphEventVertex target, String propKey, + String propValue) { + JsonObject properties = new JsonObject(); + properties.addProperty(propKey, propValue); + GraphEventEdge edge = new GraphEventEdge(id, "v11", "tosca.relationships.HostedOn", source, target, properties); + return edge; + } + + @Test + public void computeHashForIdenticalVertexObjects() throws IOException { + // everything is same + GraphEventVertex sourceVertex1 = createVertex("prop1", "value1"); + GraphEventVertex targetVertex1 = createVertex("prop2", "value2"); + + GraphEventEdge edge1 = createEdge("edge1", sourceVertex1, targetVertex1, "prop1", "value1"); + + GraphEventVertex sourceVertex2 = createVertex("prop1", "value1"); + GraphEventVertex targetVertex2 = createVertex("prop2", "value2"); + + GraphEventEdge edge2 = createEdge("edge1", sourceVertex2, targetVertex2, "prop1", "value1"); + + assertThat(etagGenerator.computeHashForEdge(edge1), is(etagGenerator.computeHashForEdge(edge2))); + } + + @Test + public void computeHashForVertexObjectsWithDifferentKey() throws IOException { + // key is different + GraphEventVertex sourceVertex1 = createVertex("prop1", "value1"); + GraphEventVertex targetVertex1 = createVertex("prop2", "value2"); + + GraphEventEdge edge1 = createEdge("edge1", sourceVertex1, targetVertex1, "prop1", "value1"); + + GraphEventVertex sourceVertex2 = createVertex("prop1", "value1"); + GraphEventVertex targetVertex2 = createVertex("prop2", "value2"); + + GraphEventEdge edge2 = createEdge("edge2", sourceVertex2, targetVertex2, "prop1", "value1"); + + assertThat(etagGenerator.computeHashForEdge(edge1), not(etagGenerator.computeHashForEdge(edge2))); + } + + @Test + public void computeHashForVertexObjectsWithDifferentEdge() throws IOException { + // relationship is different + GraphEventVertex sourceVertex1 = createVertex("prop1", "value1"); + GraphEventVertex targetVertex1 = createVertex("prop2", "value2"); + + GraphEventEdge edge1 = createEdge("edge1", sourceVertex1, targetVertex1, "prop1", "value1"); + + GraphEventVertex sourceVertex2 = createVertex("prop1", "value1"); + GraphEventVertex targetVertex2 = createVertex("prop2", "value2"); + + GraphEventEdge edge2 = createEdge("edge2", sourceVertex2, targetVertex2, "prop1", "value1"); + edge2.setType("tosca.relationships.RelatedTo"); + + assertThat(etagGenerator.computeHashForEdge(edge1), not(etagGenerator.computeHashForEdge(edge2))); + } + + @Test + public void computeHashForEdgeObjectsWithDifferentVertexObjects() throws IOException { + // source/target different + GraphEventVertex sourceVertex1 = createVertex("prop1", "value1"); + GraphEventVertex targetVertex1 = createVertex("prop2", "value2"); + targetVertex1.setId("vertex2"); + + GraphEventEdge edge1 = createEdge("edge1", sourceVertex1, targetVertex1, "prop1", "value1"); + + GraphEventVertex sourceVertex2 = createVertex("prop1", "value1"); + GraphEventVertex targetVertex2 = createVertex("prop2", "value2"); + + GraphEventEdge edge2 = createEdge("edge2", sourceVertex2, targetVertex2, "prop1", "value1"); + edge2.setType("tosca.relationships.RelatedTo"); + + assertThat(etagGenerator.computeHashForEdge(edge1), not(etagGenerator.computeHashForEdge(edge2))); + } + + @Test + public void computeHashForEdgeObjectsWithDifferentProperties() throws IOException { + // property different + GraphEventVertex sourceVertex1 = createVertex("sourceprop1", "value1"); + GraphEventVertex targetVertex1 = createVertex("targetprop2", "value2"); + + GraphEventEdge edge1 = createEdge("edge1", sourceVertex1, targetVertex1, "edgeprop1", "value1"); + + GraphEventVertex sourceVertex2 = createVertex("sourceprop1", "value1"); + GraphEventVertex targetVertex2 = createVertex("targetprop2", "value2"); + + GraphEventEdge edge2 = createEdge("edge1", sourceVertex2, targetVertex2, "edgeprop2", "value2"); + + assertThat(etagGenerator.computeHashForEdge(edge1), not(etagGenerator.computeHashForEdge(edge2))); + } + + @Test + public void testComputeHashForIdenticalVertexObjects() throws IOException { + GraphEventVertex sourceVertex1 = createVertex("prop1", "value1"); + GraphEventVertex targetVertex1 = createVertex("prop1", "value1"); + assertThat(etagGenerator.computeHashForVertex(sourceVertex1), + is(etagGenerator.computeHashForVertex(targetVertex1))); + } + + @Test + public void testComputeHashForVertexObjectsWithDifferentProperties() throws IOException { + GraphEventVertex sourceVertex1 = createVertex("prop1", "value1"); + GraphEventVertex targetVertex1 = createVertex("prop2", "value2"); + assertThat(etagGenerator.computeHashForVertex(sourceVertex1), + not(etagGenerator.computeHashForVertex(targetVertex1))); + } + + @Test + public void testComputeHashForChampObjectsWithDifferentKey() throws IOException { + GraphEventVertex sourceVertex1 = createVertex("prop1", "value1"); + GraphEventVertex targetVertex1 = createVertex("prop1", "value1"); + targetVertex1.setId("vertex2"); + assertThat(etagGenerator.computeHashForVertex(sourceVertex1), + not(etagGenerator.computeHashForVertex(targetVertex1))); + } + + +} \ No newline at end of file -- 2.16.6 From 68cd3355674d66f8feee3d067960c081581a3911 Mon Sep 17 00:00:00 2001 From: Michael Arrastia Date: Mon, 18 Jun 2018 16:13:27 +0100 Subject: [PATCH 15/16] Fix Fortify scan violation Change-Id: Ia99b0a9b60b1b4eebfb47640c410f6c684393599 Issue-ID: AAI-1196 Signed-off-by: Michael Arrastia --- .../java/org/onap/crud/dao/champ/ChampDao.java | 6 +- .../org/onap/crud/util/CrudJaxbTransformation.java | 89 ---------------------- 2 files changed, 3 insertions(+), 92 deletions(-) delete mode 100644 src/main/java/org/onap/crud/util/CrudJaxbTransformation.java diff --git a/src/main/java/org/onap/crud/dao/champ/ChampDao.java b/src/main/java/org/onap/crud/dao/champ/ChampDao.java index c8488ba..65d1d99 100644 --- a/src/main/java/org/onap/crud/dao/champ/ChampDao.java +++ b/src/main/java/org/onap/crud/dao/champ/ChampDao.java @@ -132,7 +132,7 @@ public class ChampDao implements GraphDao { if (!vert.getType().equalsIgnoreCase(type)) { // We didn't find a vertex with the supplied type, so just throw an // exception. - throw new CrudException("No vertex with id " + id + "and type " + type + " found in graph", + throw new CrudException("No vertex with id " + id + " and type " + type + " found in graph", javax.ws.rs.core.Response.Status.NOT_FOUND); } return getResult; @@ -579,10 +579,10 @@ public class ChampDao implements GraphDao { } // https://stackoverflow.com/questions/26942330/convert-mapstring-string-to-listnamevaluepair-is-this-the-most-efficient - private List convertToNameValuePair(String key, HashSet values) { + private List convertToNameValuePair(String k, HashSet values) { List nvpList = new ArrayList<>(values.size()); - values.forEach((value) -> nvpList.add(new BasicNameValuePair(key, value))); + values.forEach((v) -> nvpList.add(new BasicNameValuePair(k, v))); return nvpList; } diff --git a/src/main/java/org/onap/crud/util/CrudJaxbTransformation.java b/src/main/java/org/onap/crud/util/CrudJaxbTransformation.java deleted file mode 100644 index 5e72534..0000000 --- a/src/main/java/org/onap/crud/util/CrudJaxbTransformation.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 Amdocs - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ -package org.onap.crud.util; - -import org.eclipse.persistence.dynamic.DynamicEntity; -import org.eclipse.persistence.jaxb.JAXBMarshaller; -import org.eclipse.persistence.jaxb.MarshallerProperties; -import org.eclipse.persistence.jaxb.UnmarshallerProperties; -import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContext; - -import java.io.StringReader; -import java.io.StringWriter; -import javax.ws.rs.core.MediaType; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.transform.stream.StreamSource; - -public class CrudJaxbTransformation { - /** - * Marshal a dynamic entity into a string. - * - * @param entity the dynamic entity - * @param jaxbContext the dynamic jaxb context - * @return the marshaled entity - * @throws RouterException on error - */ - public static String marshal(MediaType mediaType, final DynamicEntity entity, - final DynamicJAXBContext jaxbContext) throws JAXBException { - - final JAXBMarshaller marshaller = jaxbContext.createMarshaller(); - marshaller.setProperty(JAXBMarshaller.JAXB_FORMATTED_OUTPUT, false); - - if (MediaType.APPLICATION_JSON_TYPE.isCompatible(mediaType)) { - marshaller.setProperty("eclipselink.media-type", "application/json"); - marshaller.setProperty("eclipselink.json.include-root", false); - marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, Boolean.FALSE); - } - - final StringWriter writer = new StringWriter(); - marshaller.marshal(entity, writer); - return writer.toString(); - - } - - /** - * @param type - * @param json - * @param mediaType - * @return - * @throws JAXBException - * @throws Exception - */ - public static Object unmarshal(String javaClass, String content, MediaType mediaType, - final DynamicJAXBContext jaxbContext) throws JAXBException { - Object clazz = null; - Unmarshaller unmarshaller = null; - - clazz = jaxbContext.newDynamicEntity(javaClass); - - unmarshaller = jaxbContext.createUnmarshaller(); - if (mediaType.equals(MediaType.APPLICATION_JSON_TYPE)) { - unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, "application/json"); - unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, false); - unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true); - } - - return unmarshaller.unmarshal(new StreamSource(new StringReader(content)), - clazz.getClass()).getValue(); - } - -} -- 2.16.6 From d10a218c76633374f083f7a2802c198e93a6abae Mon Sep 17 00:00:00 2001 From: michaere Date: Wed, 27 Jun 2018 09:51:34 +0100 Subject: [PATCH 16/16] Apply multiplicity Rule upon Edge creation Uses multiplicity type from dbedge rules json to validate whether to and from vertices meet the multiplicity constraint e.g. ONE2MANY. This validation is applied when creating or updating an edge. Issue-ID: AAI-1197 Change-Id: Id6e78635c5cbea66d8a35e6901b7e1b673125e4e Signed-off-by: michaere --- .../java/org/onap/crud/dao/champ/ChampDao.java | 10 +- src/main/java/org/onap/crud/entity/Vertex.java | 2 +- .../event/response/GraphEventResponseHandler.java | 4 +- .../onap/crud/{service => parser}/BulkPayload.java | 2 +- .../org/onap/crud/parser/CrudResponseBuilder.java | 4 - .../onap/crud/{service => parser}/EdgePayload.java | 2 +- .../crud/{service => parser}/VertexPayload.java | 2 +- .../org/onap/crud/parser/util/EdgePayloadUtil.java | 145 + .../org/onap/crud/service/AaiResourceService.java | 19 +- .../crud/service/AbstractGraphDataService.java | 33 +- .../crud/service/CrudAsyncGraphDataService.java | 10 +- .../onap/crud/service/CrudGraphDataService.java | 40 +- .../org/onap/crud/service/CrudRestService.java | 3 + .../java/org/onap/crud/util/CrudServiceUtil.java | 3 +- src/main/java/org/onap/schema/EdgeRulesLoader.java | 27 +- .../java/org/onap/schema/RelationshipSchema.java | 55 +- .../schema/validation/MultiplicityValidator.java | 119 + .../schema/{ => validation}/OxmModelValidator.java | 11 +- .../RelationshipSchemaValidator.java | 240 +- .../onap/crud/parser/util/EdgePayloadUtilTest.java | 110 + .../onap/crud/service/AaiResourceServiceTest.java | 3 +- .../org/onap/crud/service/BulkPayloadTest.java | 2 +- .../org/onap/crud/service/CrudRestServiceTest.java | 155 +- .../org/onap/crud/util/CrudServiceUtilTest.java | 2 +- .../org/onap/schema/RelationshipSchemaTest.java | 14 +- .../validation/MultiplicityValidatorTest.java | 159 + .../{model => edgeProps}/edge_properties_v10.json | 0 .../{model => edgeProps}/edge_properties_v8.json | 0 .../{model => edgeProps}/edge_properties_v9.json | 0 src/test/resources/model/edge_properties_v11.json | 6 - src/test/resources/oxm/aai_oxm_v10.xml | 6363 ++++++++++++++++++++ src/test/resources/oxm/aai_oxm_v8.xml | 6363 ++++++++++++++++++++ src/test/resources/oxm/aai_oxm_v9.xml | 6363 ++++++++++++++++++++ .../{model => rules}/DbEdgeRules_v10.json | 11 + .../resources/{model => rules}/DbEdgeRules_v8.json | 11 + .../resources/{model => rules}/DbEdgeRules_v9.json | 11 + 36 files changed, 19978 insertions(+), 326 deletions(-) rename src/main/java/org/onap/crud/{service => parser}/BulkPayload.java (98%) rename src/main/java/org/onap/crud/{service => parser}/EdgePayload.java (98%) rename src/main/java/org/onap/crud/{service => parser}/VertexPayload.java (98%) create mode 100644 src/main/java/org/onap/crud/parser/util/EdgePayloadUtil.java create mode 100644 src/main/java/org/onap/schema/validation/MultiplicityValidator.java rename src/main/java/org/onap/schema/{ => validation}/OxmModelValidator.java (99%) rename src/main/java/org/onap/schema/{ => validation}/RelationshipSchemaValidator.java (54%) create mode 100644 src/test/java/org/onap/crud/parser/util/EdgePayloadUtilTest.java create mode 100644 src/test/java/org/onap/schema/validation/MultiplicityValidatorTest.java rename src/test/resources/{model => edgeProps}/edge_properties_v10.json (100%) rename src/test/resources/{model => edgeProps}/edge_properties_v8.json (100%) rename src/test/resources/{model => edgeProps}/edge_properties_v9.json (100%) delete mode 100644 src/test/resources/model/edge_properties_v11.json create mode 100644 src/test/resources/oxm/aai_oxm_v10.xml create mode 100644 src/test/resources/oxm/aai_oxm_v8.xml create mode 100644 src/test/resources/oxm/aai_oxm_v9.xml rename src/test/resources/{model => rules}/DbEdgeRules_v10.json (99%) rename src/test/resources/{model => rules}/DbEdgeRules_v8.json (99%) rename src/test/resources/{model => rules}/DbEdgeRules_v9.json (99%) diff --git a/src/main/java/org/onap/crud/dao/champ/ChampDao.java b/src/main/java/org/onap/crud/dao/champ/ChampDao.java index 65d1d99..7bd4754 100644 --- a/src/main/java/org/onap/crud/dao/champ/ChampDao.java +++ b/src/main/java/org/onap/crud/dao/champ/ChampDao.java @@ -173,7 +173,7 @@ public class ChampDao implements GraphDao { @Override public OperationResult getVertices(String type, Map filter, HashSet properties, String version) throws CrudException { - filter.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + filter.put(org.onap.schema.validation.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); List queryParams = convertToNameValuePair(filter); queryParams.addAll(convertToNameValuePair("properties", properties)); @@ -242,7 +242,7 @@ public class ChampDao implements GraphDao { // Add the aai_node_type so that AAI can read the data created by gizmo // TODO: This probably shouldn't be here - properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + properties.put(org.onap.schema.validation.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); Vertex.Builder insertVertexBuilder = new Vertex.Builder(type); properties.forEach(insertVertexBuilder::property); @@ -266,7 +266,7 @@ public class ChampDao implements GraphDao { // Add the aai_node_type so that AAI can read the data created by gizmo // TODO: This probably shouldn't be here - properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + properties.put(org.onap.schema.validation.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); Vertex.Builder insertVertexBuilder = new Vertex.Builder(type); insertVertexBuilder.id(id); @@ -414,7 +414,7 @@ public class ChampDao implements GraphDao { // Add the aai_node_type so that AAI can read the data created by gizmo // TODO: This probably shouldn't be here - properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + properties.put(org.onap.schema.validation.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); Vertex.Builder insertVertexBuilder = new Vertex.Builder(type); properties.forEach(insertVertexBuilder::property); @@ -463,7 +463,7 @@ public class ChampDao implements GraphDao { // Add the aai_node_type so that AAI can read the data created by gizmo // TODO: This probably shouldn't be here - properties.put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + properties.put(org.onap.schema.validation.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); Vertex.Builder insertVertexBuilder = new Vertex.Builder(type); insertVertexBuilder.id(id); diff --git a/src/main/java/org/onap/crud/entity/Vertex.java b/src/main/java/org/onap/crud/entity/Vertex.java index cffdcf1..fd03827 100644 --- a/src/main/java/org/onap/crud/entity/Vertex.java +++ b/src/main/java/org/onap/crud/entity/Vertex.java @@ -34,7 +34,7 @@ import org.json.JSONObject; import org.onap.crud.exception.CrudException; import org.onap.crud.util.CrudServiceUtil; import org.onap.schema.OxmModelLoader; -import org.onap.schema.OxmModelValidator; +import org.onap.schema.validation.OxmModelValidator; import com.google.common.base.CaseFormat; import com.google.gson.Gson; import com.google.gson.GsonBuilder; diff --git a/src/main/java/org/onap/crud/event/response/GraphEventResponseHandler.java b/src/main/java/org/onap/crud/event/response/GraphEventResponseHandler.java index 8146aa3..d858384 100644 --- a/src/main/java/org/onap/crud/event/response/GraphEventResponseHandler.java +++ b/src/main/java/org/onap/crud/event/response/GraphEventResponseHandler.java @@ -29,8 +29,8 @@ import org.onap.crud.event.envelope.GraphEventEnvelope; import org.onap.crud.exception.CrudException; import org.onap.crud.logging.CrudServiceMsgs; import org.onap.crud.parser.CrudResponseBuilder; -import org.onap.schema.OxmModelValidator; -import org.onap.schema.RelationshipSchemaValidator; +import org.onap.schema.validation.OxmModelValidator; +import org.onap.schema.validation.RelationshipSchemaValidator; /** * Reads event responses, logs and generates exceptions if errors are found. diff --git a/src/main/java/org/onap/crud/service/BulkPayload.java b/src/main/java/org/onap/crud/parser/BulkPayload.java similarity index 98% rename from src/main/java/org/onap/crud/service/BulkPayload.java rename to src/main/java/org/onap/crud/parser/BulkPayload.java index 8dc99c4..33e9a2e 100644 --- a/src/main/java/org/onap/crud/service/BulkPayload.java +++ b/src/main/java/org/onap/crud/parser/BulkPayload.java @@ -18,7 +18,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.crud.service; +package org.onap.crud.parser; import com.google.gson.Gson; import com.google.gson.GsonBuilder; diff --git a/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java b/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java index 0a81884..29d8824 100644 --- a/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java +++ b/src/main/java/org/onap/crud/parser/CrudResponseBuilder.java @@ -27,11 +27,7 @@ import java.util.Map; import org.onap.crud.entity.Edge; import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; -import org.onap.crud.service.BulkPayload; -import org.onap.crud.service.EdgePayload; -import org.onap.crud.service.VertexPayload; import org.onap.schema.EdgeRulesLoader; - import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; diff --git a/src/main/java/org/onap/crud/service/EdgePayload.java b/src/main/java/org/onap/crud/parser/EdgePayload.java similarity index 98% rename from src/main/java/org/onap/crud/service/EdgePayload.java rename to src/main/java/org/onap/crud/parser/EdgePayload.java index a670b54..a1499db 100644 --- a/src/main/java/org/onap/crud/service/EdgePayload.java +++ b/src/main/java/org/onap/crud/parser/EdgePayload.java @@ -18,7 +18,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.crud.service; +package org.onap.crud.parser; import javax.ws.rs.core.Response.Status; import org.onap.crud.exception.CrudException; diff --git a/src/main/java/org/onap/crud/service/VertexPayload.java b/src/main/java/org/onap/crud/parser/VertexPayload.java similarity index 98% rename from src/main/java/org/onap/crud/service/VertexPayload.java rename to src/main/java/org/onap/crud/parser/VertexPayload.java index 172d03b..b5ff345 100644 --- a/src/main/java/org/onap/crud/service/VertexPayload.java +++ b/src/main/java/org/onap/crud/parser/VertexPayload.java @@ -18,7 +18,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.crud.service; +package org.onap.crud.parser; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/onap/crud/parser/util/EdgePayloadUtil.java b/src/main/java/org/onap/crud/parser/util/EdgePayloadUtil.java new file mode 100644 index 0000000..0f72625 --- /dev/null +++ b/src/main/java/org/onap/crud/parser/util/EdgePayloadUtil.java @@ -0,0 +1,145 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.crud.parser.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.ws.rs.core.Response.Status; +import org.onap.crud.entity.Edge; +import org.onap.crud.entity.Vertex; +import org.onap.crud.exception.CrudException; + +/** + * Utility Class to extract data from the Edge Payload + */ +public class EdgePayloadUtil { + + private static final Pattern URL_MATCHER = Pattern.compile("services/inventory/(.*)/(.*)/(.*)"); + + private static Matcher getVertexMatcher(String vertex) throws CrudException { + Matcher matcher = URL_MATCHER.matcher(vertex); + if (!matcher.matches()) { + throw new CrudException("Invalid Source/Target Urls", Status.BAD_REQUEST); + } + return matcher; + } + + /** + * Returns the node type from a vertex on the edge payload + * + * @param vertex + * @return + * @throws CrudException + */ + public static String getVertexNodeType(String vertex) throws CrudException { + return getVertexMatcher(vertex).group(2); + } + + /** + * Returns the node id from a vertex on the edge payload + * + * @param vertex + * @return + * @throws CrudException + */ + public static String getVertexNodeId(String vertex) throws CrudException { + return getVertexMatcher(vertex).group(3); + } + + /** + * Generates a key based on the edge payload content + * + * @param source + * @param target + * @param type + * @return + * @throws CrudException + */ + public static String generateEdgeKey(String source, String target, String type) throws CrudException { + return getVertexNodeType(source) + ":" + getVertexNodeType(target) + ":" + type; + } + + /** + * Returns an Edge Builder object from the payload properties + * + * @param source + * @param target + * @param type + * @return + * @throws CrudException + */ + public static Edge.Builder getBuilderFromEdgePayload(String source, String target, String type) throws CrudException { + Edge.Builder edgeBuilder = new Edge.Builder(type); + + edgeBuilder.source(new Vertex.Builder(getVertexNodeType(source)).id(getVertexNodeId(source)).build()); + edgeBuilder.target(new Vertex.Builder(getVertexNodeType(target)).id(getVertexNodeId(target)).build()); + + return edgeBuilder; + } + + /** + * Returns an Edge Builder object from an Edge object properties + * + * @param edge + * @return + */ + public static Edge.Builder getBuilderFromEdge(Edge edge) { + Edge.Builder edgeBuilder = new Edge.Builder(edge.getType()).id(edge.getId().get()); + + edgeBuilder + .source(new Vertex.Builder(edge.getSource().getType()).id(edge.getSource().getId().get()).build()); + edgeBuilder + .target(new Vertex.Builder(edge.getTarget().getType()).id(edge.getTarget().getId().get()).build()); + + return edgeBuilder; + } + + /** + * Filter Edges by its source/target vertex type and the edge type + * + * @param sourceTargetType the new Edge source/target type + * @param type + * @param edges + * @return List + */ + public static List filterEdgesByRelatedVertexAndType(String sourceTargetType, String type, List edges) { + List filteredEdges = new ArrayList<>(); + if (edges != null) { + for (Edge edge : edges) { + if (doesEdgeTypeMatch(edge, type) && doesEdgeSourceTargetTypeMatch(edge, sourceTargetType)) { + filteredEdges.add(edge); + } + } + } + return filteredEdges; + } + + private static boolean doesEdgeTypeMatch(Edge edge, String type) { + return edge.getType() != null && edge.getType().equals(type); + } + + private static boolean doesEdgeSourceTargetTypeMatch(Edge edge, String sourceTargetType) { + return (edge.getSource().getType() != null && edge.getSource().getType().equals(sourceTargetType)) + || ((edge.getTarget().getType() != null && edge.getTarget().getType().equals(sourceTargetType))); + } +} diff --git a/src/main/java/org/onap/crud/service/AaiResourceService.java b/src/main/java/org/onap/crud/service/AaiResourceService.java index afabe7e..c0375b4 100644 --- a/src/main/java/org/onap/crud/service/AaiResourceService.java +++ b/src/main/java/org/onap/crud/service/AaiResourceService.java @@ -54,10 +54,11 @@ import org.onap.aaiauth.auth.Auth; import org.onap.crud.exception.CrudException; import org.onap.crud.logging.CrudServiceMsgs; import org.onap.crud.logging.LoggingUtil; +import org.onap.crud.parser.EdgePayload; +import org.onap.crud.parser.util.EdgePayloadUtil; import org.onap.crud.service.CrudRestService.Action; import org.onap.crud.util.CrudServiceConstants; import org.onap.schema.EdgeRulesLoader; -import org.onap.schema.RelationshipSchemaValidator; import org.slf4j.MDC; import com.google.gson.Gson; import com.google.gson.JsonElement; @@ -397,16 +398,15 @@ public class AaiResourceService { public EdgePayload applyEdgeRulesToPayload(EdgePayload payload) throws CrudException { // Extract the types for both the source and target vertices. - String srcType = RelationshipSchemaValidator.vertexTypeFromUri(payload.getSource()); - String tgtType = RelationshipSchemaValidator.vertexTypeFromUri(payload.getTarget()); + String srcType = EdgePayloadUtil.getVertexNodeType(payload.getSource()); + String tgtType = EdgePayloadUtil.getVertexNodeType(payload.getTarget()); - // Now, get the default properties for this edge based on the edge rules definition... - Map props = getEdgeRuleProperties(srcType, tgtType); - - // ...and merge them with any custom properties provided in the request. - JsonElement mergedProperties = mergeProperties(payload.getProperties(), props); - payload.setProperties(mergedProperties); + // Now, get the default properties for this edge based on the edge rules definition... + Map props = getEdgeRuleProperties(srcType, tgtType); + // ...and merge them with any custom properties provided in the request. + JsonElement mergedProperties = mergeProperties(payload.getProperties(), props); + payload.setProperties(mergedProperties); if(logger.isDebugEnabled()) { logger.debug("Edge properties after applying rules for '" + srcType + " -> " + tgtType + "': " + mergedProperties); @@ -430,6 +430,7 @@ public class AaiResourceService { * * @throws CrudException */ + @SuppressWarnings("unchecked") public JsonElement mergeProperties(JsonElement propertiesFromRequest, Map propertyDefaults) throws CrudException { // Convert the properties from the edge payload into something we can diff --git a/src/main/java/org/onap/crud/service/AbstractGraphDataService.java b/src/main/java/org/onap/crud/service/AbstractGraphDataService.java index 7c1168e..fed12fd 100644 --- a/src/main/java/org/onap/crud/service/AbstractGraphDataService.java +++ b/src/main/java/org/onap/crud/service/AbstractGraphDataService.java @@ -36,10 +36,14 @@ import org.onap.crud.dao.champ.ChampVertexSerializer; import org.onap.crud.entity.Edge; import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; +import org.onap.crud.parser.BulkPayload; import org.onap.crud.parser.CrudResponseBuilder; +import org.onap.crud.parser.EdgePayload; +import org.onap.crud.parser.VertexPayload; +import org.onap.crud.parser.util.EdgePayloadUtil; import org.onap.crud.util.CrudServiceUtil; -import org.onap.schema.OxmModelValidator; -import org.onap.schema.RelationshipSchemaValidator; +import org.onap.schema.validation.OxmModelValidator; +import org.onap.schema.validation.RelationshipSchemaValidator; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; @@ -228,12 +232,31 @@ public abstract class AbstractGraphDataService { edgePayload .setTarget("services/inventory/" + version + "/" + target.getType() + "/" + target.getId().get()); } - validatedEdge = RelationshipSchemaValidator.validateIncomingAddPayload(version, edgePayload.getType(), - edgePayload); + + List sourceVertexEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType(EdgePayloadUtil.getVertexNodeType(edgePayload.getSource()), edgePayload.getType(), + daoForGet.getVertexEdges(EdgePayloadUtil.getVertexNodeId(edgePayload.getSource()), null)); + + List targetVertexEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType(EdgePayloadUtil.getVertexNodeType(edgePayload.getTarget()), edgePayload.getType(), + daoForGet.getVertexEdges(EdgePayloadUtil.getVertexNodeId(edgePayload.getTarget()), null)); + + validatedEdge = RelationshipSchemaValidator.validateIncomingAddPayload(version, edgePayload.getType(), edgePayload, sourceVertexEdges, + targetVertexEdges); persistedEdge = addBulkEdge(validatedEdge, version, txId); } else if (opr.getValue().getAsString().equalsIgnoreCase("modify")) { Edge edge = dao.getEdge(edgePayload.getId(), edgePayload.getType(), txId); - validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, edgePayload); + + // load source and target vertex relationships for validation + List sourceVertexEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType(EdgePayloadUtil.getVertexNodeType(edgePayload.getSource()), edgePayload.getType(), + daoForGet.getVertexEdges(EdgePayloadUtil.getVertexNodeId(edgePayload.getSource()), null)); + + List targetVertexEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType(EdgePayloadUtil.getVertexNodeType(edgePayload.getTarget()), edgePayload.getType(), + daoForGet.getVertexEdges(EdgePayloadUtil.getVertexNodeId(edgePayload.getTarget()), null)); + + validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, edgePayload, edgePayload.getType(), sourceVertexEdges, targetVertexEdges); persistedEdge = updateBulkEdge(validatedEdge, version, txId); } else { if ( (edgePayload.getId() == null) || (edgePayload.getType() == null) ) { diff --git a/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java b/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java index 6b447a1..c2d2591 100644 --- a/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java +++ b/src/main/java/org/onap/crud/service/CrudAsyncGraphDataService.java @@ -56,11 +56,13 @@ import org.onap.crud.event.envelope.GraphEventEnvelope; import org.onap.crud.event.response.GraphEventResponseHandler; import org.onap.crud.exception.CrudException; import org.onap.crud.logging.CrudServiceMsgs; +import org.onap.crud.parser.EdgePayload; +import org.onap.crud.parser.VertexPayload; import org.onap.crud.util.CrudProperties; import org.onap.crud.util.CrudServiceConstants; import org.onap.crud.util.etag.EtagGenerator; -import org.onap.schema.OxmModelValidator; -import org.onap.schema.RelationshipSchemaValidator; +import org.onap.schema.validation.OxmModelValidator; +import org.onap.schema.validation.RelationshipSchemaValidator; public class CrudAsyncGraphDataService extends AbstractGraphDataService { @@ -211,7 +213,7 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService { throws CrudException { // Validate the incoming payload Vertex vertex = OxmModelValidator.validateIncomingUpsertPayload(null, version, type, payload.getProperties()); - vertex.getProperties().put(org.onap.schema.OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); + vertex.getProperties().put(OxmModelValidator.Metadata.NODE_TYPE.propertyName(), type); // Create graph request event GraphEvent event = GraphEvent.builder(GraphEventOperation.CREATE) .vertex(GraphEventVertex.fromVertex(vertex, version)).build(); @@ -233,6 +235,7 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService { public ImmutablePair addEdge(String version, String type, EdgePayload payload) throws CrudException { Edge edge = RelationshipSchemaValidator.validateIncomingAddPayload(version, type, payload); + // Create graph request event GraphEvent event = GraphEvent.builder(GraphEventOperation.CREATE).edge(GraphEventEdge.fromEdge(edge, version)).build(); @@ -320,6 +323,7 @@ public class CrudAsyncGraphDataService extends AbstractGraphDataService { OperationResult operationResult = dao.getEdge(id, type, new HashMap()); Edge edge = Edge.fromJson(operationResult.getResult()); Edge validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, payload); + GraphEvent event = GraphEvent.builder(GraphEventOperation.UPDATE) .edge(GraphEventEdge.fromEdge(validatedEdge, version)).build(); diff --git a/src/main/java/org/onap/crud/service/CrudGraphDataService.java b/src/main/java/org/onap/crud/service/CrudGraphDataService.java index 5b1c2dd..2888ace 100644 --- a/src/main/java/org/onap/crud/service/CrudGraphDataService.java +++ b/src/main/java/org/onap/crud/service/CrudGraphDataService.java @@ -22,6 +22,7 @@ package org.onap.crud.service; import java.util.HashMap; +import java.util.List; import javax.ws.rs.core.EntityTag; import org.apache.commons.lang3.tuple.ImmutablePair; import org.onap.aai.restclient.client.OperationResult; @@ -30,9 +31,12 @@ import org.onap.crud.entity.Edge; import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; import org.onap.crud.parser.CrudResponseBuilder; +import org.onap.crud.parser.EdgePayload; +import org.onap.crud.parser.VertexPayload; +import org.onap.crud.parser.util.EdgePayloadUtil; import org.onap.crud.util.CrudServiceUtil; -import org.onap.schema.OxmModelValidator; -import org.onap.schema.RelationshipSchemaValidator; +import org.onap.schema.validation.OxmModelValidator; +import org.onap.schema.validation.RelationshipSchemaValidator; public class CrudGraphDataService extends AbstractGraphDataService { @@ -70,7 +74,17 @@ public class CrudGraphDataService extends AbstractGraphDataService { @Override public ImmutablePair addEdge(String version, String type, EdgePayload payload) throws CrudException { - Edge edge = RelationshipSchemaValidator.validateIncomingAddPayload(version, type, payload); + // load source and target vertex relationships for validation + List sourceVertexEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType(EdgePayloadUtil.getVertexNodeType(payload.getSource()), type, + daoForGet.getVertexEdges(EdgePayloadUtil.getVertexNodeId(payload.getSource()), null)); + + List targetVertexEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType(EdgePayloadUtil.getVertexNodeType(payload.getTarget()), type, + daoForGet.getVertexEdges(EdgePayloadUtil.getVertexNodeId(payload.getTarget()), null)); + + Edge edge = RelationshipSchemaValidator.validateIncomingAddPayload(version, type, payload, sourceVertexEdges, targetVertexEdges); + return addEdge(version, edge); } @@ -133,7 +147,20 @@ public class CrudGraphDataService extends AbstractGraphDataService { @Override public ImmutablePair updateEdge(String version, String id, String type, EdgePayload payload) throws CrudException { - Edge validatedEdge = getValidatedEdge(version, id, type, payload); + OperationResult edgeResult = dao.getEdge(id, type, new HashMap()); + Edge edge = Edge.fromJson(edgeResult.getResult()); + + // load source and target vertex relationships for validation + List sourceVertexEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType(EdgePayloadUtil.getVertexNodeType(payload.getSource()), type, + daoForGet.getVertexEdges(EdgePayloadUtil.getVertexNodeId(payload.getSource()), null)); + + List targetVertexEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType(EdgePayloadUtil.getVertexNodeType(payload.getTarget()), type, + daoForGet.getVertexEdges(EdgePayloadUtil.getVertexNodeId(payload.getTarget()), null)); + + Edge validatedEdge = RelationshipSchemaValidator.validateIncomingUpdatePayload(edge, version, payload, type, sourceVertexEdges, targetVertexEdges); + return updateEdge(version, validatedEdge); } @@ -152,11 +179,6 @@ public class CrudGraphDataService extends AbstractGraphDataService { .buildUpsertEdgeResponse(RelationshipSchemaValidator.validateOutgoingPayload(version, updatedEdge), version); } - private Edge getValidatedEdge(String version, String id, String type, EdgePayload payload) throws CrudException { - OperationResult operationResult = dao.getEdge(id, type, new HashMap()); - return RelationshipSchemaValidator.validateIncomingUpdatePayload(Edge.fromJson(operationResult.getResult()), version, payload); - } - @Override public ImmutablePair patchEdge(String version, String id, String type, EdgePayload payload) throws CrudException { diff --git a/src/main/java/org/onap/crud/service/CrudRestService.java b/src/main/java/org/onap/crud/service/CrudRestService.java index 583fee6..a43d7e5 100644 --- a/src/main/java/org/onap/crud/service/CrudRestService.java +++ b/src/main/java/org/onap/crud/service/CrudRestService.java @@ -52,6 +52,9 @@ import org.onap.aaiauth.auth.Auth; import org.onap.crud.exception.CrudException; import org.onap.crud.logging.CrudServiceMsgs; import org.onap.crud.logging.LoggingUtil; +import org.onap.crud.parser.BulkPayload; +import org.onap.crud.parser.EdgePayload; +import org.onap.crud.parser.VertexPayload; import org.onap.crud.util.CrudProperties; import org.onap.crud.util.CrudServiceConstants; import org.onap.crud.util.CrudServiceUtil; diff --git a/src/main/java/org/onap/crud/util/CrudServiceUtil.java b/src/main/java/org/onap/crud/util/CrudServiceUtil.java index 6b5cdcd..ed5fe53 100644 --- a/src/main/java/org/onap/crud/util/CrudServiceUtil.java +++ b/src/main/java/org/onap/crud/util/CrudServiceUtil.java @@ -31,9 +31,8 @@ import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response.Status; import org.onap.aai.db.props.AAIProperties; import org.onap.crud.exception.CrudException; -import org.onap.schema.OxmModelLoader; import org.onap.schema.EdgeRulesLoader; - +import org.onap.schema.OxmModelLoader; import com.google.gson.Gson; import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; diff --git a/src/main/java/org/onap/schema/EdgeRulesLoader.java b/src/main/java/org/onap/schema/EdgeRulesLoader.java index a990ae5..7f08949 100644 --- a/src/main/java/org/onap/schema/EdgeRulesLoader.java +++ b/src/main/java/org/onap/schema/EdgeRulesLoader.java @@ -20,29 +20,30 @@ */ package org.onap.schema; -import com.google.common.collect.Multimap; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import javax.ws.rs.core.Response.Status; import org.apache.commons.io.IOUtils; import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.edges.EdgeRule; import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException; -import org.onap.aai.edges.EdgeIngestor; import org.onap.aai.setup.ConfigTranslator; import org.onap.aai.setup.SchemaLocationsBean; import org.onap.aai.setup.Version; import org.onap.crud.exception.CrudException; import org.onap.crud.logging.CrudServiceMsgs; import org.onap.schema.util.SchemaIngestPropertyReader; -import org.springframework.core.io.UrlResource; - -import javax.ws.rs.core.Response.Status; -import java.io.*; -import java.util.Arrays; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; +import com.google.common.collect.Multimap; public class EdgeRulesLoader { diff --git a/src/main/java/org/onap/schema/RelationshipSchema.java b/src/main/java/org/onap/schema/RelationshipSchema.java index fc91662..2aab7a9 100644 --- a/src/main/java/org/onap/schema/RelationshipSchema.java +++ b/src/main/java/org/onap/schema/RelationshipSchema.java @@ -20,21 +20,25 @@ */ package org.onap.schema; -import com.google.common.collect.Multimap; -import org.codehaus.jackson.map.ObjectMapper; -import org.onap.aai.edges.EdgeRule; -import org.onap.crud.exception.CrudException; import java.io.IOException; -import java.util.*; +import java.util.HashMap; +import java.util.Map; import java.util.stream.Collectors; import javax.ws.rs.core.Response.Status; +import org.codehaus.jackson.map.ObjectMapper; +import org.onap.aai.edges.EdgeRule; +import org.onap.crud.exception.CrudException; +import com.google.common.collect.Multimap; public class RelationshipSchema { + public static final String SCHEMA_SOURCE_NODE_TYPE = "from"; + public static final String SCHEMA_TARGET_NODE_TYPE = "to"; public static final String SCHEMA_RELATIONSHIP_TYPE = "label"; - + public static final String SCHEMA_MULTIPLICITY_TYPE = "multiplicity"; + public static final String SCHEMA_RULES_ARRAY = "rules"; private Map>> relations = new HashMap<>(); /** @@ -42,8 +46,18 @@ public class RelationshipSchema { */ private Map>> relationTypes = new HashMap<>(); - public RelationshipSchema( Multimap rules, String props) throws CrudException, IOException { + private Map relationshipRules = new HashMap<>(); + + @SuppressWarnings("unchecked") + public RelationshipSchema(Multimap rules, String props) throws CrudException, IOException { HashMap properties = new ObjectMapper().readValue(props, HashMap.class); + + // hold the true values of the edge rules by key - convert to java 8 + for (EdgeRule rule : rules.values()) { + String key = buildRelation(rule.getFrom(), rule.getTo(), rule.getLabel()); + relationshipRules.put(key, rule); + } + Map> edgeProps = properties.entrySet().stream().collect(Collectors.toMap(p -> p.getKey(), p -> { try { return resolveClass(p.getValue()); @@ -63,6 +77,27 @@ public class RelationshipSchema { return this.relations.get(key); } + /** + * Extract the multiplicity type from the Edge rules + * + * @param key + * @return + * @throws CrudException + */ + public String lookupRelationMultiplicity(String key) throws CrudException { + EdgeRule edgeRule = relationshipRules.get(key); + + if (edgeRule == null) { + throw new CrudException("Invalid source/target/relationship type: " + key, Status.BAD_REQUEST); + } + + if (edgeRule.getMultiplicityRule() != null) { + return edgeRule.getMultiplicityRule().toString(); + } + + return null; + } + public Map> lookupRelationType(String type) { return this.relationTypes.get(type); } @@ -72,7 +107,7 @@ public class RelationshipSchema { } - private String buildRelation(String source, String target, String relation){ + private String buildRelation(String source, String target, String relation) { return source + ":" + target + ":" + relation; } @@ -88,6 +123,4 @@ public class RelationshipSchema { throw new CrudException("", Status.BAD_REQUEST); } } -} - - +} \ No newline at end of file diff --git a/src/main/java/org/onap/schema/validation/MultiplicityValidator.java b/src/main/java/org/onap/schema/validation/MultiplicityValidator.java new file mode 100644 index 0000000..1c1075c --- /dev/null +++ b/src/main/java/org/onap/schema/validation/MultiplicityValidator.java @@ -0,0 +1,119 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.schema.validation; + +import java.util.List; +import javax.ws.rs.core.Response.Status; +import org.onap.crud.entity.Edge; +import org.onap.crud.exception.CrudException; +import org.onap.crud.parser.EdgePayload; +import org.onap.crud.parser.util.EdgePayloadUtil; +import org.onap.schema.EdgeRulesLoader; +import org.onap.schema.RelationshipSchema; + +/** + * Validator to enforce multiplicity rules on the creation of a new Edge + * + */ +public class MultiplicityValidator { + + public enum MultiplicityType { + MANY2ONE("Many2One"), MANY2MANY("Many2Many"), ONE2MANY("One2Many"), ONE2ONE("One2One"); + + private final String value; + + MultiplicityType(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } + + /** + * Validates the Edge payload's source and target vertices against multiplicity rule + * + * @param payload + * @param edgesForSourceVertex + * @param edgesForTargetVertex + * @param type + * @param version + * @throws CrudException + */ + public static void validatePayloadMultiplicity(EdgePayload payload, List edgesForSourceVertex, + List edgesForTargetVertex, String type, String version) + throws CrudException { + RelationshipSchema schema = EdgeRulesLoader.getSchemaForVersion(version); + // find the validate the key from the schema + String key = EdgePayloadUtil.generateEdgeKey(payload.getSource(), payload.getTarget(), type); + + // get the multiplicity rule for the relationships + String multiplicityTypeValue = schema.lookupRelationMultiplicity(key); + if (multiplicityTypeValue != null) { + MultiplicityType multiplicityType = MultiplicityType.valueOf(multiplicityTypeValue.toUpperCase()); + + boolean isVertexValidForMultiplicityType = + isVertexValidForMultiplicityType(edgesForSourceVertex, edgesForTargetVertex, multiplicityType); + + if (!isVertexValidForMultiplicityType) { + throw new CrudException( + multiplicityType.toString() + " multiplicity rule broken for Edge:" + key, + Status.BAD_REQUEST); + } + } + } + + /** + * Compare vertex existing relationships to ensure its not in breach of multiplicity rules + * + * @param edgesForVertex + * @param multiplicityType + * @return + */ + public static Boolean isVertexValidForMultiplicityType(List edgesForSourceVertex, + List edgesForTargetVertex, + MultiplicityType multiplicityType) { + + switch (multiplicityType) { + case MANY2MANY: + return true; + case MANY2ONE: + if (edgesForSourceVertex != null && !edgesForSourceVertex.isEmpty()) { + return false; + } + break; + case ONE2MANY: + if (edgesForTargetVertex != null && !edgesForTargetVertex.isEmpty()) { + return false; + } + break; + case ONE2ONE: + if ((edgesForSourceVertex != null && !edgesForSourceVertex.isEmpty()) + || (edgesForTargetVertex != null && !edgesForTargetVertex.isEmpty())) { + return false; + } + break; + } + return true; + } + +} \ No newline at end of file diff --git a/src/main/java/org/onap/schema/OxmModelValidator.java b/src/main/java/org/onap/schema/validation/OxmModelValidator.java similarity index 99% rename from src/main/java/org/onap/schema/OxmModelValidator.java rename to src/main/java/org/onap/schema/validation/OxmModelValidator.java index 24d4a8c..89b8030 100644 --- a/src/main/java/org/onap/schema/OxmModelValidator.java +++ b/src/main/java/org/onap/schema/validation/OxmModelValidator.java @@ -18,7 +18,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.schema; +package org.onap.schema.validation; import java.util.HashMap; import java.util.Map; @@ -36,13 +36,14 @@ import org.onap.crud.exception.CrudException; import org.onap.crud.logging.CrudServiceMsgs; import org.onap.crud.util.CrudServiceConstants; import org.onap.crud.util.CrudServiceUtil; +import org.onap.schema.OxmModelLoader; import com.google.common.base.CaseFormat; import com.google.gson.JsonElement; import com.google.gson.JsonNull; public class OxmModelValidator { private static Logger logger = LoggerFactory.getInstance().getLogger(OxmModelValidator.class.getName()); - + public enum Metadata { NODE_TYPE("aai-node-type"), URI("aai-uri"), @@ -162,7 +163,7 @@ public class OxmModelValidator { public static Vertex validateIncomingUpsertPayload(String id, String version, String type, JsonElement properties) throws CrudException { - + try { type = resolveCollectionType(version, type); DynamicJAXBContext jaxbContext = OxmModelLoader.getContextForVersion(version); @@ -319,7 +320,7 @@ public class OxmModelValidator { return null; } - public static Vertex validateOutgoingPayload(String version, Vertex vertex) { + public static Vertex validateOutgoingPayload(String version, Vertex vertex) { Vertex.Builder modelVertexBuilder = new Vertex.Builder(vertex.getType()).id(vertex.getId().get()); try { @@ -340,7 +341,7 @@ public class OxmModelValidator { modelVertexBuilder.property(key, vertex.getProperties().get(key)); } } - + return modelVertexBuilder.build(); } catch (Exception ex) { return vertex; diff --git a/src/main/java/org/onap/schema/RelationshipSchemaValidator.java b/src/main/java/org/onap/schema/validation/RelationshipSchemaValidator.java similarity index 54% rename from src/main/java/org/onap/schema/RelationshipSchemaValidator.java rename to src/main/java/org/onap/schema/validation/RelationshipSchemaValidator.java index 15b1762..f2717d5 100644 --- a/src/main/java/org/onap/schema/RelationshipSchemaValidator.java +++ b/src/main/java/org/onap/schema/validation/RelationshipSchemaValidator.java @@ -18,37 +18,32 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -package org.onap.schema; - -import com.google.gson.JsonElement; -import com.google.gson.JsonNull; +package org.onap.schema.validation; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.ws.rs.core.Response.Status; import org.onap.crud.entity.Edge; import org.onap.crud.entity.Vertex; import org.onap.crud.exception.CrudException; -import org.onap.crud.service.EdgePayload; +import org.onap.crud.parser.EdgePayload; +import org.onap.crud.parser.util.EdgePayloadUtil; import org.onap.crud.util.CrudServiceUtil; -import org.onap.schema.OxmModelValidator.Metadata; +import org.onap.schema.EdgeRulesLoader; +import org.onap.schema.RelationshipSchema; +import org.onap.schema.validation.OxmModelValidator.Metadata; import org.radeox.util.logging.Logger; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import javax.ws.rs.core.Response.Status; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; public class RelationshipSchemaValidator { - public static final String SOURCE_NODE = "source"; - public static final String TARGET_NODE = "target"; - - final static Pattern urlPattern = Pattern.compile("services/inventory/(.*)/(.*)/(.*)"); - - public static Map resolveCollectionfilter(String version, String type, - Map filter) - throws CrudException { + private static final String SOURCE_LABEL = "Source"; + private static final String TARGET_LABEL = "Target"; + public static Map resolveCollectionfilter(String version, String type, Map filter) throws CrudException { RelationshipSchema schema = EdgeRulesLoader.getSchemaForVersion(version); if (schema == null) { throw new CrudException("", Status.NOT_FOUND); @@ -64,19 +59,15 @@ public class RelationshipSchemaValidator { Object value = CrudServiceUtil.validateFieldType(filter.get(key), props.get(key)); result.put(key, value); } catch (Exception ex) { - // Skip any exceptions thrown while validating the filter - // key value + // Skip any exceptions thrown while validating the filter key value continue; } } } - return result; - } public static void validateType(String version, String type) throws CrudException { - RelationshipSchema schema = EdgeRulesLoader.getSchemaForVersion(version); if (!schema.isValidType(type)) { throw new CrudException("Invalid " + RelationshipSchema.SCHEMA_RELATIONSHIP_TYPE @@ -86,17 +77,16 @@ public class RelationshipSchemaValidator { } - public static Edge validateIncomingAddPayload(String version, String type, Vertex sourceNode, - Vertex targetNode, JsonElement properties) - throws CrudException { - EdgePayload payload = new EdgePayload(); - payload.setSource("services/inventory/" + version + "/" + sourceNode.getType() - + "/" + sourceNode.getId().get()); - payload.setTarget("services/inventory/" + version + "/" + targetNode.getType() - + "/" + targetNode.getId().get()); - payload.setType(type); - payload.setProperties(properties); - return validateIncomingAddPayload(version, type, payload); + public static Edge validateIncomingAddPayload(String version, String type, EdgePayload payload, + List sourceVertexEdges, List targetVertexEdges) throws CrudException { + + //perform standard validation + Edge edge = validateIncomingAddPayload(version, type, payload); + + // validate payload using multiplicity edge rules + MultiplicityValidator.validatePayloadMultiplicity(payload, sourceVertexEdges, targetVertexEdges, type, version); + + return edge; } public static Edge validateIncomingAddPayload(String version, String type, EdgePayload payload) @@ -104,49 +94,28 @@ public class RelationshipSchemaValidator { RelationshipSchema schema = EdgeRulesLoader.getSchemaForVersion(version); try { - if (payload.getSource() == null || payload.getTarget() == null) { throw new CrudException("Source/Target not specified", Status.BAD_REQUEST); } - Matcher sourceMatcher = urlPattern.matcher(payload.getSource()); - Matcher targetMatcher = urlPattern.matcher(payload.getTarget()); - - if (!sourceMatcher.matches() || !targetMatcher.matches()) { - throw new CrudException("Invalid Source/Target Urls", Status.BAD_REQUEST); - } - - // create key based on source:target:relationshipType - String sourceNodeType = sourceMatcher.group(2); - String targetNodeType = targetMatcher.group(2); - - String sourceNodeId = sourceMatcher.group(3); - String targetNodeId = targetMatcher.group(3); - - String key = sourceNodeType + ":" + targetNodeType + ":" + type; + String key = EdgePayloadUtil.generateEdgeKey(payload.getSource(), payload.getTarget(), type); // find the validate the key from the schema Map> schemaObject = schema.lookupRelation(key); if (schemaObject == null) { - throw new CrudException("Invalid source/target/relationship type: " + key, - Status.BAD_REQUEST); + throw new CrudException("Invalid source/target/relationship type: " + key, Status.BAD_REQUEST); } - Edge.Builder modelEdgeBuilder = new Edge.Builder(type); - - modelEdgeBuilder.source(new Vertex.Builder(sourceNodeType).id(sourceNodeId).build()); - modelEdgeBuilder.target(new Vertex.Builder(targetNodeType).id(targetNodeId).build()); + Edge.Builder modelEdgeBuilder = EdgePayloadUtil.getBuilderFromEdgePayload(payload.getSource(), payload.getTarget(), type); // validate it properties validateEdgeProps(modelEdgeBuilder, payload.getProperties(), schemaObject); return modelEdgeBuilder.build(); } catch (Exception ex) { - throw new CrudException(ex.getMessage(), Status.BAD_REQUEST); } - } public static Edge validateIncomingPatchPayload(Edge edge, String version, EdgePayload payload) @@ -154,42 +123,20 @@ public class RelationshipSchemaValidator { RelationshipSchema schema = EdgeRulesLoader.getSchemaForVersion(version); try { - if (payload.getSource() != null) { - Matcher sourceMatcher = urlPattern.matcher(payload.getSource()); - - if (!sourceMatcher.matches()) { - throw new CrudException("Invalid Target Urls", Status.BAD_REQUEST); - } - String sourceNodeId = sourceMatcher.group(3); - if (!sourceNodeId.equals(edge.getSource().getId().get())) { - throw new CrudException("Source can't be updated", Status.BAD_REQUEST); - } - } - - if (payload.getTarget() != null) { - Matcher targetMatcher = urlPattern.matcher(payload.getTarget()); + validateEdgeVertexMatchesPayload(edge.getSource(), payload.getSource(), SOURCE_LABEL); + validateEdgeVertexMatchesPayload(edge.getTarget(), payload.getTarget(), TARGET_LABEL); - if (!targetMatcher.matches()) { - throw new CrudException("Invalid Target Urls", Status.BAD_REQUEST); - } - String sourceNodeId = targetMatcher.group(3); - if (!sourceNodeId.equals(edge.getTarget().getId().get())) { - throw new CrudException("Target can't be updated", Status.BAD_REQUEST); - } - } - // Remove the timestamp properties from the existing edge, as these should be managed by Champ. Map existingProps = edge.getProperties(); - + if (existingProps.containsKey(Metadata.CREATED_TS.propertyName())) { existingProps.remove(Metadata.CREATED_TS.propertyName()); } if (existingProps.containsKey(Metadata.UPDATED_TS.propertyName())) { existingProps.remove(Metadata.UPDATED_TS.propertyName()); } - - // create key based on source:target:relationshipType + // create key based on source:target:relationshipType String key = edge.getSource().getType() + ":" + edge.getTarget().getType() + ":" + edge.getType(); @@ -202,43 +149,40 @@ public class RelationshipSchemaValidator { return edge; } - Set> entries = payload.getProperties() - .getAsJsonObject().entrySet(); + validateEdgePropertiesFromPayload(edge, payload, schemaObject); - for (Map.Entry entry : entries) { + return edge; + } catch (Exception ex) { + throw new CrudException(ex.getMessage(), Status.BAD_REQUEST); + } + } - if (!schemaObject.containsKey(entry.getKey())) { - throw new CrudException("Invalid property: " + entry.getKey(), Status.BAD_REQUEST); - } else if (entry.getValue() instanceof JsonNull && edge.getProperties() - .containsKey(entry.getKey())) { - edge.getProperties().remove(entry.getKey()); - } else if (!(entry.getValue() instanceof JsonNull)) { - Object value = CrudServiceUtil.validateFieldType(entry.getValue().getAsString(), - schemaObject.get(entry.getKey())); - edge.getProperties().put(entry.getKey(), value); - } + private static void validateEdgePropertiesFromPayload(Edge edge, EdgePayload payload, Map> schemaObject) throws CrudException { + Set> entries = payload.getProperties().getAsJsonObject().entrySet(); + for (Map.Entry entry : entries) { + if (!schemaObject.containsKey(entry.getKey())) { + throw new CrudException("Invalid property: " + entry.getKey(), Status.BAD_REQUEST); + } else if (entry.getValue() instanceof JsonNull && edge.getProperties().containsKey(entry.getKey())) { + edge.getProperties().remove(entry.getKey()); + } else if (!(entry.getValue() instanceof JsonNull)) { + Object value = CrudServiceUtil.validateFieldType(entry.getValue().getAsString(), schemaObject.get(entry.getKey())); + edge.getProperties().put(entry.getKey(), value); } + } + } - return edge; - } catch (Exception ex) { + public static Edge validateIncomingUpdatePayload(Edge edge, String version, EdgePayload payload, String type, + List sourceVertexEdges, List targetVertexEdges) throws CrudException { - throw new CrudException(ex.getMessage(), Status.BAD_REQUEST); - } - } + //perform standard validation + Edge validatedEdge = validateIncomingUpdatePayload(edge, version, payload); - public static Edge validateIncomingUpdatePayload(Edge edge, String version, Vertex sourceNode, - Vertex targetNode, JsonElement properties) - throws CrudException { - EdgePayload payload = new EdgePayload(); - payload.setSource("services/inventory/" + version + "/" + sourceNode.getType() - + "/" + sourceNode.getId().get()); - payload.setTarget("services/inventory/" + version + "/" + targetNode.getType() - + "/" + targetNode.getId().get()); - payload.setType(edge.getType()); - payload.setProperties(properties); - return validateIncomingUpdatePayload(edge, version, payload); + // validate payload using multiplicity edge rules + MultiplicityValidator.validatePayloadMultiplicity(payload, sourceVertexEdges, targetVertexEdges, type, version); + + return validatedEdge; } public static Edge validateIncomingUpdatePayload(Edge edge, String version, EdgePayload payload) @@ -246,32 +190,10 @@ public class RelationshipSchemaValidator { RelationshipSchema schema = EdgeRulesLoader.getSchemaForVersion(version); try { + validateEdgeVertexMatchesPayload(edge.getSource(), payload.getSource(), SOURCE_LABEL); + validateEdgeVertexMatchesPayload(edge.getTarget(), payload.getTarget(), TARGET_LABEL); - if (payload.getSource() != null) { - Matcher sourceMatcher = urlPattern.matcher(payload.getSource()); - - if (!sourceMatcher.matches()) { - throw new CrudException("Invalid Target Urls", Status.BAD_REQUEST); - } - String sourceNodeId = sourceMatcher.group(3); - if (!sourceNodeId.equals(edge.getSource().getId().get())) { - throw new CrudException("Source can't be updated", Status.BAD_REQUEST); - } - } - - if (payload.getTarget() != null) { - Matcher targetMatcher = urlPattern.matcher(payload.getTarget()); - - if (!targetMatcher.matches()) { - throw new CrudException("Invalid Target Urls", Status.BAD_REQUEST); - } - String sourceNodeId = targetMatcher.group(3); - if (!sourceNodeId.equals(edge.getTarget().getId().get())) { - throw new CrudException("Target can't be updated", Status.BAD_REQUEST); - } - } // create key based on source:target:relationshipType - String key = edge.getSource().getType() + ":" + edge.getTarget().getType() + ":" + edge.getType(); @@ -284,32 +206,29 @@ public class RelationshipSchemaValidator { return edge; } - Edge.Builder updatedEdgeBuilder = new Edge.Builder(edge.getType()).id(edge.getId().get()); - - updatedEdgeBuilder - .source(new Vertex.Builder(edge.getSource().getType()).id(edge.getSource().getId() - .get()).build()); - updatedEdgeBuilder - .target(new Vertex.Builder(edge.getTarget().getType()).id(edge.getTarget().getId() - .get()).build()); + Edge.Builder updatedEdgeBuilder = EdgePayloadUtil.getBuilderFromEdge(edge); validateEdgeProps(updatedEdgeBuilder, payload.getProperties(), schemaObject); return updatedEdgeBuilder.build(); } catch (Exception ex) { - throw new CrudException(ex.getMessage(), Status.BAD_REQUEST); } } + private static void validateEdgeVertexMatchesPayload(Vertex edgeVertex, String payloadVertex, String vertexTypeLabel) throws CrudException { + if (payloadVertex != null) { + String sourceNodeId = EdgePayloadUtil.getVertexNodeId(payloadVertex); + if (!sourceNodeId.equals(edgeVertex.getId().get())) { + throw new CrudException(vertexTypeLabel + " can't be updated", Status.BAD_REQUEST); + } + } + } - private static void validateEdgeProps(Edge.Builder builder, JsonElement props, - Map> schemaObject) - throws CrudException { + private static void validateEdgeProps(Edge.Builder builder, JsonElement props, Map> schemaObject) throws CrudException { Set> entries = props.getAsJsonObject().entrySet(); for (Map.Entry entry : entries) { - if (!schemaObject.containsKey(entry.getKey())) { throw new CrudException("Invalid property: " + entry.getKey(), Status.BAD_REQUEST); } else { @@ -317,13 +236,10 @@ public class RelationshipSchemaValidator { schemaObject.get(entry.getKey())); builder.property(entry.getKey(), value); } - } - } public static Edge validateOutgoingPayload(String version, Edge edge) throws CrudException { - Edge.Builder modelEdgeBuilder = new Edge.Builder(edge.getType()).id(edge.getId() .get()).source(edge.getSource()) .target(edge.getTarget()); @@ -346,16 +262,4 @@ public class RelationshipSchemaValidator { } return modelEdgeBuilder.build(); } - - - public static String vertexTypeFromUri(String uri) throws CrudException { - - Matcher matcher = urlPattern.matcher(uri); - - if (!matcher.matches()) { - throw new CrudException("Invalid Source/Target Urls", Status.BAD_REQUEST); - } - - return matcher.group(2); - } } diff --git a/src/test/java/org/onap/crud/parser/util/EdgePayloadUtilTest.java b/src/test/java/org/onap/crud/parser/util/EdgePayloadUtilTest.java new file mode 100644 index 0000000..f5baae8 --- /dev/null +++ b/src/test/java/org/onap/crud/parser/util/EdgePayloadUtilTest.java @@ -0,0 +1,110 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.crud.parser.util; + +import java.util.ArrayList; +import java.util.List; +import org.junit.Assert; +import org.junit.Test; +import org.onap.crud.entity.Edge; +import org.onap.crud.entity.Vertex; +import org.onap.crud.exception.CrudException; + +public class EdgePayloadUtilTest { + + @Test + public void testGetVertexNodeType() throws CrudException { + Assert.assertEquals("vserver", EdgePayloadUtil + .getVertexNodeType("services/inventory/v12/vserver/50bdab41-ad1c-4d00-952c-a0aa5d827811")); + } + + @Test + public void testGetVertexNodeId() throws CrudException { + Assert.assertEquals("50bdab41-ad1c-4d00-952c-a0aa5d827811", + EdgePayloadUtil.getVertexNodeId("services/inventory/v12/vserver/50bdab41-ad1c-4d00-952c-a0aa5d827811")); + } + + @Test + public void testGenerateEdgeKey() throws CrudException { + Assert.assertEquals("vserver:pserver:tosca.relationships.HostedOn", + EdgePayloadUtil.generateEdgeKey("services/inventory/v12/vserver/50bdab41-ad1c-4d00-952c-a0aa5d827811", + "services/inventory/v12/pserver/1d326bc7-b985-492b-9604-0d5d1f06f908", + "tosca.relationships.HostedOn")); + } + + @Test + public void testKeyGenerationEnforcesSourceAndTargetOrder() throws Exception { + String generateEdgeKey1 = EdgePayloadUtil.generateEdgeKey( + "services/inventory/v12/vserver/50bdab41-ad1c-4d00-952c-a0aa5d827811", + "services/inventory/v12/pserver/1d326bc7-b985-492b-9604-0d5d1f06f908", "tosca.relationships.HostedOn"); + + String generateEdgeKey2 = EdgePayloadUtil.generateEdgeKey( + "services/inventory/v12/pserver/1d326bc7-b985-492b-9604-0d5d1f06f908", + "services/inventory/v12/vserver/50bdab41-ad1c-4d00-952c-a0aa5d827811", "tosca.relationships.HostedOn"); + + Assert.assertNotEquals(generateEdgeKey1, generateEdgeKey2); + } + + + @Test + public void testGetBuilderFromEdgePayload() throws CrudException { + Edge.Builder builder = EdgePayloadUtil.getBuilderFromEdgePayload( + "services/inventory/v12/vserver/50bdab41-ad1c-4d00-952c-a0aa5d827811", + "services/inventory/v12/pserver/1d326bc7-b985-492b-9604-0d5d1f06f908", "tosca.relationships.HostedOn"); + + Edge edge = builder.build(); + Assert.assertEquals("tosca.relationships.HostedOn", edge.getType()); + Assert.assertEquals("vserver", edge.getSource().getType()); + Assert.assertEquals("50bdab41-ad1c-4d00-952c-a0aa5d827811", edge.getSource().getId().get()); + Assert.assertEquals("pserver", edge.getTarget().getType()); + Assert.assertEquals("1d326bc7-b985-492b-9604-0d5d1f06f908", edge.getTarget().getId().get()); + } + + @Test + public void tesGetBuilderFromEdge() throws CrudException { + Edge edge = createEdge("vserver", "pserver"); + + Assert.assertNotNull(edge); + Assert.assertNotNull(EdgePayloadUtil.getBuilderFromEdge(edge)); + } + + @Test + public void testFilterEdgesByRelatedVertexAndType() throws CrudException { + List edges = new ArrayList<>(); + edges.add(createEdge("vserver", "pserver")); + edges.add(createEdge("vce", "pserver")); + edges.add(createEdge("snapshot", "pserver")); + edges.add(createEdge("vserver", "pserver")); + + List filteredEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType("vserver", "tosca.relationships.HostedOn", edges); + + Assert.assertNotNull(filteredEdges); + Assert.assertEquals(2, filteredEdges.size()); + } + + private Edge createEdge(String sourceVertexType, String targetVertexType) { + return new Edge.Builder("tosca.relationships.HostedOn").id("test") + .source(new Vertex.Builder(sourceVertexType).id("50bdab41-ad1c-4d00-952c-a0aa5d827811").build()) + .target(new Vertex.Builder(targetVertexType).id("1d326bc7-b985-492b-9604-0d5d1f06f908").build()) + .build(); + } +} diff --git a/src/test/java/org/onap/crud/service/AaiResourceServiceTest.java b/src/test/java/org/onap/crud/service/AaiResourceServiceTest.java index 5eb8a68..c23f3ac 100644 --- a/src/test/java/org/onap/crud/service/AaiResourceServiceTest.java +++ b/src/test/java/org/onap/crud/service/AaiResourceServiceTest.java @@ -33,8 +33,7 @@ import org.onap.aai.serialization.db.EdgeRule; import org.onap.aai.serialization.db.EdgeRules; import org.onap.aai.serialization.db.EdgeType; import org.onap.crud.exception.CrudException; -import org.onap.crud.service.EdgePayload; - +import org.onap.crud.parser.EdgePayload; import com.google.gson.JsonElement; public class AaiResourceServiceTest { diff --git a/src/test/java/org/onap/crud/service/BulkPayloadTest.java b/src/test/java/org/onap/crud/service/BulkPayloadTest.java index 89c2269..c768339 100644 --- a/src/test/java/org/onap/crud/service/BulkPayloadTest.java +++ b/src/test/java/org/onap/crud/service/BulkPayloadTest.java @@ -25,7 +25,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import org.junit.Test; - +import org.onap.crud.parser.BulkPayload; import java.util.ArrayList; import java.util.List; import java.util.Map; diff --git a/src/test/java/org/onap/crud/service/CrudRestServiceTest.java b/src/test/java/org/onap/crud/service/CrudRestServiceTest.java index 68c876c..ddf3847 100644 --- a/src/test/java/org/onap/crud/service/CrudRestServiceTest.java +++ b/src/test/java/org/onap/crud/service/CrudRestServiceTest.java @@ -36,7 +36,6 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.mockito.Mockito; import org.onap.crud.exception.CrudException; -import org.onap.crud.service.TestDao; import org.onap.crud.service.util.TestHeaders; import org.onap.crud.service.util.TestRequest; import org.onap.crud.service.util.TestUriInfo; @@ -50,36 +49,36 @@ public class CrudRestServiceTest { "\"properties\": {" + "\"fqdn\": \"myhost.onap.com\"," + "\"hostname\": \"myhost\" } }"; - + private final String postVertexPayload = "{" + "\"type\": \"pserver\"," + "\"properties\": {" + "\"fqdn\": \"myhost.onap.com\"," + "\"hostname\": \"myhost\" } }"; - + private final String postMissingPropVertexPayload = "{" + "\"type\": \"pserver\"," + "\"properties\": {" + "\"fqdn\": \"myhost.onap.com\"," + "\"equip-type\": \"box\" } }"; - + private final String postEdgePayload = "{" + "\"type\": \"tosca.relationships.HostedOn\"," + - "\"source\": \"services/inventory/v12/vserver/50bdab41-ad1c-4d00-952c-a0aa5d827811\"," + - "\"target\": \"services/inventory/v12/pserver/1d326bc7-b985-492b-9604-0d5d1f06f908\"," + + "\"source\": \"services/inventory/v11/vserver/50bdab41-ad1c-4d00-952c-a0aa5d827811\"," + + "\"target\": \"services/inventory/v11/pserver/1d326bc7-b985-492b-9604-0d5d1f06f908\"," + "\"properties\": {" + "\"prevent-delete\": \"NONE\" } }"; - + private CrudRestService mockService; - + @Rule public ExpectedException thrown = ExpectedException.none(); @Before public void init() throws Exception { ClassLoader classLoader = getClass().getClassLoader(); - File dir = new File(classLoader.getResource("model").getFile()); + File dir = new File(classLoader.getResource("rules").getFile()); System.setProperty("CONFIG_HOME", dir.getParent()); EdgeRulesLoader.resetSchemaVersionContext(); @@ -91,150 +90,170 @@ public class CrudRestServiceTest { Mockito.anyString(), Mockito.anyString(), Mockito.any(CrudRestService.Action.class), Mockito.anyString(), Mockito.any(HttpHeaders.class)); } - + @Test public void testDelete() throws CrudException { Response response; - - response = mockService.deleteVertex("", "v11", "pserver", "872dd5df-0be9-4167-95e9-2cf4b21165ed", + + response = mockService.deleteVertex("", "v11", "pserver", "872dd5df-0be9-4167-95e9-2cf4b21165ed", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); assertTrue(response.getStatus() == 200); - - response = mockService.deleteEdge("", "v11", "tosca.relationships.HostedOn", - "872dd5df-0be9-4167-95e9-2cf4b21165ed", + + response = mockService.deleteEdge("", "v11", "tosca.relationships.HostedOn", "872dd5df-0be9-4167-95e9-2cf4b21165ed", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); assertTrue(response.getStatus() == 200); } - + @Test public void testAddVertex() throws CrudException { Response response; - + // Cannot find OXM version - response = mockService.addVertex(postVertexPayload, "v8", "services/inventory/v8", + response = mockService.addVertex(postVertexPayload, "v7", "services/inventory/v8", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 500); Assert.assertNull(response.getEntityTag()); - - response = mockService.addVertex(postMissingPropVertexPayload, "v11", "services/inventory/v11", + + response = mockService.addVertex(postMissingPropVertexPayload, "v11", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 400); Assert.assertNull(response.getEntityTag()); - - response = mockService.addVertex(postVertexPayload, "v11", "services/inventory/v11", + + response = mockService.addVertex(postVertexPayload, "v11", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 201); Assert.assertEquals(response.getEntityTag().getValue(), "test123"); - - response = mockService.addVertex(postMissingPropVertexPayload, "v11", "pserver", "services/inventory/v11", + + response = mockService.addVertex(postMissingPropVertexPayload, "v11", "pserver", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 400); Assert.assertNull(response.getEntityTag()); - - response = mockService.addVertex(postVertexPayload, "v11", "pserver", "services/inventory/v11", + + response = mockService.addVertex(postVertexPayload, "v11", "pserver", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 201); Assert.assertEquals(response.getEntityTag().getValue(), "test123"); } - + @Test public void testAddEdge() throws CrudException { Response response; - - response = mockService.addEdge(postEdgePayload, "v11", "services/inventory/v11", + + response = mockService.addEdge(postEdgePayload, "v9", "services/inventory/v9", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 201); Assert.assertEquals(response.getEntityTag().getValue(), "test123"); - - response = mockService.addEdge(postEdgePayload, "v11", "tosca.relationships.HostedOn", "services/inventory/v11", + + response = mockService.addEdge(postEdgePayload, "v9", "tosca.relationships.HostedOn", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 201); Assert.assertEquals(response.getEntityTag().getValue(), "test123"); } - + + @Test + public void testAddEdgeMultiplicityRules() throws CrudException { + Response response; + + response = mockService.addEdge(postEdgePayload, "v10", "services/inventory/v10", + new TestHeaders(), null, new TestRequest()); + Assert.assertEquals("MANY2ONE multiplicity rule broken for Edge:vserver:pserver:tosca.relationships.HostedOn", + response.getEntity().toString()); + Assert.assertEquals(400, response.getStatus()); + + response = mockService.addEdge(postEdgePayload, "v9", "tosca.relationships.HostedOn", "services/inventory/v9", + new TestHeaders(), null, new TestRequest()); + Assert.assertEquals(201, response.getStatus()); + + response = mockService.addEdge(postEdgePayload, "v8", "tosca.relationships.HostedOn", "services/inventory/v8", + new TestHeaders(), null, new TestRequest()); + Assert.assertEquals("ONE2MANY multiplicity rule broken for Edge:vserver:pserver:tosca.relationships.HostedOn", + response.getEntity().toString()); + Assert.assertEquals(400, response.getStatus()); + } + @Test public void testUpdateVertex() throws CrudException { Response response; // Cannot find OXM version - response = mockService.updateVertex(putVertexPayload, "v8", "pserver", "test-uuid", "services/inventory/v8", + response = mockService.updateVertex(putVertexPayload, "v7", "pserver", "test-uuid", "services/inventory/v8", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 500); Assert.assertNull(response.getEntityTag()); - + // Test ID mismatch - response = mockService.updateVertex(putVertexPayload, "v11", "pserver", "bad-id", + response = mockService.updateVertex(putVertexPayload, "v11", "pserver", "bad-id", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 400); - Assert.assertNull(response.getEntityTag()); - + Assert.assertNull(response.getEntityTag()); + // Success case response = mockService.updateVertex(putVertexPayload, "v11", "pserver", "test-uuid", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); - assertTrue(response.getStatus() == 200); + assertTrue(response.getStatus() == 200); Assert.assertEquals(response.getEntityTag().getValue(), "test123"); - + // Patch - response = mockService.patchVertex(putVertexPayload, "v11", "pserver", "test-uuid", + response = mockService.patchVertex(putVertexPayload, "v11", "pserver", "test-uuid", "services/inventory/v11", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); - assertTrue(response.getStatus() == 200); + assertTrue(response.getStatus() == 200); Assert.assertEquals(response.getEntityTag().getValue(), "test123"); } - + @Test public void testUpdateEdge() throws CrudException { Response response; - - response = mockService.updateEdge(postEdgePayload, "v11", "tosca.relationships.HostedOn", "my-uuid", - "services/inventory/v11", new TestHeaders(), null, new TestRequest()); + + response = mockService.updateEdge(postEdgePayload, "v9", "tosca.relationships.HostedOn", "my-uuid", + "services/inventory/v9", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); - assertTrue(response.getStatus() == 200); + assertTrue(response.getStatus() == 200); Assert.assertEquals(response.getEntityTag().getValue(), "test123"); - + // Patch - response = mockService.patchEdge(postEdgePayload, "v11", "tosca.relationships.HostedOn", "my-uuid", - "services/inventory/v11", new TestHeaders(), null, new TestRequest()); + response = mockService.patchEdge(postEdgePayload, "v9", "tosca.relationships.HostedOn", "my-uuid", + "services/inventory/v9", new TestHeaders(), null, new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 200); Assert.assertEquals(response.getEntityTag().getValue(), "test123"); } - + @Test public void testGet() throws CrudException { Response response; - - response = mockService.getVertex("", "v11", "pserver", "872dd5df-0be9-4167-95e9-2cf4b21165ed", + + response = mockService.getVertex("", "v11", "pserver", "872dd5df-0be9-4167-95e9-2cf4b21165ed", "services/inventory/v11", new TestHeaders(), new TestUriInfo(), new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 200); - - response = mockService.getEdge("", "v11", "tosca.relationships.HostedOn", "872dd5df-0be9-4167-95e9-2cf4b21165ed", + + response = mockService.getEdge("", "v11", "tosca.relationships.HostedOn", "872dd5df-0be9-4167-95e9-2cf4b21165ed", "services/inventory/v11", new TestHeaders(), new TestUriInfo(), new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 200); - - response = mockService.getVertices("", "v11", "pserver", + + response = mockService.getVertices("", "v11", "pserver", "services/inventory/v11", new TestHeaders(), new TestUriInfo(), new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 200); - - response = mockService.getEdges("", "v11", "tosca.relationships.HostedOn", + + response = mockService.getEdges("", "v11", "tosca.relationships.HostedOn", "services/inventory/v11", new TestHeaders(), new TestUriInfo(), new TestRequest()); System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 200); } - + @Test public void testValidRequestHeader() throws CrudException { TestHeaders testHeaders = new TestHeaders(); @@ -270,7 +289,7 @@ public class CrudRestServiceTest { testHeaders.clearRequestHeader("X-TransactionId", "X-FromAppId"); mockService.validateRequestHeader(testHeaders); } - + @Test public void testEmptyRequestHeader() throws CrudException { thrown.expect(CrudException.class); @@ -306,21 +325,21 @@ public class CrudRestServiceTest { System.out.println("Response: " + response.getStatus() + "\n" + response.getEntity().toString()); assertTrue(response.getStatus() == 200); } - + @Test public void testBulk() throws CrudException, IOException { Response response; - + File bulkFile = new File("src/test/resources/payloads/bulk.json"); - String payloadStr = readFileToString(bulkFile); + String payloadStr = readFileToString(bulkFile); System.out.println(payloadStr); - - response = mockService.addBulk(payloadStr, "v11", "", - "services/inventory/v11", new TestHeaders(), null, new TestRequest()); + + response = mockService.addBulk(payloadStr, "v9", "", + "services/inventory/v9", new TestHeaders(), null, new TestRequest()); System.out.println("Bulk Response: " + response.getStatus() + "\n" + response.getEntity().toString()); - assertTrue(response.getStatus() == 200); + assertTrue(response.getStatus() == 200); } - + public static String readFileToString(File aFile) throws IOException { BufferedReader br = new BufferedReader(new FileReader(aFile)); diff --git a/src/test/java/org/onap/crud/util/CrudServiceUtilTest.java b/src/test/java/org/onap/crud/util/CrudServiceUtilTest.java index 872586e..37cdeec 100644 --- a/src/test/java/org/onap/crud/util/CrudServiceUtilTest.java +++ b/src/test/java/org/onap/crud/util/CrudServiceUtilTest.java @@ -22,7 +22,7 @@ package org.onap.crud.util; import org.junit.Assert; import org.junit.Test; -import org.onap.crud.service.VertexPayload; +import org.onap.crud.parser.VertexPayload; import org.onap.crud.service.util.TestHeaders; import com.google.gson.JsonElement; diff --git a/src/test/java/org/onap/schema/RelationshipSchemaTest.java b/src/test/java/org/onap/schema/RelationshipSchemaTest.java index 9467f41..a32762f 100644 --- a/src/test/java/org/onap/schema/RelationshipSchemaTest.java +++ b/src/test/java/org/onap/schema/RelationshipSchemaTest.java @@ -20,18 +20,16 @@ */ package org.onap.schema; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; +import static org.junit.Assert.*; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import org.junit.Test; import org.onap.aai.edges.EdgeRule; import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException; import org.onap.crud.exception.CrudException; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import static org.junit.Assert.*; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; public class RelationshipSchemaTest { diff --git a/src/test/java/org/onap/schema/validation/MultiplicityValidatorTest.java b/src/test/java/org/onap/schema/validation/MultiplicityValidatorTest.java new file mode 100644 index 0000000..409ce3c --- /dev/null +++ b/src/test/java/org/onap/schema/validation/MultiplicityValidatorTest.java @@ -0,0 +1,159 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.schema.validation; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.crud.entity.Edge; +import org.onap.crud.entity.Vertex; +import org.onap.crud.exception.CrudException; +import org.onap.crud.parser.EdgePayload; +import org.onap.schema.EdgeRulesLoader; +import org.onap.schema.validation.MultiplicityValidator.MultiplicityType; + +public class MultiplicityValidatorTest { + + private final String postEdgePayload = "{" + "\"type\": \"tosca.relationships.HostedOn\"," + + "\"source\": \"services/inventory/v12/vserver/50bdab41-ad1c-4d00-952c-a0aa5d827811\"," + + "\"target\": \"services/inventory/v12/pserver/1d326bc7-b985-492b-9604-0d5d1f06f908\"," + + "\"properties\": {" + "\"prevent-delete\": \"NONE\" } }"; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Before + public void init() { + ClassLoader classLoader = getClass().getClassLoader(); + File dir = new File(classLoader.getResource("rules").getFile()); + System.setProperty("CONFIG_HOME", dir.getParent()); + EdgeRulesLoader.resetSchemaVersionContext(); + } + + @Test + public void testValidPayloadForMultiplicityRule() throws CrudException { + Map> vertexMap = getEdgesForVertex(MultiplicityType.MANY2ONE, true); + MultiplicityValidator.validatePayloadMultiplicity(EdgePayload.fromJson(postEdgePayload), + vertexMap.get("source"), vertexMap.get("target"), + "tosca.relationships.HostedOn", "v11"); + } + + @Test + public void testInvalidPayloadForMultiplicityRule() throws CrudException { + thrown.expect(CrudException.class); + thrown.expectMessage("MANY2ONE multiplicity rule broken for Edge:vserver:pserver:tosca.relationships.HostedOn"); + + Map> vertexMap = getEdgesForVertex(MultiplicityType.MANY2ONE, false); + MultiplicityValidator.validatePayloadMultiplicity(EdgePayload.fromJson(postEdgePayload), + vertexMap.get("source"), vertexMap.get("target"), + "tosca.relationships.HostedOn", "v11"); + } + + @Test + public void testIsVertexValidForMultiplicityType() throws CrudException { + + Map> vertexMap = getEdgesForVertex(MultiplicityType.MANY2MANY, true); + Assert.assertTrue(MultiplicityValidator.isVertexValidForMultiplicityType(vertexMap.get("source"), + vertexMap.get("target"), MultiplicityType.MANY2MANY)); + + vertexMap = getEdgesForVertex(MultiplicityType.MANY2ONE, true); + Assert.assertTrue(MultiplicityValidator.isVertexValidForMultiplicityType( + vertexMap.get("source"), vertexMap.get("target"), MultiplicityType.MANY2ONE)); + + vertexMap = getEdgesForVertex(MultiplicityType.ONE2MANY, true); + Assert.assertTrue(MultiplicityValidator.isVertexValidForMultiplicityType( + vertexMap.get("source"), vertexMap.get("target"), MultiplicityType.ONE2MANY)); + + vertexMap = getEdgesForVertex(MultiplicityType.ONE2ONE, true); + Assert.assertTrue(MultiplicityValidator.isVertexValidForMultiplicityType( + vertexMap.get("source"), vertexMap.get("target"), MultiplicityType.ONE2ONE)); + + vertexMap = getEdgesForVertex(MultiplicityType.ONE2MANY, false); + Assert.assertFalse(MultiplicityValidator.isVertexValidForMultiplicityType( + vertexMap.get("source"), vertexMap.get("target"), MultiplicityType.ONE2MANY)); + + vertexMap = getEdgesForVertex(MultiplicityType.ONE2ONE, false); + Assert.assertFalse(MultiplicityValidator.isVertexValidForMultiplicityType( + vertexMap.get("source"), vertexMap.get("target"), MultiplicityType.ONE2ONE)); + } + + private Map> getEdgesForVertex(MultiplicityType multiplicityType, boolean pass) { + + Map> vertexMap = new HashMap>(); + List edgesForSourceVertex = new ArrayList<>(); + List edgesForTargetVertex = new ArrayList<>(); + + switch (multiplicityType) { + case MANY2MANY: + if (pass) { + Edge edge = new Edge.Builder("type").source(new Vertex.Builder("source").build()) + .target(new Vertex.Builder("target").build()).build(); + edgesForSourceVertex.add(edge); + edgesForTargetVertex.add(edge); + } + break; + case MANY2ONE: + if (pass) { + Edge edge = new Edge.Builder("type").source(new Vertex.Builder("source").build()) + .target(new Vertex.Builder("target").build()).build(); + edgesForTargetVertex.add(edge); + } else { + Edge edge = new Edge.Builder("type").source(new Vertex.Builder("source").build()) + .target(new Vertex.Builder("target").build()).build(); + edgesForSourceVertex.add(edge); + edgesForTargetVertex.add(edge); + } + break; + case ONE2MANY: + if (pass) { + Edge edge = new Edge.Builder("type").source(new Vertex.Builder("source").build()) + .target(new Vertex.Builder("target").build()).build(); + edgesForSourceVertex.add(edge); + } else { + Edge edge = new Edge.Builder("type").source(new Vertex.Builder("source").build()) + .target(new Vertex.Builder("target").build()).build(); + edgesForSourceVertex.add(edge); + edgesForTargetVertex.add(edge); + } + break; + case ONE2ONE: + if (!pass) { + Edge edge = new Edge.Builder("type").source(new Vertex.Builder("source").build()) + .target(new Vertex.Builder("target").build()).build(); + edgesForSourceVertex.add(edge); + edgesForTargetVertex.add(edge); + } + break; + } + vertexMap.put("source", edgesForSourceVertex); + vertexMap.put("target", edgesForTargetVertex); + + return vertexMap; + } + +} diff --git a/src/test/resources/model/edge_properties_v10.json b/src/test/resources/edgeProps/edge_properties_v10.json similarity index 100% rename from src/test/resources/model/edge_properties_v10.json rename to src/test/resources/edgeProps/edge_properties_v10.json diff --git a/src/test/resources/model/edge_properties_v8.json b/src/test/resources/edgeProps/edge_properties_v8.json similarity index 100% rename from src/test/resources/model/edge_properties_v8.json rename to src/test/resources/edgeProps/edge_properties_v8.json diff --git a/src/test/resources/model/edge_properties_v9.json b/src/test/resources/edgeProps/edge_properties_v9.json similarity index 100% rename from src/test/resources/model/edge_properties_v9.json rename to src/test/resources/edgeProps/edge_properties_v9.json diff --git a/src/test/resources/model/edge_properties_v11.json b/src/test/resources/model/edge_properties_v11.json deleted file mode 100644 index 8d00636..0000000 --- a/src/test/resources/model/edge_properties_v11.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "contains-other-v": "java.lang.String", - "delete-other-v": "java.lang.String", - "SVC-INFRA": "java.lang.String", - "prevent-delete": "java.lang.String" -} \ No newline at end of file diff --git a/src/test/resources/oxm/aai_oxm_v10.xml b/src/test/resources/oxm/aai_oxm_v10.xml new file mode 100644 index 0000000..5c3d450 --- /dev/null +++ b/src/test/resources/oxm/aai_oxm_v10.xml @@ -0,0 +1,6363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/oxm/aai_oxm_v8.xml b/src/test/resources/oxm/aai_oxm_v8.xml new file mode 100644 index 0000000..5c3d450 --- /dev/null +++ b/src/test/resources/oxm/aai_oxm_v8.xml @@ -0,0 +1,6363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/oxm/aai_oxm_v9.xml b/src/test/resources/oxm/aai_oxm_v9.xml new file mode 100644 index 0000000..5c3d450 --- /dev/null +++ b/src/test/resources/oxm/aai_oxm_v9.xml @@ -0,0 +1,6363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/model/DbEdgeRules_v10.json b/src/test/resources/rules/DbEdgeRules_v10.json similarity index 99% rename from src/test/resources/model/DbEdgeRules_v10.json rename to src/test/resources/rules/DbEdgeRules_v10.json index 0381090..01d042b 100644 --- a/src/test/resources/model/DbEdgeRules_v10.json +++ b/src/test/resources/rules/DbEdgeRules_v10.json @@ -1320,6 +1320,17 @@ "SVC-INFRA": "${direction}", "prevent-delete": "!${direction}" }, + { + "from": "vserver", + "to": "pserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "Many2One", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}" + }, { "from": "vserver", "to": "volume", diff --git a/src/test/resources/model/DbEdgeRules_v8.json b/src/test/resources/rules/DbEdgeRules_v8.json similarity index 99% rename from src/test/resources/model/DbEdgeRules_v8.json rename to src/test/resources/rules/DbEdgeRules_v8.json index 6d5b06f..872c80f 100644 --- a/src/test/resources/model/DbEdgeRules_v8.json +++ b/src/test/resources/rules/DbEdgeRules_v8.json @@ -1188,6 +1188,17 @@ "SVC-INFRA": "${direction}", "prevent-delete": "!${direction}" }, + { + "from": "vserver", + "to": "pserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "One2Many", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}" + }, { "from": "vserver", "to": "volume", diff --git a/src/test/resources/model/DbEdgeRules_v9.json b/src/test/resources/rules/DbEdgeRules_v9.json similarity index 99% rename from src/test/resources/model/DbEdgeRules_v9.json rename to src/test/resources/rules/DbEdgeRules_v9.json index 88801e4..163bb56 100644 --- a/src/test/resources/model/DbEdgeRules_v9.json +++ b/src/test/resources/rules/DbEdgeRules_v9.json @@ -1265,6 +1265,17 @@ "SVC-INFRA": "${direction}", "prevent-delete": "!${direction}" }, + { + "from": "vserver", + "to": "pserver", + "label": "tosca.relationships.HostedOn", + "direction": "OUT", + "multiplicity": "Many2Many", + "contains-other-v": "NONE", + "delete-other-v": "NONE", + "SVC-INFRA": "${direction}", + "prevent-delete": "!${direction}" + }, { "from": "vserver", "to": "volume", -- 2.16.6