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.versioning.VersioningManager;
25 import org.openecomp.sdc.versioning.dao.VersionInfoDao;
26 import org.openecomp.sdc.versioning.dao.VersionInfoDaoFactory;
27 import org.openecomp.sdc.versioning.dao.VersionInfoDeletedDao;
28 import org.openecomp.sdc.versioning.dao.VersionInfoDeletedDaoFactory;
29 import org.openecomp.sdc.versioning.dao.VersionableEntityDao;
30 import org.openecomp.sdc.versioning.dao.VersionableEntityDaoFactory;
31 import org.openecomp.sdc.versioning.dao.types.UserCandidateVersion;
32 import org.openecomp.sdc.versioning.dao.types.Version;
33 import org.openecomp.sdc.versioning.dao.types.VersionHistoryEntity;
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.dao.types.VersionType;
38 import org.openecomp.sdc.versioning.dao.types.VersionableEntityId;
39 import org.openecomp.sdc.versioning.errors.CheckinOnEntityLockedByOtherErrorBuilder;
40 import org.openecomp.sdc.versioning.errors.CheckinOnUnlockedEntityErrorBuilder;
41 import org.openecomp.sdc.versioning.errors.CheckoutOnLockedEntityErrorBuilder;
42 import org.openecomp.sdc.versioning.errors.DeleteOnLockedEntityErrorBuilder;
43 import org.openecomp.sdc.versioning.errors.EditOnEntityLockedByOtherErrorBuilder;
44 import org.openecomp.sdc.versioning.errors.EditOnUnlockedEntityErrorBuilder;
45 import org.openecomp.sdc.versioning.errors.EntityAlreadyExistErrorBuilder;
46 import org.openecomp.sdc.versioning.errors.EntityAlreadyFinalizedErrorBuilder;
47 import org.openecomp.sdc.versioning.errors.EntityNotExistErrorBuilder;
48 import org.openecomp.sdc.versioning.errors.SubmitLockedEntityNotAllowedErrorBuilder;
49 import org.openecomp.sdc.versioning.errors.UndoCheckoutOnEntityLockedByOtherErrorBuilder;
50 import org.openecomp.sdc.versioning.errors.UndoCheckoutOnUnlockedEntityErrorBuilder;
51 import org.openecomp.sdc.versioning.types.VersionInfo;
52 import org.openecomp.sdc.versioning.types.VersionableEntityAction;
53 import org.openecomp.sdc.versioning.types.VersionableEntityMetadata;
55 import java.util.Collection;
56 import java.util.HashMap;
57 import java.util.HashSet;
58 import java.util.List;
61 import java.util.stream.Collectors;
63 public class VersioningManagerImpl implements VersioningManager {
65 private static final Version INITIAL_ACTIVE_VERSION = new Version(0, 0);
66 private static VersionInfoDao versionInfoDao =
67 VersionInfoDaoFactory.getInstance().createInterface();
68 private static VersionInfoDeletedDao versionInfoDeletedDao =
69 VersionInfoDeletedDaoFactory.getInstance().createInterface();
70 private static VersionableEntityDao versionableEntityDao =
71 VersionableEntityDaoFactory.getInstance().createInterface();
73 private static Map<String, Set<VersionableEntityMetadata>> versionableEntities = new HashMap<>();
75 private static VersionInfo getVersionInfo(VersionInfoEntity versionInfoEntity, String user,
76 VersionableEntityAction action) {
77 return getVersionInfo(versionInfoEntity.getEntityId(),
78 versionInfoEntity.getEntityType(),
79 versionInfoEntity.getActiveVersion(),
80 versionInfoEntity.getCandidate(),
81 versionInfoEntity.getStatus(),
82 versionInfoEntity.getLatestFinalVersion(),
83 versionInfoEntity.getViewableVersions(),
88 private static VersionInfo getVersionInfo(VersionInfoDeletedEntity versionInfoEntity, String user,
89 VersionableEntityAction action) {
90 return getVersionInfo(versionInfoEntity.getEntityId(),
91 versionInfoEntity.getEntityType(),
92 versionInfoEntity.getActiveVersion(),
93 versionInfoEntity.getCandidate(),
94 versionInfoEntity.getStatus(),
95 versionInfoEntity.getLatestFinalVersion(),
96 versionInfoEntity.getViewableVersions(),
101 private static VersionInfo getVersionInfo(String entityId, String entityType, Version activeVer,
102 UserCandidateVersion candidate, VersionStatus status,
103 Version latestFinalVersion,
104 Set<Version> viewableVersions,
105 VersionableEntityAction action, String user) {
106 Version activeVersion;
108 if (action == VersionableEntityAction.Write) {
109 if (candidate != null) {
110 if (user.equals(candidate.getUser())) {
111 activeVersion = candidate.getVersion();
113 throw new CoreException(
114 new EditOnEntityLockedByOtherErrorBuilder(entityType, entityId, candidate.getUser())
118 throw new CoreException(new EditOnUnlockedEntityErrorBuilder(entityType, entityId).build());
121 if (candidate != null && user.equals(candidate.getUser())) {
122 activeVersion = candidate.getVersion();
124 activeVersion = activeVer;
128 VersionInfo versionInfo = new VersionInfo();
129 versionInfo.setActiveVersion(activeVersion);
130 versionInfo.setLatestFinalVersion(latestFinalVersion);
131 versionInfo.setViewableVersions(toSortedList(viewableVersions));
132 versionInfo.setFinalVersions(getFinalVersions(viewableVersions));
133 versionInfo.setStatus(status);
134 if (candidate != null) {
135 versionInfo.setLockingUser(candidate.getUser());
136 if (user.equals(candidate.getUser())) {
137 versionInfo.getViewableVersions().add(candidate.getVersion());
143 private static List<Version> toSortedList(
144 Set<Version> versions) { // changing the Set to List in DB will require migration...
145 return versions.stream().sorted((o1, o2) -> {
146 return o1.getMajor() > o2.getMajor() ? 1
147 : o1.getMajor() == o2.getMajor() ? (o1.getMinor() > o2.getMinor() ? 1
148 : o1.getMinor() == o2.getMinor() ? 0 : -1) : -1;
149 }).collect(Collectors.toList());
152 private static List<Version> getFinalVersions(Set<Version> versions) {
153 return versions.stream().filter(version -> version.isFinal()).collect(Collectors.toList());
157 public void register(String entityType, VersionableEntityMetadata entityMetadata) {
158 Set<VersionableEntityMetadata> entitiesMetadata = versionableEntities.get(entityType);
159 if (entitiesMetadata == null) {
160 entitiesMetadata = new HashSet<>();
161 versionableEntities.put(entityType, entitiesMetadata);
163 entitiesMetadata.add(entityMetadata);
167 public Version create(String entityType, String entityId, String user) {
168 VersionInfoEntity versionInfoEntity =
169 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
170 if (versionInfoEntity != null) {
171 throw new CoreException(new EntityAlreadyExistErrorBuilder(entityType, entityId).build());
174 versionInfoEntity = new VersionInfoEntity(entityType, entityId);
175 versionInfoEntity.setActiveVersion(INITIAL_ACTIVE_VERSION);
176 markAsCheckedOut(versionInfoEntity, user);
177 versionInfoDao.create(versionInfoEntity);
179 return versionInfoEntity.getCandidate().getVersion();
183 public Version checkout(String entityType, String entityId, String user) {
184 VersionInfoEntity versionInfoEntity =
185 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
186 if (versionInfoEntity == null) {
187 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
190 Version checkoutVersion = null;
191 switch (versionInfoEntity.getStatus()) {
193 throw new CoreException(new CheckoutOnLockedEntityErrorBuilder(entityType, entityId,
194 versionInfoEntity.getCandidate().getUser()).build());
197 checkoutVersion = doCheckout(versionInfoEntity, user);
201 return checkoutVersion;
205 public Version undoCheckout(String entityType, String entityId, String user) {
206 VersionInfoEntity versionInfoEntity =
207 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
208 if (versionInfoEntity == null) {
209 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
212 Version activeVersion = null;
213 switch (versionInfoEntity.getStatus()) {
215 if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
216 throw new CoreException(
217 new UndoCheckoutOnEntityLockedByOtherErrorBuilder(entityType, entityId,
218 versionInfoEntity.getCandidate().getUser()).build());
220 activeVersion = undoCheckout(versionInfoEntity);
224 throw new CoreException(
225 new UndoCheckoutOnUnlockedEntityErrorBuilder(entityType, entityId).build());
228 return activeVersion;
231 private Version undoCheckout(VersionInfoEntity versionInfoEntity) {
232 deleteVersionFromEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
233 versionInfoEntity.getCandidate().getVersion());
235 versionInfoEntity.setStatus(versionInfoEntity.getActiveVersion().isFinal() ? VersionStatus.Final
236 : VersionStatus.Available);
237 versionInfoEntity.setCandidate(null);
238 versionInfoDao.update(versionInfoEntity);
239 return versionInfoEntity.getActiveVersion();
243 public Version checkin(String entityType, String entityId, String user,
244 String checkinDescription) {
245 VersionInfoEntity versionInfoEntity =
246 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
247 if (versionInfoEntity == null) {
248 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
251 Version checkedInVersion = null;
252 switch (versionInfoEntity.getStatus()) {
255 throw new CoreException(
256 new CheckinOnUnlockedEntityErrorBuilder(entityType, entityId).build());
258 if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
259 throw new CoreException(new CheckinOnEntityLockedByOtherErrorBuilder(entityType, entityId,
260 versionInfoEntity.getCandidate().getUser()).build());
262 checkedInVersion = doCheckin(versionInfoEntity, checkinDescription);
266 return checkedInVersion;
270 public Version submit(String entityType, String entityId, String user, String submitDescription) {
271 VersionInfoEntity versionInfoEntity =
272 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
273 if (versionInfoEntity == null) {
274 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
277 Version submitVersion = null;
278 switch (versionInfoEntity.getStatus()) {
280 throw new CoreException(
281 new EntityAlreadyFinalizedErrorBuilder(entityType, entityId).build());
283 throw new CoreException(new SubmitLockedEntityNotAllowedErrorBuilder(entityType, entityId,
284 versionInfoEntity.getCandidate().getUser()).build());
286 submitVersion = doSubmit(versionInfoEntity, user, submitDescription);
290 return submitVersion;
294 public VersionInfo getEntityVersionInfo(String entityType, String entityId, String user,
295 VersionableEntityAction action) {
296 VersionInfoEntity versionInfoEntity =
297 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
298 if (versionInfoEntity == null) {
299 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
301 return getVersionInfo(versionInfoEntity, user, action);
305 public Map<String, VersionInfo> listEntitiesVersionInfo(String entityType, String user,
306 VersionableEntityAction action) {
307 Collection<VersionInfoEntity> versionInfoEntities =
308 versionInfoDao.list(new VersionInfoEntity(entityType, null));
309 Map<String, VersionInfo> activeVersions = new HashMap<>();
310 for (VersionInfoEntity versionInfoEntity : versionInfoEntities) {
312 .put(versionInfoEntity.getEntityId(), getVersionInfo(versionInfoEntity, user, action));
314 return activeVersions;
318 public Map<String, VersionInfo> listDeletedEntitiesVersionInfo(String entityType, String user,
319 VersionableEntityAction action) {
320 Collection<VersionInfoDeletedEntity> versionInfoDeletedEntities =
321 versionInfoDeletedDao.list(new VersionInfoDeletedEntity(entityType, null));
322 Map<String, VersionInfo> activeVersions = new HashMap<>();
325 for (VersionInfoDeletedEntity versionInfoDeletedEntity : versionInfoDeletedEntities) {
326 activeVersions.put(versionInfoDeletedEntity.getEntityId(),
327 getVersionInfo(versionInfoDeletedEntity, user, action));
329 return activeVersions;
333 public void delete(String entityType, String entityId, String user) {
334 VersionInfoEntity versionInfoEntity =
335 versionInfoDao.get(new VersionInfoEntity(entityType, entityId));
336 if (versionInfoEntity == null) {
337 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
340 switch (versionInfoEntity.getStatus()) {
342 throw new CoreException(new DeleteOnLockedEntityErrorBuilder(entityType, entityId,
343 versionInfoEntity.getCandidate().getUser()).build());
347 doDelete(versionInfoEntity, user);
351 public void undoDelete(String entityType, String entityId, String user) {
352 VersionInfoDeletedEntity versionInfoDeletedEntity =
353 versionInfoDeletedDao.get(new VersionInfoDeletedEntity(entityType, entityId));
354 if (versionInfoDeletedEntity == null) {
355 throw new CoreException(new EntityNotExistErrorBuilder(entityType, entityId).build());
358 doUndoDelete(versionInfoDeletedEntity, user);
361 private void markAsCheckedOut(VersionInfoEntity versionInfoEntity, String checkingOutUser) {
362 versionInfoEntity.setStatus(VersionStatus.Locked);
363 versionInfoEntity.setCandidate(new UserCandidateVersion(checkingOutUser,
364 versionInfoEntity.getActiveVersion().calculateNextCandidate()));
367 private Version doCheckout(VersionInfoEntity versionInfoEntity, String user) {
368 markAsCheckedOut(versionInfoEntity, user);
369 versionInfoDao.update(versionInfoEntity);
371 initVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
372 versionInfoEntity.getActiveVersion(), versionInfoEntity.getCandidate().getVersion());
374 return versionInfoEntity.getCandidate().getVersion();
377 private void doDelete(VersionInfoEntity versionInfoEntity, String user) {
379 VersionInfoDeletedEntity versionInfoDeletedEntity = new VersionInfoDeletedEntity();
380 versionInfoDeletedEntity.setStatus(versionInfoEntity.getStatus());
381 versionInfoDeletedEntity.setViewableVersions(versionInfoEntity.getViewableVersions());
382 versionInfoDeletedEntity.setActiveVersion(versionInfoEntity.getActiveVersion());
383 versionInfoDeletedEntity.setCandidate(versionInfoEntity.getCandidate());
384 versionInfoDeletedEntity.setEntityId(versionInfoEntity.getEntityId());
385 versionInfoDeletedEntity.setEntityType(versionInfoEntity.getEntityType());
386 versionInfoDeletedEntity.setLatestFinalVersion(versionInfoEntity.getLatestFinalVersion());
387 versionInfoDeletedDao.create(versionInfoDeletedEntity);
388 versionInfoDao.delete(versionInfoEntity);
392 private void doUndoDelete(VersionInfoDeletedEntity versionInfoDeletedEntity, String user) {
394 VersionInfoEntity versionInfoEntity = new VersionInfoEntity();
395 versionInfoEntity.setStatus(versionInfoDeletedEntity.getStatus());
396 versionInfoEntity.setViewableVersions(versionInfoDeletedEntity.getViewableVersions());
397 versionInfoEntity.setActiveVersion(versionInfoDeletedEntity.getActiveVersion());
398 versionInfoEntity.setCandidate(versionInfoDeletedEntity.getCandidate());
399 versionInfoEntity.setEntityId(versionInfoDeletedEntity.getEntityId());
400 versionInfoEntity.setEntityType(versionInfoDeletedEntity.getEntityType());
401 versionInfoEntity.setLatestFinalVersion(versionInfoDeletedEntity.getLatestFinalVersion());
402 versionInfoDao.create(versionInfoEntity);
403 versionInfoDeletedDao.delete(versionInfoDeletedEntity);
407 private Version doCheckin(VersionInfoEntity versionInfoEntity, String checkinDescription) {
408 UserCandidateVersion userCandidateVersion = versionInfoEntity.getCandidate();
409 versionInfoEntity.setCandidate(null);
410 versionInfoEntity.setActiveVersion(userCandidateVersion.getVersion());
411 versionInfoEntity.getViewableVersions().add(versionInfoEntity.getActiveVersion());
412 versionInfoEntity.setStatus(VersionStatus.Available);
413 versionInfoDao.update(versionInfoEntity);
415 return versionInfoEntity.getActiveVersion();
418 private Version doSubmit(VersionInfoEntity versionInfoEntity, String submittingUser,
419 String submitDescription) {
420 Version finalVersion = versionInfoEntity.getActiveVersion().calculateNextFinal();
421 initVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
422 versionInfoEntity.getActiveVersion(), finalVersion);
424 Set<Version> viewableVersions = new HashSet<>();
425 for (Version version : versionInfoEntity.getViewableVersions()) {
426 if (version.isFinal()) {
427 viewableVersions.add(version);
430 viewableVersions.add(finalVersion);
431 versionInfoEntity.setViewableVersions(viewableVersions);
432 versionInfoEntity.setActiveVersion(finalVersion);
433 versionInfoEntity.setLatestFinalVersion(finalVersion);
434 versionInfoEntity.setStatus(VersionStatus.Final);
435 versionInfoDao.update(versionInfoEntity);
440 private void createVersionHistory(VersionableEntityId entityId, Version version, String user,
441 String description, VersionType type) {
442 VersionHistoryEntity versionHistory = new VersionHistoryEntity(entityId);
443 versionHistory.setVersion(version);
444 versionHistory.setUser(user);
445 versionHistory.setDescription(description);
446 versionHistory.setType(type);
449 private void initVersionOnEntity(String entityType, String entityId, Version baseVersion,
450 Version newVersion) {
451 Set<VersionableEntityMetadata> entityMetadatas = versionableEntities.get(entityType);
452 if (entityMetadatas != null) {
453 for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
454 versionableEntityDao.initVersion(entityMetadata, entityId, baseVersion, newVersion);
459 private void deleteVersionFromEntity(String entityType, String entityId,
460 Version versionToDelete) {
461 Set<VersionableEntityMetadata> entityMetadatas = versionableEntities.get(entityType);
462 if (entityMetadatas != null) {
463 for (VersionableEntityMetadata entityMetadata : entityMetadatas) {
464 versionableEntityDao.deleteVersion(entityMetadata, entityId, versionToDelete);