Update license date and text
[aai/champ.git] / champ-lib / champ-core / src / main / java / org / onap / aai / champcore / graph / impl / AbstractValidatingChampGraph.java
1 /**
2  * ============LICENSE_START==========================================
3  * org.onap.aai
4  * ===================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017-2018 Amdocs
7  * ===================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *        http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END============================================
20  */
21 package org.onap.aai.champcore.graph.impl;
22
23 import java.util.Map;
24 import java.util.Optional;
25
26 import org.onap.aai.champcore.ChampTransaction;
27 import org.onap.aai.champcore.event.AbstractLoggingChampGraph;
28 import org.onap.aai.champcore.exceptions.ChampMarshallingException;
29 import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
30 import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException;
31 import org.onap.aai.champcore.exceptions.ChampSchemaViolationException;
32 import org.onap.aai.champcore.exceptions.ChampTransactionException;
33 import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
34 import org.onap.aai.champcore.model.ChampObject;
35 import org.onap.aai.champcore.model.ChampObjectConstraint;
36 import org.onap.aai.champcore.model.ChampPartition;
37 import org.onap.aai.champcore.model.ChampRelationship;
38 import org.onap.aai.champcore.model.ChampRelationshipConstraint;
39 import org.onap.aai.champcore.model.ChampSchema;
40 import org.onap.aai.champcore.schema.ChampSchemaEnforcer;
41
42 public abstract class AbstractValidatingChampGraph extends AbstractLoggingChampGraph {
43
44         private ChampSchema schema = ChampSchema.emptySchema();
45
46         protected abstract ChampSchemaEnforcer getSchemaEnforcer();
47         protected abstract boolean isShutdown();
48
49         /**
50          * Updates an existing vertex in the graph data store.
51          * <p>
52      * If a transaction context is not provided, then a transaction will be automatically 
53      * created and committed for this operation only, otherwise, the supplied transaction
54      * will be used and it will be up to the caller to commit the transaction at its 
55      * discretion.
56      * <p>
57      * 
58          * @param object      - The vertex to be updated in the graph data store.
59          * @param transaction - Optional transaction context to perform the operation in.
60          * 
61          * @return - The updated vertex, marshaled as a {@link ChampObject}
62          * 
63          * @throws ChampMarshallingException     - If the {@code relationship} is not able to be 
64      *                                         marshalled into the backend representation
65          * @throws ChampObjectNotExistsException - If {@link org.onap.aai.champcore.model.ChampObject#getKey} 
66      *                                         is not present or object not found in the graph
67          */
68         protected abstract ChampObject doReplaceObject(ChampObject object, Optional<ChampTransaction> transaction) throws ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException, ChampTransactionException;
69         
70     /** 
71      * Creates or updates a vertex in the graph data store.
72      * <p>
73      * If a transaction context is not provided, then a transaction will be automatically 
74      * created and committed for this operation only, otherwise, the supplied transaction
75      * will be used and it will be up to the caller to commit the transaction at its 
76      * discretion.
77      * 
78          * @param object      - The vertex to be stored in the graph data store.
79          * @param transaction - Optional transaction context to perform the operation in.
80          * 
81          * @return - The vertex which was created, marshaled as a {@link ChampObject}
82          * 
83      * @throws ChampMarshallingException     - If the {@code relationship} is not able to be 
84      *                                         marshaled into the back end representation
85      * @throws ChampObjectNotExistsException - If {@link org.onap.aai.champcore.model.ChampObject#getKey} 
86      *                                         is not present or object not found in the graph
87          */
88         protected abstract ChampObject doStoreObject(ChampObject object, Optional<ChampTransaction> transaction) throws ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException;
89         
90         /**
91          * Replaces an edge in the graph data store.
92      * <p>
93      * If a transaction context is not provided, then a transaction will be automatically 
94      * created and committed for this operation only, otherwise, the supplied transaction
95      * will be used and it will be up to the caller to commit the transaction at its 
96      * discretion.
97      * 
98          * @param relationship - The edge to be replaced in the graph data store.
99          * @param transaction  - Optional transaction context to perform the operation in.
100          * 
101          * @return - The edge as it was replaced, marshaled as a {@link ChampRelationship}
102          * 
103          * @throws ChampUnmarshallingException         - If the edge which was created could not be 
104      *                                               unmarshaled into a ChampObject
105          * @throws ChampRelationshipNotExistsException - If {@link org.onap.aai.champcore.model.ChampRelationship#getKey}.isPresent() 
106      *                                               but the object cannot be found in the graph
107          * @throws ChampMarshallingException           - If the {@code relationship} is not able to be 
108      *                                               marshaled into the back end representation
109          */
110         protected abstract ChampRelationship doReplaceRelationship(ChampRelationship relationship, Optional<ChampTransaction> transaction) throws ChampUnmarshallingException, ChampRelationshipNotExistsException, ChampMarshallingException, ChampTransactionException;
111         
112         /**
113          * Creates or updates a relationship in the graph data store.
114      * <p>
115      * If a transaction context is not provided, then a transaction will be automatically 
116      * created and committed for this operation only, otherwise, the supplied transaction
117      * will be used and it will be up to the caller to commit the transaction at its 
118      * discretion.
119      *  
120          * @param relationship - The relationship to be stored in the graph data store.
121          * @param transaction  - Optional transaction context to perform the operation in.
122          * 
123          * @return - The relationship that was stored.
124          * 
125          * @throws ChampUnmarshallingException         - If the edge which was created could not be 
126      *                                               unmarshalled into a ChampObject
127          * @throws ChampObjectNotExistsException       - If {@link org.onap.aai.champcore.model.ChampObject#getKey} 
128      *                                               is not present or object not found in the graph
129          * @throws ChampRelationshipNotExistsException - If {@link org.onap.aai.champcore.model.ChampRelationship#getKey}.isPresent() 
130    *                                                 but the object cannot be found in the graph
131          * @throws ChampMarshallingException           - If the {@code relationship} is not able to be 
132      *                                               marshalled into the backend representation
133          */
134         protected abstract ChampRelationship doStoreRelationship(ChampRelationship relationship, Optional<ChampTransaction> transaction) throws ChampUnmarshallingException, ChampObjectNotExistsException, ChampRelationshipNotExistsException, ChampMarshallingException, ChampTransactionException;
135                 
136         /**
137          * Creates or updates a partition in the graph data store.
138          * 
139          * @param partition   - The partition to be stored in the graph data store.
140          * @param transaction - Optional transaction context to perform the operation in.
141          * 
142          * @return - The partition that was stored.
143          * 
144          * @throws ChampRelationshipNotExistsException - If {@link org.onap.aai.champcore.model.ChampRelationship#getKey}.isPresent() 
145    *                                                 but the object cannot be found in the graph
146          * @throws ChampMarshallingException           - If the {@code relationship} is not able to be 
147      *                                               marshalled into the backend representation
148          * @throws ChampObjectNotExistsException       - If {@link org.onap.aai.champcore.model.ChampObject#getKey} 
149      *                                               is not present or object not found in the graph
150          */
151         protected abstract ChampPartition doStorePartition(ChampPartition partition, Optional<ChampTransaction> transaction) throws ChampRelationshipNotExistsException, ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException;
152
153         protected AbstractValidatingChampGraph(Map<String, Object> properties) {
154           super(properties);
155         }
156         
157         @Override
158         public ChampObject executeStoreObject(ChampObject object, Optional<ChampTransaction> transaction)
159                         throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException {
160           
161           if (isShutdown()) {
162             throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()");
163           }
164
165       validate(object);
166
167       return doStoreObject(object, transaction);
168         }
169           
170
171         @Override
172         public ChampObject executeReplaceObject(ChampObject object, Optional<ChampTransaction> transaction)
173                         throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException {
174           
175                 if (isShutdown()) {
176                   throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()");
177                 }
178
179                 validate(object);
180
181                 return doReplaceObject(object, transaction);
182         }
183
184         @Override
185         public ChampRelationship executeStoreRelationship(ChampRelationship relationship, Optional<ChampTransaction> transaction)
186                         throws ChampUnmarshallingException, ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampTransactionException {   
187                 
188           if (isShutdown()) {
189             throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()");
190           }
191
192           validate(relationship);
193
194           return doStoreRelationship(relationship, transaction);
195         }
196         
197         @Override
198         public ChampRelationship executeReplaceRelationship(ChampRelationship relationship, Optional<ChampTransaction> transaction)
199                         throws ChampUnmarshallingException, ChampMarshallingException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampTransactionException {  
200                 
201           if (isShutdown()) {
202             throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()");
203           }
204
205           validate(relationship);
206
207           return doReplaceRelationship(relationship, transaction);
208         }
209
210         @Override
211         public ChampPartition executeStorePartition(ChampPartition partition, Optional<ChampTransaction> transaction) throws ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException {
212
213           if (isShutdown()) {
214             throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()");
215           }
216
217           validate(partition);
218
219           return doStorePartition(partition, transaction);
220         }
221
222         protected void validate(ChampObject object) throws ChampSchemaViolationException {
223                 final Optional<ChampObjectConstraint> objectConstraint = retrieveSchema().getObjectConstraint(object.getType());
224
225                 if (objectConstraint.isPresent()) getSchemaEnforcer().validate(object, objectConstraint.get());
226         }
227
228         protected void validate(ChampRelationship relationship) throws ChampSchemaViolationException {
229                 final ChampSchema graphSchema = retrieveSchema();
230                 final Optional<ChampRelationshipConstraint> relationshipConstraint = graphSchema.getRelationshipConstraint(relationship.getType());
231                 final Optional<ChampObjectConstraint> sourceObjConstraint = graphSchema.getObjectConstraint(relationship.getSource().getType());
232                 final Optional<ChampObjectConstraint> targetObjConstraint = graphSchema.getObjectConstraint(relationship.getTarget().getType());
233
234                 if (relationshipConstraint.isPresent()) getSchemaEnforcer().validate(relationship, relationshipConstraint.get());
235                 if (sourceObjConstraint.isPresent()) getSchemaEnforcer().validate(relationship.getSource(), sourceObjConstraint.get());
236                 if (targetObjConstraint.isPresent()) getSchemaEnforcer().validate(relationship.getTarget(), targetObjConstraint.get());
237         }
238
239         protected void validate(ChampPartition partition) throws ChampSchemaViolationException {
240                 for (ChampObject object : partition.getChampObjects()) {
241                         validate(object);
242                 }
243
244                 for (ChampRelationship relationship : partition.getChampRelationships()) {
245                         validate(relationship);
246                 }
247         }
248
249         @Override
250         public void storeSchema(ChampSchema schema) throws ChampSchemaViolationException {
251                 if (isShutdown()) throw new IllegalStateException("Cannot call storeSchema() after shutdown has been initiated");
252
253                 this.schema = schema;
254         }
255
256         @Override
257         public ChampSchema retrieveSchema() {
258                 if (isShutdown()) throw new IllegalStateException("Cannot call retrieveSchema() after shutdown has been initiated");
259
260                 return schema;
261         }
262
263         @Override
264         public void updateSchema(ChampObjectConstraint objectConstraint) throws ChampSchemaViolationException {
265                 if (isShutdown()) throw new IllegalStateException("Cannot call updateSchema() after shutdown has been initiated");
266
267                 final ChampSchema currentSchema = retrieveSchema();
268                 final ChampSchema updatedSchema = new ChampSchema.Builder(currentSchema)
269                                                                                                 .constraint(objectConstraint)
270                                                                                                 .build();
271                 
272                 storeSchema(updatedSchema);
273         }
274
275         @Override
276         public void updateSchema(ChampRelationshipConstraint relationshipConstraint) throws ChampSchemaViolationException {
277                 if (isShutdown()) throw new IllegalStateException("Cannot call updateSchema() after shutdown has been initiated");
278
279                 final ChampSchema currentSchema = retrieveSchema();
280                 final ChampSchema updatedSchema = new ChampSchema.Builder(currentSchema)
281                                                                                                 .constraint(relationshipConstraint)
282                                                                                                 .build();
283                 
284                 storeSchema(updatedSchema);
285         }
286
287         @Override
288         public void deleteSchema() {
289                 if (isShutdown()) throw new IllegalStateException("Cannot call deleteSchema() after shutdown has been initiated");
290                 this.schema = ChampSchema.emptySchema();
291         }
292 }