Convert Sparky to Spring-Boot
[aai/sparky-be.git] / sparkybe-onap-service / src / main / java / org / onap / aai / sparky / editattributes / AttributeUpdater.java
1 /**
2  * ============LICENSE_START===================================================
3  * SPARKY (AAI UI service)
4  * ============================================================================
5  * Copyright © 2017 AT&T Intellectual Property.
6  * Copyright © 2017 Amdocs
7  * All rights reserved.
8  * ============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=====================================================
21  *
22  * ECOMP and OpenECOMP are trademarks
23  * and service marks of AT&T Intellectual Property.
24  */
25 package org.onap.aai.sparky.editattributes;
26
27 import java.net.URI;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33
34 import javax.ws.rs.core.UriBuilder;
35
36 import org.eclipse.persistence.dynamic.DynamicType;
37 import org.onap.aai.cl.api.Logger;
38 import org.onap.aai.cl.eelf.LoggerFactory;
39 import org.onap.aai.restclient.client.OperationResult;
40 import org.onap.aai.sparky.config.oxm.OxmEntityLookup;
41 import org.onap.aai.sparky.config.oxm.OxmModelLoader;
42 import org.onap.aai.sparky.dal.ActiveInventoryAdapter;
43 import org.onap.aai.sparky.editattributes.exception.AttributeUpdateException;
44 import org.onap.aai.sparky.logging.AaiUiMsgs;
45
46 import com.fasterxml.jackson.core.JsonProcessingException;
47 import com.fasterxml.jackson.databind.ObjectMapper;
48 import com.fasterxml.jackson.databind.ObjectWriter;
49 import com.fasterxml.jackson.databind.PropertyNamingStrategy;
50
51 /**
52  * Class to process attribute updates on AAI objects.
53  *
54  *
55  */
56 public class AttributeUpdater {
57   
58   /**
59    * The Class AaiEditObject.
60    */
61   public class AaiEditObject {
62     String objectType;
63     String rootElement;
64     String keyName;
65     String keyValue;
66     String schemaVersion;
67
68     /**
69      * Instantiates a new aai edit object.
70      */
71     public AaiEditObject() {
72
73     }
74
75     /**
76      * Instantiates a new aai edit object.
77      *
78      * @param objectType the object type
79      * @param idName the id name
80      * @param schemaVersion the schema version
81      */
82     public AaiEditObject(String objectType, String idName, String schemaVersion) {
83       super();
84       this.objectType = objectType;
85       this.keyName = idName;
86       this.schemaVersion = schemaVersion;
87     }
88
89     public String getObjectType() {
90       return objectType;
91     }
92
93     public void setObjectType(String objectType) {
94       this.objectType = objectType;
95     }
96
97     public String getKeyName() {
98       return keyName;
99     }
100
101     public void setKeyName(String idName) {
102       this.keyName = idName;
103     }
104
105     public String getSchemaVersion() {
106       return schemaVersion;
107     }
108
109     public void setSchemaVersion(String schemaVersion) {
110       this.schemaVersion = schemaVersion;
111     }
112
113     public void setKeyValue(String keyValue) {
114       this.keyValue = keyValue;
115     }
116
117     public String getKeyValue() {
118       return keyValue;
119     }
120
121     public String getRootElement() {
122       return rootElement;
123     }
124
125     public void setRootElement(String rootElement) {
126       this.rootElement = rootElement;
127     }
128
129   }
130
131   private static final Logger LOG = LoggerFactory.getInstance().getLogger(AttributeUpdater.class);
132   private static final String MESSAGE_VERSION_EXTRACTION_REGEX = "\\/(v[0-9]+)";
133   private static final String ATTRIBUTES_UPDATED_SUCCESSFULLY = "Attributes updated successfully";
134   private static final String ATTRIBUTES_NOT_UPDATED = "Attributes not updated. ";
135
136   private ActiveInventoryAdapter aaiAdapter;
137   private UserValidator validator;
138   private OxmModelLoader oxmModelLoader;
139   private OxmEntityLookup oxmEntityLookup;
140   
141   /**
142    * Instantiates a new attribute updater.
143    * @throws AttributeUpdateException 
144    */
145   public AttributeUpdater(OxmModelLoader oxmModelLoader, OxmEntityLookup oxmEntityLookup, ActiveInventoryAdapter activeInventoryAdapter) throws AttributeUpdateException {
146     super();
147     this.oxmModelLoader = oxmModelLoader;
148     this.oxmEntityLookup = oxmEntityLookup;
149     this.aaiAdapter = activeInventoryAdapter;
150     
151     try {
152       this.validator = new UserValidator();
153     } catch (Exception exc) {
154       LOG.error(AaiUiMsgs.ATTRIBUTES_ERROR_GETTING_AAI_CONFIG_OR_ADAPTER, exc.getLocalizedMessage());
155       throw new AttributeUpdateException(exc);
156     }
157   }
158   
159   protected String getResourceBasePath() {
160
161     String versionStr = null;
162     if (oxmModelLoader != null) {
163       versionStr = String.valueOf(oxmModelLoader.getLatestVersionNum());
164     }
165
166     return "/aai/v" + versionStr;
167
168   }
169   
170   protected URI getBaseUri() {
171     return UriBuilder
172         .fromUri("https://" + aaiAdapter.getEndpointConfig().getEndpointIpAddress() + ":"
173             + aaiAdapter.getEndpointConfig().getEndpointServerPort() + getResourceBasePath())
174         .build();
175   }
176
177   /**
178    * Update object attribute.
179    *
180    * @param objectUri - Valid URI of the object as per OXM model.
181    * @param attributeValues - Map of (attribute-name & attribute-value) for
182    *        any attributes to be updated to the value.
183    * @param attUid - ATTUID of the user requesting the update.
184    * @return - OperationResult with success or failure reason.
185    */
186   public OperationResult updateObjectAttribute(String objectUri, Map<String, Object> attributeValues, String attUid) {
187     OperationResult result = new OperationResult();
188     LOG.info(AaiUiMsgs.ATTRIBUTES_UPDATE_METHOD_CALLED, objectUri, attUid, String.valueOf(attributeValues));
189     if (!validator.isAuthorizedUser(attUid)) {
190       result.setResultCode(403);
191       result.setResult(String.format("User %s is not authorized for Attributes update ", attUid));
192       LOG.error(AaiUiMsgs.ATTRIBUTES_USER_NOT_AUTHORIZED_TO_UPDATE, attUid);
193       return result;
194     }
195
196     AaiEditObject object = null;
197
198     try {
199       object = getEditObjectFromUri(objectUri);
200     } catch (AttributeUpdateException exc) {
201       result.setResultCode(400);
202       result.setResult(ATTRIBUTES_NOT_UPDATED);
203       LOG.error(AaiUiMsgs.ATTRIBUTES_NOT_UPDATED_EXCEPTION, exc.getLocalizedMessage());
204       return result;
205     }
206     try {
207       String jsonPayload = convertEditRequestToJson(object, attributeValues);
208       String patchUri = getBaseUri().toString() + getRelativeUri(objectUri);
209
210       
211       /*
212        * FIX ME:   Dave Adams, 8-Nov-2017
213        */
214       
215       //result = aaiAdapter.doPatch(patchUri, jsonPayload, MediaType.APPLICATION_JSON);
216
217       result = new OperationResult();
218       result.setResultCode(404);
219       
220       if (result.getResultCode() == 200) {
221         result.setResult(ATTRIBUTES_UPDATED_SUCCESSFULLY);
222         String message = result.getResult() + " for " + objectUri;
223         LOG.info(AaiUiMsgs.INFO_GENERIC, message);
224       } else {
225         String message = ATTRIBUTES_NOT_UPDATED + " For: " + objectUri + ". AAI PATCH Status Code : "
226             + result.getResultCode() + ". Error : " + result.getResult();
227         LOG.error(AaiUiMsgs.ATTRIBUTES_NOT_UPDATED_MESSAGE, message);
228       }
229     } catch (AttributeUpdateException exc) {
230       result.setResultCode(500);
231       result.setResult(ATTRIBUTES_NOT_UPDATED + exc.getLocalizedMessage());
232       LOG.error(AaiUiMsgs.ATTRIBUTES_NOT_UPDATED_EXCEPTION, exc.getLocalizedMessage());
233     }
234     return result;
235
236   }
237
238   /**
239    * Gets the relative uri.
240    *
241    * @param objectUri the object uri
242    * @return the relative uri
243    */
244   public String getRelativeUri(String objectUri) {
245     String tempUri = objectUri;
246     final Pattern pattern = Pattern.compile(MESSAGE_VERSION_EXTRACTION_REGEX, Pattern.DOTALL);
247     Matcher matcher = pattern.matcher(objectUri);
248     while (matcher.find()) {
249       tempUri = objectUri.substring(matcher.end());
250     }
251     if (!tempUri.startsWith("/")) {
252       tempUri = "/" + tempUri;
253     }
254     return tempUri;
255   }
256
257   /**
258    * Gets the edits the object from uri.
259    *
260    * @param objectUri the object uri
261    * @return the edits the object from uri
262    * @throws AttributeUpdateException the attribute update exception
263    */
264   public AaiEditObject getEditObjectFromUri(String objectUri) throws AttributeUpdateException {
265
266     AaiEditObject object = new AaiEditObject();
267     String version = getVersionFromUri(objectUri);
268
269     if ( null == version ) {
270       version = "v" + String.valueOf(oxmModelLoader.getLatestVersionNum());
271     }
272     object.setSchemaVersion(version);
273
274     String[] values = objectUri.split("/");
275     if (values.length < 2) {
276       throw new AttributeUpdateException("Invalid or malformed object URI : " + objectUri);
277     }
278     String keyValue = values[values.length - 1];
279     String rootElement = values[values.length - 2];
280
281     object.setKeyValue(keyValue);
282     object.setRootElement(rootElement);
283
284     String objectJavaType = null;
285     Map<String, DynamicType> entityTypeLookup = oxmEntityLookup.getEntityTypeLookup();
286     DynamicType entity = entityTypeLookup.get(rootElement);
287     if ( null != entity ) {
288       objectJavaType = entity.getName();
289       String message = "Descriptor: Alias: " + objectJavaType + " : DefaultRootElement: "
290           + rootElement;
291       LOG.debug(AaiUiMsgs.DEBUG_GENERIC, message);
292     }
293     
294     
295     if (objectJavaType == null) {
296       throw new AttributeUpdateException(
297           "Object type could not be determined from the URI : " + objectUri);
298     }
299     object.setObjectType(objectJavaType);
300
301     // Set key attribute name
302     final List<String> primaryKeys = entity.getDescriptor().getPrimaryKeyFieldNames();
303
304     if (primaryKeys.isEmpty()) {
305       throw new AttributeUpdateException("Object primary key not found in OXM version " + version);
306     }
307
308     for (int i = 0; i < primaryKeys.size(); i++) {
309       final String primaryKey = primaryKeys.get(i);
310       if (primaryKey.indexOf("/text()") != -1) {
311         primaryKeys.set(i, primaryKey.replace("/text()", ""));
312       }
313     }
314     object.setKeyName(primaryKeys.iterator().next());
315
316     return object;
317   }
318
319   /**
320    * Gets the version from uri.
321    *
322    * @param objectUri the object uri
323    * @return the version from uri
324    * @throws AttributeUpdateException the attribute update exception
325    */
326   private String getVersionFromUri(String objectUri) throws AttributeUpdateException {
327     final Pattern pattern = Pattern.compile(MESSAGE_VERSION_EXTRACTION_REGEX, Pattern.DOTALL);
328     Matcher matcher = pattern.matcher(objectUri);
329     String messageSchemaVersion = null;
330     while (matcher.find()) {
331       messageSchemaVersion = matcher.group(1);
332       break;
333     }
334     return messageSchemaVersion;
335   }
336
337   /**
338    * Convert edit request to json.
339    *
340    * @param object the object
341    * @param attributeValues the attribute values
342    * @return the string
343    * @throws AttributeUpdateException the attribute update exception
344    */
345   private static String convertEditRequestToJson(AaiEditObject object,
346       Map<String, Object> attributeValues) throws AttributeUpdateException {
347
348     ObjectMapper mapper = new ObjectMapper();
349     mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.KebabCaseStrategy());
350     ObjectWriter ow = mapper.writer();
351
352     Map<String, Object> patchAttributes = new HashMap<>();
353     patchAttributes.put(object.getKeyName(), object.getKeyValue());
354     patchAttributes.putAll(attributeValues);
355
356     try {
357       return ow.writeValueAsString(patchAttributes);
358     } catch (JsonProcessingException exc) {
359       throw new AttributeUpdateException("Caught a JPE while creating PATCH request body = ", exc);
360     }
361   }
362 }