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