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