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);