Make URIParser code more readable - Part 2
[aai/aai-common.git] / aai-core / src / main / java / org / onap / aai / serialization / db / EdgeSerializer.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 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
10  *
11  *    http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.aai.serialization.db;
22
23 import java.util.EnumMap;
24 import java.util.Map;
25 import java.util.Map.Entry;
26 import java.util.Optional;
27 import java.util.UUID;
28
29 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
30 import org.apache.tinkerpop.gremlin.structure.Direction;
31 import org.apache.tinkerpop.gremlin.structure.Edge;
32 import org.apache.tinkerpop.gremlin.structure.Vertex;
33 import org.onap.aai.db.props.AAIProperties;
34 import org.onap.aai.edges.EdgeIngestor;
35 import org.onap.aai.edges.EdgeRule;
36 import org.onap.aai.edges.EdgeRuleQuery;
37 import org.onap.aai.edges.enums.EdgeField;
38 import org.onap.aai.edges.enums.EdgeProperty;
39 import org.onap.aai.edges.enums.EdgeType;
40 import org.onap.aai.edges.enums.MultiplicityRule;
41 import org.onap.aai.edges.exceptions.AmbiguousRuleChoiceException;
42 import org.onap.aai.edges.exceptions.EdgeRuleNotFoundException;
43 import org.onap.aai.exceptions.AAIException;
44 import org.onap.aai.serialization.db.exceptions.EdgeMultiplicityException;
45 import org.onap.aai.serialization.db.exceptions.MultipleEdgeRuleFoundException;
46 import org.onap.aai.serialization.db.exceptions.NoEdgeRuleFoundException;
47 import org.springframework.beans.factory.annotation.Autowired;
48 import org.springframework.stereotype.Component;
49
50 @Component
51 public class EdgeSerializer {
52
53     @Autowired
54     private EdgeIngestor edgerules;
55
56     public EdgeSerializer(EdgeIngestor ei) {
57         this.edgerules = ei;
58     }
59
60     /**
61      * Adds the tree edge.
62      *
63      * @param aVertex the out vertex
64      * @param bVertex the in vertex
65      * @return the edge
66      * @throws AAIException the AAI exception
67      */
68     public Edge addTreeEdge(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException {
69         return this.addEdge(EdgeType.TREE, traversalSource, aVertex, bVertex, false, null);
70     }
71
72     /**
73      * Adds the edge.
74      *
75      * @param aVertex the out vertex
76      * @param bVertex the in vertex
77      * @return the edge
78      * @throws AAIException the AAI exception
79      */
80     public Edge addEdge(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex) throws AAIException {
81         return this.addEdge(traversalSource, aVertex, bVertex, null);
82     }
83
84     public Edge addEdge(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex, String label)
85             throws AAIException {
86         return this.addEdge(EdgeType.COUSIN, traversalSource, aVertex, bVertex, false, label);
87     }
88
89     public Edge addPrivateEdge(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex, String label)
90             throws AAIException, EdgeRuleNotFoundException, AmbiguousRuleChoiceException {
91         return this.addEdge(EdgeType.COUSIN, traversalSource, aVertex, bVertex, false, label, true);
92     }
93
94     private Edge addEdge(EdgeType type, GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex,
95             boolean isBestEffort, String label, boolean isPrivateEdge)
96             throws AAIException, EdgeRuleNotFoundException, AmbiguousRuleChoiceException {
97
98         EdgeRule rule = null;
99
100         String aType = aVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
101         String bType = bVertex.<String>property(AAIProperties.NODE_TYPE).orElse(null);
102         EdgeRuleQuery edgeQuery =
103                 new EdgeRuleQuery.Builder(aType, bType).label(label).setPrivate(isPrivateEdge).build();
104
105         rule = edgerules.getRule(edgeQuery);
106
107         if (rule.isPrivateEdge() != isPrivateEdge) {
108             return null;
109         }
110
111         Edge e = null;
112
113         Optional<String> message = this.validateMultiplicity(rule, traversalSource, aVertex, bVertex);
114
115         if (message.isPresent() && !isBestEffort) {
116             throw new EdgeMultiplicityException(message.get());
117         }
118         if (!message.isPresent()) {
119             if (rule.getDirection().equals(Direction.OUT)) {
120                 e = aVertex.addEdge(rule.getLabel(), bVertex);
121             } else if (rule.getDirection().equals(Direction.IN)) {
122                 e = bVertex.addEdge(rule.getLabel(), aVertex);
123             }
124
125             this.addProperties(e, rule);
126         }
127         return e;
128     }
129
130     /**
131      * Adds the tree edge.
132      *
133      * @param aVertex the out vertex
134      * @param bVertex the in vertex
135      * @return the edge
136      * @throws AAIException the AAI exception
137      */
138     public Edge addTreeEdgeIfPossible(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex)
139             throws AAIException {
140         return this.addEdge(EdgeType.TREE, traversalSource, aVertex, bVertex, true, null);
141     }
142
143     /**
144      * Adds the edge.
145      *
146      * @param aVertex the out vertex
147      * @param bVertex the in vertex
148      * @return the edge
149      * @throws AAIException the AAI exception
150      */
151     public Edge addEdgeIfPossible(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex)
152             throws AAIException {
153         return this.addEdgeIfPossible(traversalSource, aVertex, bVertex, null);
154     }
155
156     public Edge addEdgeIfPossible(GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex, String label)
157             throws AAIException {
158         return this.addEdge(EdgeType.COUSIN, traversalSource, aVertex, bVertex, true, label);
159     }
160
161     /**
162      * Adds the edge.
163      *
164      * @param type the type
165      * @param aVertex the out vertex
166      * @param bVertex the in vertex
167      * @return the edge
168      * @throws AAIException the AAI exception
169      */
170     private Edge addEdge(EdgeType type, GraphTraversalSource traversalSource, Vertex aVertex, Vertex bVertex,
171             boolean isBestEffort, String label) throws AAIException {
172         String aNodeType = (String) aVertex.property(AAIProperties.NODE_TYPE).value();
173         String bNodeType = (String) bVertex.property(AAIProperties.NODE_TYPE).value();
174         EdgeRuleQuery q = new EdgeRuleQuery.Builder(aNodeType, bNodeType).label(label).edgeType(type).build();
175         EdgeRule rule;
176         try {
177             rule = edgerules.getRule(q);
178         } catch (EdgeRuleNotFoundException e1) {
179             throw new NoEdgeRuleFoundException(e1);
180         } catch (AmbiguousRuleChoiceException e1) {
181             throw new MultipleEdgeRuleFoundException(e1);
182         }
183
184         Edge e = null;
185
186         Optional<String> message = this.validateMultiplicity(rule, traversalSource, aVertex, bVertex);
187
188         if (message.isPresent() && !isBestEffort) {
189             throw new EdgeMultiplicityException(message.get());
190         }
191         if (!message.isPresent()) {
192             if (rule.getDirection().equals(Direction.OUT)) {
193                 e = aVertex.addEdge(rule.getLabel(), bVertex);
194             } else if (rule.getDirection().equals(Direction.IN)) {
195                 e = bVertex.addEdge(rule.getLabel(), aVertex);
196             }
197
198             this.addProperties(e, rule);
199         }
200         return e;
201     }
202
203     /**
204      * Adds the properties.
205      *
206      * @param edge the edge
207      * @param rule the rule
208      */
209     public void addProperties(Edge edge, EdgeRule rule) {
210         Map<EdgeProperty, String> propMap = new EnumMap<>(EdgeProperty.class);
211         propMap.put(EdgeProperty.CONTAINS, rule.getContains());
212         propMap.put(EdgeProperty.DELETE_OTHER_V, rule.getDeleteOtherV());
213         propMap.put(EdgeProperty.PREVENT_DELETE, rule.getPreventDelete());
214
215         for (Entry<EdgeProperty, String> entry : propMap.entrySet()) {
216             edge.property(entry.getKey().toString(), entry.getValue());
217         }
218
219         edge.property(EdgeField.PRIVATE.toString(), rule.isPrivateEdge());
220         edge.property(AAIProperties.AAI_UUID, UUID.randomUUID().toString());
221     }
222
223     /**
224      * Validate multiplicity.
225      *
226      * @param rule the rule
227      * @param aVertex the out vertex
228      * @param bVertex the in vertex
229      * @return true, if successful
230      * @throws AAIException the AAI exception
231      */
232     private Optional<String> validateMultiplicity(EdgeRule rule, GraphTraversalSource traversalSource, Vertex aVertex,
233             Vertex bVertex) {
234
235         Vertex a = aVertex;
236         Vertex b = bVertex;
237
238         if (rule.getDirection().equals(Direction.OUT)) {
239             a = aVertex;
240             b = bVertex;
241         } else if (rule.getDirection().equals(Direction.IN)) {
242             a = bVertex;
243             b = aVertex;
244         }
245
246         String aVertexType = a.<String>property(AAIProperties.NODE_TYPE).orElse(null);
247         String bVertexType = b.<String>property(AAIProperties.NODE_TYPE).orElse(null);
248         String label = rule.getLabel();
249
250         MultiplicityRule multiplicityRule = rule.getMultiplicityRule();
251
252         String detail = "";
253         final String msg = "multiplicity rule violated: only one edge can exist with label: ";
254
255         if (multiplicityRule.equals(MultiplicityRule.ONE2ONE)) {
256             Long outEdgesCnt = traversalSource.V(a).out(label).has(AAIProperties.NODE_TYPE, bVertexType).count().next();
257             Long inEdgesCnt = traversalSource.V(b).in(label).has(AAIProperties.NODE_TYPE, aVertexType).count().next();
258             if (aVertexType.equals(bVertexType)) {
259                 inEdgesCnt = inEdgesCnt
260                         + traversalSource.V(a).in(label).has(AAIProperties.NODE_TYPE, aVertexType).count().next();
261                 outEdgesCnt = outEdgesCnt
262                         + traversalSource.V(b).out(label).has(AAIProperties.NODE_TYPE, bVertexType).count().next();
263             }
264             if ((inEdgesCnt != 0) || (outEdgesCnt != 0)) {
265                 detail = msg + label + " between " + aVertexType + " and " + bVertexType;
266             }
267         } else if (multiplicityRule.equals(MultiplicityRule.ONE2MANY)) {
268             Long inEdgesCnt = traversalSource.V(b).in(label).has(AAIProperties.NODE_TYPE, aVertexType).count().next();
269             if (inEdgesCnt != 0) {
270                 detail = msg + label + " between " + aVertexType + " and " + bVertexType;
271             }
272         } else if (multiplicityRule.equals(MultiplicityRule.MANY2ONE)) {
273             Long outEdgesCnt = traversalSource.V(a).out(label).has(AAIProperties.NODE_TYPE, bVertexType).count().next();
274             if (outEdgesCnt != 0) {
275                 detail = msg + label + " between " + aVertexType + " and " + bVertexType;
276             }
277         }
278
279         if (!"".equals(detail)) {
280             return Optional.of(detail);
281         } else {
282             return Optional.empty();
283         }
284     }
285 }