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 MdcDataDebugMessage mdcDataDebugMessage = new MdcDataDebugMessage();
79 private static Map<String, Set<VersionableEntityMetadata>> versionableEntities = new HashMap<>();
81 private final VersionInfoDao versionInfoDao;
82 private final VersionInfoDeletedDao versionInfoDeletedDao;
83 private VersionDao versionDao;
84 private VersionCalculator versionCalculator;
85 private ItemManager itemManager;
87 public VersioningManagerImpl(VersionInfoDao versionInfoDao,
88 VersionInfoDeletedDao versionInfoDeletedDao,
89 VersionDao versionDao,
90 VersionCalculator versionCalculator,
91 ItemManager itemManager) {
92 this.versionInfoDao = versionInfoDao;
93 this.versionInfoDeletedDao = versionInfoDeletedDao;
94 this.versionDao = versionDao;
95 this.versionCalculator = versionCalculator;
96 this.itemManager = itemManager;
99 private static VersionInfo getVersionInfo(VersionInfoEntity versionInfoEntity, String user,
100 VersionableEntityAction action) {
101 return getVersionInfo(versionInfoEntity.getEntityId(),
102 versionInfoEntity.getEntityType(),
103 versionInfoEntity.getActiveVersion(),
104 versionInfoEntity.getCandidate(),
105 versionInfoEntity.getStatus(),
106 versionInfoEntity.getLatestFinalVersion(),
107 versionInfoEntity.getViewableVersions(),
112 private static VersionInfo getVersionInfo(VersionInfoDeletedEntity versionInfoEntity, String user,
113 VersionableEntityAction action) {
114 return getVersionInfo(versionInfoEntity.getEntityId(),
115 versionInfoEntity.getEntityType(),
116 versionInfoEntity.getActiveVersion(),
117 versionInfoEntity.getCandidate(),
118 versionInfoEntity.getStatus(),
119 versionInfoEntity.getLatestFinalVersion(),
120 versionInfoEntity.getViewableVersions(),
125 private static VersionInfo getVersionInfo(String entityId, String entityType, Version activeVer,
126 UserCandidateVersion candidate, VersionStatus status,
127 Version latestFinalVersion,
128 Set<Version> viewableVersions,
129 VersionableEntityAction action, String user) {
132 mdcDataDebugMessage.debugEntryMessage("entity Id", entityId);
134 Version activeVersion;
136 if (action == VersionableEntityAction.Write) {
137 if (candidate != null) {
138 if (user.equals(candidate.getUser())) {
139 activeVersion = candidate.getVersion();
141 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
142 LoggerTragetServiceName.GET_VERSION_INFO, ErrorLevel.ERROR.name(),
143 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't get entity version info");
144 throw new CoreException(
145 new EditOnEntityLockedByOtherErrorBuilder(entityType, entityId, candidate.getUser())
149 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
150 LoggerTragetServiceName.GET_VERSION_INFO, ErrorLevel.ERROR.name(),
151 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't get entity version info");
152 throw new CoreException(new EditOnUnlockedEntityErrorBuilder(entityType, entityId).build());
155 if (candidate != null && user.equals(candidate.getUser())) {
156 activeVersion = candidate.getVersion();
158 activeVersion = activeVer;
162 VersionInfo versionInfo = new VersionInfo();
163 versionInfo.setStatus(status);
164 activeVersion.setStatus(status);
165 if (latestFinalVersion != null) {
166 latestFinalVersion.setStatus(status);
168 if (viewableVersions != null) {
169 viewableVersions.forEach(version -> version.setStatus(status));
171 versionInfo.setActiveVersion(activeVersion);
172 versionInfo.setLatestFinalVersion(latestFinalVersion);
173 versionInfo.setViewableVersions(toSortedList(viewableVersions));
174 versionInfo.setFinalVersions(getFinalVersions(viewableVersions));
175 if (candidate != null) {
176 candidate.getVersion().setStatus(status);
177 versionInfo.setLockingUser(candidate.getUser());
178 if (user.equals(candidate.getUser())) {
179 versionInfo.getViewableVersions().add(candidate.getVersion());
183 mdcDataDebugMessage.debugExitMessage("entity Id", entityId);
187 private static List<Version> toSortedList(
188 Set<Version> versions) { // changing the Set to List in DB will require migration...
189 return versions.stream().sorted((o1, o2) -> o1.getMajor() > o2.getMajor() ? 1
190 : o1.getMajor() == o2.getMajor() ? (o1.getMinor() > o2.getMinor() ? 1
191 : o1.getMinor() == o2.getMinor() ? 0 : -1) : -1).collect(Collectors.toList());
194 private static List<Version> getFinalVersions(Set<Version> versions) {
195 return versions.stream().filter(Version::isFinal).collect(Collectors.toList());
199 public void register(String entityType, VersionableEntityMetadata entityMetadata) {
200 Set<VersionableEntityMetadata> entitiesMetadata =
201 versionableEntities.computeIfAbsent(entityType, k -> new HashSet<>());
202 entitiesMetadata.add(entityMetadata);
206 public Version create(String entityType, String entityId, String user) {
208 versionInfoEntity = versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
209 if (versionInfoEntity != null) {
210 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
211 LoggerTragetServiceName.CREATE_ENTITY, ErrorLevel.ERROR.name(),
212 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't create versionable entity");
213 throw new CoreException(new EntityAlreadyExistErrorBuilder(entityType, entityId).build());
216 versionInfoEntity = new VersionInfoEntity(entityType, entityId);
217 versionInfoEntity.setActiveVersion(INITIAL_ACTIVE_VERSION);
218 markAsCheckedOut(versionInfoEntity, user);
219 versionInfoDao.create(versionInfoEntity);
221 return versionInfoEntity.getCandidate().getVersion();
225 public void delete(String entityType, String entityId, String user) {
226 VersionInfoEntity versionInfoEntity =
227 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
228 if (versionInfoEntity == null) {
229 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
230 LoggerTragetServiceName.DELETE_ENTITY, ErrorLevel.ERROR.name(),
231 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't delete versionable entity");
232 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
235 switch (versionInfoEntity.getStatus()) {
237 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
238 LoggerTragetServiceName.DELETE_ENTITY, ErrorLevel.ERROR.name(),
239 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't delete versionable entity");
240 throw new CoreException(new DeleteOnLockedEntityErrorBuilder(entityType, entityId,
241 versionInfoEntity.getCandidate().getUser()).build());
247 doDelete(versionInfoEntity);
251 public void undoDelete(String entityType, String entityId, String user) {
252 VersionInfoDeletedEntity versionInfoDeletedEntity =
253 versionInfoDeletedDao.get(new VersionInfoDeletedEntity(entityType, entityId));
254 if (versionInfoDeletedEntity == null) {
255 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
256 LoggerTragetServiceName.UNDO_DELETE_ENTITY, ErrorLevel.ERROR.name(),
257 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't undo delete for versionable entity");
258 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
261 doUndoDelete(versionInfoDeletedEntity);
265 public Version checkout(String entityType, String entityId, String user) {
266 VersionInfoEntity versionInfoEntity =
267 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
268 MDC.put(LoggerConstants.TARGET_SERVICE_NAME, LoggerTragetServiceName.CHECKOUT_ENTITY);
269 if (versionInfoEntity == null) {
270 MDC.put(LoggerConstants.ERROR_CATEGORY, ErrorLevel.ERROR.name());
271 MDC.put(LoggerConstants.TARGET_ENTITY, LoggerConstants.TARGET_ENTITY_DB);
272 MDC.put(LoggerConstants.ERROR_DESCRIPTION, LoggerErrorDescription.CHECKOUT_ENTITY);
273 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
276 Version checkoutVersion = null;
277 switch (versionInfoEntity.getStatus()) {
279 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
280 LoggerTragetServiceName.CHECKOUT_ENTITY, ErrorLevel.ERROR.name(),
281 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't checkout versionable entity");
282 throw new CoreException(new CheckoutOnLockedEntityErrorBuilder(entityType, entityId,
283 versionInfoEntity.getCandidate().getUser()).build());
286 checkoutVersion = doCheckout(versionInfoEntity, user);
293 return checkoutVersion;
297 public Version undoCheckout(String entityType, String entityId, String user) {
298 VersionInfoEntity versionInfoEntity =
299 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
300 if (versionInfoEntity == null) {
301 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
302 LoggerTragetServiceName.UNDO_CHECKOUT_ENTITY, ErrorLevel.ERROR.name(),
303 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't undo checkout for versionable entity");
304 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
307 Version activeVersion = null;
308 switch (versionInfoEntity.getStatus()) {
310 if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
311 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
312 LoggerTragetServiceName.UNDO_CHECKOUT_ENTITY, ErrorLevel.ERROR.name(),
313 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(),
314 "Can't undo checkout for versionable entity");
315 throw new CoreException(
316 new UndoCheckoutOnEntityLockedByOtherErrorBuilder(entityType, entityId,
317 versionInfoEntity.getCandidate().getUser()).build());
319 activeVersion = undoCheckout(versionInfoEntity);
323 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
324 LoggerTragetServiceName.UNDO_CHECKOUT_ENTITY, ErrorLevel.ERROR.name(),
325 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(),
326 "Can't undo checkout for versionable entity");
327 throw new CoreException(
328 new UndoCheckoutOnUnlockedEntityErrorBuilder(entityType, entityId).build());
334 return activeVersion;
337 private Version undoCheckout(VersionInfoEntity versionInfoEntity) {
338 deleteVersionFromEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
339 versionInfoEntity.getCandidate().getVersion(), versionInfoEntity.getActiveVersion());
342 .setStatus(versionInfoEntity.getActiveVersion().isFinal() ? VersionStatus.Certified
343 : VersionStatus.Draft);
344 versionInfoEntity.setCandidate(null);
345 versionInfoDao.update(versionInfoEntity);
346 return versionInfoEntity.getActiveVersion();
350 public Version checkin(String entityType, String entityId, String user,
351 String checkinDescription) {
352 VersionInfoEntity versionInfoEntity =
353 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
354 if (versionInfoEntity == null) {
355 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
356 LoggerTragetServiceName.CHECKIN_ENTITY, ErrorLevel.ERROR.name(),
357 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't checkin versionable entity");
358 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
361 Version checkedInVersion = null;
362 switch (versionInfoEntity.getStatus()) {
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(
369 new CheckinOnUnlockedEntityErrorBuilder(entityType, entityId).build());
371 if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
372 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
373 LoggerTragetServiceName.CHECKIN_ENTITY, ErrorLevel.ERROR.name(),
374 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't checkin versionable entity");
375 throw new CoreException(new CheckinOnEntityLockedByOtherErrorBuilder(entityType, entityId,
376 versionInfoEntity.getCandidate().getUser()).build());
378 checkedInVersion = doCheckin(versionInfoEntity, checkinDescription);
385 return checkedInVersion;
389 public Version submit(String entityType, String entityId, String user, String submitDescription) {
390 VersionInfoEntity versionInfoEntity =
391 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
392 if (versionInfoEntity == null) {
393 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
394 LoggerTragetServiceName.SUBMIT_ENTITY, ErrorLevel.ERROR.name(),
395 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't submit versionable entity");
396 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
399 Version submitVersion = null;
400 switch (versionInfoEntity.getStatus()) {
402 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
403 LoggerTragetServiceName.SUBMIT_ENTITY, ErrorLevel.ERROR.name(),
404 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't submit versionable entity");
405 throw new CoreException(
406 new EntityAlreadyFinalizedErrorBuilder(entityType, entityId).build());
408 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
409 LoggerTragetServiceName.SUBMIT_ENTITY, ErrorLevel.ERROR.name(),
410 LoggerErrorCode.PERMISSION_ERROR.getErrorCode(), "Can't submit versionable entity");
411 throw new CoreException(new SubmitLockedEntityNotAllowedErrorBuilder(entityType, entityId,
412 versionInfoEntity.getCandidate().getUser()).build());
414 submitVersion = doSubmit(versionInfoEntity, user, submitDescription);
421 return submitVersion;
425 public VersionInfo getEntityVersionInfo(String entityType, String entityId, String user,
426 VersionableEntityAction action) {
427 VersionInfoEntity versionInfoEntity =
428 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
429 if (versionInfoEntity == null) {
430 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
431 LoggerTragetServiceName.GET_VERSION_INFO, ErrorLevel.ERROR.name(),
432 LoggerErrorCode.DATA_ERROR.getErrorCode(), "Can't get entity version info");
433 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
435 return getVersionInfo(versionInfoEntity, user, action);
439 public Map<String, VersionInfo> listEntitiesVersionInfo(String entityType, String user,
440 VersionableEntityAction action) {
441 Collection<VersionInfoEntity> versionInfoEntities =
442 versionInfoDao.list(new VersionInfoEntity(entityType, null));
443 Map<String, VersionInfo> activeVersions = new HashMap<>();
444 for (VersionInfoEntity versionInfoEntity : versionInfoEntities) {
446 .put(versionInfoEntity.getEntityId(), getVersionInfo(versionInfoEntity, user, action));
448 return activeVersions;
452 public Map<String, VersionInfo> listDeletedEntitiesVersionInfo(String entityType, String user,
453 VersionableEntityAction action) {
454 Collection<VersionInfoDeletedEntity> versionInfoDeletedEntities =
455 versionInfoDeletedDao.list(new VersionInfoDeletedEntity(entityType, null));
456 Map<String, VersionInfo> activeVersions = new HashMap<>();
459 for (VersionInfoDeletedEntity versionInfoDeletedEntity : versionInfoDeletedEntities) {
460 activeVersions.put(versionInfoDeletedEntity.getEntityId(),
461 getVersionInfo(versionInfoDeletedEntity, user, action));
463 return activeVersions;
467 public List<Version> list(String itemId) {
469 List<Version> versions = versionDao.list(itemId);
470 Set<String> versionsNames = versions.stream().map(Version::getName).collect(Collectors.toSet());
471 versions.forEach(version -> {
472 version.setAdditionalInfo(new HashMap<>());
473 versionCalculator.injectAdditionalInfo(version, versionsNames);
479 public Version get(String itemId, Version version) {
480 return versionDao.get(itemId, version)
481 .map(retrievedVersion -> getUpdateRetrievedVersion(itemId, retrievedVersion))
482 .orElseGet(() -> getSyncedVersion(itemId, version));
485 private Version getUpdateRetrievedVersion(String itemId, Version version) {
486 if (version.getStatus() == VersionStatus.Certified &&
487 (version.getState().getSynchronizationState() == SynchronizationState.OutOfSync ||
488 version.getState().isDirty())) {
489 forceSync(itemId, version);
490 LOGGER.info("Item Id {}, version Id {}: Force sync is done", itemId, version.getId());
491 version = versionDao.get(itemId, version)
492 .orElseThrow(() -> new IllegalStateException(
493 "Get version after a successful force sync must return the version"));
498 private Version getSyncedVersion(String itemId, Version version) {
499 sync(itemId, version);
500 LOGGER.info("Item Id {}, version Id {}: First time sync is done", itemId, version.getId());
501 return versionDao.get(itemId, version)
502 .orElseThrow(() -> new IllegalStateException(
503 "Get version after a successful sync must return the version"));
507 public Version create(String itemId, Version version, VersionCreationMethod creationMethod) {
508 String baseVersionName = null;
509 if (version.getBaseId() == null) {
510 version.setDescription("Initial version");
512 baseVersionName = get(itemId, new Version(version.getBaseId())).getName();
514 String versionName = versionCalculator.calculate(baseVersionName, creationMethod);
515 validateVersionName(itemId, versionName);
516 version.setName(versionName);
518 versionDao.create(itemId, version);
519 itemManager.updateVersionStatus(itemId, VersionStatus.Draft, null);
521 publish(itemId, version, String.format("Initial version: %s ", version.getName()));
525 private void validateVersionName(String itemId, String versionName) {
526 if (versionDao.list(itemId).stream()
527 .anyMatch(version -> versionName.equals(version.getName()))) {
528 String errorDescription = String
529 .format("Item %s: create version failed, a version with the name %s already exist",
530 itemId, versionName);
532 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY,
533 LoggerTragetServiceName.CREATE_VERSION, ErrorLevel.ERROR.name(),
534 LoggerErrorCode.DATA_ERROR.getErrorCode(), errorDescription);
536 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
537 .withCategory(ErrorCategory.APPLICATION)
538 .withId("VERSION_NAME_ALREADY_EXIST")
539 .withMessage(errorDescription)
545 public void submit(String itemId, Version version, String submitDescription) {
546 version = get(itemId, version);
548 validateSubmit(itemId, version);
550 version.setStatus(VersionStatus.Certified);
551 versionDao.update(itemId, version);
553 publish(itemId, version, submitDescription);
555 itemManager.updateVersionStatus(itemId, VersionStatus.Certified, VersionStatus.Draft);
558 private void validateSubmit(String itemId, Version version) {
559 if (version.getStatus() == VersionStatus.Certified) {
560 String errorDescription = String
561 .format("Item %s: submit version failed, version %s is already Certified", itemId,
564 MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
565 LoggerTragetServiceName.SUBMIT_ENTITY, ErrorLevel.ERROR.name(),
566 LoggerErrorCode.DATA_ERROR.getErrorCode(), errorDescription);
568 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
569 .withCategory(ErrorCategory.APPLICATION)
570 .withId("VERSION_ALREADY_CERTIFIED")
571 .withMessage(errorDescription)
577 public void publish(String itemId, Version version, String message) {
578 versionDao.publish(itemId, version, message);
583 public void sync(String itemId, Version version) {
584 versionDao.sync(itemId, version);
588 public void forceSync(String itemId, Version version) {
589 versionDao.forceSync(itemId, version);
593 public void revert(String itemId, Version version, String revisionId) {
594 versionDao.revert(itemId, version, revisionId);
598 public List<Revision> listRevisions(String itemId, Version version) {
599 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 = versionableEntities.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 = versionableEntities.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 = versionableEntities.get(entityType);
708 if (entityMetadatas != null) {
709 for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
710 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
711 .closeVersion(entityMetadata, entityId, versionToClose);