1 package org.openecomp.core.zusammen.plugin.collaboration.impl;
3 import com.amdocs.zusammen.datatypes.Id;
4 import com.amdocs.zusammen.datatypes.SessionContext;
5 import com.amdocs.zusammen.datatypes.item.ElementContext;
6 import com.amdocs.zusammen.plugin.statestore.cassandra.dao.types.ElementEntityContext;
7 import org.openecomp.core.zusammen.plugin.ZusammenPluginConstants;
8 import org.openecomp.core.zusammen.plugin.collaboration.ElementPrivateStore;
9 import org.openecomp.core.zusammen.plugin.dao.ElementRepository;
10 import org.openecomp.core.zusammen.plugin.dao.ElementRepositoryFactory;
11 import org.openecomp.core.zusammen.plugin.dao.ElementSynchronizationStateRepository;
12 import org.openecomp.core.zusammen.plugin.dao.ElementSynchronizationStateRepositoryFactory;
13 import org.openecomp.core.zusammen.plugin.dao.types.ElementEntity;
14 import org.openecomp.core.zusammen.plugin.dao.types.SynchronizationStateEntity;
16 import java.util.Collection;
17 import java.util.Date;
18 import java.util.HashSet;
20 import java.util.Objects;
21 import java.util.Optional;
22 import java.util.stream.Collectors;
24 import static org.openecomp.core.zusammen.plugin.ZusammenPluginUtil.getPrivateElementContext;
25 import static org.openecomp.core.zusammen.plugin.ZusammenPluginUtil.getPrivateSpaceName;
27 public class ElementPrivateStoreImpl implements ElementPrivateStore {
28 private static final Id REVISION_ID = Id.ZERO; // the private revision id is Id.ZERO 0000000...
31 public Map<Id, Id> listIds(SessionContext context, ElementContext elementContext) {
32 return getElementRepository(context)
33 .listIds(context, new ElementEntityContext(getPrivateSpaceName(context), elementContext));
37 public Collection<ElementEntity> listSubs(SessionContext context, ElementContext elementContext,
39 if (elementId == null) {
40 elementId = ZusammenPluginConstants.ROOT_ELEMENTS_PARENT_ID;
43 ElementRepository elementRepository = getElementRepository(context);
44 ElementEntityContext privateContext =
45 new ElementEntityContext(getPrivateSpaceName(context), elementContext);
46 privateContext.setRevisionId(REVISION_ID);
47 return elementRepository.get(context, privateContext, new ElementEntity(elementId))
48 .map(ElementEntity::getSubElementIds).orElse(new HashSet<>()).stream()
49 .map(subElementId -> elementRepository
50 .get(context, privateContext, new ElementEntity(subElementId)).get())
51 .filter(Objects::nonNull)
52 .collect(Collectors.toList());
56 public Optional<ElementEntity> get(SessionContext context, ElementContext elementContext,
58 ElementEntityContext privateElementContext =
59 new ElementEntityContext(getPrivateSpaceName(context), elementContext);
60 privateElementContext.setRevisionId(REVISION_ID);
61 return getElementRepository(context)
62 .get(context, privateElementContext,
63 new ElementEntity(elementId));
67 public Optional<ElementEntity> getDescriptor(SessionContext context,
68 ElementContext elementContext, Id elementId) {
69 return getElementRepository(context)
70 .getDescriptor(context,
71 new ElementEntityContext(getPrivateSpaceName(context), getPrivateElementContext
73 new ElementEntity(elementId));
77 public Collection<SynchronizationStateEntity> listSynchronizationStates(SessionContext context,
78 ElementContext elementContext) {
79 ElementEntityContext privateElementContext =
80 new ElementEntityContext(getPrivateSpaceName(context), elementContext);
81 return getElementSyncStateRepository(context)
82 .list(context, privateElementContext);
86 public Optional<SynchronizationStateEntity> getSynchronizationState(SessionContext context,
87 ElementContext elementContext,
90 ElementEntityContext privateElementContext =
91 new ElementEntityContext(getPrivateSpaceName(context), getPrivateElementContext
93 return getElementSyncStateRepository(context)
94 .get(context, privateElementContext,
95 new SynchronizationStateEntity(elementId, REVISION_ID));
99 public void create(SessionContext context, ElementContext elementContext, ElementEntity element) {
100 create(context, elementContext, element, true, null);
104 public boolean update(SessionContext context, ElementContext elementContext,
105 ElementEntity element) {
106 ElementEntityContext privateContext =
107 new ElementEntityContext(getPrivateSpaceName(context), elementContext);
108 privateContext.setRevisionId(REVISION_ID);
110 if (!isElementChanged(context, privateContext, element)) {
114 getElementRepository(context).update(context, privateContext, element);
115 getElementSyncStateRepository(context).markAsDirty(context, privateContext,
116 new SynchronizationStateEntity(element.getId(), REVISION_ID));
121 public void delete(SessionContext context, ElementContext elementContext, ElementEntity element) {
123 ElementEntityContext privateElementContext =
124 new ElementEntityContext(getPrivateSpaceName(context), elementContext);
125 privateElementContext.setRevisionId(REVISION_ID);
126 deleteElementHierarchy(context, getElementRepository(context),
127 getElementSyncStateRepository(context),
128 privateElementContext, element);
132 public void markAsPublished(SessionContext context, ElementContext elementContext, Id elementId,
134 ElementEntityContext privateContext =
135 new ElementEntityContext(getPrivateSpaceName(context), elementContext);
136 privateContext.setRevisionId(REVISION_ID);
137 getElementSyncStateRepository(context).update(context,
139 new SynchronizationStateEntity(elementId, REVISION_ID, publishTime, false));
143 public void markDeletionAsPublished(SessionContext context, ElementContext elementContext,
144 Id elementId, Date publishTime) {
146 ElementEntityContext privateContext =
147 new ElementEntityContext(getPrivateSpaceName(context), elementContext);
148 privateContext.setRevisionId(REVISION_ID);
149 getElementSyncStateRepository(context).delete(context,
151 new SynchronizationStateEntity(elementId, REVISION_ID));
155 public void commitStagedCreate(SessionContext context, ElementContext elementContext,
156 ElementEntity element, Date publishTime) {
157 create(context, elementContext, element, false, publishTime);
161 public void commitStagedUpdate(SessionContext context, ElementContext elementContext,
162 ElementEntity element, Date publishTime) {
163 ElementEntityContext privateContext =
164 new ElementEntityContext(getPrivateSpaceName(context), elementContext);
165 privateContext.setRevisionId(REVISION_ID);
167 getElementRepository(context).update(context, privateContext, element);
168 // Currently Resolution='Other' is not supported so this is invoked after conflict was
169 // resolved with Resolution='Theirs' so dirty flag should be turned off.
170 // (if there was no conflict it's off anyway)
171 getElementSyncStateRepository(context).update(context, privateContext,
172 new SynchronizationStateEntity(element.getId(), REVISION_ID, publishTime, false));
176 public void commitStagedDelete(SessionContext context, ElementContext elementContext,
177 ElementEntity element) {
178 ElementEntityContext privateContext =
179 new ElementEntityContext(getPrivateSpaceName(context), elementContext);
180 privateContext.setRevisionId(REVISION_ID);
181 getElementRepository(context).delete(context, privateContext, element);
182 getElementSyncStateRepository(context)
183 .delete(context, privateContext,
184 new SynchronizationStateEntity(element.getId(), REVISION_ID));
188 public void commitStagedIgnore(SessionContext context, ElementContext elementContext,
189 ElementEntity element, Date publishTime) {
190 // publish time - updated to mark that this element was already synced with this publish time
191 // (even though the local data was preferred) and to prevent this conflict again.
192 // dirty - turned on because the local data which is different than the public one was
193 // preferred. It will enable future publication of this data.
194 getElementSyncStateRepository(context).update(context,
195 new ElementEntityContext(getPrivateSpaceName(context), elementContext),
196 new SynchronizationStateEntity(element.getId(), REVISION_ID, publishTime, true));
199 private void create(SessionContext context, ElementContext elementContext,
200 ElementEntity element, boolean dirty, Date publishTime) {
201 ElementEntityContext privateContext =
202 new ElementEntityContext(getPrivateSpaceName(context), elementContext);
203 privateContext.setRevisionId(REVISION_ID);
204 getElementRepository(context).create(context, privateContext, element);
205 getElementSyncStateRepository(context).create(context, privateContext,
206 new SynchronizationStateEntity(element.getId(), REVISION_ID, publishTime, dirty));
210 private void deleteElementHierarchy(
211 SessionContext context, ElementRepository elementRepository,
212 ElementSynchronizationStateRepository elementSyncStateRepository,
213 ElementEntityContext elementContext, ElementEntity element) {
215 Optional<ElementEntity> retrieved = elementRepository.get(context, elementContext, element);
216 if (!retrieved.isPresent()) {
219 retrieved.get().getSubElementIds().stream()
220 .map(ElementEntity::new)
221 .forEach(subElementEntity -> deleteElementHierarchy(
222 context, elementRepository, elementSyncStateRepository, elementContext,
225 // only for the first one the parentId will populated (so it'll be removed from its parent)
226 elementRepository.delete(context, elementContext, element);
227 handleDeletedElementSyncState(context, elementSyncStateRepository, elementContext, element);
230 private void handleDeletedElementSyncState(SessionContext context,
231 ElementSynchronizationStateRepository elementSyncStateRepository,
232 ElementEntityContext elementContext,
233 ElementEntity element) {
234 SynchronizationStateEntity elementSyncState = new SynchronizationStateEntity(element.getId(),
236 if (elementSyncStateRepository.get(context, elementContext, elementSyncState).
238 () -> new IllegalStateException("Synchronization state must exist for an element"))
239 .getPublishTime() == null) {
240 elementSyncStateRepository.delete(context, elementContext, elementSyncState);
242 elementSyncStateRepository.markAsDirty(context, elementContext, elementSyncState);
246 private boolean isElementChanged(SessionContext context,
247 ElementEntityContext elementContext,
248 ElementEntity newElement) {
249 return getElementHash(context, elementContext, new ElementEntity(newElement.getId()))
250 .map(existingHash -> !newElement.getElementHash().equals(existingHash))
254 private Optional<Id> getElementHash(SessionContext context,
255 ElementEntityContext elementEntityContext,
256 ElementEntity element) {
257 return getElementRepository(context).getHash(context, elementEntityContext, element);
260 protected ElementRepository getElementRepository(SessionContext context) {
261 return ElementRepositoryFactory.getInstance().createInterface(context);
264 protected ElementSynchronizationStateRepository getElementSyncStateRepository(
265 SessionContext context) {
266 return ElementSynchronizationStateRepositoryFactory.getInstance().createInterface(context);