2 * ============LICENSE_START==========================================
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 package org.onap.champ.service;
24 import org.onap.aai.champcore.ChampGraph;
25 import org.onap.aai.champcore.ChampTransaction;
26 import org.onap.aai.champcore.exceptions.ChampMarshallingException;
27 import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
28 import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException;
29 import org.onap.aai.champcore.exceptions.ChampSchemaViolationException;
30 import org.onap.aai.champcore.exceptions.ChampTransactionException;
31 import org.onap.aai.champcore.exceptions.ChampUnmarshallingException;
32 import org.onap.aai.champcore.model.ChampElement;
33 import org.onap.aai.champcore.model.ChampObject;
34 import org.onap.aai.champcore.model.ChampRelationship;
35 import org.onap.aai.champcore.model.fluent.object.ObjectBuildOrPropertiesStep;
36 import org.onap.aai.cl.api.Logger;
37 import org.onap.aai.cl.eelf.LoggerFactory;
38 import org.onap.champ.exception.ChampServiceException;
39 import org.onap.champ.service.logging.ChampMsgs;
40 import org.onap.champ.util.ChampProperties;
41 import org.onap.champ.util.ChampServiceConstants;
43 import java.util.ArrayList;
44 import java.util.HashSet;
45 import java.util.List;
47 import java.util.Optional;
48 import java.util.stream.Collectors;
49 import java.util.stream.Stream;
50 import javax.ws.rs.core.Response.Status;
52 public class ChampDataService {
53 private ChampUUIDService champUUIDService;
55 private ChampGraph graphImpl;
56 private ChampTransactionCache cache;
57 private static final String KEY_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_KEY_NAME);
58 private static final String SOT_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_SOT_NAME);
59 private static final String CREATED_TS_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_CREATED_TS_NAME);
60 private static final String LAST_MOD_TS_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_LAST_MOD_TS_NAME);
61 private Logger logger = LoggerFactory.getInstance().getLogger(ChampDataService.class);
64 public ChampDataService(ChampUUIDService champUUIDService, ChampGraph graphImpl, ChampTransactionCache cache) {
66 this.champUUIDService = champUUIDService;
67 this.graphImpl = graphImpl;
71 public ChampObject getObject(String id, Optional<ChampTransaction> transaction) throws ChampServiceException {
73 Optional<ChampObject> retrieved = Optional.empty();
75 retrieved = champUUIDService.getObjectbyUUID(id, transaction.orElse(null));
76 } catch (ChampUnmarshallingException | ChampTransactionException e) {
77 throw new ChampServiceException("Error: " + e.getMessage(), Status.INTERNAL_SERVER_ERROR);
79 if (retrieved.isPresent()) {
80 return (ChampObject) champUUIDService.populateUUIDKey(retrieved.get());
86 public ChampObject storeObject(ChampObject object, Optional<ChampTransaction> transaction)
87 throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException,
88 ChampTransactionException, ChampServiceException {
90 if (object.getProperty(KEY_NAME).isPresent() || object.getKey().isPresent()) {
91 throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST);
94 champUUIDService.populateUUIDProperty(object, java.util.UUID.randomUUID().toString());
95 addTimestamps(object, null);
96 ChampObject created = graphImpl.storeObject(object, transaction);
97 return (ChampObject) champUUIDService.populateUUIDKey(created);
100 public ChampObject replaceObject(ChampObject object, String objectId, Optional<ChampTransaction> transaction)
101 throws ChampServiceException, ChampUnmarshallingException, ChampTransactionException, ChampMarshallingException,
102 ChampSchemaViolationException, ChampObjectNotExistsException {
103 if (object.getKey().isPresent() && (!object.getKeyValue().equals(objectId))) {
104 throw new ChampServiceException("Object Id in the URI doesn't match the body.", Status.BAD_REQUEST);
107 if (object.getProperty(KEY_NAME).isPresent() && !object.getProperty(KEY_NAME).get().toString().equals(objectId)) {
108 throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST);
111 Optional<ChampObject> retrieved = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null));
112 if (!retrieved.isPresent()) {
113 throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND);
115 ObjectBuildOrPropertiesStep payloadBuilder = ChampObject.create().from(object).withKey(retrieved.get().getKey().get())
116 .withProperty(KEY_NAME, objectId);
117 if (retrieved.get().getProperty(SOT_NAME).isPresent()){
118 payloadBuilder = payloadBuilder.withProperty(SOT_NAME, retrieved.get().getProperty(SOT_NAME).get());
121 if (object.getProperty(CREATED_TS_NAME).isPresent() && retrieved.get().getProperty(CREATED_TS_NAME).isPresent()) {
122 // the timestamps in object are parsed as strings regardless of how the input json is. Convert retrieved to string for easy comparison
123 if (!retrieved.get().getProperty(CREATED_TS_NAME).get().toString().equals(object.getProperty(CREATED_TS_NAME).get())) {
124 throw new ChampServiceException(CREATED_TS_NAME + " can't be updated", Status.BAD_REQUEST);
128 if (object.getProperty(LAST_MOD_TS_NAME).isPresent() && retrieved.get().getProperty(LAST_MOD_TS_NAME).isPresent()) {
129 if (!retrieved.get().getProperty(LAST_MOD_TS_NAME).get().toString().equals(object.getProperty(LAST_MOD_TS_NAME).get())) {
130 throw new ChampServiceException(LAST_MOD_TS_NAME + " can't be updated", Status.BAD_REQUEST);
134 ChampObject payload = payloadBuilder.build();
135 addTimestamps(payload, (Long)retrieved.get().getProperty(CREATED_TS_NAME).orElse(null));
136 ChampObject updated = graphImpl.replaceObject(payload, transaction);
137 return (ChampObject) champUUIDService.populateUUIDKey(updated);
140 public void deleteObject(String objectId, Optional<ChampTransaction> transaction) throws ChampServiceException,
141 ChampObjectNotExistsException, ChampTransactionException, ChampUnmarshallingException {
142 Optional<ChampObject> retrieved = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null));
143 if (!retrieved.isPresent()) {
144 throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND);
146 Stream<ChampRelationship> relationships = graphImpl.retrieveRelationships(retrieved.get(), transaction);
148 if (relationships.count() > 0) {
149 throw new ChampServiceException("Attempt to delete vertex with id " + objectId + " which has incident edges.",
152 graphImpl.deleteObject(retrieved.get().getKey().get(), transaction);
156 public ChampRelationship storeRelationship(ChampRelationship r, Optional<ChampTransaction> transaction)
157 throws ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException,
158 ChampRelationshipNotExistsException, ChampUnmarshallingException, ChampTransactionException,
159 ChampServiceException {
161 if (r.getSource() == null || !r.getSource().getKey().isPresent() || r.getTarget() == null
162 || !r.getTarget().getKey().isPresent()) {
163 logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Source/Target Object key must be provided");
164 throw new ChampServiceException("Source/Target Object key must be provided", Status.BAD_REQUEST);
167 if (r.getProperty(KEY_NAME).isPresent() || r.getKey().isPresent()) {
168 logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "key or " + KEY_NAME + " not allowed while creating new Objects");
169 throw new ChampServiceException("key or " + KEY_NAME + " not allowed while creating new Objects", Status.BAD_REQUEST);
173 Optional<ChampObject> source = champUUIDService.getObjectbyUUID(r.getSource().getKey().get().toString(),
174 transaction.orElse(null));
175 Optional<ChampObject> target = champUUIDService.getObjectbyUUID(r.getTarget().getKey().get().toString(),
176 transaction.orElse(null));
178 if (!source.isPresent() || !target.isPresent()) {
179 logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Source/Target object not found");
180 throw new ChampServiceException("Source/Target object not found", Status.BAD_REQUEST);
183 champUUIDService.populateUUIDProperty(r, java.util.UUID.randomUUID().toString());
185 ChampRelationship payload = new ChampRelationship.Builder(source.get(), target.get(), r.getType())
186 .properties(r.getProperties()).build();
187 addTimestamps(payload, null);
188 ChampRelationship created = graphImpl.storeRelationship(payload, transaction);
189 return (ChampRelationship) champUUIDService.populateUUIDKey(created);
192 public ChampRelationship updateRelationship(ChampRelationship r, String rId, Optional<ChampTransaction> transaction)
193 throws ChampServiceException, ChampUnmarshallingException, ChampTransactionException, ChampMarshallingException,
194 ChampSchemaViolationException, ChampRelationshipNotExistsException {
195 if (r.getKey().isPresent() && (!r.getKeyValue().equals(rId))) {
197 throw new ChampServiceException("Relationship Id in the URI \"" + rId + "\" doesn't match the URI in the body"
198 + " \"" + r.getKeyValue() + "\"", Status.BAD_REQUEST);
202 if (r.getProperty(KEY_NAME).isPresent() && !r.getProperty(KEY_NAME).get().toString().equals(rId)) {
203 throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST);
206 Optional<ChampRelationship> retrieved = champUUIDService.getRelationshipbyUUID(rId, transaction.orElse(null));
207 if (!retrieved.isPresent()) {
208 throw new ChampServiceException(rId + " not found", Status.NOT_FOUND);
210 // check if key is present or if it equals the key that is in the URI
211 if (r.getSource() == null || !r.getSource().getKey().isPresent() || r.getTarget() == null
212 || !r.getTarget().getKey().isPresent()) {
213 throw new ChampServiceException("Source/Target Object key must be provided", Status.BAD_REQUEST);
215 ChampObject source = retrieved.get().getSource();
216 ChampObject target = retrieved.get().getTarget();
218 if (!source.getProperty(KEY_NAME).get().toString().equals(r.getSource().getKey().get().toString())
219 || !target.getProperty(KEY_NAME).get().toString().equals(r.getTarget().getKey().get().toString())) {
220 throw new ChampServiceException("Source/Target cannot be updated", Status.BAD_REQUEST);
223 if (r.getProperty(CREATED_TS_NAME).isPresent() && retrieved.get().getProperty(CREATED_TS_NAME).isPresent()) {
224 if (!retrieved.get().getProperty(CREATED_TS_NAME).get().toString().equals(r.getProperty(CREATED_TS_NAME).get())) {
225 throw new ChampServiceException(CREATED_TS_NAME + " can't be updated", Status.BAD_REQUEST);
229 if (r.getProperty(LAST_MOD_TS_NAME).isPresent() && retrieved.get().getProperty(LAST_MOD_TS_NAME).isPresent()) {
230 if (!retrieved.get().getProperty(LAST_MOD_TS_NAME).get().toString().equals(r.getProperty(LAST_MOD_TS_NAME).get())) {
231 throw new ChampServiceException(LAST_MOD_TS_NAME + " can't be updated", Status.BAD_REQUEST);
235 ChampRelationship payload = new ChampRelationship.Builder(source, target, r.getType())
236 .key(retrieved.get().getKey().get()).properties(r.getProperties()).property(KEY_NAME, rId).build();
237 addTimestamps(payload, (Long)retrieved.get().getProperty(CREATED_TS_NAME).orElse(null));
238 ChampRelationship updated = graphImpl.replaceRelationship(payload, transaction);
239 return (ChampRelationship) champUUIDService.populateUUIDKey(updated);
242 public void deleteRelationship(String relationshipId, Optional<ChampTransaction> transaction)
243 throws ChampServiceException, ChampRelationshipNotExistsException, ChampTransactionException,
244 ChampUnmarshallingException {
245 Optional<ChampRelationship> retrieved = champUUIDService.getRelationshipbyUUID(relationshipId,
246 transaction.orElse(null));
247 if (!retrieved.isPresent()) {
248 throw new ChampServiceException(relationshipId + " not found", Status.NOT_FOUND);
251 graphImpl.deleteRelationship(retrieved.get(), transaction);
256 public List<ChampRelationship> getRelationshipsByObject(String objectId, Optional<ChampTransaction> transaction)
257 throws ChampServiceException {
259 Optional<ChampObject> retrievedObject = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null));
260 if (!retrievedObject.isPresent()) {
261 throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND);
263 List<ChampRelationship> relations = new ArrayList<ChampRelationship>();
265 Stream<ChampRelationship> retrieved = graphImpl.retrieveRelationships(retrievedObject.get(), transaction);
266 relations = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList()));
268 } catch (ChampObjectNotExistsException e) {
269 throw new ChampServiceException(" obj not found", Status.NOT_FOUND);
270 } catch (ChampUnmarshallingException | ChampTransactionException e) {
271 throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR);
277 * Gets the ChampObjects that pass filter
278 * @param filter key/value pairs that must be present in the returned objects
279 * @param properties properties that will show up in the object
281 * @throws ChampServiceException
283 public List<ChampObject> queryObjects(Map<String, Object> filter, HashSet<String> properties) throws ChampServiceException {
286 Stream<ChampObject> retrieved = graphImpl.queryObjects(filter);
287 List<ChampObject> objects = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList()));
289 if (!properties.contains("all")) {
290 for (ChampObject champObject : objects) {
291 champObject.dropProperties(properties);
296 } catch (ChampTransactionException e) {
297 throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR);
301 public List<ChampRelationship> queryRelationships(Map<String, Object> filter) throws ChampServiceException {
303 List<ChampRelationship> relations = new ArrayList<ChampRelationship>();
304 Stream<ChampRelationship> retrieved;
306 retrieved = graphImpl.queryRelationships(filter);
308 relations = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList()));
310 } catch (ChampTransactionException e) {
311 throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR);
315 public ChampRelationship getRelationship(String id, Optional<ChampTransaction> transaction)
316 throws ChampServiceException {
318 Optional<ChampRelationship> retrieved = Optional.empty();
320 retrieved = champUUIDService.getRelationshipbyUUID(id, transaction.orElse(null));
321 } catch (ChampUnmarshallingException | ChampTransactionException e) {
322 throw new ChampServiceException("Error: " + e.getMessage(), Status.INTERNAL_SERVER_ERROR);
324 if (retrieved.isPresent()) {
325 return (ChampRelationship) champUUIDService.populateUUIDKey(retrieved.get());
331 public String openTransaction() {
332 ChampTransaction transaction = graphImpl.openTransaction();
333 String transacId = transaction.id();
334 cache.put(transacId, transaction);
339 public void commitTransaction(String tId) throws ChampServiceException, ChampTransactionException {
340 ChampTransaction transaction = cache.get(tId);
341 if (transaction == null) {
342 throw new ChampServiceException("Transaction Not found: " + tId, Status.NOT_FOUND);
344 graphImpl.commitTransaction(transaction);
345 cache.invalidate(tId);
346 cache.invalidate(transaction.id());
350 public void rollbackTransaction(String tId) throws ChampServiceException, ChampTransactionException {
351 ChampTransaction transaction = cache.get(tId);
352 if (transaction == null) {
353 throw new ChampServiceException("Transaction Not found: " + tId, Status.NOT_FOUND);
355 graphImpl.rollbackTransaction(transaction);
356 cache.invalidate(tId);
357 cache.invalidate(transaction.id());
361 public ChampTransaction getTransaction(String id) {
362 return cache.get(id);
365 private void addTimestamps(ChampElement e, Long oldCreated) {
366 Long timestamp = System.currentTimeMillis();
368 if (oldCreated == null) {
369 e.getProperties().put(CREATED_TS_NAME, timestamp);
371 e.getProperties().put(CREATED_TS_NAME, oldCreated);
374 e.getProperties().put(LAST_MOD_TS_NAME, timestamp);