diff options
Diffstat (limited to 'src/main')
19 files changed, 496 insertions, 242 deletions
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<String, Object> filter, HashSet<String> 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<NameValuePair> 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 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 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 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<Edge>
+ */
+ public static List<Edge> filterEdgesByRelatedVertexAndType(String sourceTargetType, String type, List<Edge> edges) {
+ List<Edge> 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<EdgeProperty, String> 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<EdgeProperty, String> 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<EdgeProperty, String> 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<Edge> sourceVertexEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType(EdgePayloadUtil.getVertexNodeType(edgePayload.getSource()), edgePayload.getType(), + daoForGet.getVertexEdges(EdgePayloadUtil.getVertexNodeId(edgePayload.getSource()), null)); + + List<Edge> 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<Edge> sourceVertexEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType(EdgePayloadUtil.getVertexNodeType(edgePayload.getSource()), edgePayload.getType(), + daoForGet.getVertexEdges(EdgePayloadUtil.getVertexNodeId(edgePayload.getSource()), null)); + + List<Edge> 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<EntityTag, String> 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<String, String>()); 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<EntityTag, String> 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<Edge> sourceVertexEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType(EdgePayloadUtil.getVertexNodeType(payload.getSource()), type, + daoForGet.getVertexEdges(EdgePayloadUtil.getVertexNodeId(payload.getSource()), null)); + + List<Edge> 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<EntityTag, String> 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<String, String>()); + Edge edge = Edge.fromJson(edgeResult.getResult()); + + // load source and target vertex relationships for validation + List<Edge> sourceVertexEdges = + EdgePayloadUtil.filterEdgesByRelatedVertexAndType(EdgePayloadUtil.getVertexNodeType(payload.getSource()), type, + daoForGet.getVertexEdges(EdgePayloadUtil.getVertexNodeId(payload.getSource()), null)); + + List<Edge> 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<String, String>()); - return RelationshipSchemaValidator.validateIncomingUpdatePayload(Edge.fromJson(operationResult.getResult()), version, payload); - } - @Override public ImmutablePair<EntityTag, String> 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..25ab43a 100644 --- a/src/main/java/org/onap/crud/service/CrudRestService.java +++ b/src/main/java/org/onap/crud/service/CrudRestService.java @@ -22,6 +22,7 @@ package org.onap.crud.service; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -52,6 +53,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; @@ -783,7 +787,9 @@ public class CrudRestService { X500Principal subjectDn = clientCert.getSubjectX500Principal(); authUser = subjectDn.toString(); } - isValid = this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName); + if(null != authUser) { + isValid = this.auth.validateRequest(authUser.toLowerCase(), action.toString() + ":" + authPolicyFunctionName); + } } catch (Exception e) { logResult(action, uri, e); return false; @@ -816,7 +822,7 @@ public class CrudRestService { void logResult(Action op, String uri, Exception e) { - logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, op.toString(), uri, e.getStackTrace().toString()); + logger.error(CrudServiceMsgs.EXCEPTION_DURING_METHOD_CALL, op.toString(), uri, Arrays.toString(e.getStackTrace())); // Clear the MDC context so that no other transaction inadvertently // uses our transaction id. 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<String, Map<String, Class<?>>> relations = new HashMap<>(); /** @@ -42,8 +46,18 @@ public class RelationshipSchema { */ private Map<String, Map<String, Class<?>>> relationTypes = new HashMap<>(); - public RelationshipSchema( Multimap<String, EdgeRule> rules, String props) throws CrudException, IOException { + private Map<String, EdgeRule> relationshipRules = new HashMap<>(); + + @SuppressWarnings("unchecked") + public RelationshipSchema(Multimap<String, EdgeRule> rules, String props) throws CrudException, IOException { HashMap<String, String> 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<String, Class<?>> 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<String, Class<?>> 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<Edge> edgesForSourceVertex,
+ List<Edge> 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<Edge> edgesForSourceVertex,
+ List<Edge> 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 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 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<String, Object> resolveCollectionfilter(String version, String type, - Map<String, String> filter) - throws CrudException { + private static final String SOURCE_LABEL = "Source"; + private static final String TARGET_LABEL = "Target"; + public static Map<String, Object> resolveCollectionfilter(String version, String type, Map<String, String> 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<Edge> sourceVertexEdges, List<Edge> 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<String, Class<?>> 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<String,Object> 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<Map.Entry<String, JsonElement>> entries = payload.getProperties() - .getAsJsonObject().entrySet(); + validateEdgePropertiesFromPayload(edge, payload, schemaObject); - for (Map.Entry<String, JsonElement> 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<String, Class<?>> schemaObject) throws CrudException { + Set<Map.Entry<String, JsonElement>> entries = payload.getProperties().getAsJsonObject().entrySet(); + for (Map.Entry<String, JsonElement> 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<Edge> sourceVertexEdges, List<Edge> 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<String, Class<?>> schemaObject) - throws CrudException { + private static void validateEdgeProps(Edge.Builder builder, JsonElement props, Map<String, Class<?>> schemaObject) throws CrudException { Set<Map.Entry<String, JsonElement>> entries = props.getAsJsonObject().entrySet(); for (Map.Entry<String, JsonElement> 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); - } } |