Replaced all tabs with spaces in java and pom.xml
[so.git] / common / src / main / java / org / onap / so / client / aai / AAITransactionalClient.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.io.IOException;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Map;
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;
47
48 public class AAITransactionalClient
49         extends GraphInventoryTransactionClient<AAITransactionalClient, AAIResourceUri, AAIEdgeLabel> {
50
51     private final Transactions transactions;
52     private Transaction currentTransaction;
53
54     private AAIResourcesClient resourcesClient;
55     private AAIClient aaiClient;
56
57     protected AAITransactionalClient(AAIResourcesClient resourcesClient, AAIClient aaiClient) {
58         super();
59         this.resourcesClient = resourcesClient;
60         this.aaiClient = aaiClient;
61         this.transactions = new Transactions();
62         startTransaction();
63     }
64
65     private void startTransaction() {
66         Transaction transaction = new Transaction();
67         transactions.getTransactions().add(transaction);
68         currentTransaction = transaction;
69     }
70
71     /*
72      * (non-Javadoc)
73      * 
74      * @see org.onap.so.client.aai.GraphInventoryTransactionalClient#beginNewTransaction()
75      */
76     public AAITransactionalClient beginNewTransaction() {
77         startTransaction();
78         return this;
79     }
80
81     /*
82      * (non-Javadoc)
83      * 
84      * @see org.onap.so.client.aai.GraphInventoryTransactionalClient#execute()
85      */
86     @Override
87     public void execute() throws BulkProcessFailed {
88         try {
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());
98                     }
99                 } else {
100                     throw new BulkProcessFailed(
101                             "Transactions acccepted by A&AI, but there was no response. Unsure of result.");
102                 }
103             }
104         } finally {
105             this.transactions.getTransactions().clear();
106             this.currentTransaction = null;
107             this.actionCount = 0;
108         }
109     }
110
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<>();
117             try {
118                 for (String result : results) {
119                     parsed.add(mapper.readValue(result, new TypeReference<Map<String, Object>>() {}));
120                 }
121             } catch (IOException e) {
122                 logger.error("could not map json", e);
123             }
124             for (Map<String, Object> map : parsed) {
125                 for (Entry<String, Object> entry : map.entrySet()) {
126                     if (!entry.getKey().matches("2\\d\\d")) {
127                         AAIError error;
128                         try {
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();
133                         }
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);
138                     }
139                 }
140             }
141         }
142
143         if (!errorMessages.isEmpty()) {
144             return Optional.of(Joiner.on("\n").join(errorMessages));
145         } else {
146             return Optional.empty();
147         }
148     }
149
150     private Relationship buildRelationship(AAIResourceUri uri) {
151         return buildRelationship(uri, Optional.empty());
152     }
153
154     private Relationship buildRelationship(AAIResourceUri uri, AAIEdgeLabel label) {
155         return buildRelationship(uri, Optional.of(label));
156     }
157
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());
163         }
164         return result;
165     }
166
167     protected Transactions getTransactions() {
168         return this.transactions;
169     }
170
171     @Override
172     public void put(String uri, Object body) {
173         currentTransaction.getPut().add(new OperationBody().withUri(uri).withBody(body));
174     }
175
176     @Override
177     public void delete(String uri, Object body) {
178         currentTransaction.getDelete().add(new OperationBody().withUri(uri).withBody(body));
179
180     }
181
182     @Override
183     public void patch(String uri, Object body) {
184         currentTransaction.getPatch().add(new OperationBody().withUri(uri).withBody(body));
185     }
186
187     @Override
188     protected <T> Optional<T> get(GenericType<T> genericType, AAIResourceUri clone) {
189         return resourcesClient.get(genericType, clone);
190     }
191
192     @Override
193     protected boolean exists(AAIResourceUri uri) {
194         return resourcesClient.exists(uri);
195     }
196
197     @Override
198     protected String getGraphDBName() {
199         return aaiClient.getGraphDBName();
200     }
201
202     @Override
203     protected GraphInventoryPatchConverter getPatchConverter() {
204         return this.patchConverter;
205     }
206 }