696c63e498d7327b9ceef8b4e5fb5eed43274606
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.action.impl;
18
19 import static org.openecomp.sdc.action.ActionConstants.ACTION_VERSIONABLE_TYPE;
20 import static org.openecomp.sdc.action.ActionConstants.ARTIFACT_METADATA_ATTR_NAME;
21 import static org.openecomp.sdc.action.ActionConstants.ARTIFACT_METADATA_ATTR_UUID;
22 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_CATEGORY;
23 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_MODEL;
24 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_NAME;
25 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_NONE;
26 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_OPEN_ECOMP_COMPONENT;
27 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_VENDOR;
28 import static org.openecomp.sdc.action.ActionConstants.SERVICE_INSTANCE_ID;
29 import static org.openecomp.sdc.action.ActionConstants.STATUS;
30 import static org.openecomp.sdc.action.ActionConstants.TARGET_ENTITY_API;
31 import static org.openecomp.sdc.action.ActionConstants.TARGET_ENTITY_DB;
32 import static org.openecomp.sdc.action.ActionConstants.UNIQUE_ID;
33 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_ALREADY_EXISTS;
34 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_ALREADY_EXISTS_CODE;
35 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_DELETE_READ_ONLY;
36 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_DELETE_READ_ONLY_MSG;
37 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_UPDATE_NAME_INVALID;
38 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_UPDATE_READ_ONLY;
39 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_UPDATE_READ_ONLY_MSG;
40 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_CHECKIN_ON_ENTITY_LOCKED_BY_OTHER_USER;
41 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_CHECKIN_ON_UNLOCKED_ENTITY;
42 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_CHECKOUT_ON_LOCKED_ENTITY;
43 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_CHECKOUT_ON_LOCKED_ENTITY_OTHER_USER;
44 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_DELETE_ON_LOCKED_ENTITY_CODE;
45 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_EDIT_ON_ENTITY_LOCKED_BY_OTHER_USER;
46 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_NOT_EXIST;
47 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_NOT_EXIST_CODE;
48 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_UNIQUE_VALUE_ERROR;
49 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_UNIQUE_VALUE_MSG;
50 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_INTERNAL_SERVER_ERR_CODE;
51 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUESTED_VERSION_INVALID;
52 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_SUBMIT_FINALIZED_ENTITY_NOT_ALLOWED;
53 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_SUBMIT_LOCKED_ENTITY_NOT_ALLOWED;
54 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UNDO_CHECKOUT_ON_ENTITY_LOCKED_BY_OTHER_USER;
55 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UNDO_CHECKOUT_ON_UNLOCKED_ENTITY;
56 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_INVALID_VERSION;
57 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_NOT_ALLOWED_CODE;
58 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_NOT_ALLOWED_CODE_NAME;
59 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_NOT_ALLOWED_FOR_NAME;
60 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_ON_UNLOCKED_ENTITY;
61 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_PARAM_INVALID;
62 import static org.openecomp.sdc.action.util.ActionUtil.actionLogPostProcessor;
63 import static org.openecomp.sdc.action.util.ActionUtil.actionLogPreProcessor;
64 import static org.openecomp.sdc.action.util.ActionUtil.getCurrentTimeStampUtc;
65 import static org.openecomp.sdc.versioning.dao.types.Version.VERSION_STRING_VIOLATION_MSG;
66
67 import java.util.ArrayList;
68 import java.util.Collections;
69 import java.util.Iterator;
70 import java.util.LinkedHashMap;
71 import java.util.LinkedList;
72 import java.util.List;
73 import java.util.Map;
74 import java.util.UUID;
75 import org.apache.commons.collections4.CollectionUtils;
76 import org.apache.commons.lang.StringUtils;
77 import org.openecomp.core.dao.UniqueValueDaoFactory;
78 import org.openecomp.core.util.UniqueValueUtil;
79 import org.openecomp.core.utilities.CommonMethods;
80 import org.openecomp.core.utilities.json.JsonUtil;
81 import org.openecomp.sdc.action.ActionConstants;
82 import org.openecomp.sdc.action.ActionManager;
83 import org.openecomp.sdc.action.dao.ActionArtifactDao;
84 import org.openecomp.sdc.action.dao.ActionArtifactDaoFactory;
85 import org.openecomp.sdc.action.dao.ActionDao;
86 import org.openecomp.sdc.action.dao.ActionDaoFactory;
87 import org.openecomp.sdc.action.dao.types.ActionArtifactEntity;
88 import org.openecomp.sdc.action.dao.types.ActionEntity;
89 import org.openecomp.sdc.action.errors.ActionErrorConstants;
90 import org.openecomp.sdc.action.errors.ActionException;
91 import org.openecomp.sdc.action.logging.StatusCode;
92 import org.openecomp.sdc.action.types.Action;
93 import org.openecomp.sdc.action.types.ActionArtifact;
94 import org.openecomp.sdc.action.types.ActionArtifactProtection;
95 import org.openecomp.sdc.action.types.ActionStatus;
96 import org.openecomp.sdc.action.types.ActionSubOperation;
97 import org.openecomp.sdc.action.types.OpenEcompComponent;
98 import org.openecomp.sdc.common.errors.CoreException;
99 import org.openecomp.sdc.logging.api.Logger;
100 import org.openecomp.sdc.logging.api.LoggerFactory;
101 import org.openecomp.sdc.versioning.ActionVersioningManager;
102 import org.openecomp.sdc.versioning.ActionVersioningManagerFactory;
103 import org.openecomp.sdc.versioning.dao.VersionInfoDao;
104 import org.openecomp.sdc.versioning.dao.VersionInfoDaoFactory;
105 import org.openecomp.sdc.versioning.dao.types.UserCandidateVersion;
106 import org.openecomp.sdc.versioning.dao.types.Version;
107 import org.openecomp.sdc.versioning.dao.types.VersionInfoEntity;
108 import org.openecomp.sdc.versioning.errors.EntityNotExistErrorBuilder;
109 import org.openecomp.sdc.versioning.errors.VersioningErrorCodes;
110 import org.openecomp.sdc.versioning.types.VersionInfo;
111 import org.openecomp.sdc.versioning.types.VersionableEntityAction;
112 import org.slf4j.MDC;
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 ActionVersioningManager versioningManager =
122       ActionVersioningManagerFactory.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     UniqueValueUtil uniqueValueUtil =
287         new UniqueValueUtil(UniqueValueDaoFactory.getInstance().createInterface());
288     try {
289       actionLogPreProcessor(ActionSubOperation.VALIDATE_ACTION_UNIQUE_NAME, TARGET_ENTITY_API);
290       uniqueValueUtil
291           .validateUniqueValue(ActionConstants.UniqueValues.ACTION_NAME, action.getName());
292       actionLogPostProcessor(StatusCode.COMPLETE);
293     } catch (CoreException exception) {
294       String errorDesc = String
295           .format(ACTION_ENTITY_UNIQUE_VALUE_MSG, ActionConstants.UniqueValues.ACTION_NAME,
296               action.getName());
297       log.error(errorDesc, exception);
298       actionLogPostProcessor(StatusCode.ERROR, ACTION_ENTITY_UNIQUE_VALUE_ERROR, errorDesc, false);
299       throw new ActionException(ACTION_ENTITY_UNIQUE_VALUE_ERROR, errorDesc);
300     } finally {
301       log.metrics("");
302     }
303     action.setUser(user);
304     action.setTimestamp(getCurrentTimeStampUtc());
305     action.setActionInvariantUuId(CommonMethods.nextUuId());
306     action.setActionUuId(CommonMethods.nextUuId());
307
308     actionLogPreProcessor(ActionSubOperation.CREATE_ACTION_VERSION, TARGET_ENTITY_API);
309     Version version =
310         versioningManager.create(ACTION_VERSIONABLE_TYPE, action.getActionInvariantUuId(), user);
311     actionLogPostProcessor(StatusCode.COMPLETE);
312     log.metrics("");
313
314     action.setVersion(version.toString());
315     action.setStatus(ActionStatus.Locked);
316     action = updateData(action);
317     action = actionDao.createAction(action);
318
319     actionLogPreProcessor(ActionSubOperation.CREATE_ACTION_UNIQUE_VALUE, TARGET_ENTITY_API);
320     uniqueValueUtil.createUniqueValue(ActionConstants.UniqueValues.ACTION_NAME, action.getName());
321     actionLogPostProcessor(StatusCode.COMPLETE);
322     log.metrics("");
323
324     return action;
325   }
326
327   /**
328    * Update an existing action.
329    *
330    * @param action Action object model of the user request for creating an action
331    * @param user   AT&T id of the user sending the update request
332    * @return {@link Action} model object for the update action
333    * @throws ActionException Exception with an action library specific code, short description and
334    *                         detailed message for the error occurred for the error occurred during
335    *                         the operation
336    */
337   @Override
338   public Action updateAction(Action action, String user) throws ActionException {
339     try {
340       log.debug("entering updateAction to update action with invariantUuId = "
341           + action.getActionInvariantUuId() + " by user = " + user);
342       String invariantUuId = action.getActionInvariantUuId();
343       actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_API);
344       VersionInfo versionInfo = versioningManager
345           .getEntityVersionInfo(ACTION_VERSIONABLE_TYPE, invariantUuId, user,
346               VersionableEntityAction.Write);
347       actionLogPostProcessor(StatusCode.COMPLETE);
348       log.metrics("");
349
350       Version activeVersion = versionInfo.getActiveVersion();
351       validateActions(action, activeVersion);
352       action.setStatus(ActionStatus.Locked); //Status will be Checkout for update
353       updateData(action);
354       action.setUser(user);
355       action.setTimestamp(getCurrentTimeStampUtc());
356       actionDao.updateAction(action);
357
358     } catch (CoreException ce) {
359       formAndThrowException(ce);
360     }
361     log.debug("exit updateAction");
362     return action;
363   }
364
365   /**
366    * Checkout an existing action.
367    *
368    * @param invariantUuId actionInvariantUuId of the action to be checked out
369    * @param user          AT&T id of the user sending the checkout request
370    * @return {@link Action} model object for the checkout action
371    * @throws ActionException Exception with an action library specific code, short description and
372    *                         detailed message for the error occurred for the error occurred during
373    *                         the operation
374    */
375   @Override
376   public Action checkout(String invariantUuId, String user) throws ActionException {
377     Version version = null;
378     ActionEntity actionEntity = null;
379     try {
380       log.debug(
381           "entering checkout for Action with invariantUUID= " + invariantUuId + " by user = "
382               + user);
383       actionLogPreProcessor(ActionSubOperation.CHECKOUT_ACTION, TARGET_ENTITY_API);
384       version = versioningManager.checkout(ACTION_VERSIONABLE_TYPE, invariantUuId, user);
385       actionLogPostProcessor(StatusCode.COMPLETE);
386       log.metrics("");
387
388       actionEntity =
389           updateUniqueIdForVersion(invariantUuId, version, ActionStatus.Locked.name(), user);
390     } catch (CoreException exception) {
391       if (exception.code() != null && exception.code().id().equals(
392           VersioningErrorCodes.CHECKOT_ON_LOCKED_ENTITY)) {
393         actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_DB);
394         VersionInfoEntity versionInfoEntity =
395             versionInfoDao.get(new VersionInfoEntity(ACTION_VERSIONABLE_TYPE, invariantUuId));
396         actionLogPostProcessor(StatusCode.COMPLETE);
397         log.metrics("");
398         String checkoutUser = versionInfoEntity.getCandidate().getUser();
399         log.debug(
400             "Actual checkout user for Action with invariantUUID= " + invariantUuId + " is = "
401                 + checkoutUser);
402         if (!checkoutUser.equals(user)) {
403           throw new ActionException(ACTION_CHECKOUT_ON_LOCKED_ENTITY_OTHER_USER,
404               exception.getMessage());
405         }
406       }
407       formAndThrowException(exception);
408     }
409     log.debug(
410         "exit checkout for Action with invariantUUID= " + invariantUuId + " by user = " + user);
411     return actionEntity != null ? actionEntity.toDto() : new Action();
412   }
413
414   /**
415    * Undo an already checked out action.
416    *
417    * @param invariantUuId actionInvariantUuId of the checked out action
418    * @param user          AT&T id of the user sending the request
419    * @throws ActionException Exception with an action library specific code, short description and
420    *                         detailed message for the error occurred for the error occurred during
421    *                         the operation
422    */
423   @Override
424   public void undoCheckout(String invariantUuId, String user) throws ActionException {
425     Version version;
426     try {
427       log.debug(
428           "entering undoCheckout for Action with invariantUUID= " + invariantUuId + " by user = "
429               + user);
430
431       actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_DB);
432       //Get list of uploaded artifacts in this checked out version
433       VersionInfoEntity versionInfoEntity =
434           versionInfoDao.get(new VersionInfoEntity(ACTION_VERSIONABLE_TYPE, invariantUuId));
435       actionLogPostProcessor(StatusCode.COMPLETE);
436       log.metrics("");
437       if (versionInfoEntity == null) {
438         throw new CoreException(
439             new EntityNotExistErrorBuilder(ACTION_VERSIONABLE_TYPE, invariantUuId).build());
440       }
441       UserCandidateVersion candidate = versionInfoEntity.getCandidate();
442       Version activeVersion;
443       if (candidate != null) {
444         activeVersion = candidate.getVersion();
445       } else {
446         activeVersion = versionInfoEntity.getActiveVersion();
447       }
448
449       actionLogPreProcessor(ActionSubOperation.GET_ACTIONENTITY_BY_VERSION, TARGET_ENTITY_DB);
450       Action action = actionDao.get(new ActionEntity(invariantUuId, activeVersion)).toDto();
451       actionLogPostProcessor(StatusCode.COMPLETE);
452       log.metrics("");
453
454       //Perform undo checkout on the action
455       actionLogPreProcessor(ActionSubOperation.UNDO_CHECKOUT_ACTION, TARGET_ENTITY_API);
456       version = versioningManager.undoCheckout(ACTION_VERSIONABLE_TYPE, invariantUuId, user);
457       actionLogPostProcessor(StatusCode.COMPLETE);
458       log.metrics("");
459
460       if (version.equals(new Version(0, 0))) {
461         actionLogPreProcessor(ActionSubOperation.DELETE_UNIQUEVALUE, TARGET_ENTITY_API);
462         UniqueValueUtil uniqueValueUtil =
463             new UniqueValueUtil(UniqueValueDaoFactory.getInstance().createInterface());
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) &&
480           currentVersionArtifacts.size() > 0) {
481         for (ActionArtifact artifact : currentVersionArtifacts) {
482           ActionArtifactEntity artifactDeleteEntity =
483               new ActionArtifactEntity(artifact.getArtifactUuId(),
484                   getEffectiveVersion(activeVersion.toString()));
485           actionLogPreProcessor(ActionSubOperation.DELETE_ARTIFACT, TARGET_ENTITY_DB);
486           actionArtifactDao.delete(artifactDeleteEntity);
487           actionLogPostProcessor(StatusCode.COMPLETE);
488           log.metrics("");
489         }
490       }
491     } catch (CoreException exception) {
492       formAndThrowException(exception);
493     }
494     log.debug(
495         "exit undoCheckout for Action with invariantUUID= " + invariantUuId + " by user = " + user);
496   }
497
498   /**
499    * Checkin a checked out action.
500    *
501    * @param invariantUuId actionInvariantUuId of the checked out action
502    * @param user          AT&T id of the user sending the request
503    * @return {@link Action} model object for the updated action
504    * @throws ActionException Exception with an action library specific code, short description and
505    *                         detailed message for the error occurred for the error occurred during
506    *                         the operation
507    */
508   @Override
509   public Action checkin(String invariantUuId, String user) throws ActionException {
510     Version version = null;
511     ActionEntity actionEntity = null;
512     try {
513       log.debug("entering checkin for Action with invariantUUID= " + invariantUuId + " by user = "
514           + user);
515       actionLogPreProcessor(ActionSubOperation.CHECKIN_ACTION, TARGET_ENTITY_API);
516       version = versioningManager.checkin(ACTION_VERSIONABLE_TYPE, invariantUuId, user, null);
517       actionLogPostProcessor(StatusCode.COMPLETE);
518       log.metrics("");
519       actionEntity =
520           updateStatusForVersion(invariantUuId, version, ActionStatus.Available.name(), user);
521     } catch (CoreException exception) {
522       formAndThrowException(exception);
523     }
524     log.debug(
525         "exit checkin for Action with invariantUUID= " + invariantUuId + " by user = " + user);
526     return actionEntity != null ? actionEntity.toDto() : new Action();
527   }
528
529   /**
530    * Submit a checked in action.
531    *
532    * @param invariantUuId actionInvariantUuId of the checked in action
533    * @param user          AT&T id of the user sending the request
534    * @return {@link Action} model object for the updated action
535    * @throws ActionException Exception with an action library specific code, short description and
536    *                         detailed message for the error occurred for the error occurred during
537    *                         the operation
538    */
539   @Override
540   public Action submit(String invariantUuId, String user) throws ActionException {
541     Version version = null;
542     ActionEntity actionEntity = null;
543     try {
544       log.debug(
545           "entering submit for Action with invariantUUID= " + invariantUuId + " by user = " + user);
546       actionLogPreProcessor(ActionSubOperation.SUBMIT_ACTION, TARGET_ENTITY_API);
547       version = versioningManager.submit(ACTION_VERSIONABLE_TYPE, invariantUuId, user, null);
548       actionLogPostProcessor(StatusCode.COMPLETE);
549       log.metrics("");
550       actionEntity =
551           updateUniqueIdForVersion(invariantUuId, version, ActionStatus.Final.name(), user);
552     } catch (CoreException exception) {
553       formAndThrowException(exception);
554     }
555     log.debug("exit submit for Action with invariantUUID= " + invariantUuId + " by user = " + user);
556     return actionEntity != null ? actionEntity.toDto() : new Action();
557   }
558
559   /**
560    * Download an artifact of an action.
561    *
562    * @param artifactUuId {@link ActionArtifact} object representing the artifact and its metadata
563    * @param actionUuId   UUID of the action for which the artifact has to be downloaded
564    * @return downloaded action artifact object
565    */
566   @Override
567   public ActionArtifact downloadArtifact(String actionUuId, String artifactUuId)
568       throws ActionException {
569     log.debug(" entering downloadArtifact with actionUUID= " + actionUuId + " and artifactUUID= "
570         + artifactUuId);
571     Action action = actionDao.getActionsByActionUuId(actionUuId);
572     ActionArtifact actionArtifact;
573     if (action != null) {
574       MDC.put(SERVICE_INSTANCE_ID, action.getActionInvariantUuId());
575       List<ActionArtifact> artifacts = action.getArtifacts();
576       String actionVersion = action.getVersion();
577       int effectiveVersion = getEffectiveVersion(actionVersion);
578       ActionArtifact artifactMetadata =
579           getArtifactMetadataFromAction(artifacts, ARTIFACT_METADATA_ATTR_UUID, artifactUuId);
580       if (artifactMetadata != null) {
581         String artifactName = artifactMetadata.getArtifactName();
582         actionArtifact = actionArtifactDao.downloadArtifact(effectiveVersion, artifactUuId);
583         actionArtifact.setArtifactName(artifactName);
584
585       } else {
586         throw new ActionException(ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST_CODE,
587             ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST);
588       }
589     } else {
590       throw new ActionException(ActionErrorConstants.ACTION_ENTITY_NOT_EXIST_CODE,
591           ActionErrorConstants.ACTION_ENTITY_NOT_EXIST);
592     }
593     log.debug(" exit downloadArtifact with actionUUID= " + actionUuId + " and artifactUUID= "
594         + artifactUuId);
595     return actionArtifact;
596   }
597
598   /**
599    * Upload an artifact to an action.
600    *
601    * @param artifact            {@link ActionArtifact} object representing the artifact and its
602    *                            metadata
603    * @param actionInvariantUuId Invariant UUID of the action to which the artifact has to be
604    *                            uploaded
605    * @param user                User ID of the user sending the request
606    * @return Uploaded action artifact object
607    */
608   @Override
609   public ActionArtifact uploadArtifact(ActionArtifact artifact, String actionInvariantUuId,
610                                        String user) {
611     ActionArtifact uploadArtifactResponse = new ActionArtifact();
612     try {
613       log.debug("entering uploadArtifact with actionInvariantUuId= " + actionInvariantUuId
614           + "artifactName= " + artifact.getArtifactName());
615       actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_DB);
616       VersionInfo versionInfo = versioningManager
617           .getEntityVersionInfo(ACTION_VERSIONABLE_TYPE, actionInvariantUuId, user,
618               VersionableEntityAction.Write);
619       actionLogPostProcessor(StatusCode.COMPLETE);
620       log.metrics("");
621       Version activeVersion = versionInfo.getActiveVersion();
622       actionLogPreProcessor(ActionSubOperation.GET_ACTIONENTITY_BY_ACTIONINVID, TARGET_ENTITY_DB);
623       Action action = actionDao.get(new ActionEntity(actionInvariantUuId, activeVersion)).toDto();
624       actionLogPostProcessor(StatusCode.COMPLETE);
625       log.metrics("");
626       String artifactUuId = generateActionArtifactUuId(action, artifact.getArtifactName());
627       //Check for Unique document name
628       List<ActionArtifact> actionArtifacts = action.getArtifacts();
629       ActionArtifact artifactMetadata =
630           getArtifactMetadataFromAction(actionArtifacts, ARTIFACT_METADATA_ATTR_NAME,
631               artifact.getArtifactName());
632       if (artifactMetadata != null) {
633         throw new ActionException(ACTION_ARTIFACT_ALREADY_EXISTS_CODE,
634             String.format(ACTION_ARTIFACT_ALREADY_EXISTS, actionInvariantUuId));
635       }
636
637       //Create the artifact
638       artifact.setArtifactUuId(artifactUuId);
639       artifact.setTimestamp(getCurrentTimeStampUtc());
640       artifact.setEffectiveVersion(getEffectiveVersion(activeVersion.toString()));
641       actionArtifactDao.uploadArtifact(artifact);
642
643       //Update the action data field and timestamp
644       addArtifactMetadataInActionData(action, artifact);
645
646       //Set the response object
647       uploadArtifactResponse.setArtifactUuId(artifact.getArtifactUuId());
648     } catch (CoreException ce) {
649       formAndThrowException(ce);
650     }
651     log.debug(
652         "exit uploadArtifact with actionInvariantUuId= " + actionInvariantUuId + "artifactName= "
653             + artifact.getArtifactName());
654     return uploadArtifactResponse;
655   }
656
657   @Override
658   public void deleteArtifact(String actionInvariantUuId, String artifactUuId, String user)
659       throws ActionException {
660     log.debug(
661         "enter deleteArtifact with actionInvariantUuId= " + actionInvariantUuId + "artifactUUID= "
662             + artifactUuId + " and user = " + user);
663     Action action = actionDao.getLockedAction(actionInvariantUuId, user);
664     List<ActionArtifact> actionArtifacts = action.getArtifacts();
665     ActionArtifact artifactMetadata =
666         getArtifactMetadataFromAction(actionArtifacts, ARTIFACT_METADATA_ATTR_UUID, artifactUuId);
667     if (artifactMetadata == null) {
668       throw new ActionException(ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST_CODE,
669           ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST);
670     }
671     if (artifactMetadata.getArtifactProtection().equals(ActionArtifactProtection.readOnly.name())) {
672       throw new ActionException(ACTION_ARTIFACT_DELETE_READ_ONLY,
673           ACTION_ARTIFACT_DELETE_READ_ONLY_MSG);
674     } else {
675
676       //Update action by removing artifact metadata
677       String jsonData = action.getData();
678       List<ActionArtifact> artifacts = action.getArtifacts();//action.getArtifacts();
679       ActionArtifact artifact = null;
680       Iterator<ActionArtifact> it = artifacts.iterator();
681       while (it.hasNext()) {
682         artifact = it.next();
683         String artifactId = artifact.getArtifactUuId();
684         if (artifactId.equals(artifactUuId)) {
685           it.remove();
686         }
687       }
688
689       Map dataMap = JsonUtil.json2Object(jsonData, LinkedHashMap.class);
690       dataMap.put("artifacts", artifacts);
691       String data = JsonUtil.object2Json(dataMap);
692       ActionEntity actionEntity = action.toEntity();
693       actionEntity.setData(data);
694       actionLogPreProcessor(ActionSubOperation.UPDATE_ACTION, TARGET_ENTITY_DB);
695       actionDao.update(actionEntity);
696       actionLogPostProcessor(StatusCode.COMPLETE, null, "", false);
697       log.metrics("");
698       // delete Artifact if it's upload and delete action on same checkout version
699       String artifactName = artifactMetadata.getArtifactName();
700       String generatedArtifactUuId = generateActionArtifactUuId(action, artifactName);
701       if (generatedArtifactUuId.equals(artifactUuId)) {
702         if (artifact != null) {
703           ActionArtifactEntity artifactDeleteEntity =
704               new ActionArtifactEntity(artifact.getArtifactUuId(),
705                   getEffectiveVersion(action.getVersion()));
706           actionLogPreProcessor(ActionSubOperation.DELETE_ACTION_ARTIFACT, TARGET_ENTITY_DB);
707           actionArtifactDao.delete(artifactDeleteEntity);
708         }
709         actionLogPostProcessor(StatusCode.COMPLETE, null, "", false);
710         log.metrics("");
711       }
712
713     }
714     log.debug(
715         "exit deleteArtifact with actionInvariantUuId= " + actionInvariantUuId + "artifactUUID= "
716             + artifactUuId + " and user = " + user);
717   }
718
719   /**
720    * Update an existing artifact.
721    *
722    * @param artifact            {@link ActionArtifact} object representing the artifact and its
723    *                            metadata
724    * @param actionInvariantUuId Invariant UUID of the action to which the artifact has to be
725    *                            uploaded
726    * @param user                User ID of the user sending the request
727    */
728   public void updateArtifact(ActionArtifact artifact, String actionInvariantUuId, String user) {
729     try {
730       log.debug("Enter updateArtifact with actionInvariantUuId= " + actionInvariantUuId
731           + "artifactUUID= " + artifact.getArtifactUuId() + " and user = " + user);
732       actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_API);
733       VersionInfo versionInfo = versioningManager
734           .getEntityVersionInfo(ACTION_VERSIONABLE_TYPE, actionInvariantUuId, user,
735               VersionableEntityAction.Write);
736       actionLogPostProcessor(StatusCode.COMPLETE, null, "", false);
737       log.metrics("");
738       Version activeVersion = versionInfo.getActiveVersion();
739       actionLogPreProcessor(ActionSubOperation.GET_ACTIONENTITY_BY_ACTIONINVID, TARGET_ENTITY_DB);
740       Action action = actionDao.get(new ActionEntity(actionInvariantUuId, activeVersion)).toDto();
741       actionLogPostProcessor(StatusCode.COMPLETE, null, "", false);
742       log.metrics("");
743       List<ActionArtifact> actionArtifacts = action.getArtifacts();
744       ActionArtifact artifactMetadataByUuId =
745           getArtifactMetadataFromAction(actionArtifacts, ARTIFACT_METADATA_ATTR_UUID,
746               artifact.getArtifactUuId());
747       //Check if artifact is already in action or not
748       if (artifactMetadataByUuId == null) {
749         throw new ActionException(ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST_CODE,
750             ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST);
751       }
752       //If user tries to change artifact name
753       if (artifact.getArtifactName() != null
754           && !artifactMetadataByUuId.getArtifactName().equalsIgnoreCase(
755           artifact.getArtifactName())) {
756         throw new ActionException(ACTION_UPDATE_NOT_ALLOWED_CODE,
757             ACTION_ARTIFACT_UPDATE_NAME_INVALID);
758       }
759
760       byte[] payload = artifact.getArtifact();
761       String artifactLabel = artifact.getArtifactLabel();
762       String artifactCategory = artifact.getArtifactCategory();
763       String artifactDescription = artifact.getArtifactDescription();
764       String artifactProtection = artifact.getArtifactProtection();
765       String artifactName = artifact.getArtifactName();
766       //If artifact read only
767       if (artifactMetadataByUuId.getArtifactProtection()
768           .equals(ActionArtifactProtection.readOnly.name())) {
769         if (artifactName != null || artifactLabel != null || artifactCategory != null
770             || artifactDescription != null || payload != null) {
771           throw new ActionException(ACTION_ARTIFACT_UPDATE_READ_ONLY,
772               ACTION_ARTIFACT_UPDATE_READ_ONLY_MSG);
773         }
774         //Changing value from readOnly to readWrite
775         if (artifactProtection != null
776             && artifactProtection.equals(ActionArtifactProtection.readWrite.name())) {
777           artifactMetadataByUuId.setArtifactProtection(ActionArtifactProtection.readWrite.name());
778           artifactMetadataByUuId.setTimestamp(getCurrentTimeStampUtc());
779           updateArtifactMetadataInActionData(action, artifactMetadataByUuId);
780         }
781       } else {
782         int effectiveVersion = getEffectiveVersion(activeVersion.toString());
783         if (artifactLabel != null) {
784           artifactMetadataByUuId.setArtifactLabel(artifactLabel);
785         }
786         if (artifactCategory != null) {
787           artifactMetadataByUuId.setArtifactCategory(artifactCategory);
788         }
789         if (artifactDescription != null) {
790           artifactMetadataByUuId.setArtifactDescription(artifactDescription);
791         }
792         if (artifactProtection != null) {
793           artifactMetadataByUuId.setArtifactProtection(artifactProtection);
794         }
795         if (payload != null) {
796           //get artifact data from action_artifact table for updating the content
797           ActionArtifact artifactContent = new ActionArtifact();
798           artifactContent.setArtifactUuId(artifact.getArtifactUuId());
799           artifactContent.setArtifact(payload);
800           artifactContent.setEffectiveVersion(effectiveVersion);
801           actionArtifactDao.updateArtifact(artifactContent);
802         }
803         //Update the action data field and timestamp
804         artifactMetadataByUuId.setTimestamp(getCurrentTimeStampUtc());
805         updateArtifactMetadataInActionData(action, artifactMetadataByUuId);
806       }
807       log.debug("exit updateArtifact with actionInvariantUuId= " + actionInvariantUuId
808           + "artifactUUID= " + artifact.getArtifactUuId() + " and user = " + user);
809     } catch (CoreException coreException) {
810       formAndThrowException(coreException);
811     }
812   }
813
814   /**
815    * Generate artifact UUID at runtime using action name and effective version.
816    *
817    * @param action       {@link Action} for which the artifact is being uploaded/updated/downloaded
818    * @param artifactName Artifact name
819    * @return Generated UUID string
820    */
821   private String generateActionArtifactUuId(Action action, String artifactName) {
822     int effectiveVersion = getEffectiveVersion(action.getVersion());
823     //Upper case for maintaining case-insensitive behavior for the artifact names
824     String artifactUuIdString =
825         action.getName().toUpperCase() + effectiveVersion + artifactName.toUpperCase();
826     String generateArtifactUuId =
827         UUID.nameUUIDFromBytes((artifactUuIdString).getBytes()).toString();
828     String artifactUuId = generateArtifactUuId.replace("-", "");
829     return artifactUuId.toUpperCase();
830   }
831
832   /**
833    * Generate the effective action version for artifact operations.
834    *
835    * @param actionVersion Version of the action as a string
836    * @return Effective version to be used for artifact operations
837    */
838   private int getEffectiveVersion(String actionVersion) {
839     Version version = Version.valueOf(actionVersion);
840     return version.getMajor() * 10000 + version.getMinor();
841   }
842
843   /**
844    * Update the data field of the Action object with the modified/generated fields after an
845    * operation.
846    *
847    * @param action Action object whose data field has to be updated
848    * @return Updated {@link Action} object
849    */
850   private Action updateData(Action action) {
851     log.debug("entering updateData to update data json for action with actionuuid=  "
852         + action.getActionUuId());
853     Map<String, String> dataMap = new LinkedHashMap<>();
854     dataMap.put(ActionConstants.UNIQUE_ID, action.getActionUuId());
855     dataMap.put(ActionConstants.VERSION, action.getVersion());
856     dataMap.put(ActionConstants.INVARIANTUUID, action.getActionInvariantUuId());
857     dataMap.put(ActionConstants.STATUS, action.getStatus().name());
858
859     String data = action.getData();
860     Map<String, String> currentDataMap = JsonUtil.json2Object(data, LinkedHashMap.class);
861     dataMap.putAll(currentDataMap);
862     data = JsonUtil.object2Json(dataMap);
863     action.setData(data);
864     log.debug("exit updateData");
865     return action;
866   }
867
868   /**
869    * Method to add the artifact metadata in the data attribute of action table.
870    *
871    * @param action   Action to which artifact is uploaded
872    * @param artifact Uploaded artifact object
873    */
874   private void addArtifactMetadataInActionData(Action action, ActionArtifact artifact) {
875
876     ActionArtifact artifactMetadata = new ActionArtifact();
877     artifactMetadata.setArtifactUuId(artifact.getArtifactUuId());
878     artifactMetadata.setArtifactName(artifact.getArtifactName());
879     artifactMetadata.setArtifactProtection(artifact.getArtifactProtection());
880     artifactMetadata.setArtifactLabel(artifact.getArtifactLabel());
881     artifactMetadata.setArtifactDescription(artifact.getArtifactDescription());
882     artifactMetadata.setArtifactCategory(artifact.getArtifactCategory());
883     artifactMetadata.setTimestamp(artifact.getTimestamp());
884
885     List<ActionArtifact> actionArtifacts = action.getArtifacts();
886     if (actionArtifacts == null) {
887       actionArtifacts = new ArrayList<>();
888     }
889     actionArtifacts.add(artifactMetadata);
890     action.setArtifacts(actionArtifacts);
891     String currentData = action.getData();
892     Map<String, Object> currentDataMap = JsonUtil.json2Object(currentData, LinkedHashMap.class);
893     currentDataMap.put(ActionConstants.ARTIFACTS, actionArtifacts);
894     String updatedActionData = JsonUtil.object2Json(currentDataMap);
895     action.setData(updatedActionData);
896     action.setTimestamp(artifact.getTimestamp());
897     actionDao.updateAction(action);
898   }
899
900   /**
901    * Get a list of last major and last minor version (no candidate) of action from a list of
902    * actions.
903    *
904    * @param actions Exhaustive list of the action versions
905    * @return List {@link Action} of last major and last minor version (no candidate) of action from
906    * a list of actions
907    */
908   private List<Action> getMajorMinorVersionActions(List<Action> actions) {
909     log.debug(" entering getMajorMinorVersionActions for actions ");
910     List<Action> list = new LinkedList<>();
911     actionLogPreProcessor(ActionSubOperation.GET_VERSIONINFO_FOR_ALL_ACTIONS, TARGET_ENTITY_API);
912     Map<String, VersionInfo> actionVersionMap = versioningManager
913         .listEntitiesVersionInfo(ACTION_VERSIONABLE_TYPE, "", VersionableEntityAction.Read);
914     actionLogPostProcessor(StatusCode.COMPLETE);
915     log.metrics("");
916     for (Action action : actions) {
917       if (action.getStatus() == ActionStatus.Deleted) {
918         continue;
919       }
920       VersionInfo actionVersionInfo = actionVersionMap.get(action.getActionInvariantUuId());
921       if (actionVersionInfo.getActiveVersion() != null
922           && actionVersionInfo.getActiveVersion().equals(Version.valueOf(action.getVersion()))) {
923         list.add(action);
924       } else if (actionVersionInfo.getLatestFinalVersion() != null
925           && actionVersionInfo.getLatestFinalVersion().equals(Version.valueOf(action.getVersion()))
926           &&
927           !actionVersionInfo.getLatestFinalVersion().equals(actionVersionInfo.getActiveVersion())) {
928         list.add(action);
929       }
930     }
931     log.debug(" exit getMajorMinorVersionActions for actions ");
932     return list;
933   }
934
935   /**
936    * CoreException object wrapper from Version library to Action Library Exception.
937    *
938    * @param exception CoreException object from version library
939    */
940   private void formAndThrowException(CoreException exception) {
941     log.debug("entering formAndThrowException with input CoreException =" + exception.code().id()
942         + " " + exception.getMessage());
943     String errorDescription = exception.getMessage();
944     String errorCode = exception.code().id();
945     ActionException actionException = new ActionException();
946     switch (errorCode) {
947       case VersioningErrorCodes.VERSIONABLE_ENTITY_NOT_EXIST:
948         actionException.setErrorCode(ACTION_ENTITY_NOT_EXIST_CODE);
949         actionException.setDescription(ACTION_ENTITY_NOT_EXIST);
950         break;
951       case VersioningErrorCodes.CHECKOT_ON_LOCKED_ENTITY:
952         actionException.setErrorCode(ACTION_CHECKOUT_ON_LOCKED_ENTITY);
953         actionException.setDescription(errorDescription);
954         break;
955       case VersioningErrorCodes.CHECKIN_ON_UNLOCKED_ENTITY:
956         actionException.setErrorCode(ACTION_CHECKIN_ON_UNLOCKED_ENTITY);
957         actionException.setDescription(errorDescription);
958         break;
959       case VersioningErrorCodes.SUBMIT_FINALIZED_ENTITY_NOT_ALLOWED:
960         actionException.setErrorCode(ACTION_SUBMIT_FINALIZED_ENTITY_NOT_ALLOWED);
961         actionException.setDescription(errorDescription);
962         break;
963       case VersioningErrorCodes.SUBMIT_LOCKED_ENTITY_NOT_ALLOWED:
964         actionException.setErrorCode(ACTION_SUBMIT_LOCKED_ENTITY_NOT_ALLOWED);
965         actionException.setDescription(errorDescription);
966         break;
967       case VersioningErrorCodes.UNDO_CHECKOUT_ON_UNLOCKED_ENTITY:
968         actionException.setErrorCode(ACTION_UNDO_CHECKOUT_ON_UNLOCKED_ENTITY);
969         actionException.setDescription(errorDescription);
970         break;
971       case VersioningErrorCodes.EDIT_ON_ENTITY_LOCKED_BY_OTHER_USER:
972         actionException.setErrorCode(ACTION_EDIT_ON_ENTITY_LOCKED_BY_OTHER_USER);
973         actionException.setDescription(errorDescription.replace("edit", "updat"));
974         break;
975       case VersioningErrorCodes.CHECKIN_ON_ENTITY_LOCKED_BY_OTHER_USER:
976         actionException.setErrorCode(ACTION_CHECKIN_ON_ENTITY_LOCKED_BY_OTHER_USER);
977         actionException.setDescription(errorDescription);
978         break;
979       case VersioningErrorCodes.UNDO_CHECKOUT_ON_ENTITY_LOCKED_BY_OTHER_USER:
980         actionException.setErrorCode(ACTION_UNDO_CHECKOUT_ON_ENTITY_LOCKED_BY_OTHER_USER);
981         actionException.setDescription(errorDescription);
982         break;
983       case VersioningErrorCodes.EDIT_ON_UNLOCKED_ENTITY:
984         actionException.setErrorCode(ACTION_UPDATE_ON_UNLOCKED_ENTITY);
985         actionException.setDescription(errorDescription.replace("edit", "update"));
986         break;
987       case VersioningErrorCodes.DELETE_ON_LOCKED_ENTITY:
988         actionException.setErrorCode(ACTION_DELETE_ON_LOCKED_ENTITY_CODE);
989         actionException.setDescription(errorDescription);
990         break;
991       default:
992         actionException.setErrorCode(ACTION_INTERNAL_SERVER_ERR_CODE);
993         actionException.setDescription(exception.getMessage());
994
995     }
996     //Todo - Uncomment only if class to be added in ERROR Log
997     /*actionErrorLogProcessor(CategoryLogLevel.ERROR, actionException.getErrorCode(),
998     actionException.getDescription());
999     log.error("");*/
1000     log.debug(
1001         "exit formAndThrowException with ActionException =" + actionException.getErrorCode()
1002             + " " + actionException.getDescription());
1003     throw actionException;
1004   }
1005
1006   /**
1007    * Validates an action object for business layer validations before an update operation.
1008    *
1009    * @param action        Action object to be validated
1010    * @param activeVersion Active version of the actoin object
1011    */
1012   private void validateActions(Action action, Version activeVersion) {
1013     try {
1014       //Set version if not already available in input request
1015       //If version set in input compare it with version from DB
1016       if (StringUtils.isEmpty(action.getVersion())) {
1017         action.setVersion(activeVersion.toString());
1018       } else {
1019         if (!activeVersion.equals(Version.valueOf(action.getVersion()))) {
1020           throw new ActionException(ACTION_UPDATE_INVALID_VERSION,
1021               String.format(ACTION_REQUESTED_VERSION_INVALID, action.getVersion()));
1022         }
1023       }
1024       String invariantUuId = action.getActionInvariantUuId();
1025       Version version = Version.valueOf(action.getVersion());
1026       Action existingAction = getActions(invariantUuId, version);
1027       if (existingAction == null || existingAction.getActionInvariantUuId() == null) {
1028         throw new ActionException(ACTION_ENTITY_NOT_EXIST_CODE, ACTION_ENTITY_NOT_EXIST);
1029       }
1030       List<String> invalidParameters = new LinkedList<>();
1031       //Prevent update of name, version and id fields
1032       if (!existingAction.getName().equals(action.getName())) {
1033         throw new ActionException(ACTION_UPDATE_NOT_ALLOWED_CODE_NAME,
1034             ACTION_UPDATE_NOT_ALLOWED_FOR_NAME);
1035       }
1036       if (!StringUtils.isEmpty(action.getActionUuId())
1037           && !existingAction.getActionUuId().equals(action.getActionUuId())) {
1038         invalidParameters.add(UNIQUE_ID);
1039       }
1040       if (action.getStatus() != null && (existingAction.getStatus() != action.getStatus())) {
1041         invalidParameters.add(STATUS);
1042       }
1043
1044       if (!invalidParameters.isEmpty()) {
1045         throw new ActionException(ACTION_UPDATE_NOT_ALLOWED_CODE,
1046             String.format(ACTION_UPDATE_PARAM_INVALID, StringUtils.join(invalidParameters, ", ")));
1047       }
1048       action.setActionUuId(existingAction.getActionUuId());
1049     } catch (IllegalArgumentException iae) {
1050       String message = iae.getMessage();
1051       if (message == VERSION_STRING_VIOLATION_MSG) {
1052         throw new ActionException(ACTION_UPDATE_NOT_ALLOWED_CODE, message);
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 }