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;
46 public abstract class GraphInventoryResourcesClient<Self, Uri extends GraphInventoryResourceUri<?, ?>, SingleUri extends GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?>, PluralUri extends GraphInventoryPluralResourceUri<?, ?>, EdgeLabel extends GraphInventoryEdgeLabel, Wrapper extends GraphInventoryResultWrapper, TransactionalClient, SingleTransactionClient> {
48 protected GraphInventoryClient client;
50 protected GraphInventoryResourcesClient(GraphInventoryClient client) {
55 * creates a new object in GraphInventory
57 * @param obj - can be any object which will marshal into a valid GraphInventory payload
61 public void create(SingleUri uri, Object obj) {
62 RestClient giRC = client.createClient(uri);
67 * creates a new object in GraphInventory with no payload body
72 public void createEmpty(SingleUri uri) {
73 RestClient giRC = client.createClient(uri);
78 * returns false if the object does not exist in GraphInventory
83 public boolean exists(Uri uri) {
84 GraphInventoryResourceUri<?, ?> forceMinimal = (Uri) uri.clone();
85 forceMinimal.format(Format.COUNT);
86 forceMinimal.limit(1);
88 RestClient giRC = client.createClient(forceMinimal);
90 return giRC.get().getStatus() == Status.OK.getStatusCode();
91 } catch (NotFoundException e) {
97 * Adds a relationship between two objects in GraphInventory
103 public void connect(SingleUri uriA, SingleUri uriB) {
104 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> uriAClone = (SingleUri) uriA.clone();
105 RestClient giRC = client.createClient(uriAClone.relationshipAPI());
106 giRC.put(this.buildRelationship(uriB));
110 * Adds a relationship between two objects in GraphInventory with a given edge label
117 public void connect(SingleUri uriA, SingleUri uriB, EdgeLabel label) {
118 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> uriAClone = (SingleUri) uriA.clone();
119 RestClient giRC = client.createClient(uriAClone.relationshipAPI());
120 giRC.put(this.buildRelationship(uriB, label));
124 * Removes relationship from two objects in GraphInventory
130 public void disconnect(SingleUri uriA, SingleUri uriB) {
131 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> uriAClone = (SingleUri) uriA.clone();
132 RestClient giRC = client.createClient(uriAClone.relationshipAPI());
133 giRC.delete(this.buildRelationship(uriB));
137 * Deletes object from GraphInventory. Automatically handles resource-version.
142 public void delete(SingleUri uri) {
143 GraphInventorySingleResourceUri<?, ?, ?, ?, ?, ?> clone = (SingleUri) uri.clone();
144 RestClient giRC = client.createClient(clone);
145 Map<String, Object> result = giRC.get(new GenericType<Map<String, Object>>() {}).orElseThrow(
146 () -> new NotFoundException(clone.build() + " does not exist in " + client.getGraphDBName()));
147 String resourceVersion = (String) result.get("resource-version");
148 giRC = client.createClient(clone.resourceVersion(resourceVersion));
153 * @param obj - can be any object which will marshal into a valid GraphInventory payload
157 public void update(SingleUri uri, Object obj) {
158 RestClient giRC = client.createClient(uri);
163 * Retrieves an object from GraphInventory and unmarshalls it into the Class specified
169 public <T> Optional<T> get(Class<T> clazz, Uri uri) {
171 return client.createClient(uri).get(clazz);
172 } catch (NotFoundException e) {
173 if (this.getRestProperties().mapNotFoundToEmpty()) {
174 return Optional.empty();
182 * Retrieves an object from GraphInventory and returns complete response
187 public Response getFullResponse(Uri uri) {
189 return client.createClient(uri).get();
190 } catch (NotFoundException e) {
191 if (this.getRestProperties().mapNotFoundToEmpty()) {
192 return e.getResponse();
200 * Retrieves an object from GraphInventory and automatically unmarshalls it into a Map or List
206 public <T> Optional<T> get(GenericType<T> resultClass, Uri uri) {
208 return client.createClient(uri).get(resultClass);
209 } catch (NotFoundException e) {
210 if (this.getRestProperties().mapNotFoundToEmpty()) {
211 return Optional.empty();
218 public <T, R> Optional<R> getOne(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
219 Optional<List<R>> result = unwrapPlural(pluralClass, resultClass, uri);
221 if (result.isPresent()) {
222 if (result.get().size() == 1) {
223 return Optional.of(result.get().get(0));
225 throw new GraphInventoryMultipleItemsException(result.get().size(), uri);
229 return Optional.empty();
232 public <T, R> Optional<R> getFirst(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
233 Optional<List<R>> result = unwrapPlural(pluralClass, resultClass, uri);
235 if (result.isPresent() && !result.get().isEmpty()) {
236 return Optional.of(result.get().get(0));
239 return Optional.empty();
242 public <T, R> Optional<Wrapper> getFirstWrapper(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
244 Optional<R> result = getFirst(pluralClass, resultClass, uri);
245 if (result.isPresent()) {
246 return Optional.of(this.createWrapper(result.get()));
248 return Optional.empty();
252 public <T, R> Optional<Wrapper> getOneWrapper(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
254 Optional<R> result = getOne(pluralClass, resultClass, uri);
255 if (result.isPresent()) {
256 return Optional.of(this.createWrapper(result.get()));
258 return Optional.empty();
262 protected <T, R> Optional<List<R>> unwrapPlural(Class<T> pluralClass, Class<R> resultClass, PluralUri uri) {
264 PluralUri clone = (PluralUri) uri.clone().limit(1);
265 Optional<T> obj = client.createClient(clone).get(pluralClass);
266 if (obj.isPresent()) {
267 Optional<Method> listMethod = Arrays.stream(obj.get().getClass().getMethods()).filter(method -> {
269 Type returnType = method.getGenericReturnType();
270 if (returnType instanceof ParameterizedType) {
271 Type[] types = ((ParameterizedType) returnType).getActualTypeArguments();
272 if (types != null && types[0] instanceof Class) {
273 Class<?> listClass = (Class<?>) types[0];
274 return resultClass.equals(listClass);
280 if (listMethod.isPresent()) {
282 return Optional.of((List<R>) listMethod.get().invoke(obj.get()));
284 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
285 throw new RuntimeException(e);
289 return Optional.empty();
291 } catch (NotFoundException e) {
292 if (this.getRestProperties().mapNotFoundToEmpty()) {
293 return Optional.empty();
301 * Retrieves an object from GraphInventory wrapped in a helper class which offer additional features
306 public Wrapper get(Uri uri) {
309 json = client.createClient(uri).get(String.class).orElse(null);
310 } catch (NotFoundException e) {
311 if (this.getRestProperties().mapNotFoundToEmpty()) {
317 return this.createWrapper(json);
321 * Retrieves an object from GraphInventory wrapped in a helper class which offer additional features If the object
322 * cannot be found in GraphInventory the method will throw the runtime exception included as an argument
327 public Wrapper get(Uri uri, Class<? extends RuntimeException> c) {
330 json = client.createClient(uri).get(String.class).orElseThrow(() -> createException(c,
331 uri.build() + " not found in " + client.getGraphDBName(), Optional.empty()));
332 } catch (NotFoundException e) {
333 throw createException(c, "could not construct uri for use with " + client.getGraphDBName(), Optional.of(e));
336 return this.createWrapper(json);
339 private RuntimeException createException(Class<? extends RuntimeException> c, String message,
340 Optional<Throwable> t) {
344 e = c.getConstructor(String.class, Throwable.class).newInstance(message, t.get());
346 e = c.getConstructor(String.class).newInstance(message);
348 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
349 | NoSuchMethodException | SecurityException e1) {
350 throw new IllegalArgumentException("could not create instance for " + c.getName());
357 * Will automatically create the object if it does not exist
359 * @param obj - Optional object which serializes to a valid GraphInventory payload
363 public Self createIfNotExists(SingleUri uri, Optional<Object> obj) {
364 if (!this.exists((Uri) uri)) {
365 if (obj.isPresent()) {
366 this.create(uri, obj.get());
368 this.createEmpty(uri);
375 protected Relationship buildRelationship(SingleUri uri) {
376 return buildRelationship(uri, Optional.empty());
379 protected Relationship buildRelationship(SingleUri uri, GraphInventoryEdgeLabel label) {
380 return buildRelationship(uri, Optional.of(label));
383 protected Relationship buildRelationship(SingleUri uri, Optional<GraphInventoryEdgeLabel> label) {
384 final Relationship result = new Relationship();
385 if (uri instanceof HttpAwareUri) {
386 result.setRelatedLink(((HttpAwareUri) uri).locateAndBuild().toString());
388 result.setRelatedLink(uri.build().toString());
390 if (label.isPresent()) {
391 result.setRelationshipLabel(label.get().toString());
396 public abstract Wrapper createWrapper(String json);
398 public abstract Wrapper createWrapper(Object json);
401 * Starts a transaction which encloses multiple GraphInventory mutations
405 public abstract TransactionalClient beginTransaction();
408 * Starts a transaction groups multiple GraphInventory mutations
412 public abstract SingleTransactionClient beginSingleTransaction();
414 public <T extends RestProperties> T getRestProperties() {
415 return client.getRestProperties();