a69e86258222a870fe4d5d9a4a1d59ab381ae7bf
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
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
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package org.openecomp.sdc.versioning.impl;
17
18 import java.util.Collection;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Set;
24 import java.util.stream.Collectors;
25 import org.openecomp.sdc.common.errors.CoreException;
26 import org.openecomp.sdc.common.errors.ErrorCategory;
27 import org.openecomp.sdc.common.errors.ErrorCode;
28 import org.openecomp.sdc.logging.api.Logger;
29 import org.openecomp.sdc.logging.api.LoggerFactory;
30 import org.openecomp.sdc.versioning.ActionVersioningManager;
31 import org.openecomp.sdc.versioning.AsdcItemManager;
32 import org.openecomp.sdc.versioning.VersionCalculator;
33 import org.openecomp.sdc.versioning.dao.VersionDao;
34 import org.openecomp.sdc.versioning.dao.VersionInfoDao;
35 import org.openecomp.sdc.versioning.dao.VersionInfoDeletedDao;
36 import org.openecomp.sdc.versioning.dao.VersionableEntityDaoFactory;
37 import org.openecomp.sdc.versioning.dao.types.Revision;
38 import org.openecomp.sdc.versioning.dao.types.SynchronizationState;
39 import org.openecomp.sdc.versioning.dao.types.UserCandidateVersion;
40 import org.openecomp.sdc.versioning.dao.types.Version;
41 import org.openecomp.sdc.versioning.dao.types.VersionInfoDeletedEntity;
42 import org.openecomp.sdc.versioning.dao.types.VersionInfoEntity;
43 import org.openecomp.sdc.versioning.dao.types.VersionStatus;
44 import org.openecomp.sdc.versioning.errors.CheckinOnEntityLockedByOtherErrorBuilder;
45 import org.openecomp.sdc.versioning.errors.CheckinOnUnlockedEntityErrorBuilder;
46 import org.openecomp.sdc.versioning.errors.CheckoutOnLockedEntityErrorBuilder;
47 import org.openecomp.sdc.versioning.errors.DeleteOnLockedEntityErrorBuilder;
48 import org.openecomp.sdc.versioning.errors.EditOnEntityLockedByOtherErrorBuilder;
49 import org.openecomp.sdc.versioning.errors.EditOnUnlockedEntityErrorBuilder;
50 import org.openecomp.sdc.versioning.errors.EntityAlreadyExistErrorBuilder;
51 import org.openecomp.sdc.versioning.errors.EntityAlreadyFinalizedErrorBuilder;
52 import org.openecomp.sdc.versioning.errors.EntityNotExistErrorBuilder;
53 import org.openecomp.sdc.versioning.errors.SubmitLockedEntityNotAllowedErrorBuilder;
54 import org.openecomp.sdc.versioning.errors.UndoCheckoutOnEntityLockedByOtherErrorBuilder;
55 import org.openecomp.sdc.versioning.errors.UndoCheckoutOnUnlockedEntityErrorBuilder;
56 import org.openecomp.sdc.versioning.types.VersionCreationMethod;
57 import org.openecomp.sdc.versioning.types.VersionInfo;
58 import org.openecomp.sdc.versioning.types.VersionableEntityAction;
59 import org.openecomp.sdc.versioning.types.VersionableEntityMetadata;
60
61 public class ActionVersioningManagerImpl implements ActionVersioningManager {
62
63     private static final Logger LOGGER = LoggerFactory.getLogger(ActionVersioningManagerImpl.class);
64     private static final Version INITIAL_ACTIVE_VERSION = new Version(0, 0);
65     private static final Map<String, Set<VersionableEntityMetadata>> VERSIONABLE_ENTITIES = new HashMap<>();
66     private final VersionInfoDao versionInfoDao;
67     private final VersionInfoDeletedDao versionInfoDeletedDao;
68     private VersionDao versionDao;
69     private VersionCalculator versionCalculator;
70     private AsdcItemManager asdcItemManager;
71
72     public ActionVersioningManagerImpl(VersionInfoDao versionInfoDao, VersionInfoDeletedDao versionInfoDeletedDao, VersionDao versionDao,
73                                        VersionCalculator versionCalculator, AsdcItemManager asdcItemManager) {
74         this.versionInfoDao = versionInfoDao;
75         this.versionInfoDeletedDao = versionInfoDeletedDao;
76         this.versionDao = versionDao;
77         this.versionCalculator = versionCalculator;
78         this.asdcItemManager = asdcItemManager;
79     }
80
81     private static VersionInfo getVersionInfo(VersionInfoEntity versionInfoEntity, String user, VersionableEntityAction action) {
82         return getVersionInfo(versionInfoEntity.getEntityId(), versionInfoEntity.getEntityType(), versionInfoEntity.getActiveVersion(),
83             versionInfoEntity.getCandidate(), versionInfoEntity.getStatus(), versionInfoEntity.getLatestFinalVersion(),
84             versionInfoEntity.getViewableVersions(), action, user);
85     }
86
87     private static VersionInfo getVersionInfo(VersionInfoDeletedEntity versionInfoEntity, String user, VersionableEntityAction action) {
88         return getVersionInfo(versionInfoEntity.getEntityId(), versionInfoEntity.getEntityType(), versionInfoEntity.getActiveVersion(),
89             versionInfoEntity.getCandidate(), versionInfoEntity.getStatus(), versionInfoEntity.getLatestFinalVersion(),
90             versionInfoEntity.getViewableVersions(), action, user);
91     }
92
93     private static VersionInfo getVersionInfo(String entityId, String entityType, Version activeVer, UserCandidateVersion candidate,
94                                               VersionStatus status, Version latestFinalVersion, Set<Version> viewableVersions,
95                                               VersionableEntityAction action, String user) {
96         Version activeVersion;
97         if (action == VersionableEntityAction.Write) {
98             if (candidate != null) {
99                 if (user.equals(candidate.getUser())) {
100                     activeVersion = candidate.getVersion();
101                 } else {
102                     throw new CoreException(new EditOnEntityLockedByOtherErrorBuilder(entityType, entityId, candidate.getUser()).build());
103                 }
104             } else {
105                 throw new CoreException(new EditOnUnlockedEntityErrorBuilder(entityType, entityId).build());
106             }
107         } else {
108             if (candidate != null && user.equals(candidate.getUser())) {
109                 activeVersion = candidate.getVersion();
110             } else {
111                 activeVersion = activeVer;
112             }
113         }
114         VersionInfo versionInfo = new VersionInfo();
115         versionInfo.setStatus(status);
116         activeVersion.setStatus(status);
117         if (latestFinalVersion != null) {
118             latestFinalVersion.setStatus(status);
119         }
120         if (viewableVersions != null) {
121             viewableVersions.forEach(version -> version.setStatus(status));
122             versionInfo.setViewableVersions(toSortedList(viewableVersions));
123             versionInfo.setFinalVersions(getFinalVersions(viewableVersions));
124         }
125         versionInfo.setActiveVersion(activeVersion);
126         versionInfo.setLatestFinalVersion(latestFinalVersion);
127         if (candidate != null) {
128             candidate.getVersion().setStatus(status);
129             versionInfo.setLockingUser(candidate.getUser());
130             if (user.equals(candidate.getUser())) {
131                 versionInfo.getViewableVersions().add(candidate.getVersion());
132             }
133         }
134         return versionInfo;
135     }
136
137     private static List<Version> toSortedList(
138         Set<Version> versions) { // changing the Set to List in DB will require migration...
139         return versions.stream().sorted((o1, o2) -> o1.getMajor() > o2.getMajor() ? 1
140             : o1.getMajor() == o2.getMajor() ? (o1.getMinor() > o2.getMinor() ? 1 : o1.getMinor() == o2.getMinor() ? 0 : -1) : -1)
141             .collect(Collectors.toList());
142     }
143
144     private static List<Version> getFinalVersions(Set<Version> versions) {
145         return versions.stream().filter(Version::isFinal).collect(Collectors.toList());
146     }
147
148     @Override
149     public void register(String entityType, VersionableEntityMetadata entityMetadata) {
150         Set<VersionableEntityMetadata> entitiesMetadata = VERSIONABLE_ENTITIES.computeIfAbsent(entityType, k -> new HashSet<>());
151         entitiesMetadata.add(entityMetadata);
152     }
153
154     @Override
155     public Version create(String entityType, String entityId, String user) {
156         VersionInfoEntity versionInfoEntity = versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
157         if (versionInfoEntity != null) {
158             throw new CoreException(new EntityAlreadyExistErrorBuilder(entityType, entityId).build());
159         }
160         versionInfoEntity = new VersionInfoEntity(entityType, entityId);
161         versionInfoEntity.setActiveVersion(INITIAL_ACTIVE_VERSION);
162         markAsCheckedOut(versionInfoEntity, user);
163         versionInfoDao.create(versionInfoEntity);
164         return versionInfoEntity.getCandidate().getVersion();
165     }
166
167     @Override
168     public void delete(String entityType, String entityId, String user) {
169         VersionInfoEntity versionInfoEntity = versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
170         if (versionInfoEntity == null) {
171             throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
172         }
173         switch (versionInfoEntity.getStatus()) {
174             case Locked:
175                 throw new CoreException(
176                     new DeleteOnLockedEntityErrorBuilder(entityType, entityId, versionInfoEntity.getCandidate().getUser()).build());
177             default:
178                 //do nothing
179                 break;
180         }
181         doDelete(versionInfoEntity);
182     }
183
184     @Override
185     public void undoDelete(String entityType, String entityId, String user) {
186         VersionInfoDeletedEntity versionInfoDeletedEntity = versionInfoDeletedDao.get(new VersionInfoDeletedEntity(entityType, entityId));
187         if (versionInfoDeletedEntity == null) {
188             throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
189         }
190         doUndoDelete(versionInfoDeletedEntity);
191     }
192
193     @Override
194     public Version checkout(String entityType, String entityId, String user) {
195         VersionInfoEntity versionInfoEntity = versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
196         if (versionInfoEntity == null) {
197             throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
198         }
199         Version checkoutVersion = null;
200         switch (versionInfoEntity.getStatus()) {
201             case Locked:
202                 throw new CoreException(
203                     new CheckoutOnLockedEntityErrorBuilder(entityType, entityId, versionInfoEntity.getCandidate().getUser()).build());
204             case Certified:
205             case Draft:
206                 checkoutVersion = doCheckout(versionInfoEntity, user);
207                 break;
208             default:
209                 //do nothing
210                 break;
211         }
212         return checkoutVersion;
213     }
214
215     @Override
216     public Version undoCheckout(String entityType, String entityId, String user) {
217         VersionInfoEntity versionInfoEntity = versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
218         if (versionInfoEntity == null) {
219             throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
220         }
221         Version activeVersion = null;
222         switch (versionInfoEntity.getStatus()) {
223             case Locked:
224                 if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
225                     throw new CoreException(
226                         new UndoCheckoutOnEntityLockedByOtherErrorBuilder(entityType, entityId, versionInfoEntity.getCandidate().getUser()).build());
227                 }
228                 activeVersion = undoCheckout(versionInfoEntity);
229                 break;
230             case Certified:
231             case Draft:
232                 throw new CoreException(new UndoCheckoutOnUnlockedEntityErrorBuilder(entityType, entityId).build());
233             default:
234                 //do nothing
235                 break;
236         }
237         return activeVersion;
238     }
239
240     private Version undoCheckout(VersionInfoEntity versionInfoEntity) {
241         deleteVersionFromEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(), versionInfoEntity.getCandidate().getVersion(),
242             versionInfoEntity.getActiveVersion());
243         versionInfoEntity.setStatus(versionInfoEntity.getActiveVersion().isFinal() ? VersionStatus.Certified : VersionStatus.Draft);
244         versionInfoEntity.setCandidate(null);
245         versionInfoDao.update(versionInfoEntity);
246         return versionInfoEntity.getActiveVersion();
247     }
248
249     @Override
250     public Version checkin(String entityType, String entityId, String user, String checkinDescription) {
251         VersionInfoEntity versionInfoEntity = versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
252         if (versionInfoEntity == null) {
253             throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
254         }
255         Version checkedInVersion = null;
256         switch (versionInfoEntity.getStatus()) {
257             case Draft:
258             case Certified:
259                 throw new CoreException(new CheckinOnUnlockedEntityErrorBuilder(entityType, entityId).build());
260             case Locked:
261                 if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
262                     throw new CoreException(
263                         new CheckinOnEntityLockedByOtherErrorBuilder(entityType, entityId, versionInfoEntity.getCandidate().getUser()).build());
264                 }
265                 checkedInVersion = doCheckin(versionInfoEntity, checkinDescription);
266                 break;
267             default:
268                 //do nothing
269                 break;
270         }
271         return checkedInVersion;
272     }
273
274     @Override
275     public Version submit(String entityType, String entityId, String user, String submitDescription) {
276         VersionInfoEntity versionInfoEntity = versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
277         if (versionInfoEntity == null) {
278             throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
279         }
280         Version submitVersion = null;
281         switch (versionInfoEntity.getStatus()) {
282             case Certified:
283                 throw new CoreException(new EntityAlreadyFinalizedErrorBuilder(entityType, entityId).build());
284             case Locked:
285                 throw new CoreException(
286                     new SubmitLockedEntityNotAllowedErrorBuilder(entityType, entityId, versionInfoEntity.getCandidate().getUser()).build());
287             case Draft:
288                 submitVersion = doSubmit(versionInfoEntity, user, submitDescription);
289                 break;
290             default:
291                 //do nothing
292                 break;
293         }
294         return submitVersion;
295     }
296
297     @Override
298     public VersionInfo getEntityVersionInfo(String entityType, String entityId, String user, VersionableEntityAction action) {
299         VersionInfoEntity versionInfoEntity = versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
300         if (versionInfoEntity == null) {
301             throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
302         }
303         return getVersionInfo(versionInfoEntity, user, action);
304     }
305
306     @Override
307     public Map<String, VersionInfo> listEntitiesVersionInfo(String entityType, String user, VersionableEntityAction action) {
308         Collection<VersionInfoEntity> versionInfoEntities = versionInfoDao.list(new VersionInfoEntity(entityType, null));
309         Map<String, VersionInfo> activeVersions = new HashMap<>();
310         for (VersionInfoEntity versionInfoEntity : versionInfoEntities) {
311             activeVersions.put(versionInfoEntity.getEntityId(), getVersionInfo(versionInfoEntity, user, action));
312         }
313         return activeVersions;
314     }
315
316     @Override
317     public Map<String, VersionInfo> listDeletedEntitiesVersionInfo(String entityType, String user, VersionableEntityAction action) {
318         Collection<VersionInfoDeletedEntity> versionInfoDeletedEntities = versionInfoDeletedDao.list(new VersionInfoDeletedEntity(entityType, null));
319         Map<String, VersionInfo> activeVersions = new HashMap<>();
320         for (VersionInfoDeletedEntity versionInfoDeletedEntity : versionInfoDeletedEntities) {
321             activeVersions.put(versionInfoDeletedEntity.getEntityId(), getVersionInfo(versionInfoDeletedEntity, user, action));
322         }
323         return activeVersions;
324     }
325
326     @Override
327     public List<Version> list(String itemId) {
328         List<Version> versions = versionDao.list(itemId);
329         Set<String> versionsNames = versions.stream().map(Version::getName).collect(Collectors.toSet());
330         versions.forEach(version -> {
331             version.setAdditionalInfo(new HashMap<>());
332             versionCalculator.injectAdditionalInfo(version, versionsNames);
333         });
334         return versions;
335     }
336
337     @Override
338     public Version get(String itemId, Version version) {
339         return versionDao.get(itemId, version).map(retrievedVersion -> getUpdateRetrievedVersion(itemId, retrievedVersion))
340             .orElseGet(() -> getSyncedVersion(itemId, version));
341     }
342
343     private Version getUpdateRetrievedVersion(String itemId, Version version) {
344         if (version.getStatus() == VersionStatus.Certified && (version.getState().getSynchronizationState() == SynchronizationState.OutOfSync
345             || version.getState().isDirty())) {
346             forceSync(itemId, version);
347             LOGGER.info("Item Id {}, version Id {}: Force sync is done", itemId, version.getId());
348             version = versionDao.get(itemId, version)
349                 .orElseThrow(() -> new IllegalStateException("Get version after a successful force sync must return the version"));
350         }
351         return version;
352     }
353
354     private Version getSyncedVersion(String itemId, Version version) {
355         sync(itemId, version);
356         LOGGER.info("Item Id {}, version Id {}: First time sync is done", itemId, version.getId());
357         return versionDao.get(itemId, version)
358             .orElseThrow(() -> new IllegalStateException("Get version after a successful sync must return the version"));
359     }
360
361     @Override
362     public Version create(String itemId, Version version, VersionCreationMethod creationMethod) {
363         String baseVersionName = null;
364         if (version.getBaseId() == null) {
365             version.setDescription("Initial version");
366         } else {
367             baseVersionName = get(itemId, new Version(version.getBaseId())).getName();
368         }
369         String versionName = versionCalculator.calculate(baseVersionName, creationMethod);
370         validateVersionName(itemId, versionName);
371         version.setName(versionName);
372         versionDao.create(itemId, version);
373         asdcItemManager.updateVersionStatus(itemId, VersionStatus.Draft, null);
374         publish(itemId, version, String.format("Create version: %s", version.getName()));
375         return version;
376     }
377
378     private void validateVersionName(String itemId, String versionName) {
379         if (versionDao.list(itemId).stream().anyMatch(version -> versionName.equals(version.getName()))) {
380             String errorDescription = String.format("Item %s: create version failed, a version with the name %s already exist", itemId, versionName);
381             throw new CoreException(new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION).withId("VERSION_NAME_ALREADY_EXIST")
382                 .withMessage(errorDescription).build());
383         }
384     }
385
386     @Override
387     public void submit(String itemId, Version version, String submitDescription) {
388         version = get(itemId, version);
389         validateSubmit(itemId, version);
390         version.setStatus(VersionStatus.Certified);
391         versionDao.update(itemId, version);
392         publish(itemId, version, submitDescription);
393         asdcItemManager.updateVersionStatus(itemId, VersionStatus.Certified, VersionStatus.Draft);
394     }
395
396     private void validateSubmit(String itemId, Version version) {
397         if (version.getStatus() == VersionStatus.Certified) {
398             String errorDescription = String.format("Item %s: submit version failed, version %s is already Certified", itemId, version.getId());
399             throw new CoreException(new ErrorCode.ErrorCodeBuilder().withCategory(ErrorCategory.APPLICATION).withId("VERSION_ALREADY_CERTIFIED")
400                 .withMessage(errorDescription).build());
401         }
402     }
403
404     @Override
405     public void publish(String itemId, Version version, String message) {
406         versionDao.publish(itemId, version, message);
407     }
408
409     @Override
410     public void sync(String itemId, Version version) {
411         versionDao.sync(itemId, version);
412     }
413
414     @Override
415     public void forceSync(String itemId, Version version) {
416         versionDao.forceSync(itemId, version);
417     }
418
419     @Override
420     public void revert(String itemId, Version version, String revisionId) {
421         versionDao.revert(itemId, version, revisionId);
422     }
423
424     @Override
425     public List<Revision> listRevisions(String itemId, Version version) {
426         return versionDao.listRevisions(itemId, version);
427     }
428
429     private void markAsCheckedOut(VersionInfoEntity versionInfoEntity, String checkingOutUser) {
430         versionInfoEntity.setStatus(VersionStatus.Locked);
431         versionInfoEntity.setCandidate(new UserCandidateVersion(checkingOutUser, versionInfoEntity.getActiveVersion().calculateNextCandidate()));
432     }
433
434     private Version doCheckout(VersionInfoEntity versionInfoEntity, String user) {
435         markAsCheckedOut(versionInfoEntity, user);
436         versionInfoDao.update(versionInfoEntity);
437         initVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(), versionInfoEntity.getActiveVersion(),
438             versionInfoEntity.getCandidate().getVersion());
439         return versionInfoEntity.getCandidate().getVersion();
440     }
441
442     private void doDelete(VersionInfoEntity versionInfoEntity) {
443         VersionInfoDeletedEntity versionInfoDeletedEntity = new VersionInfoDeletedEntity();
444         versionInfoDeletedEntity.setStatus(versionInfoEntity.getStatus());
445         versionInfoDeletedEntity.setViewableVersions(versionInfoEntity.getViewableVersions());
446         versionInfoDeletedEntity.setActiveVersion(versionInfoEntity.getActiveVersion());
447         versionInfoDeletedEntity.setCandidate(versionInfoEntity.getCandidate());
448         versionInfoDeletedEntity.setEntityId(versionInfoEntity.getEntityId());
449         versionInfoDeletedEntity.setEntityType(versionInfoEntity.getEntityType());
450         versionInfoDeletedEntity.setLatestFinalVersion(versionInfoEntity.getLatestFinalVersion());
451         versionInfoDeletedDao.create(versionInfoDeletedEntity);
452         versionInfoDao.delete(versionInfoEntity);
453     }
454
455     private void doUndoDelete(VersionInfoDeletedEntity versionInfoDeletedEntity) {
456         VersionInfoEntity versionInfoEntity = new VersionInfoEntity();
457         versionInfoEntity.setStatus(versionInfoDeletedEntity.getStatus());
458         versionInfoEntity.setViewableVersions(versionInfoDeletedEntity.getViewableVersions());
459         versionInfoEntity.setActiveVersion(versionInfoDeletedEntity.getActiveVersion());
460         versionInfoEntity.setCandidate(versionInfoDeletedEntity.getCandidate());
461         versionInfoEntity.setEntityId(versionInfoDeletedEntity.getEntityId());
462         versionInfoEntity.setEntityType(versionInfoDeletedEntity.getEntityType());
463         versionInfoEntity.setLatestFinalVersion(versionInfoDeletedEntity.getLatestFinalVersion());
464         versionInfoDao.create(versionInfoEntity);
465         versionInfoDeletedDao.delete(versionInfoDeletedEntity);
466     }
467
468     private Version doCheckin(VersionInfoEntity versionInfoEntity, String checkinDescription) {
469         UserCandidateVersion userCandidateVersion = versionInfoEntity.getCandidate();
470         versionInfoEntity.setCandidate(null);
471         versionInfoEntity.setActiveVersion(userCandidateVersion.getVersion());
472         versionInfoEntity.getViewableVersions().add(versionInfoEntity.getActiveVersion());
473         versionInfoEntity.setStatus(VersionStatus.Draft);
474         closeVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(), versionInfoEntity.getActiveVersion());
475         versionInfoDao.update(versionInfoEntity);
476         return versionInfoEntity.getActiveVersion();
477     }
478
479     private Version doSubmit(VersionInfoEntity versionInfoEntity, String submittingUser, String submitDescription) {
480         Version finalVersion = versionInfoEntity.getActiveVersion().calculateNextFinal();
481         initVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(), versionInfoEntity.getActiveVersion(), finalVersion);
482         closeVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(), finalVersion);
483         Set<Version> viewableVersions = new HashSet<>();
484         for (Version version : versionInfoEntity.getViewableVersions()) {
485             if (version.isFinal()) {
486                 viewableVersions.add(version);
487             }
488         }
489         viewableVersions.add(finalVersion);
490         versionInfoEntity.setViewableVersions(viewableVersions);
491         versionInfoEntity.setActiveVersion(finalVersion);
492         versionInfoEntity.setLatestFinalVersion(finalVersion);
493         versionInfoEntity.setStatus(VersionStatus.Certified);
494         versionInfoDao.update(versionInfoEntity);
495         return finalVersion;
496     }
497
498     private void initVersionOnEntity(String entityType, String entityId, Version baseVersion, Version newVersion) {
499         Set<VersionableEntityMetadata> entityMetadatas = VERSIONABLE_ENTITIES.get(entityType);
500         if (entityMetadatas != null) {
501             for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
502                 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
503                     .initVersion(entityMetadata, entityId, baseVersion, newVersion);
504             }
505         }
506     }
507
508     private void deleteVersionFromEntity(String entityType, String entityId, Version versionToDelete, Version backToVersion) {
509         Set<VersionableEntityMetadata> entityMetadatas = VERSIONABLE_ENTITIES.get(entityType);
510         if (entityMetadatas != null) {
511             for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
512                 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
513                     .deleteVersion(entityMetadata, entityId, versionToDelete, backToVersion);
514             }
515         }
516     }
517
518     private void closeVersionOnEntity(String entityType, String entityId, Version versionToClose) {
519         Set<VersionableEntityMetadata> entityMetadatas = VERSIONABLE_ENTITIES.get(entityType);
520         if (entityMetadatas != null) {
521             for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
522                 VersionableEntityDaoFactory.getInstance().createInterface(entityMetadata.getStoreType())
523                     .closeVersion(entityMetadata, entityId, versionToClose);
524             }
525         }
526     }
527 }