2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.openecomp.aai.serialization.db;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
29 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
30 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
31 import org.apache.tinkerpop.gremlin.structure.Direction;
32 import org.apache.tinkerpop.gremlin.structure.Edge;
33 import org.apache.tinkerpop.gremlin.structure.Vertex;
35 import org.openecomp.aai.db.props.AAIProperties;
36 import org.openecomp.aai.dbmodel.DbEdgeRules;
37 import org.openecomp.aai.exceptions.AAIException;
38 import org.openecomp.aai.serialization.db.exceptions.NoEdgeRuleFoundException;
39 import com.google.common.collect.ArrayListMultimap;
40 import com.google.common.collect.Multimap;
42 public class EdgeRules {
44 private Multimap<String, String> rules = DbEdgeRules.EdgeRules;
45 private Multimap<String, String> deleteScope = DbEdgeRules.DefaultDeleteScope;
46 private final int EDGE_NAME = 0;
47 private final int DIRECTION = 1;
48 private final int MULTIPLICITY_RULE = 2;
49 private final int IS_PARENT = 3;
50 private final int USES_RESOURCE = 4;
51 private final int HAS_DEL_TARGET = 5;
52 private final int SVC_INFRA = 6;
55 * Instantiates a new edge rules.
60 private static class Helper {
61 private static final EdgeRules INSTANCE = new EdgeRules();
66 * Gets the single instance of EdgeRules.
68 * @return single instance of EdgeRules
70 public static EdgeRules getInstance() {
71 return Helper.INSTANCE;
78 * @param aVertex the out vertex
79 * @param bVertex the in vertex
81 * @throws AAIException the AAI exception
82 * @throws NoEdgeRuleFoundException
84 public Edge addTreeEdge(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException {
85 return this.addEdge(EdgeType.TREE, traversalSource, aVertex, bVertex);
91 * @param aVertex the out vertex
92 * @param bVertex the in vertex
94 * @throws AAIException the AAI exception
95 * @throws NoEdgeRuleFoundException
97 public Edge addEdge(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException {
98 return this.addEdge(EdgeType.COUSIN, traversalSource, aVertex, bVertex);
104 * @param type the type
105 * @param aVertex the out vertex
106 * @param bVertex the in vertex
108 * @throws AAIException the AAI exception
109 * @throws NoEdgeRuleFoundException
111 private Edge addEdge(EdgeType type, GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException, NoEdgeRuleFoundException {
113 EdgeRule rule = this.getEdgeRule(type, aVertex, bVertex);
116 if (this.validateMultiplicity(rule, traversalSource, aVertex, bVertex)) {
117 if (rule.getDirection().equals(Direction.OUT)) {
118 e = aVertex.addEdge(rule.getLabel(), bVertex);
119 } else if (rule.getDirection().equals(Direction.IN)) {
120 e = bVertex.addEdge(rule.getLabel(), aVertex);
123 this.addProperties(e, rule);
129 * Adds the properties.
131 * @param edge the edge
132 * @param rule the rule
134 public void addProperties(Edge edge, EdgeRule rule) {
136 // In DbEdgeRules.EdgeRules -- What we have as "edgeRule" is a comma-delimited set of strings.
137 // The first item is the edgeLabel.
138 // The second in the list is always "direction" which is always OUT for the way we've implemented it.
139 // Items starting at "firstTagIndex" and up are all assumed to be booleans that map according to
140 // tags as defined in EdgeInfoMap.
141 // Note - if they are tagged as 'reverse', that means they get the tag name with "-REV" on it
142 Map<String, String> propMap = rule.getEdgeProperties();
144 for (String key : propMap.keySet()) {
145 String revKeyname = key + "-REV";
146 String triple = propMap.get(key);
147 if(triple.equals("true")){
148 edge.property(key, true);
149 edge.property(revKeyname,false);
150 } else if (triple.equals("false")) {
151 edge.property(key, false);
152 edge.property(revKeyname,false);
153 } else if (triple.equals("reverse")) {
154 edge.property(key, false);
155 edge.property(revKeyname,true);
161 * Checks for edge rule.
163 * @param outType the out type
164 * @param inType the in type
165 * @return true, if successful
167 public boolean hasEdgeRule(String outType, String inType) {
169 Collection<String> collection = rules.get(outType + "|" + inType);
171 return !collection.isEmpty();
176 * Checks for edge rule.
178 * @param aVertex the out vertex
179 * @param bVertex the in vertex
180 * @return true, if successful
182 public boolean hasEdgeRule(Vertex aVertex, Vertex bVertex) {
183 String outType = (String)aVertex.<String>property("aai-node-type").orElse(null);
184 String inType = (String)bVertex.<String>property("aai-node-type").orElse(null);
186 return this.hasEdgeRule(outType, inType);
190 public Map<String, EdgeRule> getEdgeRules(String outType, String inType) throws AAIException {
191 Map<String, EdgeRule> result = new HashMap<>();
192 EdgeRule rule = null;
193 for (EdgeType type : EdgeType.values()) {
195 rule = this.getEdgeRule(type, outType, inType);
196 result.put(rule.getLabel(), rule);
197 } catch (NoEdgeRuleFoundException e) {
205 * Gets the edge rule.
207 * @param outType the out type
208 * @param inType the in type
209 * @return the edge rule
210 * @throws AAIException the AAI exception
212 public EdgeRule getEdgeRule(EdgeType type, String outType, String inType) throws AAIException {
213 EdgeRule rule = new EdgeRule();
214 Collection<String> collection = null;
215 boolean isFlipped = false;
216 if (this.hasEdgeRule(outType, inType) || this.hasEdgeRule(inType, outType)) {
218 String detail = "No EdgeRule found for passed nodeTypes: " + outType + ", " + inType + ".";
219 throw new AAIException("AAI_6120", detail);
221 String key = outType + "|" + inType;
222 collection = rules.get(key);
224 String[] info = null;
225 Iterator<String> iterator = collection.iterator();
226 info = this.findRuleForContext(type, key, iterator);
227 if (info == null) { //didn't find anything in that order, look again
228 key = inType + "|" + outType;
229 collection = rules.get(key);
230 iterator = collection.iterator();
231 info = this.findRuleForContext(type, key, iterator);
235 throw new NoEdgeRuleFoundException("No EdgeRule found for EdgeType: " + type + " and node types: " + outType + " " + inType);
237 rule.setLabel(info[this.EDGE_NAME]);
238 rule.setMultiplicityRule(MultiplicityRule.valueOf(info[this.MULTIPLICITY_RULE].toUpperCase()));
239 rule.setHasDelTarget(info[this.HAS_DEL_TARGET]);
240 rule.setUsesResource(info[this.USES_RESOURCE]);
241 rule.setIsParent(info[this.IS_PARENT]);
242 rule.setServiceInfrastructure(info[this.SVC_INFRA]);
243 Direction direction = Direction.valueOf(info[this.DIRECTION]);
244 if (isFlipped && direction.equals(Direction.OUT)) {
245 rule.setDirection(Direction.IN);
246 } else if (isFlipped && direction.equals(Direction.IN)){
247 rule.setDirection(Direction.OUT);
249 rule.setDirection(direction);
255 private String[] findRuleForContext (EdgeType type, String key, Iterator<String> itr) {
256 String[] result = null;
258 String isParent = "";
259 String[] info = new String[10];
260 while (itr.hasNext()) {
263 isParent = info[this.IS_PARENT];
264 //lazily stop iterating if we find a match
265 //should there be a mismatch between type and isParent,
266 //the caller will receive something.
267 //this operates on the assumption that there are at most two rules
268 //for a given vertex pair
269 if (type.equals(EdgeType.TREE) && (isParent.equals("true") || isParent.equals("reverse"))) {
272 } else if (type.equals(EdgeType.COUSIN) && isParent.equals("false")) {
282 * Gets the edge rule.
284 * @param aVertex the out vertex
285 * @param bVertex the in vertex
286 * @return the edge rule
287 * @throws AAIException the AAI exception
288 * @throws NoEdgeRuleFoundException
290 public EdgeRule getEdgeRule(EdgeType type, Vertex aVertex, Vertex bVertex) throws AAIException, NoEdgeRuleFoundException {
291 String outType = (String)aVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
292 String inType = (String)bVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
294 return this.getEdgeRule(type, outType, inType);
300 * Gets the delete semantic.
302 * @param nodeType the node type
303 * @return the delete semantic
305 public DeleteSemantic getDeleteSemantic(String nodeType) {
306 Collection<String> semanticCollection = deleteScope.get(nodeType);
307 String semantic = semanticCollection.iterator().next();
309 return DeleteSemantic.valueOf(semantic);
314 * Validate multiplicity.
316 * @param rule the rule
317 * @param aVertex the out vertex
318 * @param bVertex the in vertex
319 * @return true, if successful
320 * @throws AAIException the AAI exception
322 private boolean validateMultiplicity(EdgeRule rule, GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException {
324 if (rule.getDirection().equals(Direction.OUT)) {
326 } else if (rule.getDirection().equals(Direction.IN)) {
327 Vertex tempV = bVertex;
332 String aVertexType = aVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
333 String bVertexType = bVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
334 String label = rule.getLabel();
335 MultiplicityRule multiplicityRule = rule.getMultiplicityRule();
336 List<Edge> outEdges = traversalSource.V(aVertex).outE(label).where(__.inV().has(AAIProperties.NODE_TYPE, bVertexType)).toList();
337 List<Edge> inEdges = traversalSource.V(bVertex).inE(label).where(__.outV().has(AAIProperties.NODE_TYPE, aVertexType)).toList();
339 if (multiplicityRule.equals(MultiplicityRule.ONE2ONE)) {
340 if (inEdges.size() >= 1 || outEdges.size() >= 1 ) {
341 detail = "multiplicity rule violated: only one edge can exist with label: " + label + " between " + aVertexType + " and " + bVertexType;
343 } else if (multiplicityRule.equals(MultiplicityRule.ONE2MANY)) {
344 if (inEdges.size() >= 1) {
345 detail = "multiplicity rule violated: only one edge can exist with label: " + label + " between " + aVertexType + " and " + bVertexType;
347 } else if (multiplicityRule.equals(MultiplicityRule.MANY2ONE)) {
348 if (outEdges.size() >= 1) {
349 detail = "multiplicity rule violated: only one edge can exist with label: " + label + " between " + aVertexType + " and " + bVertexType;
355 if (!detail.equals("")) {
356 throw new AAIException("AAI_6140", detail);
363 public Multimap<String, EdgeRule> getAllRules() throws AAIException {
365 Multimap<String, EdgeRule> result = ArrayListMultimap.create();
367 for (String key : this.rules.keySet()) {
370 String[] split = key.split("\\|");
373 result.putAll(key,this.getEdgeRules(outType, inType).values());