36493e2b144d99cd678f791c3081e461aef41c79
[sdc.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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.openecomp.sdc.action.impl;
22
23 import static org.openecomp.sdc.action.ActionConstants.ACTION_VERSIONABLE_TYPE;
24 import static org.openecomp.sdc.action.ActionConstants.ARTIFACT_METADATA_ATTR_NAME;
25 import static org.openecomp.sdc.action.ActionConstants.ARTIFACT_METADATA_ATTR_UUID;
26 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_CATEGORY;
27 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_OPEN_ECOMP_COMPONENT;
28 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_MODEL;
29 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_NAME;
30 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_NONE;
31 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_VENDOR;
32 import static org.openecomp.sdc.action.ActionConstants.SERVICE_INSTANCE_ID;
33 import static org.openecomp.sdc.action.ActionConstants.STATUS;
34 import static org.openecomp.sdc.action.ActionConstants.TARGET_ENTITY_API;
35 import static org.openecomp.sdc.action.ActionConstants.TARGET_ENTITY_DB;
36 import static org.openecomp.sdc.action.ActionConstants.UNIQUE_ID;
37 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_ALREADY_EXISTS;
38 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_ALREADY_EXISTS_CODE;
39 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_DELETE_READ_ONLY;
40 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_DELETE_READ_ONLY_MSG;
41 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_UPDATE_NAME_INVALID;
42 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_UPDATE_READ_ONLY;
43 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_UPDATE_READ_ONLY_MSG;
44 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_CHECKIN_ON_ENTITY_LOCKED_BY_OTHER_USER;
45 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_CHECKIN_ON_UNLOCKED_ENTITY;
46 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_CHECKOUT_ON_LOCKED_ENTITY;
47 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_CHECKOUT_ON_LOCKED_ENTITY_OTHER_USER;
48 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_DELETE_ON_LOCKED_ENTITY_CODE;
49 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_EDIT_ON_ENTITY_LOCKED_BY_OTHER_USER;
50 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_NOT_EXIST;
51 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_NOT_EXIST_CODE;
52 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_UNIQUE_VALUE_ERROR;
53 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_UNIQUE_VALUE_MSG;
54 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_INTERNAL_SERVER_ERR_CODE;
55 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUESTED_VERSION_INVALID;
56 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_SUBMIT_FINALIZED_ENTITY_NOT_ALLOWED;
57 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_SUBMIT_LOCKED_ENTITY_NOT_ALLOWED;
58 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UNDO_CHECKOUT_ON_ENTITY_LOCKED_BY_OTHER_USER;
59 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UNDO_CHECKOUT_ON_UNLOCKED_ENTITY;
60 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_INVALID_VERSION;
61 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_NOT_ALLOWED_CODE;
62 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_NOT_ALLOWED_CODE_NAME;
63 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_NOT_ALLOWED_FOR_NAME;
64 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_ON_UNLOCKED_ENTITY;
65 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_PARAM_INVALID;
66 import static org.openecomp.sdc.action.util.ActionUtil.actionLogPostProcessor;
67 import static org.openecomp.sdc.action.util.ActionUtil.actionLogPreProcessor;
68 import static org.openecomp.sdc.action.util.ActionUtil.getCurrentTimeStampUtc;
69 import static org.openecomp.sdc.versioning.dao.types.Version.VERSION_STRING_VIOLATION_MSG;
70
71 import org.apache.commons.collections4.CollectionUtils;
72 import org.apache.commons.lang.StringUtils;
73 import org.openecomp.sdc.action.types.*;
74 import org.openecomp.sdc.logging.api.Logger;
75 import org.openecomp.sdc.logging.api.LoggerFactory;
76 import org.openecomp.core.util.UniqueValueUtil;
77 import org.openecomp.core.utilities.CommonMethods;
78 import org.openecomp.core.utilities.json.JsonUtil;
79 import org.openecomp.sdc.action.ActionConstants;
80 import org.openecomp.sdc.action.ActionManager;
81 import org.openecomp.sdc.action.dao.ActionArtifactDao;
82 import org.openecomp.sdc.action.dao.ActionArtifactDaoFactory;
83 import org.openecomp.sdc.action.dao.ActionDao;
84 import org.openecomp.sdc.action.dao.ActionDaoFactory;
85 import org.openecomp.sdc.action.dao.types.ActionArtifactEntity;
86 import org.openecomp.sdc.action.dao.types.ActionEntity;
87 import org.openecomp.sdc.action.errors.ActionErrorConstants;
88 import org.openecomp.sdc.action.errors.ActionException;
89 import org.openecomp.sdc.action.logging.StatusCode;
90 import org.openecomp.sdc.action.types.OpenEcompComponent;
91 import org.openecomp.sdc.common.errors.CoreException;
92 import org.openecomp.sdc.versioning.VersioningManager;
93 import org.openecomp.sdc.versioning.VersioningManagerFactory;
94 import org.openecomp.sdc.versioning.dao.VersionInfoDao;
95 import org.openecomp.sdc.versioning.dao.VersionInfoDaoFactory;
96 import org.openecomp.sdc.versioning.dao.types.UserCandidateVersion;
97 import org.openecomp.sdc.versioning.dao.types.Version;
98 import org.openecomp.sdc.versioning.dao.types.VersionInfoEntity;
99 import org.openecomp.sdc.versioning.errors.EntityNotExistErrorBuilder;
100 import org.openecomp.sdc.versioning.errors.VersioningErrorCodes;
101 import org.openecomp.sdc.versioning.types.VersionInfo;
102 import org.openecomp.sdc.versioning.types.VersionableEntityAction;
103 import org.slf4j.MDC;
104
105 import java.util.ArrayList;
106 import java.util.Collections;
107 import java.util.Iterator;
108 import java.util.LinkedHashMap;
109 import java.util.LinkedList;
110 import java.util.List;
111 import java.util.Map;
112 import java.util.UUID;
113
114 /**
115  * Manager Implementation for {@link ActionManager Action Library Operations} <br> Handles Business
116  * layer validations and acts as an interface between the REST and DAO layers.
117  */
118 public class ActionManagerImpl implements ActionManager {
119
120   private static final ActionDao actionDao = ActionDaoFactory.getInstance().createInterface();
121   private static final VersioningManager versioningManager =
122       VersioningManagerFactory.getInstance().createInterface();
123   private static final ActionArtifactDao actionArtifactDao =
124       ActionArtifactDaoFactory.getInstance().createInterface();
125   private static VersionInfoDao versionInfoDao =
126       VersionInfoDaoFactory.getInstance().createInterface();
127
128   private final Logger log = (Logger) LoggerFactory.getLogger(this.getClass().getName());
129
130   public ActionManagerImpl() {
131     actionDao.registerVersioning(ACTION_VERSIONABLE_TYPE);
132   }
133
134   /**
135    * List All Major, Last Minor and Candidate version (if any) for Given Action Invariant UUID
136    *
137    * @param invariantId Invariant UUID of the action for which the information is required
138    * @return List of All Major, Last Minor and Candidate version if any Of {@link Action} with given
139      actionInvariantUuId.
140    * @throws ActionException Exception with an action library specific code, short description and
141    *                         detailed message for the error occurred during the operation
142    */
143
144   @Override
145   public List<Action> getActionsByActionInvariantUuId(String invariantId) throws ActionException {
146     List<Action> actions;
147
148     log.debug(" entering getActionsByActionInvariantUuId with  invariantID = " + invariantId);
149     actions = actionDao
150         .getActionsByActionInvariantUuId(invariantId != null ? invariantId.toUpperCase() : null);
151
152     if (actions != null && actions.isEmpty()) {
153       throw new ActionException(ACTION_ENTITY_NOT_EXIST_CODE, ACTION_ENTITY_NOT_EXIST);
154     }
155
156     log.debug(" exit getActionsByActionInvariantUuId with  invariantID = " + invariantId);
157     return actions;
158   }
159
160   /**
161    * Get list of actions based on a filter criteria. If no filter is sent all actions will be
162    * returned
163    *
164    * @param filterType  Filter by Vendor/Category/Model/Component/None
165    * @param filterValue Filter Parameter Value (Vendor ID/Category ID/Model ID/Component ID)
166    * @return List of {@link Action} objects based on a filter criteria <br> Empty List if no records
167      match the provided filter criteria
168    * @throws ActionException Exception with an action library specific code, short description and
169    *                         detailed message for the error occurred for the error occurred during
170    *                         the operation
171    */
172   @Override
173   public List<Action> getFilteredActions(String filterType, String filterValue)
174       throws ActionException {
175     List<Action> actions;
176     log.debug(" entering getFilteredActions By filterType = " + filterType + " With value = "
177         + filterValue);
178     switch (filterType) {
179       case FILTER_TYPE_NONE:
180         //Business validation for OPENECOMP Component type fetch (if any)
181         break;
182       case FILTER_TYPE_VENDOR:
183         //Business validation for vendor type fetch (if any)
184         break;
185       case FILTER_TYPE_CATEGORY:
186         //Business validation for Category type fetch (if any)
187         break;
188       case FILTER_TYPE_MODEL:
189         //Business validation for model type fetch (if any)
190         break;
191       case FILTER_TYPE_OPEN_ECOMP_COMPONENT:
192         //Business validation for OPENECOMP Component type fetch (if any)
193         break;
194       case FILTER_TYPE_NAME:
195         actions = actionDao
196             .getFilteredActions(filterType, filterValue != null ? filterValue.toLowerCase() : null);
197         if (actions != null && actions.isEmpty()) {
198           throw new ActionException(ACTION_ENTITY_NOT_EXIST_CODE, ACTION_ENTITY_NOT_EXIST);
199         }
200         log.debug(" exit getFilteredActions By filterType = " + filterType + " With value = "
201             + filterValue);
202         return actions;
203       default:
204         break;
205     }
206     actions = actionDao
207         .getFilteredActions(filterType, filterValue != null ? filterValue.toLowerCase() : null);
208     List<Action> majorMinorVersionList = getMajorMinorVersionActions(actions);
209     Collections.sort(majorMinorVersionList);
210     log.debug(
211         " exit getFilteredActions By filterType = " + filterType + " With value = " + filterValue);
212     return majorMinorVersionList;
213   }
214
215   /**
216    * Get the properties of an action version by its UUID.
217    *
218    * @param actionUuId UUID of the specific action version
219    * @return {@link Action} object corresponding the version represented by the UUID
220    * @throws ActionException Exception with an action library specific code, short description and
221    *                         detailed message for the error occurred for the error occurred during
222    *                         the operation
223    */
224   @Override
225   public Action getActionsByActionUuId(String actionUuId) throws ActionException {
226     log.debug(" entering getActionsByActionUuId with  actionUUID = " + actionUuId);
227     Action action =
228         actionDao.getActionsByActionUuId(actionUuId != null ? actionUuId.toUpperCase() : null);
229
230     if (action == null) {
231       throw new ActionException(ACTION_ENTITY_NOT_EXIST_CODE, ACTION_ENTITY_NOT_EXIST);
232     }
233
234     log.debug(" exit getActionsByActionUuId with  actionUUID = " + actionUuId);
235     return action;
236   }
237
238   /**
239    * List OPENECOMP Components supported by Action Library.
240    *
241    * @return List of {@link OpenEcompComponent} objects supported by Action Library <br> Empty List if
242      no components are found
243    * @throws ActionException Exception with an action library specific code, short description and
244    *                         detailed message for the error occurred for the error occurred during
245    *                         the operation
246    */
247   @Override
248   public List<OpenEcompComponent> getOpenEcompComponents() throws ActionException {
249     return actionDao.getOpenEcompComponents();
250   }
251
252
253   /**
254    * Delete an action.
255    *
256    * @param actionInvariantUuId Invariant UUID of the action to be deleted
257    * @param user                User id of the user performing the operation
258    */
259   @Override
260   public void deleteAction(String actionInvariantUuId, String user) throws ActionException {
261     try {
262       log.debug("entering deleteAction with actionInvariantUuId = " + actionInvariantUuId
263           + " and user = " + user);
264       actionLogPreProcessor(ActionSubOperation.DELETE_ACTION, TARGET_ENTITY_API);
265       versioningManager.delete(ACTION_VERSIONABLE_TYPE, actionInvariantUuId, user);
266       actionLogPostProcessor(StatusCode.COMPLETE);
267       log.metrics("");
268       actionDao.deleteAction(actionInvariantUuId);
269     } catch (CoreException ce) {
270       formAndThrowException(ce);
271     }
272   }
273
274   /**
275    * Create a new Action.
276    *
277    * @param action Action object model of the user request for creating an action
278    * @param user   AT&T id of the user sending the create request
279    * @return {@link Action} model object for the created action
280    * @throws ActionException Exception with an action library specific code, short description and
281    *                         detailed message for the error occurred for the error occurred during
282    *                         the operation
283    */
284   @Override
285   public Action createAction(Action action, String user) throws ActionException {
286     try {
287       actionLogPreProcessor(ActionSubOperation.VALIDATE_ACTION_UNIQUE_NAME, TARGET_ENTITY_API);
288       UniqueValueUtil
289           .validateUniqueValue(ActionConstants.UniqueValues.ACTION_NAME, action.getName());
290       actionLogPostProcessor(StatusCode.COMPLETE);
291     } catch (CoreException exception) {
292       String errorDesc = String
293           .format(ACTION_ENTITY_UNIQUE_VALUE_MSG, ActionConstants.UniqueValues.ACTION_NAME,
294               action.getName());
295       log.error(errorDesc, exception);
296       actionLogPostProcessor(StatusCode.ERROR, ACTION_ENTITY_UNIQUE_VALUE_ERROR, errorDesc, false);
297       throw new ActionException(ACTION_ENTITY_UNIQUE_VALUE_ERROR, errorDesc);
298     } finally {
299       log.metrics("");
300     }
301     action.setUser(user);
302     action.setTimestamp(getCurrentTimeStampUtc());
303     action.setActionInvariantUuId(CommonMethods.nextUuId());
304     action.setActionUuId(CommonMethods.nextUuId());
305
306     actionLogPreProcessor(ActionSubOperation.CREATE_ACTION_VERSION, TARGET_ENTITY_API);
307     Version version =
308         versioningManager.create(ACTION_VERSIONABLE_TYPE, action.getActionInvariantUuId(), user);
309     actionLogPostProcessor(StatusCode.COMPLETE);
310     log.metrics("");
311
312     action.setVersion(version.toString());
313     action.setStatus(ActionStatus.Locked);
314     action = updateData(action);
315     action = actionDao.createAction(action);
316
317     actionLogPreProcessor(ActionSubOperation.CREATE_ACTION_UNIQUE_VALUE, TARGET_ENTITY_API);
318     UniqueValueUtil.createUniqueValue(ActionConstants.UniqueValues.ACTION_NAME, action.getName());
319     actionLogPostProcessor(StatusCode.COMPLETE);
320     log.metrics("");
321
322     return action;
323   }
324
325   /**
326    * Update an existing action.
327    *
328    * @param action Action object model of the user request for creating an action
329    * @param user   AT&T id of the user sending the update request
330    * @return {@link Action} model object for the update action
331    * @throws ActionException Exception with an action library specific code, short description and
332    *                         detailed message for the error occurred for the error occurred during
333    *                         the operation
334    */
335   @Override
336   public Action updateAction(Action action, String user) throws ActionException {
337     try {
338       log.debug("entering updateAction to update action with invariantUuId = "
339           + action.getActionInvariantUuId() + " by user = " + user);
340       String invariantUuId = action.getActionInvariantUuId();
341       actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_API);
342       VersionInfo versionInfo = versioningManager
343           .getEntityVersionInfo(ACTION_VERSIONABLE_TYPE, invariantUuId, user,
344               VersionableEntityAction.Write);
345       actionLogPostProcessor(StatusCode.COMPLETE);
346       log.metrics("");
347
348       Version activeVersion = versionInfo.getActiveVersion();
349       validateActions(action, activeVersion);
350       action.setStatus(ActionStatus.Locked); //Status will be Checkout for update
351       updateData(action);
352       action.setUser(user);
353       action.setTimestamp(getCurrentTimeStampUtc());
354       actionDao.updateAction(action);
355
356     } catch (CoreException ce) {
357       formAndThrowException(ce);
358     }
359     log.debug("exit updateAction");
360     return action;
361   }
362
363   /**
364    * Checkout an existing action.
365    *
366    * @param invariantUuId actionInvariantUuId of the action to be checked out
367    * @param user          AT&T id of the user sending the checkout request
368    * @return {@link Action} model object for the checkout action
369    * @throws ActionException Exception with an action library specific code, short description and
370    *                         detailed message for the error occurred for the error occurred during
371    *                         the operation
372    */
373   @Override
374   public Action checkout(String invariantUuId, String user) throws ActionException {
375     Version version = null;
376     ActionEntity actionEntity = null;
377     try {
378       log.debug(
379           "entering checkout for Action with invariantUUID= " + invariantUuId + " by user = "
380               + user);
381       actionLogPreProcessor(ActionSubOperation.CHECKOUT_ACTION, TARGET_ENTITY_API);
382       version = versioningManager.checkout(ACTION_VERSIONABLE_TYPE, invariantUuId, user);
383       actionLogPostProcessor(StatusCode.COMPLETE);
384       log.metrics("");
385
386       actionEntity =
387           updateUniqueIdForVersion(invariantUuId, version, ActionStatus.Locked.name(), user);
388     } catch (CoreException exception) {
389       if (exception.code() != null && exception.code().id().equals(
390           VersioningErrorCodes.CHECKOT_ON_LOCKED_ENTITY)) {
391         actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_DB);
392         VersionInfoEntity versionInfoEntity =
393             versionInfoDao.get(new VersionInfoEntity(ACTION_VERSIONABLE_TYPE, invariantUuId));
394         actionLogPostProcessor(StatusCode.COMPLETE);
395         log.metrics("");
396         String checkoutUser = versionInfoEntity.getCandidate().getUser();
397         log.debug(
398             "Actual checkout user for Action with invariantUUID= " + invariantUuId + " is = "
399                 + checkoutUser);
400         if (!checkoutUser.equals(user)) {
401           throw new ActionException(ACTION_CHECKOUT_ON_LOCKED_ENTITY_OTHER_USER,
402               exception.getMessage());
403         }
404       }
405       formAndThrowException(exception);
406     }
407     log.debug(
408         "exit checkout for Action with invariantUUID= " + invariantUuId + " by user = " + user);
409     return actionEntity != null ? actionEntity.toDto() : new Action();
410   }
411
412   /**
413    * Undo an already checked out action.
414    *
415    * @param invariantUuId actionInvariantUuId of the checked out action
416    * @param user          AT&T id of the user sending the request
417    * @throws ActionException Exception with an action library specific code, short description and
418    *                         detailed message for the error occurred for the error occurred during
419    *                         the operation
420    */
421   @Override
422   public void undoCheckout(String invariantUuId, String user) throws ActionException {
423     Version version;
424     try {
425       log.debug(
426           "entering undoCheckout for Action with invariantUUID= " + invariantUuId + " by user = "
427               + user);
428
429       actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_DB);
430       //Get list of uploaded artifacts in this checked out version
431       VersionInfoEntity versionInfoEntity =
432           versionInfoDao.get(new VersionInfoEntity(ACTION_VERSIONABLE_TYPE, invariantUuId));
433       actionLogPostProcessor(StatusCode.COMPLETE);
434       log.metrics("");
435       if (versionInfoEntity == null) {
436         throw new CoreException(
437             new EntityNotExistErrorBuilder(ACTION_VERSIONABLE_TYPE, invariantUuId).build());
438       }
439       UserCandidateVersion candidate = versionInfoEntity.getCandidate();
440       Version activeVersion;
441       if (candidate != null) {
442         activeVersion = candidate.getVersion();
443       } else {
444         activeVersion = versionInfoEntity.getActiveVersion();
445       }
446
447       actionLogPreProcessor(ActionSubOperation.GET_ACTIONENTITY_BY_VERSION, TARGET_ENTITY_DB);
448       Action action = actionDao.get(new ActionEntity(invariantUuId, activeVersion)).toDto();
449       actionLogPostProcessor(StatusCode.COMPLETE);
450       log.metrics("");
451
452       //Perform undo checkout on the action
453       actionLogPreProcessor(ActionSubOperation.UNDO_CHECKOUT_ACTION, TARGET_ENTITY_API);
454       version = versioningManager.undoCheckout(ACTION_VERSIONABLE_TYPE, invariantUuId, user);
455       actionLogPostProcessor(StatusCode.COMPLETE);
456       log.metrics("");
457
458       if (version.equals(new Version(0, 0))) {
459         actionLogPreProcessor(ActionSubOperation.DELETE_UNIQUEVALUE, TARGET_ENTITY_API);
460         UniqueValueUtil
461             .deleteUniqueValue(ActionConstants.UniqueValues.ACTION_NAME, action.getName());
462         actionLogPostProcessor(StatusCode.COMPLETE);
463         log.metrics("");
464
465         actionLogPreProcessor(ActionSubOperation.DELETE_ACTIONVERSION, TARGET_ENTITY_DB);
466         //Added for the case where Create->Undo_Checkout->Checkout should not get the action
467         versionInfoDao.delete(new VersionInfoEntity(ACTION_VERSIONABLE_TYPE, invariantUuId));
468         actionLogPostProcessor(StatusCode.COMPLETE);
469         log.metrics("");
470       }
471
472       List<ActionArtifact> currentVersionArtifacts = action.getArtifacts();
473
474       //Delete the artifacts from action_artifact table (if any)
475       if (CollectionUtils.isNotEmpty(currentVersionArtifacts) && currentVersionArtifacts.size() > 0) {
476         for (ActionArtifact artifact : currentVersionArtifacts) {
477           ActionArtifactEntity artifactDeleteEntity =
478               new ActionArtifactEntity(artifact.getArtifactUuId(),
479                   getEffectiveVersion(activeVersion.toString()));
480           actionLogPreProcessor(ActionSubOperation.DELETE_ARTIFACT, TARGET_ENTITY_DB);
481           actionArtifactDao.delete(artifactDeleteEntity);
482           actionLogPostProcessor(StatusCode.COMPLETE);
483           log.metrics("");
484         }
485       }
486     } catch (CoreException exception) {
487       formAndThrowException(exception);
488     }
489     log.debug(
490         "exit undoCheckout for Action with invariantUUID= " + invariantUuId + " by user = " + user);
491   }
492
493   /**
494    * Checkin a checked out action.
495    *
496    * @param invariantUuId actionInvariantUuId of the checked out action
497    * @param user          AT&T id of the user sending the request
498    * @return {@link Action} model object for the updated action
499    * @throws ActionException Exception with an action library specific code, short description and
500    *                         detailed message for the error occurred for the error occurred during
501    *                         the operation
502    */
503   @Override
504   public Action checkin(String invariantUuId, String user) throws ActionException {
505     Version version = null;
506     ActionEntity actionEntity = null;
507     try {
508       log.debug("entering checkin for Action with invariantUUID= " + invariantUuId + " by user = "
509           + user);
510       actionLogPreProcessor(ActionSubOperation.CHECKIN_ACTION, TARGET_ENTITY_API);
511       version = versioningManager.checkin(ACTION_VERSIONABLE_TYPE, invariantUuId, user, null);
512       actionLogPostProcessor(StatusCode.COMPLETE);
513       log.metrics("");
514       actionEntity =
515           updateStatusForVersion(invariantUuId, version, ActionStatus.Available.name(), user);
516     } catch (CoreException exception) {
517       formAndThrowException(exception);
518     }
519     log.debug(
520         "exit checkin for Action with invariantUUID= " + invariantUuId + " by user = " + user);
521     return actionEntity != null ? actionEntity.toDto() : new Action();
522   }
523
524   /**
525    * Submit a checked in action.
526    *
527    * @param invariantUuId actionInvariantUuId of the checked in action
528    * @param user          AT&T id of the user sending the request
529    * @return {@link Action} model object for the updated action
530    * @throws ActionException Exception with an action library specific code, short description and
531    *                         detailed message for the error occurred for the error occurred during
532    *                         the operation
533    */
534   @Override
535   public Action submit(String invariantUuId, String user) throws ActionException {
536     Version version = null;
537     ActionEntity actionEntity = null;
538     try {
539       log.debug(
540           "entering submit for Action with invariantUUID= " + invariantUuId + " by user = " + user);
541       actionLogPreProcessor(ActionSubOperation.SUBMIT_ACTION, TARGET_ENTITY_API);
542       version = versioningManager.submit(ACTION_VERSIONABLE_TYPE, invariantUuId, user, null);
543       actionLogPostProcessor(StatusCode.COMPLETE);
544       log.metrics("");
545       actionEntity =
546           updateUniqueIdForVersion(invariantUuId, version, ActionStatus.Final.name(), user);
547     } catch (CoreException exception) {
548       formAndThrowException(exception);
549     }
550     log.debug("exit submit for Action with invariantUUID= " + invariantUuId + " by user = " + user);
551     return actionEntity != null ? actionEntity.toDto() : new Action();
552   }
553
554   /**
555    * Download an artifact of an action.
556    *
557    * @param artifactUuId {@link ActionArtifact} object representing the artifact and its metadata
558    * @param actionUuId   UUID of the action for which the artifact has to be downloaded
559    * @return downloaded action artifact object
560    */
561   @Override
562   public ActionArtifact downloadArtifact(String actionUuId, String artifactUuId)
563       throws ActionException {
564     log.debug(" entering downloadArtifact with actionUUID= " + actionUuId + " and artifactUUID= "
565         + artifactUuId);
566     Action action = actionDao.getActionsByActionUuId(actionUuId);
567     ActionArtifact actionArtifact;
568     if (action != null) {
569       MDC.put(SERVICE_INSTANCE_ID, action.getActionInvariantUuId());
570       List<ActionArtifact> artifacts = action.getArtifacts();
571       String actionVersion = action.getVersion();
572       int effectiveVersion = getEffectiveVersion(actionVersion);
573       ActionArtifact artifactMetadata =
574           getArtifactMetadataFromAction(artifacts, ARTIFACT_METADATA_ATTR_UUID, artifactUuId);
575       if (artifactMetadata != null) {
576         String artifactName = artifactMetadata.getArtifactName();
577         actionArtifact = actionArtifactDao.downloadArtifact(effectiveVersion, artifactUuId);
578         actionArtifact.setArtifactName(artifactName);
579
580       } else {
581         throw new ActionException(ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST_CODE,
582             ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST);
583       }
584     } else {
585       throw new ActionException(ActionErrorConstants.ACTION_ENTITY_NOT_EXIST_CODE,
586           ActionErrorConstants.ACTION_ENTITY_NOT_EXIST);
587     }
588     log.debug(" exit downloadArtifact with actionUUID= " + actionUuId + " and artifactUUID= "
589         + artifactUuId);
590     return actionArtifact;
591   }
592
593   /**
594    * Upload an artifact to an action.
595    *
596    * @param artifact            {@link ActionArtifact} object representing the artifact and its
597    *                            metadata
598    * @param actionInvariantUuId Invariant UUID of the action to which the artifact has to be
599    *                            uploaded
600    * @param user                User ID of the user sending the request
601    * @return Uploaded action artifact object
602    */
603   @Override
604   public ActionArtifact uploadArtifact(ActionArtifact artifact, String actionInvariantUuId,
605                                        String user) {
606     ActionArtifact uploadArtifactResponse = new ActionArtifact();
607     try {
608       log.debug("entering uploadArtifact with actionInvariantUuId= " + actionInvariantUuId
609           + "artifactName= " + artifact.getArtifactName());
610       actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_DB);
611       VersionInfo versionInfo = versioningManager
612           .getEntityVersionInfo(ACTION_VERSIONABLE_TYPE, actionInvariantUuId, user,
613               VersionableEntityAction.Write);
614       actionLogPostProcessor(StatusCode.COMPLETE);
615       log.metrics("");
616       Version activeVersion = versionInfo.getActiveVersion();
617       actionLogPreProcessor(ActionSubOperation.GET_ACTIONENTITY_BY_ACTIONINVID, TARGET_ENTITY_DB);
618       Action action = actionDao.get(new ActionEntity(actionInvariantUuId, activeVersion)).toDto();
619       actionLogPostProcessor(StatusCode.COMPLETE);
620       log.metrics("");
621       String artifactUuId = generateActionArtifactUuId(action, artifact.getArtifactName());
622       //Check for Unique document name
623       List<ActionArtifact> actionArtifacts = action.getArtifacts();
624       ActionArtifact artifactMetadata =
625           getArtifactMetadataFromAction(actionArtifacts, ARTIFACT_METADATA_ATTR_NAME,
626               artifact.getArtifactName());
627       if (artifactMetadata != null) {
628         throw new ActionException(ACTION_ARTIFACT_ALREADY_EXISTS_CODE,
629             String.format(ACTION_ARTIFACT_ALREADY_EXISTS, actionInvariantUuId));
630       }
631
632       //Create the artifact
633       artifact.setArtifactUuId(artifactUuId);
634       artifact.setTimestamp(getCurrentTimeStampUtc());
635       artifact.setEffectiveVersion(getEffectiveVersion(activeVersion.toString()));
636       actionArtifactDao.uploadArtifact(artifact);
637
638       //Update the action data field and timestamp
639       addArtifactMetadataInActionData(action, artifact);
640
641       //Set the response object
642       uploadArtifactResponse.setArtifactUuId(artifact.getArtifactUuId());
643     } catch (CoreException ce) {
644       formAndThrowException(ce);
645     }
646     log.debug(
647         "exit uploadArtifact with actionInvariantUuId= " + actionInvariantUuId + "artifactName= "
648             + artifact.getArtifactName());
649     return uploadArtifactResponse;
650   }
651
652   @Override
653   public void deleteArtifact(String actionInvariantUuId, String artifactUuId, String user)
654       throws ActionException {
655     log.debug(
656         "enter deleteArtifact with actionInvariantUuId= " + actionInvariantUuId + "artifactUUID= "
657             + artifactUuId + " and user = " + user);
658     Action action = actionDao.getLockedAction(actionInvariantUuId, user);
659     List<ActionArtifact> actionArtifacts = action.getArtifacts();
660     ActionArtifact artifactMetadata =
661         getArtifactMetadataFromAction(actionArtifacts, ARTIFACT_METADATA_ATTR_UUID, artifactUuId);
662     if (artifactMetadata == null) {
663       throw new ActionException(ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST_CODE,
664           ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST);
665     }
666     if (artifactMetadata.getArtifactProtection().equals(ActionArtifactProtection.readOnly.name())) {
667       throw new ActionException(ACTION_ARTIFACT_DELETE_READ_ONLY,
668           ACTION_ARTIFACT_DELETE_READ_ONLY_MSG);
669     } else {
670
671       //Update action by removing artifact metadata
672       String jsonData = action.getData();
673       List<ActionArtifact> artifacts = action.getArtifacts();//action.getArtifacts();
674       ActionArtifact artifact = null;
675       Iterator<ActionArtifact> it = artifacts.iterator();
676       while (it.hasNext()) {
677         artifact = it.next();
678         String artifactId = artifact.getArtifactUuId();
679         if (artifactId.equals(artifactUuId)) {
680           it.remove();
681         }
682       }
683
684       Map dataMap = JsonUtil.json2Object(jsonData, LinkedHashMap.class);
685       dataMap.put("artifacts", artifacts);
686       String data = JsonUtil.object2Json(dataMap);
687       ActionEntity actionEntity = action.toEntity();
688       actionEntity.setData(data);
689       actionLogPreProcessor(ActionSubOperation.UPDATE_ACTION, TARGET_ENTITY_DB);
690       actionDao.update(actionEntity);
691       actionLogPostProcessor(StatusCode.COMPLETE, null, "", false);
692       log.metrics("");
693       // delete Artifact if it's upload and delete action on same checkout version
694       String artifactName = artifactMetadata.getArtifactName();
695       String generatedArtifactUuId = generateActionArtifactUuId(action, artifactName);
696       if (generatedArtifactUuId.equals(artifactUuId)) {
697         ActionArtifactEntity artifactDeleteEntity =
698             new ActionArtifactEntity(artifact.getArtifactUuId(),
699                 getEffectiveVersion(action.getVersion()));
700         actionLogPreProcessor(ActionSubOperation.DELETE_ACTION_ARTIFACT, TARGET_ENTITY_DB);
701         actionArtifactDao.delete(artifactDeleteEntity);
702         actionLogPostProcessor(StatusCode.COMPLETE, null, "", false);
703         log.metrics("");
704       }
705
706     }
707     log.debug(
708         "exit deleteArtifact with actionInvariantUuId= " + actionInvariantUuId + "artifactUUID= "
709             + artifactUuId + " and user = " + user);
710   }
711
712   /**
713    * Update an existing artifact.
714    *
715    * @param artifact            {@link ActionArtifact} object representing the artifact and its
716    *                            metadata
717    * @param actionInvariantUuId Invariant UUID of the action to which the artifact has to be
718    *                            uploaded
719    * @param user                User ID of the user sending the request
720    */
721   public void updateArtifact(ActionArtifact artifact, String actionInvariantUuId, String user) {
722     try {
723       log.debug("Enter updateArtifact with actionInvariantUuId= " + actionInvariantUuId
724           + "artifactUUID= " + artifact.getArtifactUuId() + " and user = " + user);
725       actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_API);
726       VersionInfo versionInfo = versioningManager
727           .getEntityVersionInfo(ACTION_VERSIONABLE_TYPE, actionInvariantUuId, user,
728               VersionableEntityAction.Write);
729       actionLogPostProcessor(StatusCode.COMPLETE, null, "", false);
730       log.metrics("");
731       Version activeVersion = versionInfo.getActiveVersion();
732       actionLogPreProcessor(ActionSubOperation.GET_ACTIONENTITY_BY_ACTIONINVID, TARGET_ENTITY_DB);
733       Action action = actionDao.get(new ActionEntity(actionInvariantUuId, activeVersion)).toDto();
734       actionLogPostProcessor(StatusCode.COMPLETE, null, "", false);
735       log.metrics("");
736       List<ActionArtifact> actionArtifacts = action.getArtifacts();
737       ActionArtifact artifactMetadataByUuId =
738           getArtifactMetadataFromAction(actionArtifacts, ARTIFACT_METADATA_ATTR_UUID,
739               artifact.getArtifactUuId());
740       //Check if artifact is already in action or not
741       if (artifactMetadataByUuId == null) {
742         throw new ActionException(ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST_CODE,
743             ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST);
744       }
745       //If user tries to change artifact name
746       if (artifact.getArtifactName() != null
747           && !artifactMetadataByUuId.getArtifactName().equalsIgnoreCase(
748           artifact.getArtifactName())) {
749         throw new ActionException(ACTION_UPDATE_NOT_ALLOWED_CODE,
750             ACTION_ARTIFACT_UPDATE_NAME_INVALID);
751       }
752
753       byte[] payload = artifact.getArtifact();
754       String artifactLabel = artifact.getArtifactLabel();
755       String artifactCategory = artifact.getArtifactCategory();
756       String artifactDescription = artifact.getArtifactDescription();
757       String artifactProtection = artifact.getArtifactProtection();
758       String artifactName = artifact.getArtifactName();
759       //If artifact read only
760       if (artifactMetadataByUuId.getArtifactProtection()
761           .equals(ActionArtifactProtection.readOnly.name())) {
762         if (artifactName != null || artifactLabel != null || artifactCategory != null
763             || artifactDescription != null || payload != null) {
764           throw new ActionException(ACTION_ARTIFACT_UPDATE_READ_ONLY,
765               ACTION_ARTIFACT_UPDATE_READ_ONLY_MSG);
766         }
767         //Changing value from readOnly to readWrite
768         if (artifactProtection != null
769             && artifactProtection.equals(ActionArtifactProtection.readWrite.name())) {
770           artifactMetadataByUuId.setArtifactProtection(ActionArtifactProtection.readWrite.name());
771           artifactMetadataByUuId.setTimestamp(getCurrentTimeStampUtc());
772           updateArtifactMetadataInActionData(action, artifactMetadataByUuId);
773         }
774       } else {
775         int effectiveVersion = getEffectiveVersion(activeVersion.toString());
776         if (artifactLabel != null) {
777           artifactMetadataByUuId.setArtifactLabel(artifactLabel);
778         }
779         if (artifactCategory != null) {
780           artifactMetadataByUuId.setArtifactCategory(artifactCategory);
781         }
782         if (artifactDescription != null) {
783           artifactMetadataByUuId.setArtifactDescription(artifactDescription);
784         }
785         if (artifactProtection != null) {
786           artifactMetadataByUuId.setArtifactProtection(artifactProtection);
787         }
788         if (payload != null) {
789           //get artifact data from action_artifact table for updating the content
790           ActionArtifact artifactContent = new ActionArtifact();
791           artifactContent.setArtifactUuId(artifact.getArtifactUuId());
792           artifactContent.setArtifact(payload);
793           artifactContent.setEffectiveVersion(effectiveVersion);
794           actionArtifactDao.updateArtifact(artifactContent);
795         }
796         //Update the action data field and timestamp
797         artifactMetadataByUuId.setTimestamp(getCurrentTimeStampUtc());
798         updateArtifactMetadataInActionData(action, artifactMetadataByUuId);
799       }
800       log.debug("exit updateArtifact with actionInvariantUuId= " + actionInvariantUuId
801           + "artifactUUID= " + artifact.getArtifactUuId() + " and user = " + user);
802     } catch (CoreException coreException) {
803       formAndThrowException(coreException);
804     }
805   }
806
807   /**
808    * Generate artifact UUID at runtime using action name and effective version.
809    *
810    * @param action       {@link Action} for which the artifact is being uploaded/updated/downloaded
811    * @param artifactName Artifact name
812    * @return Generated UUID string
813    */
814   private String generateActionArtifactUuId(Action action, String artifactName) {
815     int effectiveVersion = getEffectiveVersion(action.getVersion());
816     //Upper case for maintaining case-insensitive behavior for the artifact names
817     String artifactUuIdString =
818         action.getName().toUpperCase() + effectiveVersion + artifactName.toUpperCase();
819     String generateArtifactUuId =
820         UUID.nameUUIDFromBytes((artifactUuIdString).getBytes()).toString();
821     String artifactUuId = generateArtifactUuId.replace("-", "");
822     return artifactUuId.toUpperCase();
823   }
824
825   /**
826    * Generate the effective action version for artifact operations.
827    *
828    * @param actionVersion Version of the action as a string
829    * @return Effective version to be used for artifact operations
830    */
831   private int getEffectiveVersion(String actionVersion) {
832     Version version = Version.valueOf(actionVersion);
833     return version.getMajor() * 10000 + version.getMinor();
834   }
835
836   /**
837    * Update the data field of the Action object with the modified/generated fields after an
838    * operation.
839    *
840    * @param action Action object whose data field has to be updated
841    * @return Updated {@link Action} object
842    */
843   private Action updateData(Action action) {
844     log.debug("entering updateData to update data json for action with actionuuid=  "
845         + action.getActionUuId());
846     Map<String, String> dataMap = new LinkedHashMap<>();
847     dataMap.put(ActionConstants.UNIQUE_ID, action.getActionUuId());
848     dataMap.put(ActionConstants.VERSION, action.getVersion());
849     dataMap.put(ActionConstants.INVARIANTUUID, action.getActionInvariantUuId());
850     dataMap.put(ActionConstants.STATUS, action.getStatus().name());
851
852     String data = action.getData();
853     Map<String, String> currentDataMap = JsonUtil.json2Object(data, LinkedHashMap.class);
854     dataMap.putAll(currentDataMap);
855     data = JsonUtil.object2Json(dataMap);
856     action.setData(data);
857     log.debug("exit updateData");
858     return action;
859   }
860
861   /**
862    * Method to add the artifact metadata in the data attribute of action table.
863    *
864    * @param action   Action to which artifact is uploaded
865    * @param artifact Uploaded artifact object
866    */
867   private void addArtifactMetadataInActionData(Action action, ActionArtifact artifact) {
868
869     ActionArtifact artifactMetadata = new ActionArtifact();
870     artifactMetadata.setArtifactUuId(artifact.getArtifactUuId());
871     artifactMetadata.setArtifactName(artifact.getArtifactName());
872     artifactMetadata.setArtifactProtection(artifact.getArtifactProtection());
873     artifactMetadata.setArtifactLabel(artifact.getArtifactLabel());
874     artifactMetadata.setArtifactDescription(artifact.getArtifactDescription());
875     artifactMetadata.setArtifactCategory(artifact.getArtifactCategory());
876     artifactMetadata.setTimestamp(artifact.getTimestamp());
877
878     List<ActionArtifact> actionArtifacts = action.getArtifacts();
879     if (actionArtifacts == null) {
880       actionArtifacts = new ArrayList<>();
881     }
882     actionArtifacts.add(artifactMetadata);
883     action.setArtifacts(actionArtifacts);
884     String currentData = action.getData();
885     Map<String, Object> currentDataMap = JsonUtil.json2Object(currentData, LinkedHashMap.class);
886     currentDataMap.put(ActionConstants.ARTIFACTS, actionArtifacts);
887     String updatedActionData = JsonUtil.object2Json(currentDataMap);
888     action.setData(updatedActionData);
889     action.setTimestamp(artifact.getTimestamp());
890     actionDao.updateAction(action);
891   }
892
893   /**
894    * Get a list of last major and last minor version (no candidate) of action from a list of
895    * actions.
896    *
897    * @param actions Exhaustive list of the action versions
898    * @return List {@link Action} of last major and last minor version (no candidate) of action from
899      a list of actions
900    */
901   private List<Action> getMajorMinorVersionActions(List<Action> actions) {
902     log.debug(" entering getMajorMinorVersionActions for actions ");
903     List<Action> list = new LinkedList<>();
904     actionLogPreProcessor(ActionSubOperation.GET_VERSIONINFO_FOR_ALL_ACTIONS, TARGET_ENTITY_API);
905     Map<String, VersionInfo> actionVersionMap = versioningManager
906         .listEntitiesVersionInfo(ACTION_VERSIONABLE_TYPE, "", VersionableEntityAction.Read);
907     actionLogPostProcessor(StatusCode.COMPLETE);
908     log.metrics("");
909     for (Action action : actions) {
910       if (action.getStatus() == ActionStatus.Deleted) {
911         continue;
912       }
913       VersionInfo actionVersionInfo = actionVersionMap.get(action.getActionInvariantUuId());
914       if (actionVersionInfo.getActiveVersion() != null
915           && actionVersionInfo.getActiveVersion().equals(Version.valueOf(action.getVersion()))) {
916         list.add(action);
917       } else if (actionVersionInfo.getLatestFinalVersion() != null
918           && actionVersionInfo.getLatestFinalVersion().equals(Version.valueOf(action.getVersion()))
919           &&
920           !actionVersionInfo.getLatestFinalVersion().equals(actionVersionInfo.getActiveVersion())) {
921         list.add(action);
922       }
923     }
924     log.debug(" exit getMajorMinorVersionActions for actions ");
925     return list;
926   }
927
928   /**
929    * CoreException object wrapper from Version library to Action Library Exception.
930    *
931    * @param exception CoreException object from version library
932    */
933   private void formAndThrowException(CoreException exception) {
934     log.debug("entering formAndThrowException with input CoreException =" + exception.code().id()
935         + " " + exception.getMessage());
936     String errorDescription = exception.getMessage();
937     String errorCode = exception.code().id();
938     ActionException actionException = new ActionException();
939     switch (errorCode) {
940       case VersioningErrorCodes.VERSIONABLE_ENTITY_NOT_EXIST:
941         actionException.setErrorCode(ACTION_ENTITY_NOT_EXIST_CODE);
942         actionException.setDescription(ACTION_ENTITY_NOT_EXIST);
943         break;
944       case VersioningErrorCodes.CHECKOT_ON_LOCKED_ENTITY:
945         actionException.setErrorCode(ACTION_CHECKOUT_ON_LOCKED_ENTITY);
946         actionException.setDescription(errorDescription);
947         break;
948       case VersioningErrorCodes.CHECKIN_ON_UNLOCKED_ENTITY:
949         actionException.setErrorCode(ACTION_CHECKIN_ON_UNLOCKED_ENTITY);
950         actionException.setDescription(errorDescription);
951         break;
952       case VersioningErrorCodes.SUBMIT_FINALIZED_ENTITY_NOT_ALLOWED:
953         actionException.setErrorCode(ACTION_SUBMIT_FINALIZED_ENTITY_NOT_ALLOWED);
954         actionException.setDescription(errorDescription);
955         break;
956       case VersioningErrorCodes.SUBMIT_LOCKED_ENTITY_NOT_ALLOWED:
957         actionException.setErrorCode(ACTION_SUBMIT_LOCKED_ENTITY_NOT_ALLOWED);
958         actionException.setDescription(errorDescription);
959         break;
960       case VersioningErrorCodes.UNDO_CHECKOUT_ON_UNLOCKED_ENTITY:
961         actionException.setErrorCode(ACTION_UNDO_CHECKOUT_ON_UNLOCKED_ENTITY);
962         actionException.setDescription(errorDescription);
963         break;
964       case VersioningErrorCodes.EDIT_ON_ENTITY_LOCKED_BY_OTHER_USER:
965         actionException.setErrorCode(ACTION_EDIT_ON_ENTITY_LOCKED_BY_OTHER_USER);
966         actionException.setDescription(errorDescription.replace("edit", "updat"));
967         break;
968       case VersioningErrorCodes.CHECKIN_ON_ENTITY_LOCKED_BY_OTHER_USER:
969         actionException.setErrorCode(ACTION_CHECKIN_ON_ENTITY_LOCKED_BY_OTHER_USER);
970         actionException.setDescription(errorDescription);
971         break;
972       case VersioningErrorCodes.UNDO_CHECKOUT_ON_ENTITY_LOCKED_BY_OTHER_USER:
973         actionException.setErrorCode(ACTION_UNDO_CHECKOUT_ON_ENTITY_LOCKED_BY_OTHER_USER);
974         actionException.setDescription(errorDescription);
975         break;
976       case VersioningErrorCodes.EDIT_ON_UNLOCKED_ENTITY:
977         actionException.setErrorCode(ACTION_UPDATE_ON_UNLOCKED_ENTITY);
978         actionException.setDescription(errorDescription.replace("edit", "update"));
979         break;
980       case VersioningErrorCodes.DELETE_ON_LOCKED_ENTITY:
981         actionException.setErrorCode(ACTION_DELETE_ON_LOCKED_ENTITY_CODE);
982         actionException.setDescription(errorDescription);
983         break;
984       default:
985         actionException.setErrorCode(ACTION_INTERNAL_SERVER_ERR_CODE);
986         actionException.setDescription(exception.getMessage());
987
988     }
989     //Todo - Uncomment only if class to be added in ERROR Log
990     /*actionErrorLogProcessor(CategoryLogLevel.ERROR, actionException.getErrorCode(),
991     actionException.getDescription());
992     log.error("");*/
993     log.debug(
994         "exit formAndThrowException with ActionException =" + actionException.getErrorCode()
995             + " " + actionException.getDescription());
996     throw actionException;
997   }
998
999   /**
1000    * Validates an action object for business layer validations before an update operation.
1001    *
1002    * @param action        Action object to be validated
1003    * @param activeVersion Active version of the actoin object
1004    */
1005   private void validateActions(Action action, Version activeVersion) {
1006     try {
1007       //Set version if not already available in input request
1008       //If version set in input compare it with version from DB
1009       if (StringUtils.isEmpty(action.getVersion())) {
1010         action.setVersion(activeVersion.toString());
1011       } else {
1012         if (!activeVersion.equals(Version.valueOf(action.getVersion()))) {
1013           throw new ActionException(ACTION_UPDATE_INVALID_VERSION,
1014               String.format(ACTION_REQUESTED_VERSION_INVALID, action.getVersion()));
1015         }
1016       }
1017       String invariantUuId = action.getActionInvariantUuId();
1018       Version version = Version.valueOf(action.getVersion());
1019       Action existingAction = getActions(invariantUuId, version);
1020       if (existingAction == null || existingAction.getActionInvariantUuId() == null) {
1021         throw new ActionException(ACTION_ENTITY_NOT_EXIST_CODE, ACTION_ENTITY_NOT_EXIST);
1022       }
1023       List<String> invalidParameters = new LinkedList<>();
1024       //Prevent update of name, version and id fields
1025       if (!existingAction.getName().equals(action.getName())) {
1026         throw new ActionException(ACTION_UPDATE_NOT_ALLOWED_CODE_NAME,
1027             ACTION_UPDATE_NOT_ALLOWED_FOR_NAME);
1028       }
1029       if (!StringUtils.isEmpty(action.getActionUuId())
1030           && !existingAction.getActionUuId().equals(action.getActionUuId())) {
1031         invalidParameters.add(UNIQUE_ID);
1032       }
1033       if (action.getStatus() != null && (existingAction.getStatus() != action.getStatus())) {
1034         invalidParameters.add(STATUS);
1035       }
1036
1037       if (!invalidParameters.isEmpty()) {
1038         throw new ActionException(ACTION_UPDATE_NOT_ALLOWED_CODE,
1039             String.format(ACTION_UPDATE_PARAM_INVALID, StringUtils.join(invalidParameters, ", ")));
1040       }
1041       action.setActionUuId(existingAction.getActionUuId());
1042     } catch (IllegalArgumentException iae) {
1043       String message = iae.getMessage();
1044       switch (message) {
1045         case VERSION_STRING_VIOLATION_MSG:
1046           throw new ActionException(ACTION_UPDATE_NOT_ALLOWED_CODE, message);
1047         default:
1048           throw iae;
1049       }
1050     }
1051   }
1052
1053   /**
1054    * Get an action version entity object.
1055    *
1056    * @param invariantUuId Invariant UUID of the action
1057    * @param version       Version of the action
1058    * @return {@link ActionEntity} object of the action version
1059    */
1060   private ActionEntity getActionsEntityByVersion(String invariantUuId, Version version) {
1061     log.debug(
1062         "entering getActionsEntityByVersion with invariantUUID= " + invariantUuId + " and version"
1063             + version);
1064     ActionEntity entity = null;
1065     if (version != null) {
1066       actionLogPreProcessor(ActionSubOperation.GET_ACTIONENTITY_BY_VERSION, TARGET_ENTITY_DB);
1067       entity = actionDao.get(
1068           new ActionEntity(invariantUuId != null ? invariantUuId.toUpperCase() : null, version));
1069       actionLogPostProcessor(StatusCode.COMPLETE);
1070       log.metrics("");
1071     }
1072     log.debug(
1073         "exit getActionsEntityByVersion with invariantUuId= " + invariantUuId + " and version"
1074             + version);
1075     return entity;
1076   }
1077
1078   /**
1079    * Get an action version object.
1080    *
1081    * @param invariantUuId Invariant UUID of the action
1082    * @param version       Version of the action
1083    * @return {@link Action} object of the action version
1084    */
1085   private Action getActions(String invariantUuId, Version version) {
1086     ActionEntity actionEntity =
1087         getActionsEntityByVersion(invariantUuId != null ? invariantUuId.toUpperCase() : null,
1088             version);
1089     return actionEntity != null ? actionEntity.toDto() : new Action();
1090   }
1091
1092   /**
1093    * Create and set the Unique ID in for an action version row.
1094    *
1095    * @param invariantUuId Invariant UUID of the action
1096    * @param version       Version of the action
1097    * @param status        Status of the action
1098    * @param user          AT&T id of the user sending the request
1099    * @return {@link ActionEntity} object of the action version
1100    */
1101   private ActionEntity updateUniqueIdForVersion(String invariantUuId, Version version,
1102                                                 String status, String user) {
1103     log.debug(
1104         "entering updateUniqueIdForVersion to update action with invariantUuId= " + invariantUuId
1105             + " with version,status and user as ::" + version + " " + status + " " + user);
1106     //generate UUID AND update for newly created entity row
1107     ActionEntity actionEntity = getActionsEntityByVersion(invariantUuId, version);
1108     if (actionEntity != null) {
1109       log.debug("Found action to be updated");
1110       String data = actionEntity.getData();
1111       String uniqueId = CommonMethods.nextUuId();
1112       Map<String, String> dataMap = JsonUtil.json2Object(data, LinkedHashMap.class);
1113       dataMap.put(ActionConstants.UNIQUE_ID, uniqueId);
1114       dataMap.put(ActionConstants.VERSION, version.toString());
1115       dataMap.put(ActionConstants.STATUS, status);
1116       data = JsonUtil.object2Json(dataMap);
1117
1118       actionEntity.setData(data);
1119       actionEntity.setActionUuId(uniqueId);
1120       actionEntity.setStatus(status);
1121       actionEntity.setUser(user);
1122       actionEntity.setTimestamp(getCurrentTimeStampUtc());
1123       actionLogPreProcessor(ActionSubOperation.UPDATE_ACTION, TARGET_ENTITY_DB);
1124       actionDao.update(actionEntity);
1125       actionLogPostProcessor(StatusCode.COMPLETE);
1126       log.metrics("");
1127     }
1128
1129     log.debug(
1130         "exit updateUniqueIdForVersion to update action with invariantUUID= " + invariantUuId);
1131     return actionEntity;
1132   }
1133
1134   /**
1135    * Set the status for an action version row.
1136    *
1137    * @param invariantUuId Invariant UUID of the action
1138    * @param version       Version of the action
1139    * @param status        Status of the action
1140    * @param user          AT&T id of the user sending the request
1141    * @return {@link ActionEntity} object of the action version
1142    */
1143   private ActionEntity updateStatusForVersion(String invariantUuId, Version version, String status,
1144                                               String user) {
1145     log.debug(
1146         "entering updateStatusForVersion with invariantUuId= " + invariantUuId + " and version"
1147             + version + " for updating status " + status + " by user " + user);
1148     ActionEntity actionEntity = getActionsEntityByVersion(invariantUuId, version);
1149     if (actionEntity != null) {
1150       String data = actionEntity.getData();
1151       Map<String, String> dataMap = JsonUtil.json2Object(data, LinkedHashMap.class);
1152       dataMap.put(ActionConstants.STATUS, status);
1153       data = JsonUtil.object2Json(dataMap);
1154       actionEntity.setData(data);
1155       actionEntity.setStatus(status);
1156       actionEntity.setUser(user);
1157       actionEntity.setTimestamp(getCurrentTimeStampUtc());
1158       actionLogPreProcessor(ActionSubOperation.UPDATE_ACTION, TARGET_ENTITY_DB);
1159       actionDao.update(actionEntity);
1160       actionLogPostProcessor(StatusCode.COMPLETE);
1161       log.metrics("");
1162     }
1163     log.debug("exit updateStatusForVersion with invariantUuId= " + invariantUuId + " and version"
1164         + version + " for updating status " + status + " by user " + user);
1165     return actionEntity;
1166
1167   }
1168
1169   /**
1170    * Gets an artifact from the action artifact metadata by artifact name.
1171    *
1172    * @param actionArtifactList  Action's existing artifact list
1173    * @param artifactFilterType  Search criteria for artifact in action artifact metadata
1174    * @param artifactFilterValue Value of Search parameter
1175    * @return Artifact metadata object if artifact is present in action and null otherwise
1176    */
1177   private ActionArtifact getArtifactMetadataFromAction(List<ActionArtifact> actionArtifactList,
1178                                                        String artifactFilterType,
1179                                                        String artifactFilterValue) {
1180     ActionArtifact artifact = null;
1181     if (actionArtifactList != null && !actionArtifactList.isEmpty()) {
1182       for (ActionArtifact entry : actionArtifactList) {
1183         switch (artifactFilterType) {
1184           case ARTIFACT_METADATA_ATTR_UUID:
1185             String artifactUuId = entry.getArtifactUuId();
1186             if (artifactUuId != null && artifactUuId.equals(artifactFilterValue)) {
1187               artifact = entry;
1188               break;
1189             }
1190             break;
1191           case ARTIFACT_METADATA_ATTR_NAME:
1192             String existingArtifactName = entry.getArtifactName().toLowerCase();
1193             if (existingArtifactName.equals(artifactFilterValue.toLowerCase())) {
1194               artifact = entry;
1195               break;
1196             }
1197             break;
1198           default:
1199         }
1200       }
1201     }
1202     return artifact;
1203   }
1204
1205   /**
1206    * Method to update the artifact metadata in the data attribute of action table.
1207    *
1208    * @param action          Action to which artifact is uploaded
1209    * @param updatedArtifact updated artifact object
1210    */
1211   private void updateArtifactMetadataInActionData(Action action, ActionArtifact updatedArtifact) {
1212     for (ActionArtifact entry : action.getArtifacts()) {
1213       if (entry.getArtifactUuId().equals(updatedArtifact.getArtifactUuId())) {
1214         entry.setArtifactLabel(updatedArtifact.getArtifactLabel());
1215         entry.setArtifactCategory(updatedArtifact.getArtifactCategory());
1216         entry.setArtifactDescription(updatedArtifact.getArtifactDescription());
1217         entry.setArtifactProtection(updatedArtifact.getArtifactProtection());
1218         entry.setTimestamp(updatedArtifact.getTimestamp());
1219         break;
1220       }
1221     }
1222     String data = action.getData();
1223     Map<String, Object> map = JsonUtil.json2Object(data, LinkedHashMap.class);
1224     map.put(ActionConstants.ARTIFACTS, action.getArtifacts());
1225     String updatedActionData = JsonUtil.object2Json(map);
1226     action.setData(updatedActionData);
1227     action.setTimestamp(updatedArtifact.getTimestamp());
1228     actionDao.updateAction(action);
1229   }
1230 }