2 * Copyright © 2016-2017 European Support Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.openecomp.sdc.versioning.impl;
19 import org.openecomp.sdc.common.errors.CoreException;
20 import org.openecomp.sdc.common.errors.ErrorCode;
21 import org.openecomp.sdc.logging.api.Logger;
22 import org.openecomp.sdc.logging.api.LoggerFactory;
23 import org.openecomp.sdc.versioning.ItemManager;
24 import org.openecomp.sdc.versioning.VersionCalculator;
25 import org.openecomp.sdc.versioning.VersioningManager;
26 import org.openecomp.sdc.versioning.dao.VersionDao;
27 import org.openecomp.sdc.versioning.dao.VersionInfoDao;
28 import org.openecomp.sdc.versioning.dao.VersionInfoDeletedDao;
29 import org.openecomp.sdc.versioning.dao.VersionableEntityDaoFactory;
30 import org.openecomp.sdc.versioning.dao.types.Revision;
31 import org.openecomp.sdc.versioning.dao.types.SynchronizationState;
32 import org.openecomp.sdc.versioning.dao.types.UserCandidateVersion;
33 import org.openecomp.sdc.versioning.dao.types.Version;
34 import org.openecomp.sdc.versioning.dao.types.VersionInfoDeletedEntity;
35 import org.openecomp.sdc.versioning.dao.types.VersionInfoEntity;
36 import org.openecomp.sdc.versioning.dao.types.VersionStatus;
37 import org.openecomp.sdc.versioning.errors.CheckinOnEntityLockedByOtherErrorBuilder;
38 import org.openecomp.sdc.versioning.errors.CheckinOnUnlockedEntityErrorBuilder;
39 import org.openecomp.sdc.versioning.errors.CheckoutOnLockedEntityErrorBuilder;
40 import org.openecomp.sdc.versioning.errors.DeleteOnLockedEntityErrorBuilder;
41 import org.openecomp.sdc.versioning.errors.EditOnEntityLockedByOtherErrorBuilder;
42 import org.openecomp.sdc.versioning.errors.EditOnUnlockedEntityErrorBuilder;
43 import org.openecomp.sdc.versioning.errors.EntityAlreadyExistErrorBuilder;
44 import org.openecomp.sdc.versioning.errors.EntityAlreadyFinalizedErrorBuilder;
45 import org.openecomp.sdc.versioning.errors.EntityNotExistErrorBuilder;
46 import org.openecomp.sdc.versioning.errors.SubmitLockedEntityNotAllowedErrorBuilder;
47 import org.openecomp.sdc.versioning.errors.UndoCheckoutOnEntityLockedByOtherErrorBuilder;
48 import org.openecomp.sdc.versioning.errors.UndoCheckoutOnUnlockedEntityErrorBuilder;
49 import org.openecomp.sdc.versioning.types.VersionCreationMethod;
50 import org.openecomp.sdc.versioning.types.VersionInfo;
51 import org.openecomp.sdc.versioning.types.VersionableEntityAction;
52 import org.openecomp.sdc.versioning.types.VersionableEntityMetadata;
54 import java.util.Collection;
55 import java.util.HashMap;
56 import java.util.HashSet;
57 import java.util.List;
60 import java.util.stream.Collectors;
62 public class VersioningManagerImpl implements VersioningManager {
63 private static final Logger LOGGER = LoggerFactory.getLogger(VersioningManagerImpl.class);
64 private static final Version INITIAL_ACTIVE_VERSION = new Version(0, 0);
65 private static final Map<String, Set<VersionableEntityMetadata>> VERSIONABLE_ENTITIES =
68 private final VersionInfoDao versionInfoDao;
69 private final VersionInfoDeletedDao versionInfoDeletedDao;
70 private VersionDao versionDao;
71 private VersionCalculator versionCalculator;
72 private ItemManager itemManager;
74 public VersioningManagerImpl(VersionInfoDao versionInfoDao,
75 VersionInfoDeletedDao versionInfoDeletedDao,
76 VersionDao versionDao,
77 VersionCalculator versionCalculator,
78 ItemManager itemManager) {
79 this.versionInfoDao = versionInfoDao;
80 this.versionInfoDeletedDao = versionInfoDeletedDao;
81 this.versionDao = versionDao;
82 this.versionCalculator = versionCalculator;
83 this.itemManager = itemManager;
86 private static VersionInfo getVersionInfo(VersionInfoEntity versionInfoEntity, String user,
87 VersionableEntityAction action) {
88 return getVersionInfo(versionInfoEntity.getEntityId(),
89 versionInfoEntity.getEntityType(),
90 versionInfoEntity.getActiveVersion(),
91 versionInfoEntity.getCandidate(),
92 versionInfoEntity.getStatus(),
93 versionInfoEntity.getLatestFinalVersion(),
94 versionInfoEntity.getViewableVersions(),
99 private static VersionInfo getVersionInfo(VersionInfoDeletedEntity 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(String entityId, String entityType, Version activeVer,
113 UserCandidateVersion candidate, VersionStatus status,
114 Version latestFinalVersion,
115 Set<Version> viewableVersions,
116 VersionableEntityAction action, String user) {
117 Version activeVersion;
119 if (action == VersionableEntityAction.Write) {
120 if (candidate != null) {
121 if (user.equals(candidate.getUser())) {
122 activeVersion = candidate.getVersion();
124 throw new CoreException(
125 new EditOnEntityLockedByOtherErrorBuilder(entityType, entityId, candidate.getUser())
129 throw new CoreException(new EditOnUnlockedEntityErrorBuilder(entityType, entityId).build());
132 if (candidate != null && user.equals(candidate.getUser())) {
133 activeVersion = candidate.getVersion();
135 activeVersion = activeVer;
139 VersionInfo versionInfo = new VersionInfo();
140 versionInfo.setStatus(status);
141 activeVersion.setStatus(status);
142 if (latestFinalVersion != null) {
143 latestFinalVersion.setStatus(status);
145 if (viewableVersions != null) {
146 viewableVersions.forEach(version -> version.setStatus(status));
148 versionInfo.setActiveVersion(activeVersion);
149 versionInfo.setLatestFinalVersion(latestFinalVersion);
150 versionInfo.setViewableVersions(toSortedList(viewableVersions));
151 versionInfo.setFinalVersions(getFinalVersions(viewableVersions));
152 if (candidate != null) {
153 candidate.getVersion().setStatus(status);
154 versionInfo.setLockingUser(candidate.getUser());
155 if (user.equals(candidate.getUser())) {
156 versionInfo.getViewableVersions().add(candidate.getVersion());
162 private static List<Version> toSortedList(
163 Set<Version> versions) { // changing the Set to List in DB will require migration...
164 return versions.stream().sorted((o1, o2) -> o1.getMajor() > o2.getMajor() ? 1
165 : o1.getMajor() == o2.getMajor() ? (Integer.compare(o1.getMinor(), o2.getMinor())) : -1)
166 .collect(Collectors.toList());
169 private static List<Version> getFinalVersions(Set<Version> versions) {
170 return versions.stream().filter(Version::isFinal).collect(Collectors.toList());
174 public void register(String entityType, VersionableEntityMetadata entityMetadata) {
175 Set<VersionableEntityMetadata> entitiesMetadata =
176 VERSIONABLE_ENTITIES.computeIfAbsent(entityType, k -> new HashSet<>());
177 entitiesMetadata.add(entityMetadata);
181 public Version create(String entityType, String entityId, String user) {
183 versionInfoEntity = versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
184 if (versionInfoEntity != null) {
185 throw new CoreException(new EntityAlreadyExistErrorBuilder(entityType, entityId).build());
188 versionInfoEntity = new VersionInfoEntity(entityType, entityId);
189 versionInfoEntity.setActiveVersion(INITIAL_ACTIVE_VERSION);
190 markAsCheckedOut(versionInfoEntity, user);
191 versionInfoDao.create(versionInfoEntity);
193 return versionInfoEntity.getCandidate().getVersion();
197 public void delete(String entityType, String entityId, String user) {
198 VersionInfoEntity versionInfoEntity =
199 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
200 if (versionInfoEntity == null) {
201 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
204 if (versionInfoEntity.getStatus() == VersionStatus.Locked) {
205 throw new CoreException(new DeleteOnLockedEntityErrorBuilder(entityType, entityId,
206 versionInfoEntity.getCandidate().getUser()).build());
209 doDelete(versionInfoEntity);
213 public void undoDelete(String entityType, String entityId, String user) {
214 VersionInfoDeletedEntity versionInfoDeletedEntity =
215 versionInfoDeletedDao.get(new VersionInfoDeletedEntity(entityType, entityId));
216 if (versionInfoDeletedEntity == null) {
217 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
220 doUndoDelete(versionInfoDeletedEntity);
224 public Version checkout(String entityType, String entityId, String user) {
225 VersionInfoEntity versionInfoEntity =
226 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
227 if (versionInfoEntity == null) {
228 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
231 Version checkoutVersion = null;
232 switch (versionInfoEntity.getStatus()) {
234 throw new CoreException(new CheckoutOnLockedEntityErrorBuilder(entityType, entityId,
235 versionInfoEntity.getCandidate().getUser()).build());
238 checkoutVersion = doCheckout(versionInfoEntity, user);
245 return checkoutVersion;
249 public Version undoCheckout(String entityType, String entityId, String user) {
250 VersionInfoEntity versionInfoEntity =
251 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
252 if (versionInfoEntity == null) {
253 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
256 Version activeVersion = null;
257 switch (versionInfoEntity.getStatus()) {
259 if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
260 throw new CoreException(
261 new UndoCheckoutOnEntityLockedByOtherErrorBuilder(entityType, entityId,
262 versionInfoEntity.getCandidate().getUser()).build());
264 activeVersion = undoCheckout(versionInfoEntity);
268 throw new CoreException(
269 new UndoCheckoutOnUnlockedEntityErrorBuilder(entityType, entityId).build());
275 return activeVersion;
278 private Version undoCheckout(VersionInfoEntity versionInfoEntity) {
279 deleteVersionFromEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
280 versionInfoEntity.getCandidate().getVersion(), versionInfoEntity.getActiveVersion());
283 .setStatus(versionInfoEntity.getActiveVersion().isFinal() ? VersionStatus.Certified
284 : VersionStatus.Draft);
285 versionInfoEntity.setCandidate(null);
286 versionInfoDao.update(versionInfoEntity);
287 return versionInfoEntity.getActiveVersion();
291 public Version checkin(String entityType, String entityId, String user,
292 String checkinDescription) {
293 VersionInfoEntity versionInfoEntity =
294 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
295 if (versionInfoEntity == null) {
296 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
299 Version checkedInVersion = null;
300 switch (versionInfoEntity.getStatus()) {
303 throw new CoreException(
304 new CheckinOnUnlockedEntityErrorBuilder(entityType, entityId).build());
306 if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
307 throw new CoreException(new CheckinOnEntityLockedByOtherErrorBuilder(entityType, entityId,
308 versionInfoEntity.getCandidate().getUser()).build());
310 checkedInVersion = doCheckin(versionInfoEntity);
317 return checkedInVersion;
321 public Version submit(String entityType, String entityId, String user, String submitDescription) {
322 VersionInfoEntity versionInfoEntity =
323 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
324 if (versionInfoEntity == null) {
325 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
328 Version submitVersion = null;
329 switch (versionInfoEntity.getStatus()) {
331 throw new CoreException(
332 new EntityAlreadyFinalizedErrorBuilder(entityType, entityId).build());
334 throw new CoreException(new SubmitLockedEntityNotAllowedErrorBuilder(entityType, entityId,
335 versionInfoEntity.getCandidate().getUser()).build());
337 submitVersion = doSubmit(versionInfoEntity);
344 return submitVersion;
348 public VersionInfo getEntityVersionInfo(String entityType, String entityId, String user,
349 VersionableEntityAction action) {
350 VersionInfoEntity versionInfoEntity =
351 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
352 if (versionInfoEntity == null) {
353 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
355 return getVersionInfo(versionInfoEntity, user, action);
359 public Map<String, VersionInfo> listEntitiesVersionInfo(String entityType, String user,
360 VersionableEntityAction action) {
361 Collection<VersionInfoEntity> versionInfoEntities =
362 versionInfoDao.list(new VersionInfoEntity(entityType, null));
363 Map<String, VersionInfo> activeVersions = new HashMap<>();
364 for (VersionInfoEntity versionInfoEntity : versionInfoEntities) {
366 .put(versionInfoEntity.getEntityId(), getVersionInfo(versionInfoEntity, user, action));
368 return activeVersions;
372 public Map<String, VersionInfo> listDeletedEntitiesVersionInfo(String entityType, String user,
373 VersionableEntityAction action) {
374 Collection<VersionInfoDeletedEntity> versionInfoDeletedEntities =
375 versionInfoDeletedDao.list(new VersionInfoDeletedEntity(entityType, null));
376 Map<String, VersionInfo> activeVersions = new HashMap<>();
379 for (VersionInfoDeletedEntity versionInfoDeletedEntity : versionInfoDeletedEntities) {
380 activeVersions.put(versionInfoDeletedEntity.getEntityId(),
381 getVersionInfo(versionInfoDeletedEntity, user, action));
383 return activeVersions;
387 public List<Version> list(String itemId) {
389 List<Version> versions = versionDao.list(itemId);
390 Set<String> versionsNames = versions.stream().map(Version::getName).collect(Collectors.toSet());
391 versions.forEach(version -> {
392 version.setAdditionalInfo(new HashMap<>());
393 versionCalculator.injectAdditionalInfo(version, versionsNames);
399 public Version get(String itemId, Version version) {
400 return versionDao.get(itemId, version)
401 .map(retrievedVersion -> getUpdateRetrievedVersion(itemId, retrievedVersion))
402 .orElseGet(() -> getSyncedVersion(itemId, version));
405 private Version getUpdateRetrievedVersion(String itemId, Version version) {
406 if (version.getStatus() == VersionStatus.Certified &&
407 (version.getState().getSynchronizationState() == SynchronizationState.OutOfSync ||
408 version.getState().isDirty())) {
409 forceSync(itemId, version);
410 LOGGER.info("Item Id {}, version Id {}: Force sync is done", itemId, version.getId());
411 version = versionDao.get(itemId, version)
412 .orElseThrow(() -> new IllegalStateException(
413 "Get version after a successful force sync must return the version"));
418 private Version getSyncedVersion(String itemId, Version version) {
419 sync(itemId, version);
420 LOGGER.info("Item Id {}, version Id {}: First time sync is done", itemId, version.getId());
421 return versionDao.get(itemId, version)
422 .orElseThrow(() -> new IllegalStateException(
423 "Get version after a successful sync must return the version"));
427 public Version create(String itemId, Version version, VersionCreationMethod creationMethod) {
428 String baseVersionName = null;
429 if (version.getBaseId() == null) {
430 version.setDescription("Initial version");
432 baseVersionName = get(itemId, new Version(version.getBaseId())).getName();
434 String versionName = versionCalculator.calculate(baseVersionName, creationMethod);
435 validateVersionName(itemId, versionName);
436 version.setName(versionName);
438 versionDao.create(itemId, version);
439 itemManager.updateVersionStatus(itemId, VersionStatus.Draft, null);
441 publish(itemId, version, String.format("Create version: %s", version.getName()));
445 private void validateVersionName(String itemId, String versionName) {
446 if (versionDao.list(itemId).stream()
447 .anyMatch(version -> versionName.equals(version.getName()))) {
448 String errorDescription = String
449 .format("Item %s: create version failed, a version with the name %s already exist",
450 itemId, versionName);
451 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
452 .withMessage(errorDescription)
458 public void submit(String itemId, Version version, String submitDescription) {
459 version = get(itemId, version);
461 validateSubmit(itemId, version);
463 version.setStatus(VersionStatus.Certified);
464 versionDao.update(itemId, version);
466 publish(itemId, version, submitDescription);
468 itemManager.updateVersionStatus(itemId, VersionStatus.Certified, VersionStatus.Draft);
471 private void validateSubmit(String itemId, Version version) {
472 if (version.getStatus() == VersionStatus.Certified) {
473 String errorDescription = String
474 .format("Item %s: submit version failed, version %s is already Certified", itemId,
476 throw new CoreException(new ErrorCode.ErrorCodeBuilder()
477 .withMessage(errorDescription)
483 public void publish(String itemId, Version version, String message) {
484 versionDao.publish(itemId, version, message);
489 public void sync(String itemId, Version version) {
490 versionDao.sync(itemId, version);
494 public void forceSync(String itemId, Version version) {
495 versionDao.forceSync(itemId, version);
499 public void revert(String itemId, Version version, String revisionId) {
500 versionDao.revert(itemId, version, revisionId);
504 public List<Revision> listRevisions(String itemId, Version version) {
505 return versionDao.listRevisions(itemId, version);
508 private void markAsCheckedOut(VersionInfoEntity versionInfoEntity, String checkingOutUser) {
509 versionInfoEntity.setStatus(VersionStatus.Locked);
510 versionInfoEntity.setCandidate(new UserCandidateVersion(checkingOutUser,
511 versionInfoEntity.getActiveVersion().calculateNextCandidate()));
514 private Version doCheckout(VersionInfoEntity versionInfoEntity, String user) {
515 markAsCheckedOut(versionInfoEntity, user);
516 versionInfoDao.update(versionInfoEntity);
518 initVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
519 versionInfoEntity.getActiveVersion(), versionInfoEntity.getCandidate().getVersion());
521 return versionInfoEntity.getCandidate().getVersion();
524 private void doDelete(VersionInfoEntity versionInfoEntity) {
525 VersionInfoDeletedEntity versionInfoDeletedEntity = new VersionInfoDeletedEntity();
526 versionInfoDeletedEntity.setStatus(versionInfoEntity.getStatus());
527 versionInfoDeletedEntity.setViewableVersions(versionInfoEntity.getViewableVersions());
528 versionInfoDeletedEntity.setActiveVersion(versionInfoEntity.getActiveVersion());
529 versionInfoDeletedEntity.setCandidate(versionInfoEntity.getCandidate());
530 versionInfoDeletedEntity.setEntityId(versionInfoEntity.getEntityId());
531 versionInfoDeletedEntity.setEntityType(versionInfoEntity.getEntityType());
532 versionInfoDeletedEntity.setLatestFinalVersion(versionInfoEntity.getLatestFinalVersion());
533 versionInfoDeletedDao.create(versionInfoDeletedEntity);
534 versionInfoDao.delete(versionInfoEntity);
537 private void doUndoDelete(VersionInfoDeletedEntity versionInfoDeletedEntity) {
538 VersionInfoEntity versionInfoEntity = new VersionInfoEntity();
539 versionInfoEntity.setStatus(versionInfoDeletedEntity.getStatus());
540 versionInfoEntity.setViewableVersions(versionInfoDeletedEntity.getViewableVersions());
541 versionInfoEntity.setActiveVersion(versionInfoDeletedEntity.getActiveVersion());
542 versionInfoEntity.setCandidate(versionInfoDeletedEntity.getCandidate());
543 versionInfoEntity.setEntityId(versionInfoDeletedEntity.getEntityId());
544 versionInfoEntity.setEntityType(versionInfoDeletedEntity.getEntityType());
545 versionInfoEntity.setLatestFinalVersion(versionInfoDeletedEntity.getLatestFinalVersion());
546 versionInfoDao.create(versionInfoEntity);
547 versionInfoDeletedDao.delete(versionInfoDeletedEntity);
550 private Version doCheckin(VersionInfoEntity versionInfoEntity) {
551 UserCandidateVersion userCandidateVersion = versionInfoEntity.getCandidate();
552 versionInfoEntity.setCandidate(null);
553 versionInfoEntity.setActiveVersion(userCandidateVersion.getVersion());
554 versionInfoEntity.getViewableVersions().add(versionInfoEntity.getActiveVersion());
555 versionInfoEntity.setStatus(VersionStatus.Draft);
557 closeVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
558 versionInfoEntity.getActiveVersion());
560 versionInfoDao.update(versionInfoEntity);
562 return versionInfoEntity.getActiveVersion();
565 private Version doSubmit(VersionInfoEntity versionInfoEntity) {
566 Version finalVersion = versionInfoEntity.getActiveVersion().calculateNextFinal();
567 initVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
568 versionInfoEntity.getActiveVersion(), finalVersion);
569 closeVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
572 Set<Version> viewableVersions = new HashSet<>();
573 for (Version version : versionInfoEntity.getViewableVersions()) {
574 if (version.isFinal()) {
575 viewableVersions.add(version);
578 viewableVersions.add(finalVersion);
579 versionInfoEntity.setViewableVersions(viewableVersions);
580 versionInfoEntity.setActiveVersion(finalVersion);
581 versionInfoEntity.setLatestFinalVersion(finalVersion);
582 versionInfoEntity.setStatus(VersionStatus.Certified);
583 versionInfoDao.update(versionInfoEntity);
588 private void initVersionOnEntity(String entityType, String entityId, Version baseVersion,
589 Version newVersion) {
590 Set<VersionableEntityMetadata> entityMetadatas = VERSIONABLE_ENTITIES.get(entityType);
591 if (entityMetadatas != null) {
592 for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
593 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
594 .initVersion(entityMetadata, entityId, baseVersion, newVersion);
599 private void deleteVersionFromEntity(String entityType, String entityId,
600 Version versionToDelete, Version backToVersion) {
601 Set<VersionableEntityMetadata> entityMetadatas = VERSIONABLE_ENTITIES.get(entityType);
602 if (entityMetadatas != null) {
603 for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
604 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
605 .deleteVersion(entityMetadata, entityId, versionToDelete, backToVersion);
610 private void closeVersionOnEntity(String entityType, String entityId, Version versionToClose) {
611 Set<VersionableEntityMetadata> entityMetadatas = VERSIONABLE_ENTITIES.get(entityType);
612 if (entityMetadatas != null) {
613 for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
614 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
615 .closeVersion(entityMetadata, entityId, versionToClose);