f9b6bfe8a9754ec20c9ce291877d9e276b29a776
[sdc.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.action.impl;
22
23 import static org.openecomp.sdc.action.ActionConstants.ACTION_VERSIONABLE_TYPE;
24 import static org.openecomp.sdc.action.ActionConstants.ARTIFACT_METADATA_ATTR_NAME;
25 import static org.openecomp.sdc.action.ActionConstants.ARTIFACT_METADATA_ATTR_UUID;
26 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_CATEGORY;
27 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_OPEN_ECOMP_COMPONENT;
28 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_MODEL;
29 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_NAME;
30 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_NONE;
31 import static org.openecomp.sdc.action.ActionConstants.FILTER_TYPE_VENDOR;
32 import static org.openecomp.sdc.action.ActionConstants.SERVICE_INSTANCE_ID;
33 import static org.openecomp.sdc.action.ActionConstants.STATUS;
34 import static org.openecomp.sdc.action.ActionConstants.TARGET_ENTITY_API;
35 import static org.openecomp.sdc.action.ActionConstants.TARGET_ENTITY_DB;
36 import static org.openecomp.sdc.action.ActionConstants.UNIQUE_ID;
37 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_ALREADY_EXISTS;
38 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_ALREADY_EXISTS_CODE;
39 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_DELETE_READ_ONLY;
40 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_DELETE_READ_ONLY_MSG;
41 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_UPDATE_NAME_INVALID;
42 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_UPDATE_READ_ONLY;
43 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ARTIFACT_UPDATE_READ_ONLY_MSG;
44 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_CHECKIN_ON_ENTITY_LOCKED_BY_OTHER_USER;
45 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_CHECKIN_ON_UNLOCKED_ENTITY;
46 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_CHECKOUT_ON_LOCKED_ENTITY;
47 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_CHECKOUT_ON_LOCKED_ENTITY_OTHER_USER;
48 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_DELETE_ON_LOCKED_ENTITY_CODE;
49 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_EDIT_ON_ENTITY_LOCKED_BY_OTHER_USER;
50 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_NOT_EXIST;
51 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_NOT_EXIST_CODE;
52 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_UNIQUE_VALUE_ERROR;
53 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_ENTITY_UNIQUE_VALUE_MSG;
54 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_INTERNAL_SERVER_ERR_CODE;
55 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_REQUESTED_VERSION_INVALID;
56 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_SUBMIT_FINALIZED_ENTITY_NOT_ALLOWED;
57 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_SUBMIT_LOCKED_ENTITY_NOT_ALLOWED;
58 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UNDO_CHECKOUT_ON_ENTITY_LOCKED_BY_OTHER_USER;
59 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UNDO_CHECKOUT_ON_UNLOCKED_ENTITY;
60 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_INVALID_VERSION;
61 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_NOT_ALLOWED_CODE;
62 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_NOT_ALLOWED_CODE_NAME;
63 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_NOT_ALLOWED_FOR_NAME;
64 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_ON_UNLOCKED_ENTITY;
65 import static org.openecomp.sdc.action.errors.ActionErrorConstants.ACTION_UPDATE_PARAM_INVALID;
66 import static org.openecomp.sdc.action.util.ActionUtil.actionLogPostProcessor;
67 import static org.openecomp.sdc.action.util.ActionUtil.actionLogPreProcessor;
68 import static org.openecomp.sdc.action.util.ActionUtil.getCurrentTimeStampUtc;
69 import static org.openecomp.sdc.versioning.dao.types.Version.VERSION_STRING_VIOLATION_MSG;
70
71 import org.apache.commons.collections4.CollectionUtils;
72 import org.apache.commons.lang.StringUtils;
73 import org.openecomp.sdc.action.types.*;
74 import org.openecomp.sdc.logging.api.Logger;
75 import org.openecomp.sdc.logging.api.LoggerFactory;
76 import org.openecomp.core.util.UniqueValueUtil;
77 import org.openecomp.core.utilities.CommonMethods;
78 import org.openecomp.core.utilities.json.JsonUtil;
79 import org.openecomp.sdc.action.ActionConstants;
80 import org.openecomp.sdc.action.ActionManager;
81 import org.openecomp.sdc.action.dao.ActionArtifactDao;
82 import org.openecomp.sdc.action.dao.ActionArtifactDaoFactory;
83 import org.openecomp.sdc.action.dao.ActionDao;
84 import org.openecomp.sdc.action.dao.ActionDaoFactory;
85 import org.openecomp.sdc.action.dao.types.ActionArtifactEntity;
86 import org.openecomp.sdc.action.dao.types.ActionEntity;
87 import org.openecomp.sdc.action.errors.ActionErrorConstants;
88 import org.openecomp.sdc.action.errors.ActionException;
89 import org.openecomp.sdc.action.logging.StatusCode;
90 import org.openecomp.sdc.action.types.OpenEcompComponent;
91 import org.openecomp.sdc.common.errors.CoreException;
92 import org.openecomp.sdc.versioning.VersioningManager;
93 import org.openecomp.sdc.versioning.VersioningManagerFactory;
94 import org.openecomp.sdc.versioning.dao.VersionInfoDao;
95 import org.openecomp.sdc.versioning.dao.VersionInfoDaoFactory;
96 import org.openecomp.sdc.versioning.dao.types.UserCandidateVersion;
97 import org.openecomp.sdc.versioning.dao.types.Version;
98 import org.openecomp.sdc.versioning.dao.types.VersionInfoEntity;
99 import org.openecomp.sdc.versioning.errors.EntityNotExistErrorBuilder;
100 import org.openecomp.sdc.versioning.errors.VersioningErrorCodes;
101 import org.openecomp.sdc.versioning.types.VersionInfo;
102 import org.openecomp.sdc.versioning.types.VersionableEntityAction;
103 import org.slf4j.MDC;
104
105 import java.util.ArrayList;
106 import java.util.Collections;
107 import java.util.Iterator;
108 import java.util.LinkedHashMap;
109 import java.util.LinkedList;
110 import java.util.List;
111 import java.util.Map;
112 import java.util.UUID;
113
114 /**
115  * Manager Implementation for {@link ActionManager Action Library Operations} <br> Handles Business
116  * layer validations and acts as an interface between the REST and DAO layers.
117  */
118 public class ActionManagerImpl implements ActionManager {
119
120   private static final ActionDao actionDao = ActionDaoFactory.getInstance().createInterface();
121   private static final VersioningManager versioningManager =
122       VersioningManagerFactory.getInstance().createInterface();
123   private static final ActionArtifactDao actionArtifactDao =
124       ActionArtifactDaoFactory.getInstance().createInterface();
125   private static VersionInfoDao versionInfoDao =
126       VersionInfoDaoFactory.getInstance().createInterface();
127
128   private final Logger log = (Logger) LoggerFactory.getLogger(this.getClass().getName());
129
130   public ActionManagerImpl() {
131     actionDao.registerVersioning(ACTION_VERSIONABLE_TYPE);
132   }
133
134   /**
135    * List All Major, Last Minor and Candidate version (if any) for Given Action Invariant UUID
136    *
137    * @param invariantId Invariant UUID of the action for which the information is required
138    * @return List of All Major, Last Minor and Candidate version if any Of {@link Action} with given
139      actionInvariantUuId.
140    * @throws ActionException Exception with an action library specific code, short description and
141    *                         detailed message for the error occurred during the operation
142    */
143
144   @Override
145   public List<Action> getActionsByActionInvariantUuId(String invariantId) throws ActionException {
146     List<Action> actions;
147
148     log.debug(" entering getActionsByActionInvariantUuId with  invariantID = " + invariantId);
149     actions = actionDao
150         .getActionsByActionInvariantUuId(invariantId != null ? invariantId.toUpperCase() : null);
151
152     if (actions != null && actions.isEmpty()) {
153       throw new ActionException(ACTION_ENTITY_NOT_EXIST_CODE, ACTION_ENTITY_NOT_EXIST);
154     }
155
156     log.debug(" exit getActionsByActionInvariantUuId with  invariantID = " + invariantId);
157     return actions;
158   }
159
160   /**
161    * Get list of actions based on a filter criteria. If no filter is sent all actions will be
162    * returned
163    *
164    * @param filterType  Filter by Vendor/Category/Model/Component/None
165    * @param filterValue Filter Parameter Value (Vendor ID/Category ID/Model ID/Component ID)
166    * @return List of {@link Action} objects based on a filter criteria <br> Empty List if no records
167      match the provided filter criteria
168    * @throws ActionException Exception with an action library specific code, short description and
169    *                         detailed message for the error occurred for the error occurred during
170    *                         the operation
171    */
172   @Override
173   public List<Action> getFilteredActions(String filterType, String filterValue)
174       throws ActionException {
175     List<Action> actions;
176     log.debug(" entering getFilteredActions By filterType = " + filterType + " With value = "
177         + filterValue);
178     switch (filterType) {
179       case FILTER_TYPE_NONE:
180         //Business validation for OPENECOMP Component type fetch (if any)
181         break;
182       case FILTER_TYPE_VENDOR:
183         //Business validation for vendor type fetch (if any)
184         break;
185       case FILTER_TYPE_CATEGORY:
186         //Business validation for Category type fetch (if any)
187         break;
188       case FILTER_TYPE_MODEL:
189         //Business validation for model type fetch (if any)
190         break;
191       case FILTER_TYPE_OPEN_ECOMP_COMPONENT:
192         //Business validation for OPENECOMP Component type fetch (if any)
193         break;
194       case FILTER_TYPE_NAME:
195         actions = actionDao
196             .getFilteredActions(filterType, filterValue != null ? filterValue.toLowerCase() : null);
197         if (actions != null && actions.isEmpty()) {
198           throw new ActionException(ACTION_ENTITY_NOT_EXIST_CODE, ACTION_ENTITY_NOT_EXIST);
199         }
200         log.debug(" exit getFilteredActions By filterType = " + filterType + " With value = "
201             + filterValue);
202         return actions;
203       default:
204         break;
205     }
206     actions = actionDao
207         .getFilteredActions(filterType, filterValue != null ? filterValue.toLowerCase() : null);
208     List<Action> majorMinorVersionList = getMajorMinorVersionActions(actions);
209     Collections.sort(majorMinorVersionList);
210     log.debug(
211         " exit getFilteredActions By filterType = " + filterType + " With value = " + filterValue);
212     return majorMinorVersionList;
213   }
214
215   /**
216    * Get the properties of an action version by its UUID.
217    *
218    * @param actionUuId UUID of the specific action version
219    * @return {@link Action} object corresponding the version represented by the UUID
220    * @throws ActionException Exception with an action library specific code, short description and
221    *                         detailed message for the error occurred for the error occurred during
222    *                         the operation
223    */
224   @Override
225   public Action getActionsByActionUuId(String actionUuId) throws ActionException {
226     log.debug(" entering getActionsByActionUuId with  actionUUID = " + actionUuId);
227     Action action =
228         actionDao.getActionsByActionUuId(actionUuId != null ? actionUuId.toUpperCase() : null);
229
230     if (action == null) {
231       throw new ActionException(ACTION_ENTITY_NOT_EXIST_CODE, ACTION_ENTITY_NOT_EXIST);
232     }
233
234     log.debug(" exit getActionsByActionUuId with  actionUUID = " + actionUuId);
235     return action;
236   }
237
238   /**
239    * List OPENECOMP Components supported by Action Library.
240    *
241    * @return List of {@link OpenEcompComponent} objects supported by Action Library <br> Empty List if
242      no components are found
243    * @throws ActionException Exception with an action library specific code, short description and
244    *                         detailed message for the error occurred for the error occurred during
245    *                         the operation
246    */
247   @Override
248   public List<OpenEcompComponent> getOpenEcompComponents() throws ActionException {
249     return actionDao.getOpenEcompComponents();
250   }
251
252
253   /**
254    * Delete an action.
255    *
256    * @param actionInvariantUuId Invariant UUID of the action to be deleted
257    * @param user                User id of the user performing the operation
258    */
259   @Override
260   public void deleteAction(String actionInvariantUuId, String user) throws ActionException {
261     try {
262       log.debug("entering deleteAction with actionInvariantUuId = " + actionInvariantUuId
263           + " and user = " + user);
264       actionLogPreProcessor(ActionSubOperation.DELETE_ACTION, TARGET_ENTITY_API);
265       versioningManager.delete(ACTION_VERSIONABLE_TYPE, actionInvariantUuId, user);
266       actionLogPostProcessor(StatusCode.COMPLETE);
267       log.metrics("");
268       actionDao.deleteAction(actionInvariantUuId);
269     } catch (CoreException ce) {
270       formAndThrowException(ce);
271     }
272   }
273
274   /**
275    * Create a new Action.
276    *
277    * @param action Action object model of the user request for creating an action
278    * @param user   AT&T id of the user sending the create request
279    * @return {@link Action} model object for the created action
280    * @throws ActionException Exception with an action library specific code, short description and
281    *                         detailed message for the error occurred for the error occurred during
282    *                         the operation
283    */
284   @Override
285   public Action createAction(Action action, String user) throws ActionException {
286     try {
287       actionLogPreProcessor(ActionSubOperation.VALIDATE_ACTION_UNIQUE_NAME, TARGET_ENTITY_API);
288       UniqueValueUtil
289           .validateUniqueValue(ActionConstants.UniqueValues.ACTION_NAME, action.getName());
290       actionLogPostProcessor(StatusCode.COMPLETE);
291     } catch (CoreException exception) {
292       String errorDesc = String
293           .format(ACTION_ENTITY_UNIQUE_VALUE_MSG, ActionConstants.UniqueValues.ACTION_NAME,
294               action.getName());
295       log.error(errorDesc, exception);
296       actionLogPostProcessor(StatusCode.ERROR, ACTION_ENTITY_UNIQUE_VALUE_ERROR, errorDesc, false);
297       throw new ActionException(ACTION_ENTITY_UNIQUE_VALUE_ERROR, errorDesc);
298     } finally {
299       log.metrics("");
300     }
301     action.setUser(user);
302     action.setTimestamp(getCurrentTimeStampUtc());
303     action.setActionInvariantUuId(CommonMethods.nextUuId());
304     action.setActionUuId(CommonMethods.nextUuId());
305
306     actionLogPreProcessor(ActionSubOperation.CREATE_ACTION_VERSION, TARGET_ENTITY_API);
307     Version version =
308         versioningManager.create(ACTION_VERSIONABLE_TYPE, action.getActionInvariantUuId(), user);
309     actionLogPostProcessor(StatusCode.COMPLETE);
310     log.metrics("");
311
312     action.setVersion(version.toString());
313     action.setStatus(ActionStatus.Locked);
314     action = updateData(action);
315     action = actionDao.createAction(action);
316
317     actionLogPreProcessor(ActionSubOperation.CREATE_ACTION_UNIQUE_VALUE, TARGET_ENTITY_API);
318     UniqueValueUtil.createUniqueValue(ActionConstants.UniqueValues.ACTION_NAME, action.getName());
319     actionLogPostProcessor(StatusCode.COMPLETE);
320     log.metrics("");
321
322     return action;
323   }
324
325   /**
326    * Update an existing action.
327    *
328    * @param action Action object model of the user request for creating an action
329    * @param user   AT&T id of the user sending the update request
330    * @return {@link Action} model object for the update action
331    * @throws ActionException Exception with an action library specific code, short description and
332    *                         detailed message for the error occurred for the error occurred during
333    *                         the operation
334    */
335   @Override
336   public Action updateAction(Action action, String user) throws ActionException {
337     try {
338       log.debug("entering updateAction to update action with invariantUuId = "
339           + action.getActionInvariantUuId() + " by user = " + user);
340       String invariantUuId = action.getActionInvariantUuId();
341       actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_API);
342       VersionInfo versionInfo = versioningManager
343           .getEntityVersionInfo(ACTION_VERSIONABLE_TYPE, invariantUuId, user,
344               VersionableEntityAction.Write);
345       actionLogPostProcessor(StatusCode.COMPLETE);
346       log.metrics("");
347
348       Version activeVersion = versionInfo.getActiveVersion();
349       validateActions(action, activeVersion);
350       action.setStatus(ActionStatus.Locked); //Status will be Checkout for update
351       updateData(action);
352       action.setUser(user);
353       action.setTimestamp(getCurrentTimeStampUtc());
354       actionDao.updateAction(action);
355
356     } catch (CoreException ce) {
357       formAndThrowException(ce);
358     }
359     log.debug("exit updateAction");
360     return action;
361   }
362
363   /**
364    * Checkout an existing action.
365    *
366    * @param invariantUuId actionInvariantUuId of the action to be checked out
367    * @param user          AT&T id of the user sending the checkout request
368    * @return {@link Action} model object for the checkout action
369    * @throws ActionException Exception with an action library specific code, short description and
370    *                         detailed message for the error occurred for the error occurred during
371    *                         the operation
372    */
373   @Override
374   public Action checkout(String invariantUuId, String user) throws ActionException {
375     Version version = null;
376     ActionEntity actionEntity = null;
377     try {
378       log.debug(
379           "entering checkout for Action with invariantUUID= " + invariantUuId + " by user = "
380               + user);
381       actionLogPreProcessor(ActionSubOperation.CHECKOUT_ACTION, TARGET_ENTITY_API);
382       version = versioningManager.checkout(ACTION_VERSIONABLE_TYPE, invariantUuId, user);
383       actionLogPostProcessor(StatusCode.COMPLETE);
384       log.metrics("");
385
386       actionEntity =
387           updateUniqueIdForVersion(invariantUuId, version, ActionStatus.Locked.name(), user);
388     } catch (CoreException exception) {
389       if (exception.code() != null && exception.code().id().equals(
390           VersioningErrorCodes.CHECKOT_ON_LOCKED_ENTITY)) {
391         actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_DB);
392         VersionInfoEntity versionInfoEntity =
393             versionInfoDao.get(new VersionInfoEntity(ACTION_VERSIONABLE_TYPE, invariantUuId));
394         actionLogPostProcessor(StatusCode.COMPLETE);
395         log.metrics("");
396         String checkoutUser = versionInfoEntity.getCandidate().getUser();
397         log.debug(
398             "Actual checkout user for Action with invariantUUID= " + invariantUuId + " is = "
399                 + checkoutUser);
400         if (!checkoutUser.equals(user)) {
401           throw new ActionException(ACTION_CHECKOUT_ON_LOCKED_ENTITY_OTHER_USER,
402               exception.getMessage());
403         }
404       }
405       formAndThrowException(exception);
406     }
407     log.debug(
408         "exit checkout for Action with invariantUUID= " + invariantUuId + " by user = " + user);
409     return actionEntity != null ? actionEntity.toDto() : new Action();
410   }
411
412   /**
413    * Undo an already checked out action.
414    *
415    * @param invariantUuId actionInvariantUuId of the checked out action
416    * @param user          AT&T id of the user sending the request
417    * @throws ActionException Exception with an action library specific code, short description and
418    *                         detailed message for the error occurred for the error occurred during
419    *                         the operation
420    */
421   @Override
422   public void undoCheckout(String invariantUuId, String user) throws ActionException {
423     Version version;
424     try {
425       log.debug(
426           "entering undoCheckout for Action with invariantUUID= " + invariantUuId + " by user = "
427               + user);
428
429       actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_DB);
430       //Get list of uploaded artifacts in this checked out version
431       VersionInfoEntity versionInfoEntity =
432           versionInfoDao.get(new VersionInfoEntity(ACTION_VERSIONABLE_TYPE, invariantUuId));
433       actionLogPostProcessor(StatusCode.COMPLETE);
434       log.metrics("");
435       if (versionInfoEntity == null) {
436         throw new CoreException(
437             new EntityNotExistErrorBuilder(ACTION_VERSIONABLE_TYPE, invariantUuId).build());
438       }
439       UserCandidateVersion candidate = versionInfoEntity.getCandidate();
440       Version activeVersion;
441       if (candidate != null) {
442         activeVersion = candidate.getVersion();
443       } else {
444         activeVersion = versionInfoEntity.getActiveVersion();
445       }
446
447       actionLogPreProcessor(ActionSubOperation.GET_ACTIONENTITY_BY_VERSION, TARGET_ENTITY_DB);
448       Action action = actionDao.get(new ActionEntity(invariantUuId, activeVersion)).toDto();
449       actionLogPostProcessor(StatusCode.COMPLETE);
450       log.metrics("");
451
452       //Perform undo checkout on the action
453       actionLogPreProcessor(ActionSubOperation.UNDO_CHECKOUT_ACTION, TARGET_ENTITY_API);
454       version = versioningManager.undoCheckout(ACTION_VERSIONABLE_TYPE, invariantUuId, user);
455       actionLogPostProcessor(StatusCode.COMPLETE);
456       log.metrics("");
457
458       if (version.equals(new Version(0, 0))) {
459         actionLogPreProcessor(ActionSubOperation.DELETE_UNIQUEVALUE, TARGET_ENTITY_API);
460         UniqueValueUtil
461             .deleteUniqueValue(ActionConstants.UniqueValues.ACTION_NAME, action.getName());
462         actionLogPostProcessor(StatusCode.COMPLETE);
463         log.metrics("");
464
465         actionLogPreProcessor(ActionSubOperation.DELETE_ACTIONVERSION, TARGET_ENTITY_DB);
466         //Added for the case where Create->Undo_Checkout->Checkout should not get the action
467         versionInfoDao.delete(new VersionInfoEntity(ACTION_VERSIONABLE_TYPE, invariantUuId));
468         actionLogPostProcessor(StatusCode.COMPLETE);
469         log.metrics("");
470       }
471
472       List<ActionArtifact> currentVersionArtifacts = action.getArtifacts();
473
474       //Delete the artifacts from action_artifact table (if any)
475       if (CollectionUtils.isNotEmpty(currentVersionArtifacts) && currentVersionArtifacts.size() > 0) {
476         for (ActionArtifact artifact : currentVersionArtifacts) {
477           ActionArtifactEntity artifactDeleteEntity =
478               new ActionArtifactEntity(artifact.getArtifactUuId(),
479                   getEffectiveVersion(activeVersion.toString()));
480           actionLogPreProcessor(ActionSubOperation.DELETE_ARTIFACT, TARGET_ENTITY_DB);
481           actionArtifactDao.delete(artifactDeleteEntity);
482           actionLogPostProcessor(StatusCode.COMPLETE);
483           log.metrics("");
484         }
485       }
486     } catch (CoreException exception) {
487       formAndThrowException(exception);
488     }
489     log.debug(
490         "exit undoCheckout for Action with invariantUUID= " + invariantUuId + " by user = " + user);
491   }
492
493   /**
494    * Checkin a checked out action.
495    *
496    * @param invariantUuId actionInvariantUuId of the checked out action
497    * @param user          AT&T id of the user sending the request
498    * @return {@link Action} model object for the updated action
499    * @throws ActionException Exception with an action library specific code, short description and
500    *                         detailed message for the error occurred for the error occurred during
501    *                         the operation
502    */
503   @Override
504   public Action checkin(String invariantUuId, String user) throws ActionException {
505     Version version = null;
506     ActionEntity actionEntity = null;
507     try {
508       log.debug("entering checkin for Action with invariantUUID= " + invariantUuId + " by user = "
509           + user);
510       actionLogPreProcessor(ActionSubOperation.CHECKIN_ACTION, TARGET_ENTITY_API);
511       version = versioningManager.checkin(ACTION_VERSIONABLE_TYPE, invariantUuId, user, null);
512       actionLogPostProcessor(StatusCode.COMPLETE);
513       log.metrics("");
514       actionEntity =
515           updateStatusForVersion(invariantUuId, version, ActionStatus.Available.name(), user);
516     } catch (CoreException exception) {
517       formAndThrowException(exception);
518     }
519     log.debug(
520         "exit checkin for Action with invariantUUID= " + invariantUuId + " by user = " + user);
521     return actionEntity != null ? actionEntity.toDto() : new Action();
522   }
523
524   /**
525    * Submit a checked in action.
526    *
527    * @param invariantUuId actionInvariantUuId of the checked in action
528    * @param user          AT&T id of the user sending the request
529    * @return {@link Action} model object for the updated action
530    * @throws ActionException Exception with an action library specific code, short description and
531    *                         detailed message for the error occurred for the error occurred during
532    *                         the operation
533    */
534   @Override
535   public Action submit(String invariantUuId, String user) throws ActionException {
536     Version version = null;
537     ActionEntity actionEntity = null;
538     try {
539       log.debug(
540           "entering submit for Action with invariantUUID= " + invariantUuId + " by user = " + user);
541       actionLogPreProcessor(ActionSubOperation.SUBMIT_ACTION, TARGET_ENTITY_API);
542       version = versioningManager.submit(ACTION_VERSIONABLE_TYPE, invariantUuId, user, null);
543       actionLogPostProcessor(StatusCode.COMPLETE);
544       log.metrics("");
545       actionEntity =
546           updateUniqueIdForVersion(invariantUuId, version, ActionStatus.Final.name(), user);
547     } catch (CoreException exception) {
548       formAndThrowException(exception);
549     }
550     log.debug("exit submit for Action with invariantUUID= " + invariantUuId + " by user = " + user);
551     return actionEntity != null ? actionEntity.toDto() : new Action();
552   }
553
554   /**
555    * Download an artifact of an action.
556    *
557    * @param artifactUuId {@link ActionArtifact} object representing the artifact and its metadata
558    * @param actionUuId   UUID of the action for which the artifact has to be downloaded
559    * @return downloaded action artifact object
560    */
561   @Override
562   public ActionArtifact downloadArtifact(String actionUuId, String artifactUuId)
563       throws ActionException {
564     log.debug(" entering downloadArtifact with actionUUID= " + actionUuId + " and artifactUUID= "
565         + artifactUuId);
566     Action action = actionDao.getActionsByActionUuId(actionUuId);
567     ActionArtifact actionArtifact;
568     if (action != null) {
569       MDC.put(SERVICE_INSTANCE_ID, action.getActionInvariantUuId());
570       List<ActionArtifact> artifacts = action.getArtifacts();
571       String actionVersion = action.getVersion();
572       int effectiveVersion = getEffectiveVersion(actionVersion);
573       ActionArtifact artifactMetadata =
574           getArtifactMetadataFromAction(artifacts, ARTIFACT_METADATA_ATTR_UUID, artifactUuId);
575       if (artifactMetadata != null) {
576         String artifactName = artifactMetadata.getArtifactName();
577         actionArtifact = actionArtifactDao.downloadArtifact(effectiveVersion, artifactUuId);
578         actionArtifact.setArtifactName(artifactName);
579
580       } else {
581         throw new ActionException(ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST_CODE,
582             ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST);
583       }
584     } else {
585       throw new ActionException(ActionErrorConstants.ACTION_ENTITY_NOT_EXIST_CODE,
586           ActionErrorConstants.ACTION_ENTITY_NOT_EXIST);
587     }
588     log.debug(" exit downloadArtifact with actionUUID= " + actionUuId + " and artifactUUID= "
589         + artifactUuId);
590     return actionArtifact;
591   }
592
593   /**
594    * Upload an artifact to an action.
595    *
596    * @param artifact            {@link ActionArtifact} object representing the artifact and its
597    *                            metadata
598    * @param actionInvariantUuId Invariant UUID of the action to which the artifact has to be
599    *                            uploaded
600    * @param user                User ID of the user sending the request
601    * @return Uploaded action artifact object
602    */
603   @Override
604   public ActionArtifact uploadArtifact(ActionArtifact artifact, String actionInvariantUuId,
605                                        String user) {
606     ActionArtifact uploadArtifactResponse = new ActionArtifact();
607     try {
608       log.debug("entering uploadArtifact with actionInvariantUuId= " + actionInvariantUuId
609           + "artifactName= " + artifact.getArtifactName());
610       actionLogPreProcessor(ActionSubOperation.GET_ACTION_VERSION, TARGET_ENTITY_DB);
611       VersionInfo versionInfo = versioningManager
612           .getEntityVersionInfo(ACTION_VERSIONABLE_TYPE, actionInvariantUuId, user,
613               VersionableEntityAction.Write);
614       actionLogPostProcessor(StatusCode.COMPLETE);
615       log.metrics("");
616       Version activeVersion = versionInfo.getActiveVersion();
617       actionLogPreProcessor(ActionSubOperation.GET_ACTIONENTITY_BY_ACTIONINVID, TARGET_ENTITY_DB);
618       Action action = actionDao.get(new ActionEntity(actionInvariantUuId, activeVersion)).toDto();
619       actionLogPostProcessor(StatusCode.COMPLETE);
620       log.metrics("");
621       String artifactUuId = generateActionArtifactUuId(action, artifact.getArtifactName());
622       //Check for Unique document name
623       List<ActionArtifact> actionArtifacts = action.getArtifacts();
624       ActionArtifact artifactMetadata =
625           getArtifactMetadataFromAction(actionArtifacts, ARTIFACT_METADATA_ATTR_NAME,
626               artifact.getArtifactName());
627       if (artifactMetadata != null) {
628         throw new ActionException(ACTION_ARTIFACT_ALREADY_EXISTS_CODE,
629             String.format(ACTION_ARTIFACT_ALREADY_EXISTS, actionInvariantUuId));
630       }
631
632       //Create the artifact
633       artifact.setArtifactUuId(artifactUuId);
634       artifact.setTimestamp(getCurrentTimeStampUtc());
635       artifact.setEffectiveVersion(getEffectiveVersion(activeVersion.toString()));
636       actionArtifactDao.uploadArtifact(artifact);
637
638       //Update the action data field and timestamp
639       addArtifactMetadataInActionData(action, artifact);
640
641       //Set the response object
642       uploadArtifactResponse.setArtifactUuId(artifact.getArtifactUuId());
643     } catch (CoreException ce) {
644       formAndThrowException(ce);
645     }
646     log.debug(
647         "exit uploadArtifact with actionInvariantUuId= " + actionInvariantUuId + "artifactName= "
648             + artifact.getArtifactName());
649     return uploadArtifactResponse;
650   }
651
652   @Override
653   public void deleteArtifact(String actionInvariantUuId, String artifactUuId, String user)
654       throws ActionException {
655     log.debug(
656         "enter deleteArtifact with actionInvariantUuId= " + actionInvariantUuId + "artifactUUID= "
657             + artifactUuId + " and user = " + user);
658     Action action = actionDao.getLockedAction(actionInvariantUuId, user);
659     List<ActionArtifact> actionArtifacts = action.getArtifacts();
660     ActionArtifact artifactMetadata =
661         getArtifactMetadataFromAction(actionArtifacts, ARTIFACT_METADATA_ATTR_UUID, artifactUuId);
662     if (artifactMetadata == null) {
663       throw new ActionException(ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST_CODE,
664           ActionErrorConstants.ACTION_ARTIFACT_ENTITY_NOT_EXIST);
665     }
666     if (artifactMetadata.getArtifactProtection().equals(ActionArtifactProtection.readOnly.name())) {
667       throw new ActionException(ACTION_ARTIFACT_DELETE_READ_ONLY,
668           ACTION_ARTIFACT_DELETE_READ_ONLY_MSG);
669     } else {
670
671       //Update action by removing artifact metadata
672       String jsonData = action.getData();
673       List<ActionArtifact> artifacts = action.getArtifacts();//action.getArtifacts();
674       ActionArtifact artifact = null;
675       Iterator<ActionArtifact> it = artifacts.iterator();
676       while (it.hasNext()) {
677         artifact = it.next();
678         String artifactId = artifact.getArtifactUuId();
679         if (artifactId.equals(artifactUuId)) {
680           it.remove();
681         }
682       }
683
684       Map dataMap = JsonUtil.json2Object(jsonData, LinkedHashMap.class);
685       dataMap.put("artifacts", artifacts);
686       String data = JsonUtil.object2Json(dataMap);
687       ActionEntity actionEntity = action.toEntity();
688       actionEntity.setData(data);
689       actionLogPreProcessor(ActionSubOperation.UPDATE_ACTION, TARGET_ENTITY_DB);
690       actionDao.update(actionEntity);
691       actionLogPostProcessor(StatusCode.COMPLETE, null, "", false);
692       log.metrics("");
693       // delete Artifact if it's upload and delete action on same checkout version
694       String artifactName = artifactMetadata.getArtifactName();
695       String generatedArtifactUuId = generateActionArtifactUuId(action, artifactName);
696       if (generatedArtifactUuId.equals(artifactUuId)) {
697         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       }
1049       else {
1050         throw iae;
1051       }
1052     }
1053   }
1054
1055   /**
1056    * Get an action version entity object.
1057    *
1058    * @param invariantUuId Invariant UUID of the action
1059    * @param version       Version of the action
1060    * @return {@link ActionEntity} object of the action version
1061    */
1062   private ActionEntity getActionsEntityByVersion(String invariantUuId, Version version) {
1063     log.debug(
1064         "entering getActionsEntityByVersion with invariantUUID= " + invariantUuId + " and version"
1065             + version);
1066     ActionEntity entity = null;
1067     if (version != null) {
1068       actionLogPreProcessor(ActionSubOperation.GET_ACTIONENTITY_BY_VERSION, TARGET_ENTITY_DB);
1069       entity = actionDao.get(
1070           new ActionEntity(invariantUuId != null ? invariantUuId.toUpperCase() : null, version));
1071       actionLogPostProcessor(StatusCode.COMPLETE);
1072       log.metrics("");
1073     }
1074     log.debug(
1075         "exit getActionsEntityByVersion with invariantUuId= " + invariantUuId + " and version"
1076             + version);
1077     return entity;
1078   }
1079
1080   /**
1081    * Get an action version object.
1082    *
1083    * @param invariantUuId Invariant UUID of the action
1084    * @param version       Version of the action
1085    * @return {@link Action} object of the action version
1086    */
1087   private Action getActions(String invariantUuId, Version version) {
1088     ActionEntity actionEntity =
1089         getActionsEntityByVersion(invariantUuId != null ? invariantUuId.toUpperCase() : null,
1090             version);
1091     return actionEntity != null ? actionEntity.toDto() : new Action();
1092   }
1093
1094   /**
1095    * Create and set the Unique ID in for an action version row.
1096    *
1097    * @param invariantUuId Invariant UUID of the action
1098    * @param version       Version of the action
1099    * @param status        Status of the action
1100    * @param user          AT&T id of the user sending the request
1101    * @return {@link ActionEntity} object of the action version
1102    */
1103   private ActionEntity updateUniqueIdForVersion(String invariantUuId, Version version,
1104                                                 String status, String user) {
1105     log.debug(
1106         "entering updateUniqueIdForVersion to update action with invariantUuId= " + invariantUuId
1107             + " with version,status and user as ::" + version + " " + status + " " + user);
1108     //generate UUID AND update for newly created entity row
1109     ActionEntity actionEntity = getActionsEntityByVersion(invariantUuId, version);
1110     if (actionEntity != null) {
1111       log.debug("Found action to be updated");
1112       String data = actionEntity.getData();
1113       String uniqueId = CommonMethods.nextUuId();
1114       Map<String, String> dataMap = JsonUtil.json2Object(data, LinkedHashMap.class);
1115       dataMap.put(ActionConstants.UNIQUE_ID, uniqueId);
1116       dataMap.put(ActionConstants.VERSION, version.toString());
1117       dataMap.put(ActionConstants.STATUS, status);
1118       data = JsonUtil.object2Json(dataMap);
1119
1120       actionEntity.setData(data);
1121       actionEntity.setActionUuId(uniqueId);
1122       actionEntity.setStatus(status);
1123       actionEntity.setUser(user);
1124       actionEntity.setTimestamp(getCurrentTimeStampUtc());
1125       actionLogPreProcessor(ActionSubOperation.UPDATE_ACTION, TARGET_ENTITY_DB);
1126       actionDao.update(actionEntity);
1127       actionLogPostProcessor(StatusCode.COMPLETE);
1128       log.metrics("");
1129     }
1130
1131     log.debug(
1132         "exit updateUniqueIdForVersion to update action with invariantUUID= " + invariantUuId);
1133     return actionEntity;
1134   }
1135
1136   /**
1137    * Set the status for an action version row.
1138    *
1139    * @param invariantUuId Invariant UUID of the action
1140    * @param version       Version of the action
1141    * @param status        Status of the action
1142    * @param user          AT&T id of the user sending the request
1143    * @return {@link ActionEntity} object of the action version
1144    */
1145   private ActionEntity updateStatusForVersion(String invariantUuId, Version version, String status,
1146                                               String user) {
1147     log.debug(
1148         "entering updateStatusForVersion with invariantUuId= " + invariantUuId + " and version"
1149             + version + " for updating status " + status + " by user " + user);
1150     ActionEntity actionEntity = getActionsEntityByVersion(invariantUuId, version);
1151     if (actionEntity != null) {
1152       String data = actionEntity.getData();
1153       Map<String, String> dataMap = JsonUtil.json2Object(data, LinkedHashMap.class);
1154       dataMap.put(ActionConstants.STATUS, status);
1155       data = JsonUtil.object2Json(dataMap);
1156       actionEntity.setData(data);
1157       actionEntity.setStatus(status);
1158       actionEntity.setUser(user);
1159       actionEntity.setTimestamp(getCurrentTimeStampUtc());
1160       actionLogPreProcessor(ActionSubOperation.UPDATE_ACTION, TARGET_ENTITY_DB);
1161       actionDao.update(actionEntity);
1162       actionLogPostProcessor(StatusCode.COMPLETE);
1163       log.metrics("");
1164     }
1165     log.debug("exit updateStatusForVersion with invariantUuId= " + invariantUuId + " and version"
1166         + version + " for updating status " + status + " by user " + user);
1167     return actionEntity;
1168
1169   }
1170
1171   /**
1172    * Gets an artifact from the action artifact metadata by artifact name.
1173    *
1174    * @param actionArtifactList  Action's existing artifact list
1175    * @param artifactFilterType  Search criteria for artifact in action artifact metadata
1176    * @param artifactFilterValue Value of Search parameter
1177    * @return Artifact metadata object if artifact is present in action and null otherwise
1178    */
1179   private ActionArtifact getArtifactMetadataFromAction(List<ActionArtifact> actionArtifactList,
1180                                                        String artifactFilterType,
1181                                                        String artifactFilterValue) {
1182     ActionArtifact artifact = null;
1183     if (actionArtifactList != null && !actionArtifactList.isEmpty()) {
1184       for (ActionArtifact entry : actionArtifactList) {
1185         switch (artifactFilterType) {
1186           case ARTIFACT_METADATA_ATTR_UUID:
1187             String artifactUuId = entry.getArtifactUuId();
1188             if (artifactUuId != null && artifactUuId.equals(artifactFilterValue)) {
1189               artifact = entry;
1190               break;
1191             }
1192             break;
1193           case ARTIFACT_METADATA_ATTR_NAME:
1194             String existingArtifactName = entry.getArtifactName().toLowerCase();
1195             if (existingArtifactName.equals(artifactFilterValue.toLowerCase())) {
1196               artifact = entry;
1197               break;
1198             }
1199             break;
1200           default:
1201         }
1202       }
1203     }
1204     return artifact;
1205   }
1206
1207   /**
1208    * Method to update the artifact metadata in the data attribute of action table.
1209    *
1210    * @param action          Action to which artifact is uploaded
1211    * @param updatedArtifact updated artifact object
1212    */
1213   private void updateArtifactMetadataInActionData(Action action, ActionArtifact updatedArtifact) {
1214     for (ActionArtifact entry : action.getArtifacts()) {
1215       if (entry.getArtifactUuId().equals(updatedArtifact.getArtifactUuId())) {
1216         entry.setArtifactLabel(updatedArtifact.getArtifactLabel());
1217         entry.setArtifactCategory(updatedArtifact.getArtifactCategory());
1218         entry.setArtifactDescription(updatedArtifact.getArtifactDescription());
1219         entry.setArtifactProtection(updatedArtifact.getArtifactProtection());
1220         entry.setTimestamp(updatedArtifact.getTimestamp());
1221         break;
1222       }
1223     }
1224     String data = action.getData();
1225     Map<String, Object> map = JsonUtil.json2Object(data, LinkedHashMap.class);
1226     map.put(ActionConstants.ARTIFACTS, action.getArtifacts());
1227     String updatedActionData = JsonUtil.object2Json(map);
1228     action.setData(updatedActionData);
1229     action.setTimestamp(updatedArtifact.getTimestamp());
1230     actionDao.updateAction(action);
1231   }
1232 }