2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017-2018 Amdocs
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
21 package org.onap.aai.sparky.editattributes;
24 import java.util.HashMap;
25 import java.util.List;
27 import java.util.regex.Matcher;
28 import java.util.regex.Pattern;
30 import javax.ws.rs.core.UriBuilder;
32 import org.eclipse.persistence.dynamic.DynamicType;
33 import org.onap.aai.cl.api.Logger;
34 import org.onap.aai.cl.eelf.LoggerFactory;
35 import org.onap.aai.restclient.client.OperationResult;
36 import org.onap.aai.sparky.config.oxm.OxmEntityLookup;
37 import org.onap.aai.sparky.config.oxm.OxmModelLoader;
38 import org.onap.aai.sparky.dal.ActiveInventoryAdapter;
39 import org.onap.aai.sparky.editattributes.exception.AttributeUpdateException;
40 import org.onap.aai.sparky.logging.AaiUiMsgs;
42 import com.fasterxml.jackson.core.JsonProcessingException;
43 import com.fasterxml.jackson.databind.ObjectMapper;
44 import com.fasterxml.jackson.databind.ObjectWriter;
45 import com.fasterxml.jackson.databind.PropertyNamingStrategy;
48 * Class to process attribute updates on AAI objects.
52 public class AttributeUpdater {
55 * The Class AaiEditObject.
57 public class AaiEditObject {
65 * Instantiates a new aai edit object.
67 public AaiEditObject() {
72 * Instantiates a new aai edit object.
74 * @param objectType the object type
75 * @param idName the id name
76 * @param schemaVersion the schema version
78 public AaiEditObject(String objectType, String idName, String schemaVersion) {
80 this.objectType = objectType;
81 this.keyName = idName;
82 this.schemaVersion = schemaVersion;
85 public String getObjectType() {
89 public void setObjectType(String objectType) {
90 this.objectType = objectType;
93 public String getKeyName() {
97 public void setKeyName(String idName) {
98 this.keyName = idName;
101 public String getSchemaVersion() {
102 return schemaVersion;
105 public void setSchemaVersion(String schemaVersion) {
106 this.schemaVersion = schemaVersion;
109 public void setKeyValue(String keyValue) {
110 this.keyValue = keyValue;
113 public String getKeyValue() {
117 public String getRootElement() {
121 public void setRootElement(String rootElement) {
122 this.rootElement = rootElement;
127 private static final Logger LOG = LoggerFactory.getInstance().getLogger(AttributeUpdater.class);
128 private static final String MESSAGE_VERSION_EXTRACTION_REGEX = "\\/(v[0-9]+)";
129 private static final String ATTRIBUTES_UPDATED_SUCCESSFULLY = "Attributes updated successfully";
130 private static final String ATTRIBUTES_NOT_UPDATED = "Attributes not updated. ";
132 private ActiveInventoryAdapter aaiAdapter;
133 private UserValidator validator;
134 private OxmModelLoader oxmModelLoader;
135 private OxmEntityLookup oxmEntityLookup;
138 * Instantiates a new attribute updater.
139 * @throws AttributeUpdateException
141 public AttributeUpdater(OxmModelLoader oxmModelLoader, OxmEntityLookup oxmEntityLookup, ActiveInventoryAdapter activeInventoryAdapter) throws AttributeUpdateException {
143 this.oxmModelLoader = oxmModelLoader;
144 this.oxmEntityLookup = oxmEntityLookup;
145 this.aaiAdapter = activeInventoryAdapter;
148 this.validator = new UserValidator();
149 } catch (Exception exc) {
150 LOG.error(AaiUiMsgs.ATTRIBUTES_ERROR_GETTING_AAI_CONFIG_OR_ADAPTER, exc.getLocalizedMessage());
151 throw new AttributeUpdateException(exc);
155 protected String getResourceBasePath() {
157 String versionStr = null;
158 if (oxmModelLoader != null) {
159 versionStr = String.valueOf(oxmModelLoader.getLatestVersionNum());
162 return "/aai/v" + versionStr;
166 protected URI getBaseUri() {
168 .fromUri("https://" + aaiAdapter.getEndpointConfig().getEndpointIpAddress() + ":"
169 + aaiAdapter.getEndpointConfig().getEndpointServerPort() + getResourceBasePath())
174 * Update object attribute.
176 * @param objectUri - Valid URI of the object as per OXM model.
177 * @param attributeValues - Map of (attribute-name & attribute-value) for
178 * any attributes to be updated to the value.
179 * @param attUid - ATTUID of the user requesting the update.
180 * @return - OperationResult with success or failure reason.
182 public OperationResult updateObjectAttribute(String objectUri, Map<String, Object> attributeValues, String attUid) {
183 OperationResult result = new OperationResult();
184 LOG.info(AaiUiMsgs.ATTRIBUTES_UPDATE_METHOD_CALLED, objectUri, attUid, String.valueOf(attributeValues));
185 if (!validator.isAuthorizedUser(attUid)) {
186 result.setResultCode(403);
187 result.setResult(String.format("User %s is not authorized for Attributes update ", attUid));
188 LOG.error(AaiUiMsgs.ATTRIBUTES_USER_NOT_AUTHORIZED_TO_UPDATE, attUid);
192 AaiEditObject object = null;
195 object = getEditObjectFromUri(objectUri);
196 } catch (AttributeUpdateException exc) {
197 result.setResultCode(400);
198 result.setResult(ATTRIBUTES_NOT_UPDATED);
199 LOG.error(AaiUiMsgs.ATTRIBUTES_NOT_UPDATED_EXCEPTION, exc.getLocalizedMessage());
203 String jsonPayload = convertEditRequestToJson(object, attributeValues);
204 String patchUri = getBaseUri().toString() + getRelativeUri(objectUri);
208 * FIX ME: Dave Adams, 8-Nov-2017
211 //result = aaiAdapter.doPatch(patchUri, jsonPayload, MediaType.APPLICATION_JSON);
213 result = new OperationResult();
214 result.setResultCode(404);
216 if (result.getResultCode() == 200) {
217 result.setResult(ATTRIBUTES_UPDATED_SUCCESSFULLY);
218 String message = result.getResult() + " for " + objectUri;
219 LOG.info(AaiUiMsgs.INFO_GENERIC, message);
221 String message = ATTRIBUTES_NOT_UPDATED + " For: " + objectUri + ". AAI PATCH Status Code : "
222 + result.getResultCode() + ". Error : " + result.getResult();
223 LOG.error(AaiUiMsgs.ATTRIBUTES_NOT_UPDATED_MESSAGE, message);
225 } catch (AttributeUpdateException exc) {
226 result.setResultCode(500);
227 result.setResult(ATTRIBUTES_NOT_UPDATED + exc.getLocalizedMessage());
228 LOG.error(AaiUiMsgs.ATTRIBUTES_NOT_UPDATED_EXCEPTION, exc.getLocalizedMessage());
235 * Gets the relative uri.
237 * @param objectUri the object uri
238 * @return the relative uri
240 public String getRelativeUri(String objectUri) {
241 String tempUri = objectUri;
242 final Pattern pattern = Pattern.compile(MESSAGE_VERSION_EXTRACTION_REGEX, Pattern.DOTALL);
243 Matcher matcher = pattern.matcher(objectUri);
244 while (matcher.find()) {
245 tempUri = objectUri.substring(matcher.end());
247 if (!tempUri.startsWith("/")) {
248 tempUri = "/" + tempUri;
254 * Gets the edits the object from uri.
256 * @param objectUri the object uri
257 * @return the edits the object from uri
258 * @throws AttributeUpdateException the attribute update exception
260 public AaiEditObject getEditObjectFromUri(String objectUri) throws AttributeUpdateException {
262 AaiEditObject object = new AaiEditObject();
263 String version = getVersionFromUri(objectUri);
265 if ( null == version ) {
266 version = "v" + String.valueOf(oxmModelLoader.getLatestVersionNum());
268 object.setSchemaVersion(version);
270 String[] values = objectUri.split("/");
271 if (values.length < 2) {
272 throw new AttributeUpdateException("Invalid or malformed object URI : " + objectUri);
274 String keyValue = values[values.length - 1];
275 String rootElement = values[values.length - 2];
277 object.setKeyValue(keyValue);
278 object.setRootElement(rootElement);
280 String objectJavaType = null;
281 Map<String, DynamicType> entityTypeLookup = oxmEntityLookup.getEntityTypeLookup();
282 DynamicType entity = entityTypeLookup.get(rootElement);
283 if ( null != entity ) {
284 objectJavaType = entity.getName();
285 String message = "Descriptor: Alias: " + objectJavaType + " : DefaultRootElement: "
287 LOG.debug(AaiUiMsgs.DEBUG_GENERIC, message);
291 if (objectJavaType == null) {
292 throw new AttributeUpdateException(
293 "Object type could not be determined from the URI : " + objectUri);
295 object.setObjectType(objectJavaType);
297 // Set key attribute name
298 final List<String> primaryKeys = entity.getDescriptor().getPrimaryKeyFieldNames();
300 if (primaryKeys.isEmpty()) {
301 throw new AttributeUpdateException("Object primary key not found in OXM version " + version);
304 for (int i = 0; i < primaryKeys.size(); i++) {
305 final String primaryKey = primaryKeys.get(i);
306 if (primaryKey.indexOf("/text()") != -1) {
307 primaryKeys.set(i, primaryKey.replace("/text()", ""));
310 object.setKeyName(primaryKeys.iterator().next());
316 * Gets the version from uri.
318 * @param objectUri the object uri
319 * @return the version from uri
320 * @throws AttributeUpdateException the attribute update exception
322 private String getVersionFromUri(String objectUri) throws AttributeUpdateException {
323 final Pattern pattern = Pattern.compile(MESSAGE_VERSION_EXTRACTION_REGEX, Pattern.DOTALL);
324 Matcher matcher = pattern.matcher(objectUri);
325 String messageSchemaVersion = null;
326 while (matcher.find()) {
327 messageSchemaVersion = matcher.group(1);
330 return messageSchemaVersion;
334 * Convert edit request to json.
336 * @param object the object
337 * @param attributeValues the attribute values
339 * @throws AttributeUpdateException the attribute update exception
341 private static String convertEditRequestToJson(AaiEditObject object,
342 Map<String, Object> attributeValues) throws AttributeUpdateException {
344 ObjectMapper mapper = new ObjectMapper();
345 mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.KebabCaseStrategy());
346 ObjectWriter ow = mapper.writer();
348 Map<String, Object> patchAttributes = new HashMap<>();
349 patchAttributes.put(object.getKeyName(), object.getKeyValue());
350 patchAttributes.putAll(attributeValues);
353 return ow.writeValueAsString(patchAttributes);
354 } catch (JsonProcessingException exc) {
355 throw new AttributeUpdateException("Caught a JPE while creating PATCH request body = ", exc);