Refactor HttpEntryTest
[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         edge.property(EdgeProperty.CONTAINS.toString(), rule.getContains());
211         edge.property(EdgeProperty.DELETE_OTHER_V.toString(), rule.getDeleteOtherV());
212         edge.property(EdgeProperty.PREVENT_DELETE.toString(), rule.getPreventDelete());
213         edge.property(EdgeField.PRIVATE.toString(), rule.isPrivateEdge());
214         edge.property(AAIProperties.AAI_UUID, UUID.randomUUID().toString());
215     }
216
217     /**
218      * Validate multiplicity.
219      *
220      * @param rule the rule
221      * @param aVertex the out vertex
222      * @param bVertex the in vertex
223      * @return true, if successful
224      * @throws AAIException the AAI exception
225      */
226     private Optional<String> validateMultiplicity(EdgeRule rule, GraphTraversalSource traversalSource, Vertex aVertex,
227             Vertex bVertex) {
228
229         Vertex a = aVertex;
230         Vertex b = bVertex;
231
232         if (rule.getDirection().equals(Direction.OUT)) {
233             a = aVertex;
234             b = bVertex;
235         } else if (rule.getDirection().equals(Direction.IN)) {
236             a = bVertex;
237             b = aVertex;
238         }
239
240         String aVertexType = a.<String>property(AAIProperties.NODE_TYPE).orElse(null);
241         String bVertexType = b.<String>property(AAIProperties.NODE_TYPE).orElse(null);
242         String label = rule.getLabel();
243
244         MultiplicityRule multiplicityRule = rule.getMultiplicityRule();
245
246         String detail = "";
247         final String msg = "multiplicity rule violated: only one edge can exist with label: ";
248
249         if (multiplicityRule.equals(MultiplicityRule.ONE2ONE)) {
250             Long outEdgesCnt = traversalSource.V(a).out(label).has(AAIProperties.NODE_TYPE, bVertexType).count().next();
251             Long inEdgesCnt = traversalSource.V(b).in(label).has(AAIProperties.NODE_TYPE, aVertexType).count().next();
252             if (aVertexType.equals(bVertexType)) {
253                 inEdgesCnt = inEdgesCnt
254                         + traversalSource.V(a).in(label).has(AAIProperties.NODE_TYPE, aVertexType).count().next();
255                 outEdgesCnt = outEdgesCnt
256                         + traversalSource.V(b).out(label).has(AAIProperties.NODE_TYPE, bVertexType).count().next();
257             }
258             if ((inEdgesCnt != 0) || (outEdgesCnt != 0)) {
259                 detail = msg + label + " between " + aVertexType + " and " + bVertexType;
260             }
261         } else if (multiplicityRule.equals(MultiplicityRule.ONE2MANY)) {
262             Long inEdgesCnt = traversalSource.V(b).in(label).has(AAIProperties.NODE_TYPE, aVertexType).count().next();
263             if (inEdgesCnt != 0) {
264                 detail = msg + label + " between " + aVertexType + " and " + bVertexType;
265             }
266         } else if (multiplicityRule.equals(MultiplicityRule.MANY2ONE)) {
267             Long outEdgesCnt = traversalSource.V(a).out(label).has(AAIProperties.NODE_TYPE, bVertexType).count().next();
268             if (outEdgesCnt != 0) {
269                 detail = msg + label + " between " + aVertexType + " and " + bVertexType;
270             }
271         }
272
273         if (!"".equals(detail)) {
274             return Optional.of(detail);
275         } else {
276             return Optional.empty();
277         }
278     }
279 }