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