2 * ============LICENSE_START=======================================================
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
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.List;
27 import java.util.Map.Entry;
28 import java.util.Optional;
29 import javax.ws.rs.core.GenericType;
30 import javax.ws.rs.core.Response;
31 import org.onap.aai.domain.yang.Relationship;
32 import org.onap.so.client.RestClient;
33 import org.onap.so.client.aai.entities.AAIEdgeLabel;
34 import org.onap.so.client.aai.entities.AAIError;
35 import org.onap.so.client.aai.entities.bulkprocess.OperationBody;
36 import org.onap.so.client.aai.entities.bulkprocess.Transaction;
37 import org.onap.so.client.aai.entities.bulkprocess.Transactions;
38 import org.onap.so.client.aai.entities.uri.AAIResourceUri;
39 import org.onap.so.client.aai.entities.uri.AAIUriFactory;
40 import org.onap.so.client.graphinventory.GraphInventoryPatchConverter;
41 import org.onap.so.client.graphinventory.GraphInventoryTransactionClient;
42 import org.onap.so.client.graphinventory.exceptions.BulkProcessFailed;
43 import org.onap.so.jsonpath.JsonPathUtil;
44 import com.fasterxml.jackson.core.type.TypeReference;
45 import com.fasterxml.jackson.databind.ObjectMapper;
46 import com.google.common.base.Joiner;
48 public class AAITransactionalClient
49 extends GraphInventoryTransactionClient<AAITransactionalClient, AAIResourceUri, AAIEdgeLabel> {
51 private final Transactions transactions;
52 private Transaction currentTransaction;
54 private AAIResourcesClient resourcesClient;
55 private AAIClient aaiClient;
57 protected AAITransactionalClient(AAIResourcesClient resourcesClient, AAIClient aaiClient) {
59 this.resourcesClient = resourcesClient;
60 this.aaiClient = aaiClient;
61 this.transactions = new Transactions();
65 private void startTransaction() {
66 Transaction transaction = new Transaction();
67 transactions.getTransactions().add(transaction);
68 currentTransaction = transaction;
74 * @see org.onap.so.client.aai.GraphInventoryTransactionalClient#beginNewTransaction()
76 public AAITransactionalClient beginNewTransaction() {
84 * @see org.onap.so.client.aai.GraphInventoryTransactionalClient#execute()
87 public void execute() throws BulkProcessFailed {
89 if (!this.transactions.getTransactions().isEmpty()) {
90 RestClient client = aaiClient.createClient(AAIUriFactory.createResourceUri(AAIObjectType.BULK_PROCESS));
91 Response response = client.put(this.transactions);
92 if (response.hasEntity()) {
93 final Optional<String> errorMessage = this.locateErrorMessages(response.readEntity(String.class));
94 if (errorMessage.isPresent()) {
95 throw new BulkProcessFailed(
96 "One or more transactions failed in A&AI. Check logs for payloads.\nMessages:\n"
97 + errorMessage.get());
100 throw new BulkProcessFailed(
101 "Transactions acccepted by A&AI, but there was no response. Unsure of result.");
105 this.transactions.getTransactions().clear();
106 this.currentTransaction = null;
107 this.actionCount = 0;
111 protected Optional<String> locateErrorMessages(String response) {
112 final List<String> errorMessages = new ArrayList<>();
113 final List<String> results = JsonPathUtil.getInstance().locateResultList(response, "$..body");
114 final ObjectMapper mapper = new ObjectMapper();
115 if (!results.isEmpty()) {
116 List<Map<String, Object>> parsed = new ArrayList<>();
118 for (String result : results) {
119 parsed.add(mapper.readValue(result, new TypeReference<Map<String, Object>>() {}));
121 } catch (IOException e) {
122 logger.error("could not map json", e);
124 for (Map<String, Object> map : parsed) {
125 for (Entry<String, Object> entry : map.entrySet()) {
126 if (!entry.getKey().matches("2\\d\\d")) {
129 error = mapper.readValue(entry.getValue().toString(), AAIError.class);
130 } catch (IOException e) {
131 logger.error("could not parse error object from A&AI", e);
132 error = new AAIError();
134 AAIErrorFormatter formatter = new AAIErrorFormatter(error);
135 String outputMessage = formatter.getMessage();
136 logger.error("part of a bulk action failed in A&AI: " + entry.getValue());
137 errorMessages.add(outputMessage);
143 if (!errorMessages.isEmpty()) {
144 return Optional.of(Joiner.on("\n").join(errorMessages));
146 return Optional.empty();
150 private Relationship buildRelationship(AAIResourceUri uri) {
151 return buildRelationship(uri, Optional.empty());
154 private Relationship buildRelationship(AAIResourceUri uri, AAIEdgeLabel label) {
155 return buildRelationship(uri, Optional.of(label));
158 private Relationship buildRelationship(AAIResourceUri uri, Optional<AAIEdgeLabel> label) {
159 final Relationship result = new Relationship();
160 result.setRelatedLink(uri.build().toString());
161 if (label.isPresent()) {
162 result.setRelationshipLabel(label.toString());
167 protected Transactions getTransactions() {
168 return this.transactions;
172 public void put(String uri, Object body) {
173 currentTransaction.getPut().add(new OperationBody().withUri(uri).withBody(body));
177 public void delete(String uri, Object body) {
178 currentTransaction.getDelete().add(new OperationBody().withUri(uri).withBody(body));
183 public void patch(String uri, Object body) {
184 currentTransaction.getPatch().add(new OperationBody().withUri(uri).withBody(body));
188 protected <T> Optional<T> get(GenericType<T> genericType, AAIResourceUri clone) {
189 return resourcesClient.get(genericType, clone);
193 protected boolean exists(AAIResourceUri uri) {
194 return resourcesClient.exists(uri);
198 protected String getGraphDBName() {
199 return aaiClient.getGraphDBName();
203 protected GraphInventoryPatchConverter getPatchConverter() {
204 return this.patchConverter;