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