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