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;
30 import javax.ws.rs.core.GenericType;
31 import javax.ws.rs.core.Response;
33 import org.onap.aai.domain.yang.Relationship;
34 import org.onap.so.client.RestClient;
35 import org.onap.so.client.aai.entities.AAIEdgeLabel;
36 import org.onap.so.client.aai.entities.AAIError;
37 import org.onap.so.client.aai.entities.bulkprocess.OperationBody;
38 import org.onap.so.client.aai.entities.bulkprocess.Transaction;
39 import org.onap.so.client.aai.entities.bulkprocess.Transactions;
40 import org.onap.so.client.aai.entities.uri.AAIResourceUri;
41 import org.onap.so.client.aai.entities.uri.AAIUriFactory;
42 import org.onap.so.client.graphinventory.GraphInventoryPatchConverter;
43 import org.onap.so.client.graphinventory.GraphInventoryTransactionClient;
44 import org.onap.so.client.graphinventory.exceptions.BulkProcessFailed;
45 import org.onap.so.jsonpath.JsonPathUtil;
47 import com.fasterxml.jackson.core.type.TypeReference;
48 import com.fasterxml.jackson.databind.ObjectMapper;
49 import com.google.common.base.Joiner;
51 public class AAITransactionalClient extends GraphInventoryTransactionClient<AAITransactionalClient, AAIResourceUri, AAIEdgeLabel> {
53 private final Transactions transactions;
54 private Transaction currentTransaction;
56 private AAIResourcesClient resourcesClient;
57 private AAIClient aaiClient;
58 protected AAITransactionalClient(AAIResourcesClient resourcesClient, AAIClient aaiClient) {
60 this.resourcesClient = resourcesClient;
61 this.aaiClient = aaiClient;
62 this.transactions = new Transactions();
66 private void startTransaction() {
67 Transaction transaction = new Transaction();
68 transactions.getTransactions().add(transaction);
69 currentTransaction = transaction;
73 * @see org.onap.so.client.aai.GraphInventoryTransactionalClient#beginNewTransaction()
75 public AAITransactionalClient beginNewTransaction() {
81 * @see org.onap.so.client.aai.GraphInventoryTransactionalClient#execute()
84 public void execute() throws BulkProcessFailed {
85 RestClient client = aaiClient.createClient(AAIUriFactory.createResourceUri(AAIObjectType.BULK_PROCESS));
87 Response response = client.put(this.transactions);
88 if (response.hasEntity()) {
89 final Optional<String> errorMessage = this.locateErrorMessages(response.readEntity(String.class));
90 if (errorMessage.isPresent()) {
91 throw new BulkProcessFailed("One or more transactions failed in A&AI. Check logs for payloads.\nMessages:\n" + errorMessage.get());
94 throw new BulkProcessFailed("Transactions acccepted by A&AI, but there was no response. Unsure of result.");
97 this.transactions.getTransactions().clear();
98 this.currentTransaction = null;
103 protected Optional<String> locateErrorMessages(String response) {
104 final List<String> errorMessages = new ArrayList<>();
105 final List<String> results = JsonPathUtil.getInstance().locateResultList(response, "$..body");
106 final ObjectMapper mapper = new ObjectMapper();
107 if (!results.isEmpty()) {
108 List<Map<String, Object>> parsed = new ArrayList<>();
110 for (String result : results) {
111 parsed.add(mapper.readValue(result, new TypeReference<Map<String, Object>>(){}));
113 } catch (IOException e) {
114 logger.error("could not map json", e);
116 for (Map<String, Object> map : parsed) {
117 for (Entry<String, Object> entry : map.entrySet()) {
118 if (!entry.getKey().matches("2\\d\\d")) {
121 error = mapper.readValue(entry.getValue().toString(), AAIError.class);
122 } catch (IOException e) {
123 logger.error("could not parse error object from A&AI", e);
124 error = new AAIError();
126 AAIErrorFormatter formatter = new AAIErrorFormatter(error);
127 String outputMessage = formatter.getMessage();
128 logger.error("part of a bulk action failed in A&AI: " + entry.getValue());
129 errorMessages.add(outputMessage);
135 if (!errorMessages.isEmpty()) {
136 return Optional.of(Joiner.on("\n").join(errorMessages));
138 return Optional.empty();
141 private Relationship buildRelationship(AAIResourceUri uri) {
142 return buildRelationship(uri, Optional.empty());
145 private Relationship buildRelationship(AAIResourceUri uri, AAIEdgeLabel label) {
146 return buildRelationship(uri, Optional.of(label));
148 private Relationship buildRelationship(AAIResourceUri uri, Optional<AAIEdgeLabel> label) {
149 final Relationship result = new Relationship();
150 result.setRelatedLink(uri.build().toString());
151 if (label.isPresent()) {
152 result.setRelationshipLabel(label.toString());
157 protected Transactions getTransactions() {
158 return this.transactions;
162 public void put(String uri, Object body) {
163 currentTransaction.getPut().add(new OperationBody().withUri(uri).withBody(body));
167 public void delete(String uri, Object body) {
168 currentTransaction.getDelete().add(new OperationBody().withUri(uri).withBody(body));
173 public void patch(String uri, Object body) {
174 currentTransaction.getPatch().add(new OperationBody().withUri(uri).withBody(body));
178 protected <T> Optional<T> get(GenericType<T> genericType, AAIResourceUri clone) {
179 return resourcesClient.get(genericType, clone);
183 protected boolean exists(AAIResourceUri uri) {
184 return resourcesClient.exists(uri);
188 protected String getGraphDBName() {
189 return aaiClient.getGraphDBName();
193 protected GraphInventoryPatchConverter getPatchConverter() {
194 return this.patchConverter;