Unit Tests
[sdc.git] / openecomp-be / lib / openecomp-core-lib / openecomp-zusammen-lib / openecomp-zusammen-plugin / src / main / java / org / openecomp / core / zusammen / plugin / collaboration / PublishService.java
1 package org.openecomp.core.zusammen.plugin.collaboration;
2
3 import com.amdocs.zusammen.datatypes.Id;
4 import com.amdocs.zusammen.datatypes.SessionContext;
5 import com.amdocs.zusammen.datatypes.item.Action;
6 import com.amdocs.zusammen.datatypes.item.ElementContext;
7 import com.amdocs.zusammen.datatypes.response.ReturnCode;
8 import com.amdocs.zusammen.datatypes.response.ZusammenException;
9 import com.amdocs.zusammen.sdk.collaboration.types.CollaborationMergeChange;
10 import com.amdocs.zusammen.sdk.collaboration.types.CollaborationPublishResult;
11 import org.openecomp.core.zusammen.plugin.dao.types.ElementEntity;
12 import org.openecomp.core.zusammen.plugin.dao.types.SynchronizationStateEntity;
13 import org.openecomp.core.zusammen.plugin.dao.types.VersionEntity;
14
15 import java.util.Collection;
16 import java.util.Date;
17 import java.util.Map;
18 import java.util.Optional;
19 import java.util.UUID;
20
21 import static com.amdocs.zusammen.datatypes.response.Module.ZCSP;
22 import static org.openecomp.core.zusammen.plugin.ZusammenPluginConstants.ROOT_ELEMENTS_PARENT_ID;
23 import static org.openecomp.core.zusammen.plugin.ZusammenPluginUtil.convertToElementChange;
24 import static org.openecomp.core.zusammen.plugin.ZusammenPluginUtil.convertToVersionChange;
25 import static org.openecomp.core.zusammen.plugin.collaboration.ErrorCode.NO_CHANGES_TO_PUBLISH;
26
27 public class PublishService {
28   // TODO: 6/29/2017 throw ZusammenException with ReturnCode when needed.
29   private static final String PUSH_NON_EXISTING_VERSION =
30       "Item Id %s, version Id %s: Non existing version cannot be pushed.";
31
32   private VersionPublicStore versionPublicStore;
33   private VersionPrivateStore versionPrivateStore;
34   private ElementPublicStore elementPublicStore;
35   private ElementPrivateStore elementPrivateStore;
36
37   public PublishService(VersionPublicStore versionPublicStore,
38                         VersionPrivateStore versionPrivateStore,
39                         ElementPublicStore elementPublicStore,
40                         ElementPrivateStore elementPrivateStore) {
41     this.versionPublicStore = versionPublicStore;
42     this.versionPrivateStore = versionPrivateStore;
43     this.elementPublicStore = elementPublicStore;
44     this.elementPrivateStore = elementPrivateStore;
45   }
46
47   public CollaborationPublishResult publish(SessionContext context, Id itemId, Id versionId,
48                                             String message) {
49     CollaborationPublishResult result = new CollaborationPublishResult();
50     result.setChange(new CollaborationMergeChange());
51
52     Date publishTime = new Date();
53     Id revisionId = new Id(UUID.randomUUID().toString());
54     boolean versionFirstPublication = publishVersion(context, itemId, versionId, revisionId,
55         publishTime,message);
56     if (versionFirstPublication) {
57       publishAllElements(context, new ElementContext(itemId, versionId, revisionId), publishTime,
58           result);
59     } else {
60       publishDirtyElements(context, new ElementContext(itemId, versionId, revisionId), publishTime,
61           result);
62     }
63     return result;
64   }
65
66   private boolean publishVersion(SessionContext context, Id itemId, Id versionId, Id revisionId,
67                                  Date publishTime, String message) {
68     SynchronizationStateEntity privateVersionSyncState =
69         versionPrivateStore.getSynchronizationState(context, itemId, versionId)
70             .orElseThrow(() -> new IllegalArgumentException(
71                 String.format(PUSH_NON_EXISTING_VERSION, itemId.toString(), versionId.toString())));
72
73     if (!privateVersionSyncState.isDirty()) {
74       throw new ZusammenException(new ReturnCode(NO_CHANGES_TO_PUBLISH, ZCSP,
75           String.format(Message.NO_CHANGES_TO_PUBLISH, itemId, versionId), null));
76     }
77
78     Optional<SynchronizationStateEntity> publicVersionSyncState =
79         versionPublicStore.getSynchronizationState(context, itemId, versionId);
80
81     // private must be synced with public (if public exists)
82     if (publicVersionSyncState.isPresent() &&
83         !privateVersionSyncState.getPublishTime()
84             .equals(publicVersionSyncState.get().getPublishTime())) {
85       // should not happen as it is validated in zusammen-core
86       throw new UnsupportedOperationException("Out of sync item version can not be publish");
87     }
88
89     boolean versionFirstPublication;
90     Map<Id, Id> versionElementIds =
91         elementPublicStore.listIds(context, new ElementContext(itemId,
92             versionId));
93     if (publicVersionSyncState.isPresent()) {
94       versionPublicStore.update(context, itemId, new VersionEntity(versionId), revisionId,
95           versionElementIds,publishTime,message);
96       versionFirstPublication = false;
97     } else {
98       VersionEntity privateVersion = versionPrivateStore.get(context, itemId, versionId)
99           .orElseThrow(() -> new IllegalArgumentException(
100               String.format(PUSH_NON_EXISTING_VERSION, itemId.toString(), versionId.toString())));
101       versionPublicStore.create(context, itemId, privateVersion, revisionId,versionElementIds,
102           publishTime,message);
103       versionFirstPublication = true;
104     }
105     versionPrivateStore.markAsPublished(context, itemId, versionId, publishTime);
106     return versionFirstPublication;
107   }
108
109   private void publishAllElements(SessionContext context, ElementContext elementContext,
110                                   Date publishTime, CollaborationPublishResult result) {
111     Collection<SynchronizationStateEntity> privateElementSyncStates =
112         elementPrivateStore.listSynchronizationStates(context, elementContext);
113
114     for (SynchronizationStateEntity privateElementSyncState : privateElementSyncStates) {
115       Optional<ElementEntity> privateElement =
116           elementPrivateStore.get(context, elementContext, privateElementSyncState.getId());
117
118       if (!privateElement.isPresent()) {
119         continue;
120       }
121       ElementEntity elementToPublish = privateElement.get();
122
123       elementPublicStore.create(context, elementContext, elementToPublish,
124           privateElementSyncState.isDirty() ? publishTime
125               : privateElementSyncState.getPublishTime());
126
127       if (privateElementSyncState.isDirty()) {
128         elementPrivateStore
129             .markAsPublished(context, elementContext, privateElementSyncState.getId(), publishTime);
130       }
131       updateResult(elementContext, elementToPublish, Action.CREATE,
132           ROOT_ELEMENTS_PARENT_ID.equals(privateElementSyncState.getId()), result);
133     }
134   }
135
136   private void publishDirtyElements(SessionContext context, ElementContext elementContext,
137                                     Date publishTime, CollaborationPublishResult result) {
138
139     Id revisionId = elementContext.getRevisionId();
140     elementContext.setRevisionId(revisionId);
141     ElementContext privateElementContext = new ElementContext(elementContext.getItemId(),
142         elementContext.getVersionId(),Id.ZERO);
143     Collection<SynchronizationStateEntity> privateElementSyncStates =
144         elementPrivateStore.listSynchronizationStates(context, elementContext);
145
146     Collection<SynchronizationStateEntity> publicElementSyncStates =
147         elementPublicStore.listSynchronizationStates(context, elementContext);
148
149     for (SynchronizationStateEntity privateElementSyncState : privateElementSyncStates) {
150       if (!privateElementSyncState.isDirty()) {
151         continue;
152       }
153
154       Optional<ElementEntity> privateElement =
155           elementPrivateStore.get(context, privateElementContext, privateElementSyncState.getId());
156
157       ElementEntity elementToPublish;
158       Action actionOnPublic;
159       if (privateElement.isPresent()) {
160         elementToPublish = privateElement.get();
161
162         if (publicElementSyncStates.contains(privateElementSyncState)) {
163
164           elementPublicStore.update(context, elementContext, elementToPublish, publishTime);
165           actionOnPublic = Action.UPDATE;
166         } else {
167           elementPublicStore.create(context, elementContext, elementToPublish, publishTime);
168           actionOnPublic = Action.CREATE;
169         }
170
171         elementPrivateStore
172             .markAsPublished(context, privateElementContext, privateElementSyncState.getId(), publishTime);
173       } else {
174         elementToPublish =
175             elementPublicStore.get(context, elementContext, privateElementSyncState.getId())
176                 .orElseThrow(() -> new IllegalStateException(
177                     "Element that should be deleted from public must exist there"));
178         elementPublicStore.delete(context, elementContext, elementToPublish, publishTime);
179         actionOnPublic = Action.DELETE;
180
181         elementPrivateStore
182             .markDeletionAsPublished(context, privateElementContext, privateElementSyncState.getId(),
183                 publishTime);
184       }
185
186       updateResult(elementContext, elementToPublish, actionOnPublic,
187           ROOT_ELEMENTS_PARENT_ID.equals(privateElementSyncState.getId()), result);
188     }
189   }
190
191   private void updateResult(ElementContext elementContext, ElementEntity element,
192                             Action action, boolean versionDataElement,
193                             CollaborationPublishResult result) {
194     if (versionDataElement) {
195       result.getChange().setChangedVersion(convertToVersionChange(elementContext, element, action));
196     } else {
197       result.getChange().getChangedElements()
198           .add(convertToElementChange(elementContext, element, action));
199     }
200   }
201 }