2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 - 2018 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.so.client.aai;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.List;
28 import java.util.Map.Entry;
29 import java.util.Optional;
31 import javax.ws.rs.NotFoundException;
32 import javax.ws.rs.core.GenericType;
34 import org.onap.aai.domain.yang.Relationship;
35 import org.onap.so.client.RestClient;
36 import org.onap.so.client.aai.entities.AAIEdgeLabel;
37 import org.onap.so.client.aai.entities.AAIError;
38 import org.onap.so.client.aai.entities.bulkprocess.Transactions;
39 import org.onap.so.client.aai.entities.singletransaction.OperationBodyRequest;
40 import org.onap.so.client.aai.entities.singletransaction.OperationBodyResponse;
41 import org.onap.so.client.aai.entities.singletransaction.SingleTransactionRequest;
42 import org.onap.so.client.aai.entities.singletransaction.SingleTransactionResponse;
43 import org.onap.so.client.aai.entities.uri.AAIResourceUri;
44 import org.onap.so.client.aai.entities.uri.AAIUri;
45 import org.onap.so.client.aai.entities.uri.AAIUriFactory;
46 import org.onap.so.client.graphinventory.GraphInventoryPatchConverter;
47 import org.onap.so.client.graphinventory.GraphInventorySingleTransactionClient;
48 import org.onap.so.client.graphinventory.exceptions.BulkProcessFailed;
50 import com.fasterxml.jackson.core.type.TypeReference;
51 import com.fasterxml.jackson.databind.ObjectMapper;
52 import com.google.common.base.Joiner;
54 public class AAISingleTransactionClient extends AAIClient implements GraphInventorySingleTransactionClient<AAISingleTransactionClient, AAIResourceUri, AAIEdgeLabel> {
56 private final SingleTransactionRequest request;
57 private final AAIVersion version;
58 private int actionCount = 0;
60 private final GraphInventoryPatchConverter patchConverter = new GraphInventoryPatchConverter();
62 protected AAISingleTransactionClient(AAIVersion version) {
64 this.version = version;
65 this.request = new SingleTransactionRequest();
69 * @see org.onap.so.client.aai.GraphInventoryTransactionClient#create(org.onap.so.client.aai.entities.uri.AAIResourceUri, java.lang.Object)
72 public AAISingleTransactionClient create(AAIResourceUri uri, Object obj) {
73 request.getOperations().add(new OperationBodyRequest().withAction("put").withUri(uri.build().toString()).withBody(obj));
74 incrementActionAmount();
79 * @see org.onap.so.client.aai.GraphInventoryTransactionClient#createEmpty(org.onap.so.client.aai.entities.uri.AAIResourceUri)
82 public AAISingleTransactionClient createEmpty(AAIResourceUri uri) {
83 request.getOperations().add(new OperationBodyRequest().withAction("put").withUri(uri.build().toString()).withBody(new HashMap<String, String>()));
84 incrementActionAmount();
89 * @see org.onap.so.client.aai.GraphInventoryTransactionClient#connect(org.onap.so.client.aai.entities.uri.AAIResourceUri, org.onap.so.client.aai.entities.uri.AAIResourceUri)
92 public AAISingleTransactionClient connect(AAIResourceUri uriA, AAIResourceUri uriB) {
93 AAIResourceUri uriAClone = uriA.clone();
94 request.getOperations().add(new OperationBodyRequest().withAction("put").withUri(uriAClone.relationshipAPI().build().toString()).withBody(this.buildRelationship(uriB)));
95 incrementActionAmount();
100 * @see org.onap.so.client.aai.GraphInventoryTransactionClient#connect(org.onap.so.client.aai.entities.uri.AAIResourceUri, java.util.List)
103 public AAISingleTransactionClient connect(AAIResourceUri uriA, List<AAIResourceUri> uris) {
104 for (AAIResourceUri uri : uris) {
105 this.connect(uriA, uri);
111 * @see org.onap.so.client.aai.GraphInventoryTransactionClient#connect(org.onap.so.client.aai.entities.uri.AAIResourceUri, org.onap.so.client.aai.entities.uri.AAIResourceUri, org.onap.so.client.aai.entities.AAIEdgeLabel)
114 public AAISingleTransactionClient connect(AAIResourceUri uriA, AAIResourceUri uriB, AAIEdgeLabel label) {
115 AAIResourceUri uriAClone = uriA.clone();
116 RestClient aaiRC = this.createClient(uriAClone.relationshipAPI());
117 aaiRC.put(this.buildRelationship(uriB, label));
122 * @see org.onap.so.client.aai.GraphInventoryTransactionClient#connect(org.onap.so.client.aai.entities.uri.AAIResourceUri, java.util.List, org.onap.so.client.aai.entities.AAIEdgeLabel)
125 public AAISingleTransactionClient connect(AAIResourceUri uriA, List<AAIResourceUri> uris, AAIEdgeLabel label) {
126 for (AAIResourceUri uri : uris) {
127 this.connect(uriA, uri, label);
133 * @see org.onap.so.client.aai.GraphInventoryTransactionClient#disconnect(org.onap.so.client.aai.entities.uri.AAIResourceUri, org.onap.so.client.aai.entities.uri.AAIResourceUri)
136 public AAISingleTransactionClient disconnect(AAIResourceUri uriA, AAIResourceUri uriB) {
137 AAIResourceUri uriAClone = uriA.clone();
138 request.getOperations().add(new OperationBodyRequest().withAction("delete").withUri(uriAClone.relationshipAPI().build().toString()).withBody(this.buildRelationship(uriB)));
139 incrementActionAmount();
144 * @see org.onap.so.client.aai.GraphInventoryTransactionClient#disconnect(org.onap.so.client.aai.entities.uri.AAIResourceUri, java.util.List)
147 public AAISingleTransactionClient disconnect(AAIResourceUri uriA, List<AAIResourceUri> uris) {
148 for (AAIResourceUri uri : uris) {
149 this.disconnect(uriA, uri);
154 * @see org.onap.so.client.aai.GraphInventoryTransactionClient#delete(org.onap.so.client.aai.entities.uri.AAIResourceUri)
157 public AAISingleTransactionClient delete(AAIResourceUri uri) {
158 AAIResourcesClient client = new AAIResourcesClient();
159 AAIResourceUri clone = uri.clone();
160 Map<String, Object> result = client.get(new GenericType<Map<String, Object>>(){}, clone)
161 .orElseThrow(() -> new NotFoundException(clone.build() + " does not exist in A&AI"));
162 String resourceVersion = (String) result.get("resource-version");
163 request.getOperations().add(new OperationBodyRequest().withAction("delete").withUri(clone.resourceVersion(resourceVersion).build().toString()).withBody(""));
164 incrementActionAmount();
169 * @see org.onap.so.client.aai.GraphInventoryTransactionClient#update(org.onap.so.client.aai.entities.uri.AAIResourceUri, java.lang.Object)
172 public AAISingleTransactionClient update(AAIResourceUri uri, Object obj) {
174 final String payload = getPatchConverter().convertPatchFormat(obj);
175 request.getOperations().add(new OperationBodyRequest().withAction("patch").withUri(uri.build().toString()).withBody(payload));
176 incrementActionAmount();
180 private void incrementActionAmount() {
184 * @see org.onap.so.client.aai.GraphInventoryTransactionClient#execute()
187 public void execute() throws BulkProcessFailed {
188 RestClient client = this.createClient(AAIUriFactory.createResourceUri(AAIObjectType.SINGLE_TRANSACTION));
190 SingleTransactionResponse response = client.post(this.request, SingleTransactionResponse.class);
191 if (response != null) {
192 final Optional<String> errorMessage = this.locateErrorMessages(response);
193 if (errorMessage.isPresent()) {
194 throw new BulkProcessFailed("One or more transactions failed in A&AI. Check logs for payloads.\nMessages:\n" + errorMessage.get());
197 throw new BulkProcessFailed("Transactions acccepted by A&AI, but there was no response. Unsure of result.");
200 this.request.getOperations().clear();
201 this.actionCount = 0;
205 protected Optional<String> locateErrorMessages(SingleTransactionResponse response) {
206 final List<String> errorMessages = new ArrayList<>();
207 final ObjectMapper mapper = new ObjectMapper();
209 for (OperationBodyResponse body : response.getOperationResponses()) {
210 if (Optional.ofNullable(body.getResponseStatusCode()).orElse(400) > 300) {
213 error = mapper.readValue(mapper.writeValueAsString(body.getResponseBody()), AAIError.class);
214 } catch (IOException e) {
215 logger.error("could not parse error object from A&AI", e);
216 error = new AAIError();
218 AAIErrorFormatter formatter = new AAIErrorFormatter(error);
219 String outputMessage = formatter.getMessage();
220 errorMessages.add(outputMessage);
224 if (!errorMessages.isEmpty()) {
225 return Optional.of(Joiner.on("\n").join(errorMessages));
227 return Optional.empty();
231 private Relationship buildRelationship(AAIResourceUri uri) {
232 return buildRelationship(uri, Optional.empty());
235 private Relationship buildRelationship(AAIResourceUri uri, AAIEdgeLabel label) {
236 return buildRelationship(uri, Optional.of(label));
238 private Relationship buildRelationship(AAIResourceUri uri, Optional<AAIEdgeLabel> label) {
239 final Relationship result = new Relationship();
240 result.setRelatedLink(uri.build().toString());
241 if (label.isPresent()) {
242 result.setRelationshipLabel(label.toString());
248 protected AAIVersion getVersion() {
252 protected SingleTransactionRequest getRequest() {
256 protected GraphInventoryPatchConverter getPatchConverter() {
257 return this.patchConverter;