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.uri.GraphInventoryPluralResourceUri;
38 import org.onap.aaiclient.client.graphinventory.entities.uri.GraphInventoryResourceUri;
39 import org.onap.aaiclient.client.graphinventory.entities.uri.GraphInventorySingleResourceUri;
40 import org.onap.aaiclient.client.graphinventory.entities.uri.HttpAwareUri;
41 import org.onap.aaiclient.client.graphinventory.exceptions.GraphInventoryMultipleItemsException;
42 import org.onap.so.client.RestClient;
43 import org.onap.so.client.RestProperties;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
47 public abstract class GraphInventoryResourcesClient<Self, Uri extends GraphInventoryResourceUri<?, ?>, SingleUri extends GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?>, PluralUri extends GraphInventoryPluralResourceUri<?, ?>, EdgeLabel extends GraphInventoryEdgeLabel, Wrapper extends GraphInventoryResultWrapper, TransactionalClient, SingleTransactionClient> {
49 private static final Logger logger = LoggerFactory.getLogger(GraphInventoryResourcesClient.class);
51 protected GraphInventoryClient client;
53 protected GraphInventoryResourcesClient(GraphInventoryClient client) {
58 * creates a new object in GraphInventory
60 * @param obj - can be any object which will marshal into a valid GraphInventory payload
64 public void create(SingleUri uri, Object obj) {
65 RestClient giRC = client.createClient(uri);
70 * creates a new object in GraphInventory with no payload body
75 public void createEmpty(SingleUri uri) {
76 RestClient giRC = client.createClient(uri);
81 * returns false if the object does not exist in GraphInventory
86 public boolean exists(Uri uri) {
87 GraphInventoryResourceUri<?, ?> forceMinimal = (Uri) uri.clone();
88 forceMinimal.format(Format.COUNT);
89 forceMinimal.limit(1);
91 RestClient giRC = client.createClient(forceMinimal);
93 return giRC.get().getStatus() == Status.OK.getStatusCode();
94 } catch (NotFoundException e) {
100 * Adds a relationship between two objects in GraphInventory
106 public void connect(SingleUri uriA, SingleUri uriB) {
107 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> uriAClone = (SingleUri) uriA.clone();
108 RestClient giRC = client.createClient(uriAClone.relationshipAPI());
109 giRC.put(this.buildRelationship(uriB));
113 * Adds a relationship between two objects in GraphInventory with a given edge label
120 public void connect(SingleUri uriA, SingleUri uriB, EdgeLabel label) {
121 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> uriAClone = (SingleUri) uriA.clone();
122 RestClient giRC = client.createClient(uriAClone.relationshipAPI());
123 giRC.put(this.buildRelationship(uriB, label));
127 * Removes relationship from two objects in GraphInventory
133 public void disconnect(SingleUri uriA, SingleUri uriB) {
134 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> uriAClone = (SingleUri) uriA.clone();
135 RestClient giRC = client.createClient(uriAClone.relationshipAPI());
136 giRC.delete(this.buildRelationship(uriB));
140 * Deletes object from GraphInventory. Automatically handles resource-version.
145 public void delete(SingleUri uri) {
146 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> clone = (SingleUri) uri.clone();
147 RestClient giRC = client.createClient(clone);
148 Map<String, Object> result = giRC.get(new GenericType<Map<String, Object>>() {}).orElseThrow(
149 () -> new NotFoundException(clone.build() + " does not exist in " + client.getGraphDBName()));
150 String resourceVersion = (String) result.get("resource-version");
151 giRC = client.createClient(clone.resourceVersion(resourceVersion));
157 * Deletes object from GraphInventory only if exists. Automatically handles resource-version.
162 public void deleteIfExists(SingleUri uri) {
163 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> clone = (SingleUri) uri.clone();
164 RestClient giRC = client.createClient(clone);
165 Optional<Map<String, Object>> result = giRC.get(new GenericType<Map<String, Object>>() {});
166 if (result.isPresent()) {
167 String resourceVersion = (String) result.get().get("resource-version");
168 giRC = client.createClient(clone.resourceVersion(resourceVersion));
171 logger.warn(clone.build() + " already does not exist in " + client.getGraphDBName()
172 + " therefore delete call not executed");
177 * @param obj - can be any object which will marshal into a valid GraphInventory payload
181 public void update(SingleUri uri, Object obj) {
182 RestClient giRC = client.createClient(uri);
187 * Retrieves an object from GraphInventory and unmarshalls it into the Class specified
193 public <T> Optional<T> get(Class<T> clazz, Uri uri) {
195 return client.createClient(uri).get(clazz);
196 } catch (NotFoundException e) {
197 if (this.getRestProperties().mapNotFoundToEmpty()) {
198 return Optional.empty();
206 * Retrieves an object from GraphInventory and returns complete response
211 public Response getFullResponse(Uri uri) {
213 return client.createClient(uri).get();
214 } catch (NotFoundException e) {
215 if (this.getRestProperties().mapNotFoundToEmpty()) {
216 return e.getResponse();
224 * Retrieves an object from GraphInventory and automatically unmarshalls it into a Map or List
230 public <T> Optional<T> get(GenericType<T> resultClass, Uri uri) {
232 return client.createClient(uri).get(resultClass);
233 } catch (NotFoundException e) {
234 if (this.getRestProperties().mapNotFoundToEmpty()) {
235 return Optional.empty();
242 public <T, R> Optional<R> getOne(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
243 Optional<List<R>> result = unwrapPlural(pluralClass, resultClass, uri);
245 if (result.isPresent()) {
246 if (result.get().size() == 1) {
247 return Optional.of(result.get().get(0));
249 throw new GraphInventoryMultipleItemsException(result.get().size(), uri);
253 return Optional.empty();
256 public <T, R> Optional<R> getFirst(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
257 Optional<List<R>> result = unwrapPlural(pluralClass, resultClass, uri);
259 if (result.isPresent() && !result.get().isEmpty()) {
260 return Optional.of(result.get().get(0));
263 return Optional.empty();
266 public <T, R> Optional<Wrapper> getFirstWrapper(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
268 Optional<R> result = getFirst(pluralClass, resultClass, uri);
269 if (result.isPresent()) {
270 return Optional.of(this.createWrapper(result.get()));
272 return Optional.empty();
276 public <T, R> Optional<Wrapper> getOneWrapper(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
278 Optional<R> result = getOne(pluralClass, resultClass, uri);
279 if (result.isPresent()) {
280 return Optional.of(this.createWrapper(result.get()));
282 return Optional.empty();
286 protected <T, R> Optional<List<R>> unwrapPlural(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
288 PluralUri clone = (PluralUri) uri.clone().limit(1);
289 Optional<T> obj = client.createClient(clone).get(pluralClass);
290 if (obj.isPresent()) {
291 Optional<Method> listMethod = Arrays.stream(obj.get().getClass().getMethods()).filter(method -> {
293 Type returnType = method.getGenericReturnType();
294 if (returnType instanceof ParameterizedType) {
295 Type[] types = ((ParameterizedType) returnType).getActualTypeArguments();
296 if (types != null && types[0] instanceof Class) {
297 Class<?> listClass = (Class<?>) types[0];
298 return resultClass.equals(listClass);
304 if (listMethod.isPresent()) {
306 return Optional.of((List<R>) listMethod.get().invoke(obj.get()));
308 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
309 throw new RuntimeException(e);
313 return Optional.empty();
315 } catch (NotFoundException e) {
316 if (this.getRestProperties().mapNotFoundToEmpty()) {
317 return Optional.empty();
325 * Retrieves an object from GraphInventory wrapped in a helper class which offer additional features
330 public Wrapper get(Uri uri) {
333 json = client.createClient(uri).get(String.class).orElse(null);
334 } catch (NotFoundException e) {
335 if (this.getRestProperties().mapNotFoundToEmpty()) {
341 return this.createWrapper(json);
345 * Retrieves an object from GraphInventory wrapped in a helper class which offer additional features If the object
346 * cannot be found in GraphInventory the method will throw the runtime exception included as an argument
351 public Wrapper get(Uri uri, Class<? extends RuntimeException> c) {
354 json = client.createClient(uri).get(String.class).orElseThrow(() -> createException(c,
355 uri.build() + " not found in " + client.getGraphDBName(), Optional.empty()));
356 } catch (NotFoundException e) {
357 throw createException(c, "could not construct uri for use with " + client.getGraphDBName(), Optional.of(e));
360 return this.createWrapper(json);
363 private RuntimeException createException(Class<? extends RuntimeException> c, String message,
364 Optional<Throwable> t) {
368 e = c.getConstructor(String.class, Throwable.class).newInstance(message, t.get());
370 e = c.getConstructor(String.class).newInstance(message);
372 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
373 | NoSuchMethodException | SecurityException e1) {
374 throw new IllegalArgumentException("could not create instance for " + c.getName());
381 * Will automatically create the object if it does not exist
383 * @param obj - Optional object which serializes to a valid GraphInventory payload
387 public Self createIfNotExists(SingleUri uri, Optional<Object> obj) {
388 if (!this.exists((Uri) uri)) {
389 if (obj.isPresent()) {
390 this.create(uri, obj.get());
392 this.createEmpty(uri);
399 protected Relationship buildRelationship(SingleUri uri) {
400 return buildRelationship(uri, Optional.empty());
403 protected Relationship buildRelationship(SingleUri uri, GraphInventoryEdgeLabel label) {
404 return buildRelationship(uri, Optional.of(label));
407 protected Relationship buildRelationship(SingleUri uri, Optional<GraphInventoryEdgeLabel> label) {
408 final Relationship result = new Relationship();
409 if (uri instanceof HttpAwareUri) {
410 result.setRelatedLink(((HttpAwareUri) uri).locateAndBuild().toString());
412 result.setRelatedLink(uri.build().toString());
414 if (label.isPresent()) {
415 result.setRelationshipLabel(label.get().toString());
420 public abstract Wrapper createWrapper(String json);
422 public abstract Wrapper createWrapper(Object json);
425 * Starts a transaction which encloses multiple GraphInventory mutations
429 public abstract TransactionalClient beginTransaction();
432 * Starts a transaction groups multiple GraphInventory mutations
436 public abstract SingleTransactionClient beginSingleTransaction();
438 public <T extends RestProperties> T getRestProperties() {
439 return client.getRestProperties();