1 package org.onap.champ.service;
3 import org.onap.aai.champcore.ChampGraph;
4 import org.onap.aai.champcore.ChampTransaction;
5 import org.onap.aai.champcore.exceptions.ChampMarshallingException;
6 import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
7 import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException;
8 import org.onap.aai.champcore.exceptions.ChampSchemaViolationException;
9 import org.onap.aai.champcore.exceptions.ChampTransactionException;
10 import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
11 import org.onap.aai.champcore.model.ChampElement;
12 import org.onap.aai.champcore.model.ChampObject;
13 import org.onap.aai.champcore.model.ChampRelationship;
14 import org.onap.aai.champcore.model.fluent.object.ObjectBuildOrPropertiesStep;
15 import org.onap.aai.cl.api.Logger;
16 import org.onap.aai.cl.eelf.LoggerFactory;
17 import org.onap.champ.exception.ChampServiceException;
18 import org.onap.champ.service.logging.ChampMsgs;
19 import org.onap.champ.util.ChampProperties;
20 import org.onap.champ.util.ChampServiceConstants;
22 import java.util.ArrayList;
23 import java.util.HashSet;
24 import java.util.List;
26 import java.util.Optional;
27 import java.util.stream.Collectors;
28 import java.util.stream.Stream;
29 import javax.ws.rs.core.Response.Status;
31 public class ChampDataService {
32 private ChampUUIDService champUUIDService;
34 private ChampGraph graphImpl;
35 private ChampTransactionCache cache;
36 private static final String KEY_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_KEY_NAME);
37 private static final String SOT_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_SOT_NAME);
38 private static final String CREATED_TS_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_CREATED_TS_NAME);
39 private static final String LAST_MOD_TS_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_LAST_MOD_TS_NAME);
40 private Logger logger = LoggerFactory.getInstance().getLogger(ChampDataService.class);
43 public ChampDataService(ChampUUIDService champUUIDService, ChampGraph graphImpl, ChampTransactionCache cache) {
45 this.champUUIDService = champUUIDService;
46 this.graphImpl = graphImpl;
50 public ChampObject getObject(String id, Optional<ChampTransaction> transaction) throws ChampServiceException {
52 Optional<ChampObject> retrieved = Optional.empty();
54 retrieved = champUUIDService.getObjectbyUUID(id, transaction.orElse(null));
55 } catch (ChampUnmarshallingException | ChampTransactionException e) {
56 throw new ChampServiceException("Error: " + e.getMessage(), Status.INTERNAL_SERVER_ERROR);
58 if (retrieved.isPresent()) {
59 return (ChampObject) champUUIDService.populateUUIDKey(retrieved.get());
65 public ChampObject storeObject(ChampObject object, Optional<ChampTransaction> transaction)
66 throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException,
67 ChampTransactionException, ChampServiceException {
69 if (object.getProperty(KEY_NAME).isPresent() || object.getKey().isPresent()) {
70 throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST);
73 champUUIDService.populateUUIDProperty(object, java.util.UUID.randomUUID().toString());
74 addTimestamps(object, null);
75 ChampObject created = graphImpl.storeObject(object, transaction);
76 return (ChampObject) champUUIDService.populateUUIDKey(created);
79 public ChampObject replaceObject(ChampObject object, String objectId, Optional<ChampTransaction> transaction)
80 throws ChampServiceException, ChampUnmarshallingException, ChampTransactionException, ChampMarshallingException,
81 ChampSchemaViolationException, ChampObjectNotExistsException {
82 if (object.getKey().isPresent() && (!object.getKeyValue().equals(objectId))) {
83 throw new ChampServiceException("Object Id in the URI doesn't match the body.", Status.BAD_REQUEST);
86 if (object.getProperty(KEY_NAME).isPresent() && !object.getProperty(KEY_NAME).get().toString().equals(objectId)) {
87 throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST);
90 Optional<ChampObject> retrieved = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null));
91 if (!retrieved.isPresent()) {
92 throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND);
94 ObjectBuildOrPropertiesStep payloadBuilder = ChampObject.create().from(object).withKey(retrieved.get().getKey().get())
95 .withProperty(KEY_NAME, objectId);
96 if (retrieved.get().getProperty(SOT_NAME).isPresent()){
97 payloadBuilder = payloadBuilder.withProperty(SOT_NAME, retrieved.get().getProperty(SOT_NAME).get());
100 if (object.getProperty(CREATED_TS_NAME).isPresent() && retrieved.get().getProperty(CREATED_TS_NAME).isPresent()) {
101 // the timestamps in object are parsed as strings regardless of how the input json is. Convert retrieved to string for easy comparison
102 if (!retrieved.get().getProperty(CREATED_TS_NAME).get().toString().equals(object.getProperty(CREATED_TS_NAME).get())) {
103 throw new ChampServiceException(CREATED_TS_NAME + " can't be updated", Status.BAD_REQUEST);
107 if (object.getProperty(LAST_MOD_TS_NAME).isPresent() && retrieved.get().getProperty(LAST_MOD_TS_NAME).isPresent()) {
108 if (!retrieved.get().getProperty(LAST_MOD_TS_NAME).get().toString().equals(object.getProperty(LAST_MOD_TS_NAME).get())) {
109 throw new ChampServiceException(LAST_MOD_TS_NAME + " can't be updated", Status.BAD_REQUEST);
113 ChampObject payload = payloadBuilder.build();
114 addTimestamps(payload, (Long)retrieved.get().getProperty(CREATED_TS_NAME).orElse(null));
115 ChampObject updated = graphImpl.replaceObject(payload, transaction);
116 return (ChampObject) champUUIDService.populateUUIDKey(updated);
119 public void deleteObject(String objectId, Optional<ChampTransaction> transaction) throws ChampServiceException,
120 ChampObjectNotExistsException, ChampTransactionException, ChampUnmarshallingException {
121 Optional<ChampObject> retrieved = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null));
122 if (!retrieved.isPresent()) {
123 throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND);
125 Stream<ChampRelationship> relationships = graphImpl.retrieveRelationships(retrieved.get(), transaction);
127 if (relationships.count() > 0) {
128 throw new ChampServiceException("Attempt to delete vertex with id " + objectId + " which has incident edges.",
131 graphImpl.deleteObject(retrieved.get().getKey().get(), transaction);
135 public ChampRelationship storeRelationship(ChampRelationship r, Optional<ChampTransaction> transaction)
136 throws ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException,
137 ChampRelationshipNotExistsException, ChampUnmarshallingException, ChampTransactionException,
138 ChampServiceException {
140 if (r.getSource() == null || !r.getSource().getKey().isPresent() || r.getTarget() == null
141 || !r.getTarget().getKey().isPresent()) {
142 logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Source/Target Object key must be provided");
143 throw new ChampServiceException("Source/Target Object key must be provided", Status.BAD_REQUEST);
146 if (r.getProperty(KEY_NAME).isPresent() || r.getKey().isPresent()) {
147 logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "key or " + KEY_NAME + " not allowed while creating new Objects");
148 throw new ChampServiceException("key or " + KEY_NAME + " not allowed while creating new Objects", Status.BAD_REQUEST);
152 Optional<ChampObject> source = champUUIDService.getObjectbyUUID(r.getSource().getKey().get().toString(),
153 transaction.orElse(null));
154 Optional<ChampObject> target = champUUIDService.getObjectbyUUID(r.getTarget().getKey().get().toString(),
155 transaction.orElse(null));
157 if (!source.isPresent() || !target.isPresent()) {
158 logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Source/Target object not found");
159 throw new ChampServiceException("Source/Target object not found", Status.BAD_REQUEST);
162 champUUIDService.populateUUIDProperty(r, java.util.UUID.randomUUID().toString());
164 ChampRelationship payload = new ChampRelationship.Builder(source.get(), target.get(), r.getType())
165 .properties(r.getProperties()).build();
166 addTimestamps(payload, null);
167 ChampRelationship created = graphImpl.storeRelationship(payload, transaction);
168 return (ChampRelationship) champUUIDService.populateUUIDKey(created);
171 public ChampRelationship updateRelationship(ChampRelationship r, String rId, Optional<ChampTransaction> transaction)
172 throws ChampServiceException, ChampUnmarshallingException, ChampTransactionException, ChampMarshallingException,
173 ChampSchemaViolationException, ChampRelationshipNotExistsException {
174 if (r.getKey().isPresent() && (!r.getKeyValue().equals(rId))) {
176 throw new ChampServiceException("Relationship Id in the URI \"" + rId + "\" doesn't match the URI in the body"
177 + " \"" + r.getKeyValue() + "\"", Status.BAD_REQUEST);
181 if (r.getProperty(KEY_NAME).isPresent() && !r.getProperty(KEY_NAME).get().toString().equals(rId)) {
182 throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST);
185 Optional<ChampRelationship> retrieved = champUUIDService.getRelationshipbyUUID(rId, transaction.orElse(null));
186 if (!retrieved.isPresent()) {
187 throw new ChampServiceException(rId + " not found", Status.NOT_FOUND);
189 // check if key is present or if it equals the key that is in the URI
190 if (r.getSource() == null || !r.getSource().getKey().isPresent() || r.getTarget() == null
191 || !r.getTarget().getKey().isPresent()) {
192 throw new ChampServiceException("Source/Target Object key must be provided", Status.BAD_REQUEST);
194 ChampObject source = retrieved.get().getSource();
195 ChampObject target = retrieved.get().getTarget();
197 if (!source.getProperty(KEY_NAME).get().toString().equals(r.getSource().getKey().get().toString())
198 || !target.getProperty(KEY_NAME).get().toString().equals(r.getTarget().getKey().get().toString())) {
199 throw new ChampServiceException("Source/Target cannot be updated", Status.BAD_REQUEST);
202 if (r.getProperty(CREATED_TS_NAME).isPresent() && retrieved.get().getProperty(CREATED_TS_NAME).isPresent()) {
203 if (!retrieved.get().getProperty(CREATED_TS_NAME).get().toString().equals(r.getProperty(CREATED_TS_NAME).get())) {
204 throw new ChampServiceException(CREATED_TS_NAME + " can't be updated", Status.BAD_REQUEST);
208 if (r.getProperty(LAST_MOD_TS_NAME).isPresent() && retrieved.get().getProperty(LAST_MOD_TS_NAME).isPresent()) {
209 if (!retrieved.get().getProperty(LAST_MOD_TS_NAME).get().toString().equals(r.getProperty(LAST_MOD_TS_NAME).get())) {
210 throw new ChampServiceException(LAST_MOD_TS_NAME + " can't be updated", Status.BAD_REQUEST);
214 ChampRelationship payload = new ChampRelationship.Builder(source, target, r.getType())
215 .key(retrieved.get().getKey().get()).properties(r.getProperties()).property(KEY_NAME, rId).build();
216 addTimestamps(payload, (Long)retrieved.get().getProperty(CREATED_TS_NAME).orElse(null));
217 ChampRelationship updated = graphImpl.replaceRelationship(payload, transaction);
218 return (ChampRelationship) champUUIDService.populateUUIDKey(updated);
221 public void deleteRelationship(String relationshipId, Optional<ChampTransaction> transaction)
222 throws ChampServiceException, ChampRelationshipNotExistsException, ChampTransactionException,
223 ChampUnmarshallingException {
224 Optional<ChampRelationship> retrieved = champUUIDService.getRelationshipbyUUID(relationshipId,
225 transaction.orElse(null));
226 if (!retrieved.isPresent()) {
227 throw new ChampServiceException(relationshipId + " not found", Status.NOT_FOUND);
230 graphImpl.deleteRelationship(retrieved.get(), transaction);
235 public List<ChampRelationship> getRelationshipsByObject(String objectId, Optional<ChampTransaction> transaction)
236 throws ChampServiceException {
238 Optional<ChampObject> retrievedObject = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null));
239 if (!retrievedObject.isPresent()) {
240 throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND);
242 List<ChampRelationship> relations = new ArrayList<ChampRelationship>();
244 Stream<ChampRelationship> retrieved = graphImpl.retrieveRelationships(retrievedObject.get(), transaction);
245 relations = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList()));
247 } catch (ChampObjectNotExistsException e) {
248 throw new ChampServiceException(" obj not found", Status.NOT_FOUND);
249 } catch (ChampUnmarshallingException | ChampTransactionException e) {
250 throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR);
256 * Gets the ChampObjects that pass filter
257 * @param filter key/value pairs that must be present in the returned objects
258 * @param properties properties that will show up in the object
260 * @throws ChampServiceException
262 public List<ChampObject> queryObjects(Map<String, Object> filter, HashSet<String> properties) throws ChampServiceException {
265 Stream<ChampObject> retrieved = graphImpl.queryObjects(filter);
266 List<ChampObject> objects = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList()));
268 if (!properties.contains("all")) {
269 for (ChampObject champObject : objects) {
270 champObject.dropProperties(properties);
275 } catch (ChampTransactionException e) {
276 throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR);
280 public List<ChampRelationship> queryRelationships(Map<String, Object> filter) throws ChampServiceException {
282 List<ChampRelationship> relations = new ArrayList<ChampRelationship>();
283 Stream<ChampRelationship> retrieved;
285 retrieved = graphImpl.queryRelationships(filter);
287 relations = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList()));
289 } catch (ChampTransactionException e) {
290 throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR);
294 public ChampRelationship getRelationship(String id, Optional<ChampTransaction> transaction)
295 throws ChampServiceException {
297 Optional<ChampRelationship> retrieved = Optional.empty();
299 retrieved = champUUIDService.getRelationshipbyUUID(id, transaction.orElse(null));
300 } catch (ChampUnmarshallingException | ChampTransactionException e) {
301 throw new ChampServiceException("Error: " + e.getMessage(), Status.INTERNAL_SERVER_ERROR);
303 if (retrieved.isPresent()) {
304 return (ChampRelationship) champUUIDService.populateUUIDKey(retrieved.get());
310 public String openTransaction() {
311 ChampTransaction transaction = graphImpl.openTransaction();
312 String transacId = transaction.id();
313 cache.put(transacId, transaction);
318 public void commitTransaction(String tId) throws ChampServiceException, ChampTransactionException {
319 ChampTransaction transaction = cache.get(tId);
320 if (transaction == null) {
321 throw new ChampServiceException("Transaction Not found: " + tId, Status.NOT_FOUND);
323 graphImpl.commitTransaction(transaction);
324 cache.invalidate(tId);
325 cache.invalidate(transaction.id());
329 public void rollbackTransaction(String tId) throws ChampServiceException, ChampTransactionException {
330 ChampTransaction transaction = cache.get(tId);
331 if (transaction == null) {
332 throw new ChampServiceException("Transaction Not found: " + tId, Status.NOT_FOUND);
334 graphImpl.rollbackTransaction(transaction);
335 cache.invalidate(tId);
336 cache.invalidate(transaction.id());
340 public ChampTransaction getTransaction(String id) {
341 return cache.get(id);
344 private void addTimestamps(ChampElement e, Long oldCreated) {
345 Long timestamp = System.currentTimeMillis();
347 if (oldCreated == null) {
348 e.getProperties().put(CREATED_TS_NAME, timestamp);
350 e.getProperties().put(CREATED_TS_NAME, oldCreated);
353 e.getProperties().put(LAST_MOD_TS_NAME, timestamp);