Merge "added test case to CamundaClientTest.java"
[so.git] / common / src / main / java / org / onap / so / client / aai / AAIResourcesClient.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.onap.so.client.aai;
22
23 import java.lang.reflect.InvocationTargetException;
24 import java.util.Map;
25 import java.util.Optional;
26
27 import javax.ws.rs.NotFoundException;
28 import javax.ws.rs.core.GenericType;
29 import javax.ws.rs.core.Response;
30 import javax.ws.rs.core.Response.Status;
31
32 import org.onap.aai.domain.yang.Relationship;
33 import org.onap.so.client.RestClient;
34 import org.onap.so.client.RestProperties;
35 import org.onap.so.client.aai.entities.AAIEdgeLabel;
36 import org.onap.so.client.aai.entities.AAIResultWrapper;
37 import org.onap.so.client.aai.entities.uri.AAIResourceUri;
38 import org.onap.so.client.aai.entities.uri.AAIUri;
39 import org.onap.so.client.graphinventory.entities.uri.Depth;
40
41 public class AAIResourcesClient extends AAIClient {
42                         
43         public AAIResourcesClient() {
44                 super();
45         }
46         
47         public AAIResourcesClient(AAIVersion version) {
48                 super();
49                 this.version = version;
50         }
51         
52         /**
53          * creates a new object in A&AI
54          * 
55          * @param obj - can be any object which will marshal into a valid A&AI payload
56          * @param uri
57          * @return
58          */
59         public void create(AAIResourceUri uri, Object obj) {
60                 RestClient aaiRC = this.createClient(uri);
61                 aaiRC.put(obj);
62                 return;
63         }
64         
65         /**
66          * creates a new object in A&AI with no payload body
67          * 
68          * @param uri
69          * @return
70          */
71         public void createEmpty(AAIResourceUri uri) {
72                 RestClient aaiRC = this.createClient(uri);
73                 aaiRC.put("");
74                 return;
75         }
76         
77         /**
78          * returns false if the object does not exist in A&AI
79          * 
80          * @param uri
81          * @return
82          */
83         public boolean exists(AAIResourceUri uri) {
84                 AAIUri forceMinimal = this.addParams(Optional.of(Depth.ZERO), true, uri);
85                 try {
86                         RestClient aaiRC = this.createClient(forceMinimal);
87                         
88                         return aaiRC.get().getStatus() == Status.OK.getStatusCode();
89                 } catch (NotFoundException e) {
90                         return false;
91                 }
92         }
93         
94         /**
95          * Adds a relationship between two objects in A&AI 
96          * @param uriA
97          * @param uriB
98          * @return
99          */
100         public void connect(AAIResourceUri uriA, AAIResourceUri uriB) {
101                 AAIResourceUri uriAClone = uriA.clone();
102                 RestClient aaiRC = this.createClient(uriAClone.relationshipAPI());
103                 aaiRC.put(this.buildRelationship(uriB));
104                 return;
105         }
106         
107         /**
108          * Adds a relationship between two objects in A&AI 
109          * with a given edge label
110          * @param uriA
111          * @param uriB
112          * @param edge label
113          * @return
114          */
115         public void connect(AAIResourceUri uriA, AAIResourceUri uriB, AAIEdgeLabel label) {
116                 AAIResourceUri uriAClone = uriA.clone();
117                 RestClient aaiRC = this.createClient(uriAClone.relationshipAPI());
118                 aaiRC.put(this.buildRelationship(uriB, label));
119                 return;
120         }
121         
122         /**
123          * Removes relationship from two objects in A&AI
124          * 
125          * @param uriA
126          * @param uriB
127          * @return
128          */
129         public void disconnect(AAIResourceUri uriA, AAIResourceUri uriB) {
130                 AAIResourceUri uriAClone = uriA.clone();
131                 RestClient aaiRC = this.createClient(uriAClone.relationshipAPI());
132                 aaiRC.delete(this.buildRelationship(uriB));
133                 return;
134         }
135         
136         /**
137          * Deletes object from A&AI. Automatically handles resource-version.
138          * 
139          * @param uri
140          * @return
141          */
142         public void delete(AAIResourceUri uri) {
143                 AAIResourceUri clone = uri.clone();
144                 RestClient aaiRC = this.createClient(clone);
145                 Map<String, Object> result = aaiRC.get(new GenericType<Map<String, Object>>(){})
146                                 .orElseThrow(() -> new NotFoundException(clone.build() + " does not exist in A&AI"));
147                 String resourceVersion = (String) result.get("resource-version");
148                 aaiRC = this.createClient(clone.resourceVersion(resourceVersion));
149                 aaiRC.delete();
150                 return;
151         }
152         
153         /**
154          * @param obj - can be any object which will marshal into a valid A&AI payload
155          * @param uri
156          * @return
157          */
158         public void update(AAIResourceUri uri, Object obj) {
159                 RestClient aaiRC = this.createClient(uri);
160                 aaiRC.patch(obj);
161                 return;
162         }
163         
164         /**
165          * Retrieves an object from A&AI and unmarshalls it into the Class specified
166          * @param clazz
167          * @param uri
168          * @return
169          */
170         public <T> Optional<T> get(Class<T> clazz, AAIResourceUri uri) {
171                 try {
172                         return this.createClient(uri).get(clazz);
173                 } catch (NotFoundException e) {
174                         if (this.getRestProperties().mapNotFoundToEmpty()) {
175                                 return Optional.empty();
176                         } else {
177                                 throw e;
178                         }
179                 }
180         }
181         
182         /**
183          * Retrieves an object from A&AI and returns complete response
184          * @param uri
185          * @return
186          */
187         public Response getFullResponse(AAIResourceUri uri) {
188                 try {
189                         return this.createClient(uri).get();
190                 } catch (NotFoundException e) {
191                         if (this.getRestProperties().mapNotFoundToEmpty()) {
192                                 return e.getResponse();
193                         } else {
194                                 throw e;
195                         }
196                 }
197         }
198         
199         /**
200          * Retrieves an object from A&AI and automatically unmarshalls it into a Map or List 
201          * @param resultClass
202          * @param uri
203          * @return
204          */
205         public <T> Optional<T> get(GenericType<T> resultClass, AAIResourceUri uri) {
206                 try {
207                         return this.createClient(uri).get(resultClass);
208                 } catch (NotFoundException e) {
209                         if (this.getRestProperties().mapNotFoundToEmpty()) {
210                                 return Optional.empty();
211                         } else {
212                                 throw e;
213                         }
214                 }
215         }
216         
217         /**
218          * Retrieves an object from A&AI wrapped in a helper class which offer additional features
219          * 
220          * @param uri
221          * @return
222          */
223         public AAIResultWrapper get(AAIResourceUri uri) {
224                 String json;
225                 try {
226                         json = this.createClient(uri).get(String.class).orElse(null);
227                 } catch (NotFoundException e) {
228                         if (this.getRestProperties().mapNotFoundToEmpty()) {
229                                 json = null;
230                         } else {
231                                 throw e;
232                         }
233                 }
234                 return new AAIResultWrapper(json);
235         }
236         
237         /**
238          * Retrieves an object from A&AI wrapped in a helper class which offer additional features
239          * If the object cannot be found in A&AI the method will throw the runtime exception
240          * included as an argument
241          * @param uri
242          * @return
243          */
244         public AAIResultWrapper get(AAIResourceUri uri, Class<? extends RuntimeException> c) {
245                 String json;
246                 try {
247                         json = this.createClient(uri).get(String.class)
248                                         .orElseThrow(() -> createException(c, uri.build() + " not found in A&AI"));
249                 } catch (NotFoundException e) {
250                         throw createException(c, "could not construct uri for use with A&AI");
251                 }
252
253                 return new AAIResultWrapper(json);
254         }
255         
256         private RuntimeException createException(Class<? extends RuntimeException> c, String message) {
257                 RuntimeException e;
258                 try {
259                         e = c.getConstructor(String.class).newInstance(message);
260                 } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
261                                 | NoSuchMethodException | SecurityException e1) {
262                         throw new IllegalArgumentException("could not create instance for " + c.getName());
263                 }
264                 
265                 return e;
266         }
267         
268         private Relationship buildRelationship(AAIResourceUri uri) {
269                 return buildRelationship(uri, Optional.empty());
270         }
271         
272         private Relationship buildRelationship(AAIResourceUri uri, AAIEdgeLabel label) {
273                 return buildRelationship(uri, Optional.of(label));
274         }
275         private Relationship buildRelationship(AAIResourceUri uri, Optional<AAIEdgeLabel> label) {
276                 final Relationship result = new Relationship();
277                 result.setRelatedLink(uri.build().toString());
278                 if (label.isPresent()) {
279                         result.setRelationshipLabel(label.toString());
280                 }
281                 return result;
282         }
283         
284         /**
285          * Will automatically create the object if it does not exist
286          * 
287          * @param obj - Optional object which serializes to a valid A&AI payload
288          * @param uri
289          * @return
290          */
291         public AAIResourcesClient createIfNotExists(AAIResourceUri uri, Optional<Object> obj) {
292                 if(!this.exists(uri)){
293                         if (obj.isPresent()) {
294                                 this.create(uri, obj.get());
295                         } else {
296                                 this.createEmpty(uri);
297                         }
298                         
299                 }
300                 return this;
301         }
302
303         /**
304          * Starts a transaction which encloses multiple A&AI mutations
305          * 
306          * @return
307          */
308         public AAITransactionalClient beginTransaction() {
309                 return new AAITransactionalClient(this.getVersion());
310         }
311         
312         /**
313          * Starts a transaction groups multiple A&AI mutations
314          * 
315          * @return
316          */
317         public AAISingleTransactionClient beginSingleTransaction() {
318                 return new AAISingleTransactionClient(this.getVersion());
319         }
320         
321         private AAIUri addParams(Optional<Depth> depth, boolean nodesOnly, AAIUri uri) {
322                 AAIUri clone = uri.clone();
323                 if (depth.isPresent()) {
324                         clone.depth(depth.get());
325                 }
326                 if (nodesOnly) {
327                         clone.nodesOnly(nodesOnly);
328                 }
329                 
330                 return clone;
331         }
332         @Override
333         public <T extends RestProperties> T getRestProperties() {
334                 return super.getRestProperties();
335         }
336 }