push addional code
[sdc.git] / openecomp-be / lib / openecomp-sdc-versioning-lib / openecomp-sdc-versioning-core / src / main / java / org / openecomp / sdc / versioning / impl / VersioningManagerImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.openecomp.sdc.versioning.impl;
22
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;
54
55 import java.util.Collection;
56 import java.util.HashMap;
57 import java.util.HashSet;
58 import java.util.List;
59 import java.util.Map;
60 import java.util.Set;
61 import java.util.stream.Collectors;
62
63 public class VersioningManagerImpl implements VersioningManager {
64
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();
72
73   private static Map<String, Set<VersionableEntityMetadata>> versionableEntities = new HashMap<>();
74
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(),
84         action,
85         user);
86   }
87
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(),
97         action,
98         user);
99   }
100
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;
107
108     if (action == VersionableEntityAction.Write) {
109       if (candidate != null) {
110         if (user.equals(candidate.getUser())) {
111           activeVersion = candidate.getVersion();
112         } else {
113           throw new CoreException(
114               new EditOnEntityLockedByOtherErrorBuilder(entityType, entityId, candidate.getUser())
115                   .build());
116         }
117       } else {
118         throw new CoreException(new EditOnUnlockedEntityErrorBuilder(entityType, entityId).build());
119       }
120     } else {
121       if (candidate != null && user.equals(candidate.getUser())) {
122         activeVersion = candidate.getVersion();
123       } else {
124         activeVersion = activeVer;
125       }
126     }
127
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());
138       }
139     }
140     return versionInfo;
141   }
142
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());
150   }
151
152   private static List<Version> getFinalVersions(Set<Version> versions) {
153     return versions.stream().filter(version -> version.isFinal()).collect(Collectors.toList());
154   }
155
156   @Override
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);
162     }
163     entitiesMetadata.add(entityMetadata);
164   }
165
166   @Override
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());
172     }
173
174     versionInfoEntity = new VersionInfoEntity(entityType, entityId);
175     versionInfoEntity.setActiveVersion(INITIAL_ACTIVE_VERSION);
176     markAsCheckedOut(versionInfoEntity, user);
177     versionInfoDao.create(versionInfoEntity);
178
179     return versionInfoEntity.getCandidate().getVersion();
180   }
181
182   @Override
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());
188     }
189
190     Version checkoutVersion = null;
191     switch (versionInfoEntity.getStatus()) {
192       case Locked:
193         throw new CoreException(new CheckoutOnLockedEntityErrorBuilder(entityType, entityId,
194             versionInfoEntity.getCandidate().getUser()).build());
195       case Final:
196       case Available:
197         checkoutVersion = doCheckout(versionInfoEntity, user);
198         break;
199       default:
200     }
201     return checkoutVersion;
202   }
203
204   @Override
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());
210     }
211
212     Version activeVersion = null;
213     switch (versionInfoEntity.getStatus()) {
214       case Locked:
215         if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
216           throw new CoreException(
217               new UndoCheckoutOnEntityLockedByOtherErrorBuilder(entityType, entityId,
218                   versionInfoEntity.getCandidate().getUser()).build());
219         }
220         activeVersion = undoCheckout(versionInfoEntity);
221         break;
222       case Final:
223       case Available:
224         throw new CoreException(
225             new UndoCheckoutOnUnlockedEntityErrorBuilder(entityType, entityId).build());
226       default:
227     }
228     return activeVersion;
229   }
230
231   private Version undoCheckout(VersionInfoEntity versionInfoEntity) {
232     deleteVersionFromEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
233         versionInfoEntity.getCandidate().getVersion());
234
235     versionInfoEntity.setStatus(versionInfoEntity.getActiveVersion().isFinal() ? VersionStatus.Final
236         : VersionStatus.Available);
237     versionInfoEntity.setCandidate(null);
238     versionInfoDao.update(versionInfoEntity);
239     return versionInfoEntity.getActiveVersion();
240   }
241
242   @Override
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());
249     }
250
251     Version checkedInVersion = null;
252     switch (versionInfoEntity.getStatus()) {
253       case Available:
254       case Final:
255         throw new CoreException(
256             new CheckinOnUnlockedEntityErrorBuilder(entityType, entityId).build());
257       case Locked:
258         if (!user.equals(versionInfoEntity.getCandidate().getUser())) {
259           throw new CoreException(new CheckinOnEntityLockedByOtherErrorBuilder(entityType, entityId,
260               versionInfoEntity.getCandidate().getUser()).build());
261         }
262         checkedInVersion = doCheckin(versionInfoEntity, checkinDescription);
263         break;
264       default:
265     }
266     return checkedInVersion;
267   }
268
269   @Override
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());
275     }
276
277     Version submitVersion = null;
278     switch (versionInfoEntity.getStatus()) {
279       case Final:
280         throw new CoreException(
281             new EntityAlreadyFinalizedErrorBuilder(entityType, entityId).build());
282       case Locked:
283         throw new CoreException(new SubmitLockedEntityNotAllowedErrorBuilder(entityType, entityId,
284             versionInfoEntity.getCandidate().getUser()).build());
285       case Available:
286         submitVersion = doSubmit(versionInfoEntity, user, submitDescription);
287         break;
288       default:
289     }
290     return submitVersion;
291   }
292
293   @Override
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());
300     }
301     return getVersionInfo(versionInfoEntity, user, action);
302   }
303
304   @Override
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) {
311       activeVersions
312           .put(versionInfoEntity.getEntityId(), getVersionInfo(versionInfoEntity, user, action));
313     }
314     return activeVersions;
315   }
316
317   @Override
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<>();
323
324
325     for (VersionInfoDeletedEntity versionInfoDeletedEntity : versionInfoDeletedEntities) {
326       activeVersions.put(versionInfoDeletedEntity.getEntityId(),
327           getVersionInfo(versionInfoDeletedEntity, user, action));
328     }
329     return activeVersions;
330   }
331
332   @Override
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());
338     }
339
340     switch (versionInfoEntity.getStatus()) {
341       case Locked:
342         throw new CoreException(new DeleteOnLockedEntityErrorBuilder(entityType, entityId,
343             versionInfoEntity.getCandidate().getUser()).build());
344       default:
345     }
346
347     doDelete(versionInfoEntity, user);
348   }
349
350   @Override
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());
356     }
357
358     doUndoDelete(versionInfoDeletedEntity, user);
359   }
360
361   private void markAsCheckedOut(VersionInfoEntity versionInfoEntity, String checkingOutUser) {
362     versionInfoEntity.setStatus(VersionStatus.Locked);
363     versionInfoEntity.setCandidate(new UserCandidateVersion(checkingOutUser,
364         versionInfoEntity.getActiveVersion().calculateNextCandidate()));
365   }
366
367   private Version doCheckout(VersionInfoEntity versionInfoEntity, String user) {
368     markAsCheckedOut(versionInfoEntity, user);
369     versionInfoDao.update(versionInfoEntity);
370
371     initVersionOnEntity(versionInfoEntity.getEntityType(), versionInfoEntity.getEntityId(),
372         versionInfoEntity.getActiveVersion(), versionInfoEntity.getCandidate().getVersion());
373
374     return versionInfoEntity.getCandidate().getVersion();
375   }
376
377   private void doDelete(VersionInfoEntity versionInfoEntity, String user) {
378
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);
389
390   }
391
392   private void doUndoDelete(VersionInfoDeletedEntity versionInfoDeletedEntity, String user) {
393
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);
404
405   }
406
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);
414
415     return versionInfoEntity.getActiveVersion();
416   }
417
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);
423
424     Set<Version> viewableVersions = new HashSet<>();
425     for (Version version : versionInfoEntity.getViewableVersions()) {
426       if (version.isFinal()) {
427         viewableVersions.add(version);
428       }
429     }
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);
436
437     return finalVersion;
438   }
439
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);
447   }
448
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);
455       }
456     }
457   }
458
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);
465       }
466     }
467   }
468 }