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.MdcDataDebugMessage;
30 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
31 import org.openecomp.sdc.logging.types.LoggerConstants;
32 import org.openecomp.sdc.logging.types.LoggerErrorCode;
33 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
34 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
35 import org.openecomp.sdc.versioning.ItemManager;
36 import org.openecomp.sdc.versioning.VersionCalculator;
37 import org.openecomp.sdc.versioning.VersioningManager;
38 import org.openecomp.sdc.versioning.dao.VersionDao;
39 import org.openecomp.sdc.versioning.dao.VersionInfoDao;
40 import org.openecomp.sdc.versioning.dao.VersionInfoDeletedDao;
41 import org.openecomp.sdc.versioning.dao.VersionableEntityDaoFactory;
42 import org.openecomp.sdc.versioning.dao.types.Revision;
43 import org.openecomp.sdc.versioning.dao.types.SynchronizationState;
44 import org.openecomp.sdc.versioning.dao.types.UserCandidateVersion;
45 import org.openecomp.sdc.versioning.dao.types.Version;
46 import org.openecomp.sdc.versioning.dao.types.VersionInfoDeletedEntity;
47 import org.openecomp.sdc.versioning.dao.types.VersionInfoEntity;
48 import org.openecomp.sdc.versioning.dao.types.VersionStatus;
49 import org.openecomp.sdc.versioning.errors.CheckinOnEntityLockedByOtherErrorBuilder;
50 import org.openecomp.sdc.versioning.errors.CheckinOnUnlockedEntityErrorBuilder;
51 import org.openecomp.sdc.versioning.errors.CheckoutOnLockedEntityErrorBuilder;
52 import org.openecomp.sdc.versioning.errors.DeleteOnLockedEntityErrorBuilder;
53 import org.openecomp.sdc.versioning.errors.EditOnEntityLockedByOtherErrorBuilder;
54 import org.openecomp.sdc.versioning.errors.EditOnUnlockedEntityErrorBuilder;
55 import org.openecomp.sdc.versioning.errors.EntityAlreadyExistErrorBuilder;
56 import org.openecomp.sdc.versioning.errors.EntityAlreadyFinalizedErrorBuilder;
57 import org.openecomp.sdc.versioning.errors.EntityNotExistErrorBuilder;
58 import org.openecomp.sdc.versioning.errors.SubmitLockedEntityNotAllowedErrorBuilder;
59 import org.openecomp.sdc.versioning.errors.UndoCheckoutOnEntityLockedByOtherErrorBuilder;
60 import org.openecomp.sdc.versioning.errors.UndoCheckoutOnUnlockedEntityErrorBuilder;
61 import org.openecomp.sdc.versioning.types.VersionCreationMethod;
62 import org.openecomp.sdc.versioning.types.VersionInfo;
63 import org.openecomp.sdc.versioning.types.VersionableEntityAction;
64 import org.openecomp.sdc.versioning.types.VersionableEntityMetadata;
67 import java.util.Collection;
68 import java.util.HashMap;
69 import java.util.HashSet;
70 import java.util.List;
73 import java.util.stream.Collectors;
75 public class VersioningManagerImpl implements VersioningManager {
76 private static final Logger LOGGER = LoggerFactory.getLogger(VersioningManagerImpl.class);
77 private static final Version INITIAL_ACTIVE_VERSION = new Version(0, 0);
78 private static final MdcDataDebugMessage MDC_DATA_DEBUG_MESSAGE = new MdcDataDebugMessage();
79 private static final Map<String, Set<VersionableEntityMetadata>> VERSIONABLE_ENTITIES =
82 private final VersionInfoDao versionInfoDao;
83 private final VersionInfoDeletedDao versionInfoDeletedDao;
84 private VersionDao versionDao;
85 private VersionCalculator versionCalculator;
86 private ItemManager itemManager;
88 public VersioningManagerImpl(VersionInfoDao versionInfoDao,
89 VersionInfoDeletedDao versionInfoDeletedDao,
90 VersionDao versionDao,
91 VersionCalculator versionCalculator,
92 ItemManager itemManager) {
93 this.versionInfoDao = versionInfoDao;
94 this.versionInfoDeletedDao = versionInfoDeletedDao;
95 this.versionDao = versionDao;
96 this.versionCalculator = versionCalculator;
97 this.itemManager = itemManager;
100 private static VersionInfo getVersionInfo(VersionInfoEntity versionInfoEntity, String user,
101 VersionableEntityAction action) {
102 return getVersionInfo(versionInfoEntity.getEntityId(),
103 versionInfoEntity.getEntityType(),
104 versionInfoEntity.getActiveVersion(),
105 versionInfoEntity.getCandidate(),
106 versionInfoEntity.getStatus(),
107 versionInfoEntity.getLatestFinalVersion(),
108 versionInfoEntity.getViewableVersions(),
113 private static VersionInfo getVersionInfo(VersionInfoDeletedEntity versionInfoEntity, String user,
114 VersionableEntityAction action) {
115 return getVersionInfo(versionInfoEntity.getEntityId(),
116 versionInfoEntity.getEntityType(),
117 versionInfoEntity.getActiveVersion(),
118 versionInfoEntity.getCandidate(),
119 versionInfoEntity.getStatus(),
120 versionInfoEntity.getLatestFinalVersion(),
121 versionInfoEntity.getViewableVersions(),
126 private static VersionInfo getVersionInfo(String entityId, String entityType, Version activeVer,
127 UserCandidateVersion candidate, VersionStatus status,
128 Version latestFinalVersion,
129 Set<Version> viewableVersions,
130 VersionableEntityAction action, String user) {
133 MDC_DATA_DEBUG_MESSAGE.debugEntryMessage("entity Id", entityId);
135 Version activeVersion;
137 if (action == VersionableEntityAction.Write) {
138 if (candidate != null) {
139 if (user.equals(candidate.getUser())) {
140 activeVersion = candidate.getVersion();
142 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
143 LoggerTragetServiceName.GET_VERSION_INFO, ErrorLevel.ERROR.name(),
144 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't get entity version info");
145 throw new CoreException(
146 new EditOnEntityLockedByOtherErrorBuilder(entityType, entityId, candidate.getUser())
150 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
151 LoggerTragetServiceName.GET_VERSION_INFO, ErrorLevel.ERROR.name(),
152 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't get entity version info");
153 throw new CoreException(new EditOnUnlockedEntityErrorBuilder(entityType, entityId).build());
156 if (candidate != null && user.equals(candidate.getUser())) {
157 activeVersion = candidate.getVersion();
159 activeVersion = activeVer;
163 VersionInfo versionInfo = new VersionInfo();
164 versionInfo.setStatus(status);
165 activeVersion.setStatus(status);
166 if (latestFinalVersion != null) {
167 latestFinalVersion.setStatus(status);
169 if (viewableVersions != null) {
170 viewableVersions.forEach(version -> version.setStatus(status));
172 versionInfo.setActiveVersion(activeVersion);
173 versionInfo.setLatestFinalVersion(latestFinalVersion);
174 versionInfo.setViewableVersions(toSortedList(viewableVersions));
175 versionInfo.setFinalVersions(getFinalVersions(viewableVersions));
176 if (candidate != null) {
177 candidate.getVersion().setStatus(status);
178 versionInfo.setLockingUser(candidate.getUser());
179 if (user.equals(candidate.getUser())) {
180 versionInfo.getViewableVersions().add(candidate.getVersion());
184 MDC_DATA_DEBUG_MESSAGE.debugExitMessage("entity Id", entityId);
188 private static List<Version> toSortedList(
189 Set<Version> versions) { // changing the Set to List in DB will require migration...
190 return versions.stream().sorted((o1, o2) -> o1.getMajor() > o2.getMajor() ? 1
191 : o1.getMajor() == o2.getMajor() ? (o1.getMinor() > o2.getMinor() ? 1
192 : o1.getMinor() == o2.getMinor() ? 0 : -1) : -1).collect(Collectors.toList());
195 private static List<Version> getFinalVersions(Set<Version> versions) {
196 return versions.stream().filter(Version::isFinal).collect(Collectors.toList());
200 public void register(String entityType, VersionableEntityMetadata entityMetadata) {
201 Set<VersionableEntityMetadata> entitiesMetadata =
202 VERSIONABLE_ENTITIES.computeIfAbsent(entityType, k -> new HashSet<>());
203 entitiesMetadata.add(entityMetadata);
207 public Version create(String entityType, String entityId, String user) {
209 versionInfoEntity = versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
210 if (versionInfoEntity != null) {
211 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
212 LoggerTragetServiceName.CREATE_ENTITY, ErrorLevel.ERROR.name(),
213 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't create versionable entity");
214 throw new CoreException(new EntityAlreadyExistErrorBuilder(entityType, entityId).build());
217 versionInfoEntity = new VersionInfoEntity(entityType, entityId);
218 versionInfoEntity.setActiveVersion(INITIAL_ACTIVE_VERSION);
219 markAsCheckedOut(versionInfoEntity, user);
220 versionInfoDao.create(versionInfoEntity);
222 return versionInfoEntity.getCandidate().getVersion();
226 public void delete(String entityType, String entityId, String user) {
227 VersionInfoEntity versionInfoEntity =
228 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
229 if (versionInfoEntity == null) {
230 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
231 LoggerTragetServiceName.DELETE_ENTITY, ErrorLevel.ERROR.name(),
232 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't delete versionable entity");
233 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
236 switch (versionInfoEntity.getStatus()) {
238 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
239 LoggerTragetServiceName.DELETE_ENTITY, ErrorLevel.ERROR.name(),
240 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't delete versionable entity");
241 throw new CoreException(new DeleteOnLockedEntityErrorBuilder(entityType, entityId,
242 versionInfoEntity.getCandidate().getUser()).build());
248 doDelete(versionInfoEntity);
252 public void undoDelete(String entityType, String entityId, String user) {
253 VersionInfoDeletedEntity versionInfoDeletedEntity =
254 versionInfoDeletedDao.get(new VersionInfoDeletedEntity(entityType, entityId));
255 if (versionInfoDeletedEntity == null) {
256 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
257 LoggerTragetServiceName.UNDO_DELETE_ENTITY, ErrorLevel.ERROR.name(),
258 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't undo delete for versionable entity");
259 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
262 doUndoDelete(versionInfoDeletedEntity);
266 public Version checkout(String entityType, String entityId, String user) {
267 VersionInfoEntity versionInfoEntity =
268 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
269 MDC.put(LoggerConstants.TARGET_SERVICE_NAME, LoggerTragetServiceName.CHECKOUT_ENTITY);
270 if (versionInfoEntity == null) {
271 MDC.put(LoggerConstants.ERROR_CATEGORY, ErrorLevel.ERROR.name());
272 MDC.put(LoggerConstants.TARGET_ENTITY, LoggerConstants.TARGET_ENTITY_DB);
273 MDC.put(LoggerConstants.ERROR_DESCRIPTION, LoggerErrorDescription.CHECKOUT_ENTITY);
274 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
277 Version checkoutVersion = null;
278 switch (versionInfoEntity.getStatus()) {
280 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
281 LoggerTragetServiceName.CHECKOUT_ENTITY, ErrorLevel.ERROR.name(),
282 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't checkout versionable entity");
283 throw new CoreException(new CheckoutOnLockedEntityErrorBuilder(entityType, entityId,
284 versionInfoEntity.getCandidate().getUser()).build());
287 checkoutVersion = doCheckout(versionInfoEntity, user);
294 return checkoutVersion;
298 public Version undoCheckout(String entityType, String entityId, String user) {
299 VersionInfoEntity versionInfoEntity =
300 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
301 if (versionInfoEntity == null) {
302 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
303 LoggerTragetServiceName.UNDO_CHECKOUT_ENTITY, ErrorLevel.ERROR.name(),
304 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't undo checkout for versionable entity");
305 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
308 Version activeVersion = null;
309 switch (versionInfoEntity.getStatus()) {
311 if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
312 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
313 LoggerTragetServiceName.UNDO_CHECKOUT_ENTITY, ErrorLevel.ERROR.name(),
314 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(),
315 "Can't undo checkout for versionable entity");
316 throw new CoreException(
317 new UndoCheckoutOnEntityLockedByOtherErrorBuilder(entityType, entityId,
318 versionInfoEntity.getCandidate().getUser()).build());
320 activeVersion = undoCheckout(versionInfoEntity);
324 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
325 LoggerTragetServiceName.UNDO_CHECKOUT_ENTITY, ErrorLevel.ERROR.name(),
326 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(),
327 "Can't undo checkout for versionable entity");
328 throw new CoreException(
329 new UndoCheckoutOnUnlockedEntityErrorBuilder(entityType, entityId).build());
335 return activeVersion;
338 private Version undoCheckout(VersionInfoEntity versionInfoEntity) {
339 deleteVersionFromEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
340 versionInfoEntity.getCandidate().getVersion(), versionInfoEntity.getActiveVersion());
343 .setStatus(versionInfoEntity.getActiveVersion().isFinal() ? VersionStatus.Certified
344 : VersionStatus.Draft);
345 versionInfoEntity.setCandidate(null);
346 versionInfoDao.update(versionInfoEntity);
347 return versionInfoEntity.getActiveVersion();
351 public Version checkin(String entityType, String entityId, String user,
352 String checkinDescription) {
353 VersionInfoEntity versionInfoEntity =
354 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
355 if (versionInfoEntity == null) {
356 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
357 LoggerTragetServiceName.CHECKIN_ENTITY, ErrorLevel.ERROR.name(),
358 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't checkin versionable entity");
359 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
362 Version checkedInVersion = null;
363 switch (versionInfoEntity.getStatus()) {
366 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
367 LoggerTragetServiceName.CHECKIN_ENTITY, ErrorLevel.ERROR.name(),
368 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't checkin versionable entity");
369 throw new CoreException(
370 new CheckinOnUnlockedEntityErrorBuilder(entityType, entityId).build());
372 if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
373 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
374 LoggerTragetServiceName.CHECKIN_ENTITY, ErrorLevel.ERROR.name(),
375 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't checkin versionable entity");
376 throw new CoreException(new CheckinOnEntityLockedByOtherErrorBuilder(entityType, entityId,
377 versionInfoEntity.getCandidate().getUser()).build());
379 checkedInVersion = doCheckin(versionInfoEntity, checkinDescription);
386 return checkedInVersion;
390 public Version submit(String entityType, String entityId, String user, String submitDescription) {
391 VersionInfoEntity versionInfoEntity =
392 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
393 if (versionInfoEntity == null) {
394 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
395 LoggerTragetServiceName.SUBMIT_ENTITY, ErrorLevel.ERROR.name(),
396 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't submit versionable entity");
397 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
400 Version submitVersion = null;
401 switch (versionInfoEntity.getStatus()) {
403 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
404 LoggerTragetServiceName.SUBMIT_ENTITY, ErrorLevel.ERROR.name(),
405 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't submit versionable entity");
406 throw new CoreException(
407 new EntityAlreadyFinalizedErrorBuilder(entityType, entityId).build());
409 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
410 LoggerTragetServiceName.SUBMIT_ENTITY, ErrorLevel.ERROR.name(),
411 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't submit versionable entity");
412 throw new CoreException(new SubmitLockedEntityNotAllowedErrorBuilder(entityType, entityId,
413 versionInfoEntity.getCandidate().getUser()).build());
415 submitVersion = doSubmit(versionInfoEntity, user, submitDescription);
422 return submitVersion;
426 public VersionInfo getEntityVersionInfo(String entityType, String entityId, String user,
427 VersionableEntityAction action) {
428 VersionInfoEntity versionInfoEntity =
429 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
430 if (versionInfoEntity == null) {
431 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
432 LoggerTragetServiceName.GET_VERSION_INFO, ErrorLevel.ERROR.name(),
433 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't get entity version info");
434 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
436 return getVersionInfo(versionInfoEntity, user, action);
440 public Map<String, VersionInfo> listEntitiesVersionInfo(String entityType, String user,
441 VersionableEntityAction action) {
442 Collection<VersionInfoEntity> versionInfoEntities =
443 versionInfoDao.list(new VersionInfoEntity(entityType, null));
444 Map<String, VersionInfo> activeVersions = new HashMap<>();
445 for (VersionInfoEntity versionInfoEntity : versionInfoEntities) {
447 .put(versionInfoEntity.getEntityId(), getVersionInfo(versionInfoEntity, user, action));
449 return activeVersions;
453 public Map<String, VersionInfo> listDeletedEntitiesVersionInfo(String entityType, String user,
454 VersionableEntityAction action) {
455 Collection<VersionInfoDeletedEntity> versionInfoDeletedEntities =
456 versionInfoDeletedDao.list(new VersionInfoDeletedEntity(entityType, null));
457 Map<String, VersionInfo> activeVersions = new HashMap<>();
460 for (VersionInfoDeletedEntity versionInfoDeletedEntity : versionInfoDeletedEntities) {
461 activeVersions.put(versionInfoDeletedEntity.getEntityId(),
462 getVersionInfo(versionInfoDeletedEntity, user, action));
464 return activeVersions;
468 public List<Version> list(String itemId) {
470 List<Version> versions = versionDao.list(itemId);
471 Set<String> versionsNames = versions.stream().map(Version::getName).collect(Collectors.toSet());
472 versions.forEach(version -> {
473 version.setAdditionalInfo(new HashMap<>());
474 versionCalculator.injectAdditionalInfo(version, versionsNames);
480 public Version get(String itemId, Version version) {
481 return versionDao.get(itemId, version)
482 .map(retrievedVersion -> getUpdateRetrievedVersion(itemId, retrievedVersion))
483 .orElseGet(() -> getSyncedVersion(itemId, version));
486 private Version getUpdateRetrievedVersion(String itemId, Version version) {
487 if (version.getStatus() == VersionStatus.Certified &&
488 (version.getState().getSynchronizationState() == SynchronizationState.OutOfSync ||
489 version.getState().isDirty())) {
490 forceSync(itemId, version);
491 LOGGER.info("Item Id {}, version Id {}: Force sync is done", itemId, version.getId());
492 version = versionDao.get(itemId, version)
493 .orElseThrow(() -> new IllegalStateException(
494 "Get version after a successful force sync must return the version"));
499 private Version getSyncedVersion(String itemId, Version version) {
500 sync(itemId, version);
501 LOGGER.info("Item Id {}, version Id {}: First time sync is done", itemId, version.getId());
502 return versionDao.get(itemId, version)
503 .orElseThrow(() -> new IllegalStateException(
504 "Get version after a successful sync must return the version"));
508 public Version create(String itemId, Version version, VersionCreationMethod creationMethod) {
509 String baseVersionName = null;
510 if (version.getBaseId() == null) {
511 version.setDescription("Initial version");
513 baseVersionName = get(itemId, new Version(version.getBaseId())).getName();
515 String versionName = versionCalculator.calculate(baseVersionName, creationMethod);
516 validateVersionName(itemId, versionName);
517 version.setName(versionName);
519 versionDao.create(itemId, version);
520 itemManager.updateVersionStatus(itemId, VersionStatus.Draft, null);
522 publish(itemId, version, String.format("Create version: %s", version.getName()));
526 private void validateVersionName(String itemId, String versionName) {
527 if (versionDao.list(itemId).stream()
528 .anyMatch(version -> versionName.equals(version.getName()))) {
529 String errorDescription = String
530 .format("Item %s: create version failed, a version with the name %s already exist",
531 itemId, versionName);
533 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY,
534 LoggerTragetServiceName.CREATE_VERSION, ErrorLevel.ERROR.name(),
535 LoggerErrorCode.DATA_ERROR.getErrorCode(), errorDescription);
537 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
538 .withCategory(ErrorCategory.APPLICATION)
539 .withId("VERSION_NAME_ALREADY_EXIST")
540 .withMessage(errorDescription)
546 public void submit(String itemId, Version version, String submitDescription) {
547 version = get(itemId, version);
549 validateSubmit(itemId, version);
551 version.setStatus(VersionStatus.Certified);
552 versionDao.update(itemId, version);
554 publish(itemId, version, submitDescription);
556 itemManager.updateVersionStatus(itemId, VersionStatus.Certified, VersionStatus.Draft);
559 private void validateSubmit(String itemId, Version version) {
560 if (version.getStatus() == VersionStatus.Certified) {
561 String errorDescription = String
562 .format("Item %s: submit version failed, version %s is already Certified", itemId,
565 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
566 LoggerTragetServiceName.SUBMIT_ENTITY, ErrorLevel.ERROR.name(),
567 LoggerErrorCode.DATA_ERROR.getErrorCode(), errorDescription);
569 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
570 .withCategory(ErrorCategory.APPLICATION)
571 .withId("VERSION_ALREADY_CERTIFIED")
572 .withMessage(errorDescription)
578 public void publish(String itemId, Version version, String message) {
579 versionDao.publish(itemId, version, message);
584 public void sync(String itemId, Version version) {
585 versionDao.sync(itemId, version);
589 public void forceSync(String itemId, Version version) {
590 versionDao.forceSync(itemId, version);
594 public void revert(String itemId, Version version, String revisionId) {
595 versionDao.revert(itemId, version, revisionId);
599 public List<Revision> listRevisions(String itemId, Version version) {
600 return versionDao.listRevisions(itemId, version);
603 private void markAsCheckedOut(VersionInfoEntity versionInfoEntity, String checkingOutUser) {
604 versionInfoEntity.setStatus(VersionStatus.Locked);
605 versionInfoEntity.setCandidate(new UserCandidateVersion(checkingOutUser,
606 versionInfoEntity.getActiveVersion().calculateNextCandidate()));
609 private Version doCheckout(VersionInfoEntity versionInfoEntity, String user) {
610 markAsCheckedOut(versionInfoEntity, user);
611 versionInfoDao.update(versionInfoEntity);
613 initVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
614 versionInfoEntity.getActiveVersion(), versionInfoEntity.getCandidate().getVersion());
616 return versionInfoEntity.getCandidate().getVersion();
619 private void doDelete(VersionInfoEntity versionInfoEntity) {
620 VersionInfoDeletedEntity versionInfoDeletedEntity = new VersionInfoDeletedEntity();
621 versionInfoDeletedEntity.setStatus(versionInfoEntity.getStatus());
622 versionInfoDeletedEntity.setViewableVersions(versionInfoEntity.getViewableVersions());
623 versionInfoDeletedEntity.setActiveVersion(versionInfoEntity.getActiveVersion());
624 versionInfoDeletedEntity.setCandidate(versionInfoEntity.getCandidate());
625 versionInfoDeletedEntity.setEntityId(versionInfoEntity.getEntityId());
626 versionInfoDeletedEntity.setEntityType(versionInfoEntity.getEntityType());
627 versionInfoDeletedEntity.setLatestFinalVersion(versionInfoEntity.getLatestFinalVersion());
628 versionInfoDeletedDao.create(versionInfoDeletedEntity);
629 versionInfoDao.delete(versionInfoEntity);
632 private void doUndoDelete(VersionInfoDeletedEntity versionInfoDeletedEntity) {
633 VersionInfoEntity versionInfoEntity = new VersionInfoEntity();
634 versionInfoEntity.setStatus(versionInfoDeletedEntity.getStatus());
635 versionInfoEntity.setViewableVersions(versionInfoDeletedEntity.getViewableVersions());
636 versionInfoEntity.setActiveVersion(versionInfoDeletedEntity.getActiveVersion());
637 versionInfoEntity.setCandidate(versionInfoDeletedEntity.getCandidate());
638 versionInfoEntity.setEntityId(versionInfoDeletedEntity.getEntityId());
639 versionInfoEntity.setEntityType(versionInfoDeletedEntity.getEntityType());
640 versionInfoEntity.setLatestFinalVersion(versionInfoDeletedEntity.getLatestFinalVersion());
641 versionInfoDao.create(versionInfoEntity);
642 versionInfoDeletedDao.delete(versionInfoDeletedEntity);
645 private Version doCheckin(VersionInfoEntity versionInfoEntity, String checkinDescription) {
646 UserCandidateVersion userCandidateVersion = versionInfoEntity.getCandidate();
647 versionInfoEntity.setCandidate(null);
648 versionInfoEntity.setActiveVersion(userCandidateVersion.getVersion());
649 versionInfoEntity.getViewableVersions().add(versionInfoEntity.getActiveVersion());
650 versionInfoEntity.setStatus(VersionStatus.Draft);
652 closeVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
653 versionInfoEntity.getActiveVersion());
655 versionInfoDao.update(versionInfoEntity);
657 return versionInfoEntity.getActiveVersion();
660 private Version doSubmit(VersionInfoEntity versionInfoEntity, String submittingUser,
661 String submitDescription) {
662 Version finalVersion = versionInfoEntity.getActiveVersion().calculateNextFinal();
663 initVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
664 versionInfoEntity.getActiveVersion(), finalVersion);
665 closeVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
668 Set<Version> viewableVersions = new HashSet<>();
669 for (Version version : versionInfoEntity.getViewableVersions()) {
670 if (version.isFinal()) {
671 viewableVersions.add(version);
674 viewableVersions.add(finalVersion);
675 versionInfoEntity.setViewableVersions(viewableVersions);
676 versionInfoEntity.setActiveVersion(finalVersion);
677 versionInfoEntity.setLatestFinalVersion(finalVersion);
678 versionInfoEntity.setStatus(VersionStatus.Certified);
679 versionInfoDao.update(versionInfoEntity);
684 private void initVersionOnEntity(String entityType, String entityId, Version baseVersion,
685 Version newVersion) {
686 Set<VersionableEntityMetadata> entityMetadatas = VERSIONABLE_ENTITIES.get(entityType);
687 if (entityMetadatas != null) {
688 for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
689 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
690 .initVersion(entityMetadata, entityId, baseVersion, newVersion);
695 private void deleteVersionFromEntity(String entityType, String entityId,
696 Version versionToDelete, Version backToVersion) {
697 Set<VersionableEntityMetadata> entityMetadatas = VERSIONABLE_ENTITIES.get(entityType);
698 if (entityMetadatas != null) {
699 for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
700 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
701 .deleteVersion(entityMetadata, entityId, versionToDelete, backToVersion);
706 private void closeVersionOnEntity(String entityType, String entityId, Version versionToClose) {
707 Set<VersionableEntityMetadata> entityMetadatas = VERSIONABLE_ENTITIES.get(entityType);
708 if (entityMetadatas != null) {
709 for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
710 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
711 .closeVersion(entityMetadata, entityId, versionToClose);