diff options
Diffstat (limited to 'aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java')
-rw-r--r-- | aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java b/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java new file mode 100644 index 00000000..06dfe564 --- /dev/null +++ b/aai-core/src/main/java/org/openecomp/aai/serialization/db/EdgeRules.java @@ -0,0 +1,379 @@ +/*- + * ============LICENSE_START======================================================= + * org.openecomp.aai + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * 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.openecomp.aai.serialization.db; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; + +import org.openecomp.aai.db.props.AAIProperties; +import org.openecomp.aai.dbmodel.DbEdgeRules; +import org.openecomp.aai.exceptions.AAIException; +import org.openecomp.aai.serialization.db.exceptions.NoEdgeRuleFoundException; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Multimap; + +public class EdgeRules { + + private Multimap<String, String> rules = DbEdgeRules.EdgeRules; + private Multimap<String, String> deleteScope = DbEdgeRules.DefaultDeleteScope; + private final int EDGE_NAME = 0; + private final int DIRECTION = 1; + private final int MULTIPLICITY_RULE = 2; + private final int IS_PARENT = 3; + private final int USES_RESOURCE = 4; + private final int HAS_DEL_TARGET = 5; + private final int SVC_INFRA = 6; + + /** + * Instantiates a new edge rules. + */ + private EdgeRules() { + + } + private static class Helper { + private static final EdgeRules INSTANCE = new EdgeRules(); + + } + + /** + * Gets the single instance of EdgeRules. + * + * @return single instance of EdgeRules + */ + public static EdgeRules getInstance() { + return Helper.INSTANCE; + + } + + /** + * Adds the tree edge. + * + * @param aVertex the out vertex + * @param bVertex the in vertex + * @return the edge + * @throws AAIException the AAI exception + * @throws NoEdgeRuleFoundException + */ + public Edge addTreeEdge(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException { + return this.addEdge(EdgeType.TREE, traversalSource, aVertex, bVertex); + } + + /** + * Adds the edge. + * + * @param aVertex the out vertex + * @param bVertex the in vertex + * @return the edge + * @throws AAIException the AAI exception + * @throws NoEdgeRuleFoundException + */ + public Edge addEdge(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException { + return this.addEdge(EdgeType.COUSIN, traversalSource, aVertex, bVertex); + } + + /** + * Adds the edge. + * + * @param type the type + * @param aVertex the out vertex + * @param bVertex the in vertex + * @return the edge + * @throws AAIException the AAI exception + * @throws NoEdgeRuleFoundException + */ + private Edge addEdge(EdgeType type, GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException, NoEdgeRuleFoundException { + + EdgeRule rule = this.getEdgeRule(type, aVertex, bVertex); + + Edge e = null; + if (this.validateMultiplicity(rule, traversalSource, aVertex, bVertex)) { + if (rule.getDirection().equals(Direction.OUT)) { + e = aVertex.addEdge(rule.getLabel(), bVertex); + } else if (rule.getDirection().equals(Direction.IN)) { + e = bVertex.addEdge(rule.getLabel(), aVertex); + } + + this.addProperties(e, rule); + } + return e; + } + + /** + * Adds the properties. + * + * @param edge the edge + * @param rule the rule + */ + public void addProperties(Edge edge, EdgeRule rule) { + + // In DbEdgeRules.EdgeRules -- What we have as "edgeRule" is a comma-delimited set of strings. + // The first item is the edgeLabel. + // The second in the list is always "direction" which is always OUT for the way we've implemented it. + // Items starting at "firstTagIndex" and up are all assumed to be booleans that map according to + // tags as defined in EdgeInfoMap. + // Note - if they are tagged as 'reverse', that means they get the tag name with "-REV" on it + Map<String, String> propMap = rule.getEdgeProperties(); + + for (String key : propMap.keySet()) { + String revKeyname = key + "-REV"; + String triple = propMap.get(key); + if(triple.equals("true")){ + edge.property(key, true); + edge.property(revKeyname,false); + } else if (triple.equals("false")) { + edge.property(key, false); + edge.property(revKeyname,false); + } else if (triple.equals("reverse")) { + edge.property(key, false); + edge.property(revKeyname,true); + } + } + } + + /** + * Checks for edge rule. + * + * @param outType the out type + * @param inType the in type + * @return true, if successful + */ + public boolean hasEdgeRule(String outType, String inType) { + + Collection<String> collection = rules.get(outType + "|" + inType); + + return !collection.isEmpty(); + + } + + /** + * Checks for edge rule. + * + * @param aVertex the out vertex + * @param bVertex the in vertex + * @return true, if successful + */ + public boolean hasEdgeRule(Vertex aVertex, Vertex bVertex) { + String outType = (String)aVertex.<String>property("aai-node-type").orElse(null); + String inType = (String)bVertex.<String>property("aai-node-type").orElse(null); + + return this.hasEdgeRule(outType, inType); + + } + + public Map<String, EdgeRule> getEdgeRules(String outType, String inType) throws AAIException { + Map<String, EdgeRule> result = new HashMap<>(); + EdgeRule rule = null; + for (EdgeType type : EdgeType.values()) { + try { + rule = this.getEdgeRule(type, outType, inType); + result.put(rule.getLabel(), rule); + } catch (NoEdgeRuleFoundException e) { + continue; + } + } + + return result; + } + /** + * Gets the edge rule. + * + * @param outType the out type + * @param inType the in type + * @return the edge rule + * @throws AAIException the AAI exception + */ + public EdgeRule getEdgeRule(EdgeType type, String outType, String inType) throws AAIException { + EdgeRule rule = new EdgeRule(); + Collection<String> collection = null; + boolean isFlipped = false; + if (this.hasEdgeRule(outType, inType) || this.hasEdgeRule(inType, outType)) { + } else { + String detail = "No EdgeRule found for passed nodeTypes: " + outType + ", " + inType + "."; + throw new AAIException("AAI_6120", detail); + } + String key = outType + "|" + inType; + collection = rules.get(key); + + String[] info = null; + Iterator<String> iterator = collection.iterator(); + info = this.findRuleForContext(type, key, iterator); + if (info == null) { //didn't find anything in that order, look again + key = inType + "|" + outType; + collection = rules.get(key); + iterator = collection.iterator(); + info = this.findRuleForContext(type, key, iterator); + isFlipped = true; + } + if (info == null) { + throw new NoEdgeRuleFoundException("No EdgeRule found for EdgeType: " + type + " and node types: " + outType + " " + inType); + } + rule.setLabel(info[this.EDGE_NAME]); + rule.setMultiplicityRule(MultiplicityRule.valueOf(info[this.MULTIPLICITY_RULE].toUpperCase())); + rule.setHasDelTarget(info[this.HAS_DEL_TARGET]); + rule.setUsesResource(info[this.USES_RESOURCE]); + rule.setIsParent(info[this.IS_PARENT]); + rule.setServiceInfrastructure(info[this.SVC_INFRA]); + Direction direction = Direction.valueOf(info[this.DIRECTION]); + if (isFlipped && direction.equals(Direction.OUT)) { + rule.setDirection(Direction.IN); + } else if (isFlipped && direction.equals(Direction.IN)){ + rule.setDirection(Direction.OUT); + } else { + rule.setDirection(direction); + } + + return rule; + } + + private String[] findRuleForContext (EdgeType type, String key, Iterator<String> itr) { + String[] result = null; + String s = ""; + String isParent = ""; + String[] info = new String[10]; + while (itr.hasNext()) { + s = itr.next(); + info = s.split(","); + isParent = info[this.IS_PARENT]; + //lazily stop iterating if we find a match + //should there be a mismatch between type and isParent, + //the caller will receive something. + //this operates on the assumption that there are at most two rules + //for a given vertex pair + if (type.equals(EdgeType.TREE) && (isParent.equals("true") || isParent.equals("reverse"))) { + result = info; + break; + } else if (type.equals(EdgeType.COUSIN) && isParent.equals("false")) { + result = info; + break; + } + } + + + return result; + } + /** + * Gets the edge rule. + * + * @param aVertex the out vertex + * @param bVertex the in vertex + * @return the edge rule + * @throws AAIException the AAI exception + * @throws NoEdgeRuleFoundException + */ + public EdgeRule getEdgeRule(EdgeType type, Vertex aVertex, Vertex bVertex) throws AAIException, NoEdgeRuleFoundException { + String outType = (String)aVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null); + String inType = (String)bVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null); + + return this.getEdgeRule(type, outType, inType); + + + } + + /** + * Gets the delete semantic. + * + * @param nodeType the node type + * @return the delete semantic + */ + public DeleteSemantic getDeleteSemantic(String nodeType) { + Collection<String> semanticCollection = deleteScope.get(nodeType); + String semantic = semanticCollection.iterator().next(); + + return DeleteSemantic.valueOf(semantic); + + } + + /** + * Validate multiplicity. + * + * @param rule the rule + * @param aVertex the out vertex + * @param bVertex the in vertex + * @return true, if successful + * @throws AAIException the AAI exception + */ + private boolean validateMultiplicity(EdgeRule rule, GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException { + + if (rule.getDirection().equals(Direction.OUT)) { + + } else if (rule.getDirection().equals(Direction.IN)) { + Vertex tempV = bVertex; + bVertex = aVertex; + aVertex = tempV; + } + + String aVertexType = aVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null); + String bVertexType = bVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null); + String label = rule.getLabel(); + MultiplicityRule multiplicityRule = rule.getMultiplicityRule(); + List<Edge> outEdges = traversalSource.V(aVertex).outE(label).where(__.inV().has(AAIProperties.NODE_TYPE, bVertexType)).toList(); + List<Edge> inEdges = traversalSource.V(bVertex).inE(label).where(__.outV().has(AAIProperties.NODE_TYPE, aVertexType)).toList(); + String detail = ""; + if (multiplicityRule.equals(MultiplicityRule.ONE2ONE)) { + if (inEdges.size() >= 1 || outEdges.size() >= 1 ) { + detail = "multiplicity rule violated: only one edge can exist with label: " + label + " between " + aVertexType + " and " + bVertexType; + } + } else if (multiplicityRule.equals(MultiplicityRule.ONE2MANY)) { + if (inEdges.size() >= 1) { + detail = "multiplicity rule violated: only one edge can exist with label: " + label + " between " + aVertexType + " and " + bVertexType; + } + } else if (multiplicityRule.equals(MultiplicityRule.MANY2ONE)) { + if (outEdges.size() >= 1) { + detail = "multiplicity rule violated: only one edge can exist with label: " + label + " between " + aVertexType + " and " + bVertexType; + } + } else { + + } + + if (!detail.equals("")) { + throw new AAIException("AAI_6140", detail); + } + + return true; + + } + + public Multimap<String, EdgeRule> getAllRules() throws AAIException { + + Multimap<String, EdgeRule> result = ArrayListMultimap.create(); + + for (String key : this.rules.keySet()) { + String outType = ""; + String inType = ""; + String[] split = key.split("\\|"); + outType = split[0]; + inType = split[1]; + result.putAll(key,this.getEdgeRules(outType, inType).values()); + } + + return result; + } + +} |