2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 - 2019 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.onap.aaiclient.client.graphinventory;
23 import java.lang.reflect.InvocationTargetException;
24 import java.lang.reflect.Method;
25 import java.lang.reflect.ParameterizedType;
26 import java.lang.reflect.Type;
27 import java.util.Arrays;
28 import java.util.List;
30 import java.util.Optional;
31 import javax.ws.rs.NotFoundException;
32 import javax.ws.rs.core.GenericType;
33 import javax.ws.rs.core.Response;
34 import javax.ws.rs.core.Response.Status;
35 import org.onap.aai.domain.yang.Relationship;
36 import org.onap.aaiclient.client.graphinventory.entities.GraphInventoryEdgeLabel;
37 import org.onap.aaiclient.client.graphinventory.entities.GraphInventoryResultWrapper;
38 import org.onap.aaiclient.client.graphinventory.entities.uri.GraphInventoryPluralResourceUri;
39 import org.onap.aaiclient.client.graphinventory.entities.uri.GraphInventoryResourceUri;
40 import org.onap.aaiclient.client.graphinventory.entities.uri.GraphInventorySingleResourceUri;
41 import org.onap.aaiclient.client.graphinventory.entities.uri.HttpAwareUri;
42 import org.onap.aaiclient.client.graphinventory.exceptions.GraphInventoryMultipleItemsException;
43 import org.onap.so.client.RestClient;
44 import org.onap.so.client.RestProperties;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
48 public abstract class GraphInventoryResourcesClient<Self, Uri extends GraphInventoryResourceUri<?, ?>, SingleUri extends GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?>, PluralUri extends GraphInventoryPluralResourceUri<?, ?>, EdgeLabel extends GraphInventoryEdgeLabel, Wrapper extends GraphInventoryResultWrapper, TransactionalClient, SingleTransactionClient> {
50 private static final Logger logger = LoggerFactory.getLogger(GraphInventoryResourcesClient.class);
52 protected GraphInventoryClient client;
54 protected GraphInventoryResourcesClient(GraphInventoryClient client) {
59 * creates a new object in GraphInventory
61 * @param obj - can be any object which will marshal into a valid GraphInventory payload
65 public void create(SingleUri uri, Object obj) {
66 RestClient giRC = client.createClient(uri);
71 * creates a new object in GraphInventory with no payload body
76 public void createEmpty(SingleUri uri) {
77 RestClient giRC = client.createClient(uri);
82 * returns false if the object does not exist in GraphInventory
87 public boolean exists(Uri uri) {
88 GraphInventoryResourceUri<?, ?> forceMinimal = (Uri) uri.clone();
89 forceMinimal.format(Format.COUNT);
90 forceMinimal.limit(1);
92 RestClient giRC = client.createClient(forceMinimal);
94 return giRC.get().getStatus() == Status.OK.getStatusCode();
95 } catch (NotFoundException e) {
101 * Adds a relationship between two objects in GraphInventory
107 public void connect(SingleUri uriA, SingleUri uriB) {
108 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> uriAClone = (SingleUri) uriA.clone();
109 RestClient giRC = client.createClient(uriAClone.relationshipAPI());
110 giRC.put(this.buildRelationship(uriB));
114 * Adds a relationship between two objects in GraphInventory with a given edge label
121 public void connect(SingleUri uriA, SingleUri uriB, EdgeLabel label) {
122 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> uriAClone = (SingleUri) uriA.clone();
123 RestClient giRC = client.createClient(uriAClone.relationshipAPI());
124 giRC.put(this.buildRelationship(uriB, label));
128 * Removes relationship from two objects in GraphInventory
134 public void disconnect(SingleUri uriA, SingleUri uriB) {
135 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> uriAClone = (SingleUri) uriA.clone();
136 RestClient giRC = client.createClient(uriAClone.relationshipAPI());
137 giRC.delete(this.buildRelationship(uriB));
141 * Deletes object from GraphInventory. Automatically handles resource-version.
146 public void delete(SingleUri uri) {
147 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> clone = (SingleUri) uri.clone();
148 RestClient giRC = client.createClient(clone);
149 Map<String, Object> result = giRC.get(new GenericType<Map<String, Object>>() {}).orElseThrow(
150 () -> new NotFoundException(clone.build() + " does not exist in " + client.getGraphDBName()));
151 String resourceVersion = (String) result.get("resource-version");
152 giRC = client.createClient(clone.resourceVersion(resourceVersion));
158 * Deletes object from GraphInventory only if exists. Automatically handles resource-version.
163 public void deleteIfExists(SingleUri uri) {
164 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> clone = (SingleUri) uri.clone();
165 RestClient giRC = client.createClient(clone);
166 Optional<Map<String, Object>> result = giRC.get(new GenericType<Map<String, Object>>() {});
167 if (result.isPresent()) {
168 String resourceVersion = (String) result.get().get("resource-version");
169 giRC = client.createClient(clone.resourceVersion(resourceVersion));
172 logger.warn(clone.build() + " already does not exist in " + client.getGraphDBName()
173 + " therefore delete call not executed");
178 * @param obj - can be any object which will marshal into a valid GraphInventory payload
182 public void update(SingleUri uri, Object obj) {
183 RestClient giRC = client.createClient(uri);
188 * Retrieves an object from GraphInventory and unmarshalls it into the Class specified
194 public <T> Optional<T> get(Class<T> clazz, Uri uri) {
196 return client.createClient(uri).get(clazz);
197 } catch (NotFoundException e) {
198 if (this.getRestProperties().mapNotFoundToEmpty()) {
199 return Optional.empty();
207 * Retrieves an object from GraphInventory and returns complete response
212 public Response getFullResponse(Uri uri) {
214 return client.createClient(uri).get();
215 } catch (NotFoundException e) {
216 if (this.getRestProperties().mapNotFoundToEmpty()) {
217 return e.getResponse();
225 * Retrieves an object from GraphInventory and automatically unmarshalls it into a Map or List
231 public <T> Optional<T> get(GenericType<T> resultClass, Uri uri) {
233 return client.createClient(uri).get(resultClass);
234 } catch (NotFoundException e) {
235 if (this.getRestProperties().mapNotFoundToEmpty()) {
236 return Optional.empty();
243 public <T, R> Optional<R> getOne(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
244 Optional<List<R>> result = unwrapPlural(pluralClass, resultClass, uri);
246 if (result.isPresent()) {
247 if (result.get().size() == 1) {
248 return Optional.of(result.get().get(0));
250 throw new GraphInventoryMultipleItemsException(result.get().size(), uri);
254 return Optional.empty();
257 public <T, R> Optional<R> getFirst(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
258 Optional<List<R>> result = unwrapPlural(pluralClass, resultClass, uri);
260 if (result.isPresent() && !result.get().isEmpty()) {
261 return Optional.of(result.get().get(0));
264 return Optional.empty();
267 public <T, R> Optional<Wrapper> getFirstWrapper(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
269 Optional<R> result = getFirst(pluralClass, resultClass, uri);
270 if (result.isPresent()) {
271 return Optional.of(this.createWrapper(result.get()));
273 return Optional.empty();
277 public <T, R> Optional<Wrapper> getOneWrapper(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
279 Optional<R> result = getOne(pluralClass, resultClass, uri);
280 if (result.isPresent()) {
281 return Optional.of(this.createWrapper(result.get()));
283 return Optional.empty();
287 protected <T, R> Optional<List<R>> unwrapPlural(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
289 PluralUri clone = (PluralUri) uri.clone().limit(1);
290 Optional<T> obj = client.createClient(clone).get(pluralClass);
291 if (obj.isPresent()) {
292 Optional<Method> listMethod = Arrays.stream(obj.get().getClass().getMethods()).filter(method -> {
294 Type returnType = method.getGenericReturnType();
295 if (returnType instanceof ParameterizedType) {
296 Type[] types = ((ParameterizedType) returnType).getActualTypeArguments();
297 if (types != null && types[0] instanceof Class) {
298 Class<?> listClass = (Class<?>) types[0];
299 return resultClass.equals(listClass);
305 if (listMethod.isPresent()) {
307 return Optional.of((List<R>) listMethod.get().invoke(obj.get()));
309 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
310 throw new RuntimeException(e);
314 return Optional.empty();
316 } catch (NotFoundException e) {
317 if (this.getRestProperties().mapNotFoundToEmpty()) {
318 return Optional.empty();
326 * Retrieves an object from GraphInventory wrapped in a helper class which offer additional features
331 public Wrapper get(Uri uri) {
334 json = client.createClient(uri).get(String.class).orElse(null);
335 } catch (NotFoundException e) {
336 if (this.getRestProperties().mapNotFoundToEmpty()) {
342 return this.createWrapper(json);
346 * Retrieves an object from GraphInventory wrapped in a helper class which offer additional features If the object
347 * cannot be found in GraphInventory the method will throw the runtime exception included as an argument
352 public Wrapper get(Uri uri, Class<? extends RuntimeException> c) {
355 json = client.createClient(uri).get(String.class).orElseThrow(() -> createException(c,
356 uri.build() + " not found in " + client.getGraphDBName(), Optional.empty()));
357 } catch (NotFoundException e) {
358 throw createException(c, "could not construct uri for use with " + client.getGraphDBName(), Optional.of(e));
361 return this.createWrapper(json);
364 private RuntimeException createException(Class<? extends RuntimeException> c, String message,
365 Optional<Throwable> t) {
369 e = c.getConstructor(String.class, Throwable.class).newInstance(message, t.get());
371 e = c.getConstructor(String.class).newInstance(message);
373 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
374 | NoSuchMethodException | SecurityException e1) {
375 throw new IllegalArgumentException("could not create instance for " + c.getName());
382 * Will automatically create the object if it does not exist
384 * @param obj - Optional object which serializes to a valid GraphInventory payload
388 public Self createIfNotExists(SingleUri uri, Optional<Object> obj) {
389 if (!this.exists((Uri) uri)) {
390 if (obj.isPresent()) {
391 this.create(uri, obj.get());
393 this.createEmpty(uri);
400 protected Relationship buildRelationship(SingleUri uri) {
401 return buildRelationship(uri, Optional.empty());
404 protected Relationship buildRelationship(SingleUri uri, GraphInventoryEdgeLabel label) {
405 return buildRelationship(uri, Optional.of(label));
408 protected Relationship buildRelationship(SingleUri uri, Optional<GraphInventoryEdgeLabel> label) {
409 final Relationship result = new Relationship();
410 if (uri instanceof HttpAwareUri) {
411 result.setRelatedLink(((HttpAwareUri) uri).locateAndBuild().toString());
413 result.setRelatedLink(uri.build().toString());
415 if (label.isPresent()) {
416 result.setRelationshipLabel(label.get().toString());
421 public abstract Wrapper createWrapper(String json);
423 public abstract Wrapper createWrapper(Object json);
426 * Starts a transaction which encloses multiple GraphInventory mutations
430 public abstract TransactionalClient beginTransaction();
433 * Starts a transaction groups multiple GraphInventory mutations
437 public abstract SingleTransactionClient beginSingleTransaction();
439 public <T extends RestProperties> T getRestProperties() {
440 return client.getRestProperties();