2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.sdc.versioning.impl;
23 import org.openecomp.sdc.common.errors.CoreException;
24 import org.openecomp.sdc.common.errors.ErrorCategory;
25 import org.openecomp.sdc.common.errors.ErrorCode;
26 import org.openecomp.sdc.datatypes.error.ErrorLevel;
27 import org.openecomp.sdc.logging.api.Logger;
28 import org.openecomp.sdc.logging.api.LoggerFactory;
29 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
30 import org.openecomp.sdc.logging.types.LoggerConstants;
31 import org.openecomp.sdc.logging.types.LoggerErrorCode;
32 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
33 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
34 import org.openecomp.sdc.versioning.ItemManager;
35 import org.openecomp.sdc.versioning.VersionCalculator;
36 import org.openecomp.sdc.versioning.VersioningManager;
37 import org.openecomp.sdc.versioning.dao.VersionDao;
38 import org.openecomp.sdc.versioning.dao.VersionInfoDao;
39 import org.openecomp.sdc.versioning.dao.VersionInfoDeletedDao;
40 import org.openecomp.sdc.versioning.dao.VersionableEntityDaoFactory;
41 import org.openecomp.sdc.versioning.dao.types.Revision;
42 import org.openecomp.sdc.versioning.dao.types.SynchronizationState;
43 import org.openecomp.sdc.versioning.dao.types.UserCandidateVersion;
44 import org.openecomp.sdc.versioning.dao.types.Version;
45 import org.openecomp.sdc.versioning.dao.types.VersionInfoDeletedEntity;
46 import org.openecomp.sdc.versioning.dao.types.VersionInfoEntity;
47 import org.openecomp.sdc.versioning.dao.types.VersionStatus;
48 import org.openecomp.sdc.versioning.errors.CheckinOnEntityLockedByOtherErrorBuilder;
49 import org.openecomp.sdc.versioning.errors.CheckinOnUnlockedEntityErrorBuilder;
50 import org.openecomp.sdc.versioning.errors.CheckoutOnLockedEntityErrorBuilder;
51 import org.openecomp.sdc.versioning.errors.DeleteOnLockedEntityErrorBuilder;
52 import org.openecomp.sdc.versioning.errors.EditOnEntityLockedByOtherErrorBuilder;
53 import org.openecomp.sdc.versioning.errors.EditOnUnlockedEntityErrorBuilder;
54 import org.openecomp.sdc.versioning.errors.EntityAlreadyExistErrorBuilder;
55 import org.openecomp.sdc.versioning.errors.EntityAlreadyFinalizedErrorBuilder;
56 import org.openecomp.sdc.versioning.errors.EntityNotExistErrorBuilder;
57 import org.openecomp.sdc.versioning.errors.SubmitLockedEntityNotAllowedErrorBuilder;
58 import org.openecomp.sdc.versioning.errors.UndoCheckoutOnEntityLockedByOtherErrorBuilder;
59 import org.openecomp.sdc.versioning.errors.UndoCheckoutOnUnlockedEntityErrorBuilder;
60 import org.openecomp.sdc.versioning.types.VersionCreationMethod;
61 import org.openecomp.sdc.versioning.types.VersionInfo;
62 import org.openecomp.sdc.versioning.types.VersionableEntityAction;
63 import org.openecomp.sdc.versioning.types.VersionableEntityMetadata;
66 import java.util.Collection;
67 import java.util.HashMap;
68 import java.util.HashSet;
69 import java.util.List;
72 import java.util.stream.Collectors;
74 public class VersioningManagerImpl implements VersioningManager {
75 private static final Logger LOGGER = LoggerFactory.getLogger(VersioningManagerImpl.class);
76 private static final Version INITIAL_ACTIVE_VERSION = new Version(0, 0);
77 private static final Map<String, Set<VersionableEntityMetadata>> VERSIONABLE_ENTITIES =
80 private final VersionInfoDao versionInfoDao;
81 private final VersionInfoDeletedDao versionInfoDeletedDao;
82 private VersionDao versionDao;
83 private VersionCalculator versionCalculator;
84 private ItemManager itemManager;
86 public VersioningManagerImpl(VersionInfoDao versionInfoDao,
87 VersionInfoDeletedDao versionInfoDeletedDao,
88 VersionDao versionDao,
89 VersionCalculator versionCalculator,
90 ItemManager itemManager) {
91 this.versionInfoDao = versionInfoDao;
92 this.versionInfoDeletedDao = versionInfoDeletedDao;
93 this.versionDao = versionDao;
94 this.versionCalculator = versionCalculator;
95 this.itemManager = itemManager;
98 private static VersionInfo getVersionInfo(VersionInfoEntity versionInfoEntity, String user,
99 VersionableEntityAction action) {
100 return getVersionInfo(versionInfoEntity.getEntityId(),
101 versionInfoEntity.getEntityType(),
102 versionInfoEntity.getActiveVersion(),
103 versionInfoEntity.getCandidate(),
104 versionInfoEntity.getStatus(),
105 versionInfoEntity.getLatestFinalVersion(),
106 versionInfoEntity.getViewableVersions(),
111 private static VersionInfo getVersionInfo(VersionInfoDeletedEntity versionInfoEntity, String user,
112 VersionableEntityAction action) {
113 return getVersionInfo(versionInfoEntity.getEntityId(),
114 versionInfoEntity.getEntityType(),
115 versionInfoEntity.getActiveVersion(),
116 versionInfoEntity.getCandidate(),
117 versionInfoEntity.getStatus(),
118 versionInfoEntity.getLatestFinalVersion(),
119 versionInfoEntity.getViewableVersions(),
124 private static VersionInfo getVersionInfo(String entityId, String entityType, Version activeVer,
125 UserCandidateVersion candidate, VersionStatus status,
126 Version latestFinalVersion,
127 Set<Version> viewableVersions,
128 VersionableEntityAction action, String user) {
129 Version activeVersion;
131 if (action == VersionableEntityAction.Write) {
132 if (candidate != null) {
133 if (user.equals(candidate.getUser())) {
134 activeVersion = candidate.getVersion();
136 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
137 LoggerTragetServiceName.GET_VERSION_INFO, ErrorLevel.ERROR.name(),
138 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't get entity version info");
139 throw new CoreException(
140 new EditOnEntityLockedByOtherErrorBuilder(entityType, entityId, candidate.getUser())
144 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
145 LoggerTragetServiceName.GET_VERSION_INFO, ErrorLevel.ERROR.name(),
146 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't get entity version info");
147 throw new CoreException(new EditOnUnlockedEntityErrorBuilder(entityType, entityId).build());
150 if (candidate != null && user.equals(candidate.getUser())) {
151 activeVersion = candidate.getVersion();
153 activeVersion = activeVer;
157 VersionInfo versionInfo = new VersionInfo();
158 versionInfo.setStatus(status);
159 activeVersion.setStatus(status);
160 if (latestFinalVersion != null) {
161 latestFinalVersion.setStatus(status);
163 if (viewableVersions != null) {
164 viewableVersions.forEach(version -> version.setStatus(status));
166 versionInfo.setActiveVersion(activeVersion);
167 versionInfo.setLatestFinalVersion(latestFinalVersion);
168 versionInfo.setViewableVersions(toSortedList(viewableVersions));
169 versionInfo.setFinalVersions(getFinalVersions(viewableVersions));
170 if (candidate != null) {
171 candidate.getVersion().setStatus(status);
172 versionInfo.setLockingUser(candidate.getUser());
173 if (user.equals(candidate.getUser())) {
174 versionInfo.getViewableVersions().add(candidate.getVersion());
180 private static List<Version> toSortedList(
181 Set<Version> versions) { // changing the Set to List in DB will require migration...
182 return versions.stream().sorted((o1, o2) -> o1.getMajor() > o2.getMajor() ? 1
183 : o1.getMajor() == o2.getMajor() ? (o1.getMinor() > o2.getMinor() ? 1
184 : o1.getMinor() == o2.getMinor() ? 0 : -1) : -1).collect(Collectors.toList());
187 private static List<Version> getFinalVersions(Set<Version> versions) {
188 return versions.stream().filter(Version::isFinal).collect(Collectors.toList());
192 public void register(String entityType, VersionableEntityMetadata entityMetadata) {
193 Set<VersionableEntityMetadata> entitiesMetadata =
194 VERSIONABLE_ENTITIES.computeIfAbsent(entityType, k -> new HashSet<>());
195 entitiesMetadata.add(entityMetadata);
199 public Version create(String entityType, String entityId, String user) {
201 versionInfoEntity = versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
202 if (versionInfoEntity != null) {
203 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
204 LoggerTragetServiceName.CREATE_ENTITY, ErrorLevel.ERROR.name(),
205 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't create versionable entity");
206 throw new CoreException(new EntityAlreadyExistErrorBuilder(entityType, entityId).build());
209 versionInfoEntity = new VersionInfoEntity(entityType, entityId);
210 versionInfoEntity.setActiveVersion(INITIAL_ACTIVE_VERSION);
211 markAsCheckedOut(versionInfoEntity, user);
212 versionInfoDao.create(versionInfoEntity);
214 return versionInfoEntity.getCandidate().getVersion();
218 public void delete(String entityType, String entityId, String user) {
219 VersionInfoEntity versionInfoEntity =
220 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
221 if (versionInfoEntity == null) {
222 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
223 LoggerTragetServiceName.DELETE_ENTITY, ErrorLevel.ERROR.name(),
224 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't delete versionable entity");
225 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
228 switch (versionInfoEntity.getStatus()) {
230 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
231 LoggerTragetServiceName.DELETE_ENTITY, ErrorLevel.ERROR.name(),
232 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't delete versionable entity");
233 throw new CoreException(new DeleteOnLockedEntityErrorBuilder(entityType, entityId,
234 versionInfoEntity.getCandidate().getUser()).build());
240 doDelete(versionInfoEntity);
244 public void undoDelete(String entityType, String entityId, String user) {
245 VersionInfoDeletedEntity versionInfoDeletedEntity =
246 versionInfoDeletedDao.get(new VersionInfoDeletedEntity(entityType, entityId));
247 if (versionInfoDeletedEntity == null) {
248 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
249 LoggerTragetServiceName.UNDO_DELETE_ENTITY, ErrorLevel.ERROR.name(),
250 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't undo delete for versionable entity");
251 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
254 doUndoDelete(versionInfoDeletedEntity);
258 public Version checkout(String entityType, String entityId, String user) {
259 VersionInfoEntity versionInfoEntity =
260 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
261 MDC.put(LoggerConstants.TARGET_SERVICE_NAME, LoggerTragetServiceName.CHECKOUT_ENTITY);
262 if (versionInfoEntity == null) {
263 MDC.put(LoggerConstants.ERROR_CATEGORY, ErrorLevel.ERROR.name());
264 MDC.put(LoggerConstants.TARGET_ENTITY, LoggerConstants.TARGET_ENTITY_DB);
265 MDC.put(LoggerConstants.ERROR_DESCRIPTION, LoggerErrorDescription.CHECKOUT_ENTITY);
266 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
269 Version checkoutVersion = null;
270 switch (versionInfoEntity.getStatus()) {
272 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
273 LoggerTragetServiceName.CHECKOUT_ENTITY, ErrorLevel.ERROR.name(),
274 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't checkout versionable entity");
275 throw new CoreException(new CheckoutOnLockedEntityErrorBuilder(entityType, entityId,
276 versionInfoEntity.getCandidate().getUser()).build());
279 checkoutVersion = doCheckout(versionInfoEntity, user);
286 return checkoutVersion;
290 public Version undoCheckout(String entityType, String entityId, String user) {
291 VersionInfoEntity versionInfoEntity =
292 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
293 if (versionInfoEntity == null) {
294 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
295 LoggerTragetServiceName.UNDO_CHECKOUT_ENTITY, ErrorLevel.ERROR.name(),
296 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't undo checkout for versionable entity");
297 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
300 Version activeVersion = null;
301 switch (versionInfoEntity.getStatus()) {
303 if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
304 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
305 LoggerTragetServiceName.UNDO_CHECKOUT_ENTITY, ErrorLevel.ERROR.name(),
306 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(),
307 "Can't undo checkout for versionable entity");
308 throw new CoreException(
309 new UndoCheckoutOnEntityLockedByOtherErrorBuilder(entityType, entityId,
310 versionInfoEntity.getCandidate().getUser()).build());
312 activeVersion = undoCheckout(versionInfoEntity);
316 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
317 LoggerTragetServiceName.UNDO_CHECKOUT_ENTITY, ErrorLevel.ERROR.name(),
318 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(),
319 "Can't undo checkout for versionable entity");
320 throw new CoreException(
321 new UndoCheckoutOnUnlockedEntityErrorBuilder(entityType, entityId).build());
327 return activeVersion;
330 private Version undoCheckout(VersionInfoEntity versionInfoEntity) {
331 deleteVersionFromEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
332 versionInfoEntity.getCandidate().getVersion(), versionInfoEntity.getActiveVersion());
335 .setStatus(versionInfoEntity.getActiveVersion().isFinal() ? VersionStatus.Certified
336 : VersionStatus.Draft);
337 versionInfoEntity.setCandidate(null);
338 versionInfoDao.update(versionInfoEntity);
339 return versionInfoEntity.getActiveVersion();
343 public Version checkin(String entityType, String entityId, String user,
344 String checkinDescription) {
345 VersionInfoEntity versionInfoEntity =
346 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
347 if (versionInfoEntity == null) {
348 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
349 LoggerTragetServiceName.CHECKIN_ENTITY, ErrorLevel.ERROR.name(),
350 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't checkin versionable entity");
351 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
354 Version checkedInVersion = null;
355 switch (versionInfoEntity.getStatus()) {
358 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
359 LoggerTragetServiceName.CHECKIN_ENTITY, ErrorLevel.ERROR.name(),
360 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't checkin versionable entity");
361 throw new CoreException(
362 new CheckinOnUnlockedEntityErrorBuilder(entityType, entityId).build());
364 if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
365 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
366 LoggerTragetServiceName.CHECKIN_ENTITY, ErrorLevel.ERROR.name(),
367 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't checkin versionable entity");
368 throw new CoreException(new CheckinOnEntityLockedByOtherErrorBuilder(entityType, entityId,
369 versionInfoEntity.getCandidate().getUser()).build());
371 checkedInVersion = doCheckin(versionInfoEntity, checkinDescription);
378 return checkedInVersion;
382 public Version submit(String entityType, String entityId, String user, String submitDescription) {
383 VersionInfoEntity versionInfoEntity =
384 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
385 if (versionInfoEntity == null) {
386 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
387 LoggerTragetServiceName.SUBMIT_ENTITY, ErrorLevel.ERROR.name(),
388 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't submit versionable entity");
389 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
392 Version submitVersion = null;
393 switch (versionInfoEntity.getStatus()) {
395 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
396 LoggerTragetServiceName.SUBMIT_ENTITY, ErrorLevel.ERROR.name(),
397 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't submit versionable entity");
398 throw new CoreException(
399 new EntityAlreadyFinalizedErrorBuilder(entityType, entityId).build());
401 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
402 LoggerTragetServiceName.SUBMIT_ENTITY, ErrorLevel.ERROR.name(),
403 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't submit versionable entity");
404 throw new CoreException(new SubmitLockedEntityNotAllowedErrorBuilder(entityType, entityId,
405 versionInfoEntity.getCandidate().getUser()).build());
407 submitVersion = doSubmit(versionInfoEntity, user, submitDescription);
414 return submitVersion;
418 public VersionInfo getEntityVersionInfo(String entityType, String entityId, String user,
419 VersionableEntityAction action) {
420 VersionInfoEntity versionInfoEntity =
421 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
422 if (versionInfoEntity == null) {
423 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
424 LoggerTragetServiceName.GET_VERSION_INFO, ErrorLevel.ERROR.name(),
425 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't get entity version info");
426 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
428 return getVersionInfo(versionInfoEntity, user, action);
432 public Map<String, VersionInfo> listEntitiesVersionInfo(String entityType, String user,
433 VersionableEntityAction action) {
434 Collection<VersionInfoEntity> versionInfoEntities =
435 versionInfoDao.list(new VersionInfoEntity(entityType, null));
436 Map<String, VersionInfo> activeVersions = new HashMap<>();
437 for (VersionInfoEntity versionInfoEntity : versionInfoEntities) {
439 .put(versionInfoEntity.getEntityId(), getVersionInfo(versionInfoEntity, user, action));
441 return activeVersions;
445 public Map<String, VersionInfo> listDeletedEntitiesVersionInfo(String entityType, String user,
446 VersionableEntityAction action) {
447 Collection<VersionInfoDeletedEntity> versionInfoDeletedEntities =
448 versionInfoDeletedDao.list(new VersionInfoDeletedEntity(entityType, null));
449 Map<String, VersionInfo> activeVersions = new HashMap<>();
452 for (VersionInfoDeletedEntity versionInfoDeletedEntity : versionInfoDeletedEntities) {
453 activeVersions.put(versionInfoDeletedEntity.getEntityId(),
454 getVersionInfo(versionInfoDeletedEntity, user, action));
456 return activeVersions;
460 public List<Version> list(String itemId) {
462 List<Version> versions = versionDao.list(itemId);
463 Set<String> versionsNames = versions.stream().map(Version::getName).collect(Collectors.toSet());
464 versions.forEach(version -> {
465 version.setAdditionalInfo(new HashMap<>());
466 versionCalculator.injectAdditionalInfo(version, versionsNames);
472 public Version get(String itemId, Version version) {
473 return versionDao.get(itemId, version)
474 .map(retrievedVersion -> getUpdateRetrievedVersion(itemId, retrievedVersion))
475 .orElseGet(() -> getSyncedVersion(itemId, version));
478 private Version getUpdateRetrievedVersion(String itemId, Version version) {
479 if (version.getStatus() == VersionStatus.Certified &&
480 (version.getState().getSynchronizationState() == SynchronizationState.OutOfSync ||
481 version.getState().isDirty())) {
482 forceSync(itemId, version);
483 LOGGER.info("Item Id {}, version Id {}: Force sync is done", itemId, version.getId());
484 version = versionDao.get(itemId, version)
485 .orElseThrow(() -> new IllegalStateException(
486 "Get version after a successful force sync must return the version"));
491 private Version getSyncedVersion(String itemId, Version version) {
492 sync(itemId, version);
493 LOGGER.info("Item Id {}, version Id {}: First time sync is done", itemId, version.getId());
494 return versionDao.get(itemId, version)
495 .orElseThrow(() -> new IllegalStateException(
496 "Get version after a successful sync must return the version"));
500 public Version create(String itemId, Version version, VersionCreationMethod creationMethod) {
501 String baseVersionName = null;
502 if (version.getBaseId() == null) {
503 version.setDescription("Initial version");
505 baseVersionName = get(itemId, new Version(version.getBaseId())).getName();
507 String versionName = versionCalculator.calculate(baseVersionName, creationMethod);
508 validateVersionName(itemId, versionName);
509 version.setName(versionName);
511 versionDao.create(itemId, version);
512 itemManager.updateVersionStatus(itemId, VersionStatus.Draft, null);
514 publish(itemId, version, String.format("Create version: %s", version.getName()));
518 private void validateVersionName(String itemId, String versionName) {
519 if (versionDao.list(itemId).stream()
520 .anyMatch(version -> versionName.equals(version.getName()))) {
521 String errorDescription = String
522 .format("Item %s: create version failed, a version with the name %s already exist",
523 itemId, versionName);
525 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY,
526 LoggerTragetServiceName.CREATE_VERSION, ErrorLevel.ERROR.name(),
527 LoggerErrorCode.DATA_ERROR.getErrorCode(), errorDescription);
529 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
530 .withCategory(ErrorCategory.APPLICATION)
531 .withId("VERSION_NAME_ALREADY_EXIST")
532 .withMessage(errorDescription)
538 public void submit(String itemId, Version version, String submitDescription) {
539 version = get(itemId, version);
541 validateSubmit(itemId, version);
543 version.setStatus(VersionStatus.Certified);
544 versionDao.update(itemId, version);
546 publish(itemId, version, submitDescription);
548 itemManager.updateVersionStatus(itemId, VersionStatus.Certified, VersionStatus.Draft);
551 private void validateSubmit(String itemId, Version version) {
552 if (version.getStatus() == VersionStatus.Certified) {
553 String errorDescription = String
554 .format("Item %s: submit version failed, version %s is already Certified", itemId,
557 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
558 LoggerTragetServiceName.SUBMIT_ENTITY, ErrorLevel.ERROR.name(),
559 LoggerErrorCode.DATA_ERROR.getErrorCode(), errorDescription);
561 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
562 .withCategory(ErrorCategory.APPLICATION)
563 .withId("VERSION_ALREADY_CERTIFIED")
564 .withMessage(errorDescription)
570 public void publish(String itemId, Version version, String message) {
571 versionDao.publish(itemId, version, message);
576 public void sync(String itemId, Version version) {
577 versionDao.sync(itemId, version);
581 public void forceSync(String itemId, Version version) {
582 versionDao.forceSync(itemId, version);
586 public void revert(String itemId, Version version, String revisionId) {
587 versionDao.revert(itemId, version, revisionId);
591 public List<Revision> listRevisions(String itemId, Version version) {
592 return versionDao.listRevisions(itemId, version);
595 private void markAsCheckedOut(VersionInfoEntity versionInfoEntity, String checkingOutUser) {
596 versionInfoEntity.setStatus(VersionStatus.Locked);
597 versionInfoEntity.setCandidate(new UserCandidateVersion(checkingOutUser,
598 versionInfoEntity.getActiveVersion().calculateNextCandidate()));
601 private Version doCheckout(VersionInfoEntity versionInfoEntity, String user) {
602 markAsCheckedOut(versionInfoEntity, user);
603 versionInfoDao.update(versionInfoEntity);
605 initVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
606 versionInfoEntity.getActiveVersion(), versionInfoEntity.getCandidate().getVersion());
608 return versionInfoEntity.getCandidate().getVersion();
611 private void doDelete(VersionInfoEntity versionInfoEntity) {
612 VersionInfoDeletedEntity versionInfoDeletedEntity = new VersionInfoDeletedEntity();
613 versionInfoDeletedEntity.setStatus(versionInfoEntity.getStatus());
614 versionInfoDeletedEntity.setViewableVersions(versionInfoEntity.getViewableVersions());
615 versionInfoDeletedEntity.setActiveVersion(versionInfoEntity.getActiveVersion());
616 versionInfoDeletedEntity.setCandidate(versionInfoEntity.getCandidate());
617 versionInfoDeletedEntity.setEntityId(versionInfoEntity.getEntityId());
618 versionInfoDeletedEntity.setEntityType(versionInfoEntity.getEntityType());
619 versionInfoDeletedEntity.setLatestFinalVersion(versionInfoEntity.getLatestFinalVersion());
620 versionInfoDeletedDao.create(versionInfoDeletedEntity);
621 versionInfoDao.delete(versionInfoEntity);
624 private void doUndoDelete(VersionInfoDeletedEntity versionInfoDeletedEntity) {
625 VersionInfoEntity versionInfoEntity = new VersionInfoEntity();
626 versionInfoEntity.setStatus(versionInfoDeletedEntity.getStatus());
627 versionInfoEntity.setViewableVersions(versionInfoDeletedEntity.getViewableVersions());
628 versionInfoEntity.setActiveVersion(versionInfoDeletedEntity.getActiveVersion());
629 versionInfoEntity.setCandidate(versionInfoDeletedEntity.getCandidate());
630 versionInfoEntity.setEntityId(versionInfoDeletedEntity.getEntityId());
631 versionInfoEntity.setEntityType(versionInfoDeletedEntity.getEntityType());
632 versionInfoEntity.setLatestFinalVersion(versionInfoDeletedEntity.getLatestFinalVersion());
633 versionInfoDao.create(versionInfoEntity);
634 versionInfoDeletedDao.delete(versionInfoDeletedEntity);
637 private Version doCheckin(VersionInfoEntity versionInfoEntity, String checkinDescription) {
638 UserCandidateVersion userCandidateVersion = versionInfoEntity.getCandidate();
639 versionInfoEntity.setCandidate(null);
640 versionInfoEntity.setActiveVersion(userCandidateVersion.getVersion());
641 versionInfoEntity.getViewableVersions().add(versionInfoEntity.getActiveVersion());
642 versionInfoEntity.setStatus(VersionStatus.Draft);
644 closeVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
645 versionInfoEntity.getActiveVersion());
647 versionInfoDao.update(versionInfoEntity);
649 return versionInfoEntity.getActiveVersion();
652 private Version doSubmit(VersionInfoEntity versionInfoEntity, String submittingUser,
653 String submitDescription) {
654 Version finalVersion = versionInfoEntity.getActiveVersion().calculateNextFinal();
655 initVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
656 versionInfoEntity.getActiveVersion(), finalVersion);
657 closeVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
660 Set<Version> viewableVersions = new HashSet<>();
661 for (Version version : versionInfoEntity.getViewableVersions()) {
662 if (version.isFinal()) {
663 viewableVersions.add(version);
666 viewableVersions.add(finalVersion);
667 versionInfoEntity.setViewableVersions(viewableVersions);
668 versionInfoEntity.setActiveVersion(finalVersion);
669 versionInfoEntity.setLatestFinalVersion(finalVersion);
670 versionInfoEntity.setStatus(VersionStatus.Certified);
671 versionInfoDao.update(versionInfoEntity);
676 private void initVersionOnEntity(String entityType, String entityId, Version baseVersion,
677 Version newVersion) {
678 Set<VersionableEntityMetadata> entityMetadatas = VERSIONABLE_ENTITIES.get(entityType);
679 if (entityMetadatas != null) {
680 for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
681 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
682 .initVersion(entityMetadata, entityId, baseVersion, newVersion);
687 private void deleteVersionFromEntity(String entityType, String entityId,
688 Version versionToDelete, Version backToVersion) {
689 Set<VersionableEntityMetadata> entityMetadatas = VERSIONABLE_ENTITIES.get(entityType);
690 if (entityMetadatas != null) {
691 for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
692 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
693 .deleteVersion(entityMetadata, entityId, versionToDelete, backToVersion);
698 private void closeVersionOnEntity(String entityType, String entityId, Version versionToClose) {
699 Set<VersionableEntityMetadata> entityMetadatas = VERSIONABLE_ENTITIES.get(entityType);
700 if (entityMetadatas != null) {
701 for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
702 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
703 .closeVersion(entityMetadata, entityId, versionToClose);