Add collaboration feature
[sdc.git] / openecomp-be / lib / openecomp-core-lib / openecomp-zusammen-lib / openecomp-zusammen-plugin / src / main / java / org / openecomp / core / zusammen / plugin / main / CassandraCollaborationStorePluginImpl.java
index 90fd336..f9b6522 100644 (file)
@@ -21,97 +21,302 @@ import com.amdocs.zusammen.commons.health.data.HealthStatus;
 import com.amdocs.zusammen.datatypes.Id;
 import com.amdocs.zusammen.datatypes.Namespace;
 import com.amdocs.zusammen.datatypes.SessionContext;
+import com.amdocs.zusammen.datatypes.Space;
+import com.amdocs.zusammen.datatypes.item.Action;
 import com.amdocs.zusammen.datatypes.item.ElementContext;
 import com.amdocs.zusammen.datatypes.item.Info;
+import com.amdocs.zusammen.datatypes.item.ItemVersion;
 import com.amdocs.zusammen.datatypes.item.ItemVersionData;
-import com.amdocs.zusammen.datatypes.itemversion.ItemVersionHistory;
+import com.amdocs.zusammen.datatypes.item.ItemVersionDataConflict;
+import com.amdocs.zusammen.datatypes.item.ItemVersionStatus;
+import com.amdocs.zusammen.datatypes.item.Resolution;
+import com.amdocs.zusammen.datatypes.itemversion.ItemVersionRevisions;
+import com.amdocs.zusammen.datatypes.itemversion.Revision;
 import com.amdocs.zusammen.datatypes.itemversion.Tag;
+import com.amdocs.zusammen.datatypes.response.ErrorCode;
+import com.amdocs.zusammen.datatypes.response.Module;
 import com.amdocs.zusammen.datatypes.response.Response;
+import com.amdocs.zusammen.datatypes.response.ReturnCode;
 import com.amdocs.zusammen.datatypes.response.ZusammenException;
 import com.amdocs.zusammen.sdk.collaboration.CollaborationStore;
 import com.amdocs.zusammen.sdk.collaboration.types.CollaborationElement;
+import com.amdocs.zusammen.sdk.collaboration.types.CollaborationElementChange;
+import com.amdocs.zusammen.sdk.collaboration.types.CollaborationElementConflict;
+import com.amdocs.zusammen.sdk.collaboration.types.CollaborationItemVersionConflict;
 import com.amdocs.zusammen.sdk.collaboration.types.CollaborationMergeChange;
 import com.amdocs.zusammen.sdk.collaboration.types.CollaborationMergeResult;
 import com.amdocs.zusammen.sdk.collaboration.types.CollaborationPublishResult;
-import org.openecomp.core.zusammen.plugin.collaboration.ElementCollaborationStore;
-import org.openecomp.core.zusammen.plugin.collaboration.VersionCollaborationStore;
+import com.amdocs.zusammen.sdk.types.ElementConflictDescriptor;
+import com.amdocs.zusammen.sdk.types.ElementDescriptor;
+import org.openecomp.core.zusammen.plugin.ZusammenPluginUtil;
+import org.openecomp.core.zusammen.plugin.collaboration.CommitStagingService;
+import org.openecomp.core.zusammen.plugin.collaboration.ElementPrivateStore;
+import org.openecomp.core.zusammen.plugin.collaboration.ElementPublicStore;
+import org.openecomp.core.zusammen.plugin.collaboration.ElementStageStore;
+import org.openecomp.core.zusammen.plugin.collaboration.PublishService;
+import org.openecomp.core.zusammen.plugin.collaboration.RevertService;
+import org.openecomp.core.zusammen.plugin.collaboration.SyncService;
+import org.openecomp.core.zusammen.plugin.collaboration.VersionPrivateStore;
+import org.openecomp.core.zusammen.plugin.collaboration.VersionPublicStore;
+import org.openecomp.core.zusammen.plugin.collaboration.VersionStageStore;
+import org.openecomp.core.zusammen.plugin.collaboration.impl.ElementPrivateStoreImpl;
+import org.openecomp.core.zusammen.plugin.collaboration.impl.ElementPublicStoreImpl;
+import org.openecomp.core.zusammen.plugin.collaboration.impl.ElementStageStoreImpl;
+import org.openecomp.core.zusammen.plugin.collaboration.impl.VersionPrivateStoreImpl;
+import org.openecomp.core.zusammen.plugin.collaboration.impl.VersionPublicStoreImpl;
+import org.openecomp.core.zusammen.plugin.collaboration.impl.VersionStageStoreImpl;
+import org.openecomp.core.zusammen.plugin.dao.types.ElementEntity;
+import org.openecomp.core.zusammen.plugin.dao.types.StageEntity;
+import org.openecomp.core.zusammen.plugin.dao.types.SynchronizationStateEntity;
+import org.openecomp.core.zusammen.plugin.dao.types.VersionDataElement;
+import org.openecomp.core.zusammen.plugin.dao.types.VersionEntity;
 
 import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import static com.amdocs.zusammen.datatypes.item.SynchronizationStatus.MERGING;
+import static com.amdocs.zusammen.datatypes.item.SynchronizationStatus.OUT_OF_SYNC;
+import static com.amdocs.zusammen.datatypes.item.SynchronizationStatus.UP_TO_DATE;
+import static org.openecomp.core.zusammen.plugin.ZusammenPluginConstants.ROOT_ELEMENTS_PARENT_ID;
+import static org.openecomp.core.zusammen.plugin.ZusammenPluginUtil.convertToCollaborationElement;
+import static org.openecomp.core.zusammen.plugin.ZusammenPluginUtil.convertToElementChange;
+import static org.openecomp.core.zusammen.plugin.ZusammenPluginUtil.convertToElementDescriptor;
+import static org.openecomp.core.zusammen.plugin.ZusammenPluginUtil.convertToElementEntity;
+import static org.openecomp.core.zusammen.plugin.ZusammenPluginUtil.convertToItemVersion;
+import static org.openecomp.core.zusammen.plugin.ZusammenPluginUtil.convertToVersionData;
+import static org.openecomp.core.zusammen.plugin.ZusammenPluginUtil.convertToVersionEntity;
 
 public class CassandraCollaborationStorePluginImpl implements CollaborationStore {
+  // TODO: 8/15/2017 inject
+
+  private VersionPrivateStore versionPrivateStore = new VersionPrivateStoreImpl();
+  private VersionPublicStore versionPublicStore = new VersionPublicStoreImpl();
+  private VersionStageStore versionStageStore = new VersionStageStoreImpl();
+
+  private ElementPrivateStore elementPrivateStore = new ElementPrivateStoreImpl();
+  private ElementPublicStore elementPublicStore = new ElementPublicStoreImpl();
+  private ElementStageStore elementStageStore = new ElementStageStoreImpl();
 
-  private VersionCollaborationStore versionCollaborationStore = new VersionCollaborationStore();
-  private ElementCollaborationStore elementCollaborationStore = new ElementCollaborationStore();
+  // TODO: 9/4/2017
+  private CommitStagingService commitStagingService =
+      new CommitStagingService(versionPrivateStore, versionStageStore, elementPrivateStore,
+          elementStageStore);
+  private PublishService publishService =
+      new PublishService(versionPublicStore, versionPrivateStore, elementPublicStore,
+          elementPrivateStore);
+  private SyncService syncService =
+      new SyncService(versionPublicStore, versionPrivateStore, versionStageStore,
+          elementPublicStore, elementPrivateStore, elementStageStore);
+
+  private RevertService revertService =
+      new RevertService(elementPublicStore, elementPrivateStore);
 
   @Override
-  public Response<Void> createItem(SessionContext context, Id id, Info info) {
+  public Response<Void> createItem(SessionContext context, Id itemId, Info info) {
     // done by state store
     return new Response(Void.TYPE);
   }
 
   @Override
-  public Response<Void> deleteItem(SessionContext context, Id id) {
+  public Response<Void> deleteItem(SessionContext context, Id itemId) {
     // done by state store
     return new Response(Void.TYPE);
   }
 
   @Override
-  public Response<Void> createItemVersion(SessionContext context, Id itemId, Id versionId, Id id2,
-                                          ItemVersionData itemVersionData) {
-    // done by state store
+  public Response<Void> createItemVersion(SessionContext context, Id itemId, Id baseVersionId,
+                                          Id versionId, ItemVersionData itemVersionData) {
+    Date creationTime = new Date();
+    versionPrivateStore.create(context, itemId,
+        convertToVersionEntity(versionId, baseVersionId, creationTime, creationTime));
+
+    ElementContext elementContext = new ElementContext(itemId, versionId);
+    VersionDataElement versionData = new VersionDataElement(itemVersionData);
+
+    if (baseVersionId == null) {
+      elementPrivateStore.create(context, elementContext, versionData);
+    } else {
+      copyElements(context, new ElementContext(itemId, baseVersionId), elementContext);
+      elementPrivateStore.update(context, elementContext, versionData);
+    }
+
     return new Response(Void.TYPE);
   }
 
   @Override
   public Response<Void> updateItemVersion(SessionContext context, Id itemId, Id versionId,
                                           ItemVersionData itemVersionData) {
-    // done by state store
+
+    if (elementPrivateStore.update(context, new ElementContext(itemId, versionId),
+        new VersionDataElement(itemVersionData))) {
+
+      VersionEntity version = new VersionEntity(versionId);
+      version.setModificationTime(new Date());
+      versionPrivateStore.update(context, itemId, version);
+    }
+
     return new Response(Void.TYPE);
   }
 
   @Override
   public Response<Void> deleteItemVersion(SessionContext context, Id itemId, Id versionId) {
-    // done by state store
+    elementPrivateStore
+        .delete(context, new ElementContext(itemId, versionId), new VersionDataElement());
+
+    versionPrivateStore.delete(context, itemId, new VersionEntity(versionId));
     return new Response(Void.TYPE);
   }
 
   @Override
-  public Response<Void> tagItemVersion(SessionContext context, Id itemId, Id versionId, Id changeId,
+  public Response<ItemVersionStatus> getItemVersionStatus(SessionContext context, Id itemId,
+                                                          Id versionId) {
+    if (versionStageStore.get(context, itemId, new VersionEntity(versionId)).isPresent()) {
+      return new Response<>(new ItemVersionStatus(MERGING, true));
+    }
+
+    Optional<SynchronizationStateEntity> publicSyncState =
+        versionPublicStore.getSynchronizationState(context, itemId, versionId);
+
+    if (!publicSyncState.isPresent()) {
+      return new Response<>(new ItemVersionStatus(UP_TO_DATE, true));
+    }
+
+    SynchronizationStateEntity privateSyncState =
+        versionPrivateStore.getSynchronizationState(context, itemId, versionId)
+            // TODO: 7/18/2017 ?
+            .orElseThrow(() -> new IllegalStateException("private version must exist"));
+
+    return new Response<>(new ItemVersionStatus(
+        privateSyncState.getPublishTime().equals(publicSyncState.get().getPublishTime())
+            ? UP_TO_DATE
+            : OUT_OF_SYNC,
+        privateSyncState.isDirty()));
+  }
+
+  @Override
+  public Response<Void> tagItemVersion(SessionContext context, Id itemId, Id versionId,
+                                       Id revisionId,
                                        Tag tag) {
-    versionCollaborationStore.tagItemVersion(context, itemId, versionId, changeId, tag);
+   /* if (revisionId != null) {
+      throw new UnsupportedOperationException(
+          "In this plugin implementation tag is supported only on versionId");
+    }
+
+    copyElements(context,
+        new ElementContext(itemId, versionId),
+        new ElementContext(itemId, versionId, tag.getName()));*/
+
     return new Response(Void.TYPE);
   }
 
   @Override
   public Response<CollaborationPublishResult> publishItemVersion(SessionContext context,
                                                                  Id itemId, Id versionId,
-                                                                 String s) {
-    throw new UnsupportedOperationException("publishItemVersion");
+                                                                 String message) {
+    try {
+      return new Response<>(publishService.publish(context, itemId, versionId, message));
+    } catch (ZusammenException ze) {
+      return new Response<>(
+          new ReturnCode(ErrorCode.CL_ITEM_VERSION_PUBLISH, Module.ZCSP, null, ze.getReturnCode()));
+    }
+  }
+
+  @Override
+  public Response<CollaborationMergeResult> syncItemVersion(SessionContext context, Id itemId,
+                                                            Id versionId) {
+    CollaborationMergeResult result = syncService.sync(context, itemId, versionId, false);
+    commitStagingService.commitStaging(context, itemId, versionId);
+
+    return new Response<>(result);
   }
 
   @Override
-  public Response<CollaborationMergeResult> syncItemVersion(SessionContext context, Id id,
-                                                            Id id1) {
-    throw new UnsupportedOperationException("syncItemVersion");
+  public Response<CollaborationMergeResult> forceSyncItemVersion(SessionContext context, Id itemId,
+                                                                 Id versionId) {
+    CollaborationMergeResult result = syncService.sync(context, itemId, versionId, true);
+    commitStagingService.commitStaging(context, itemId, versionId);
+
+    return new Response<>(result);
   }
 
   @Override
-  public Response<CollaborationMergeResult> mergeItemVersion(SessionContext context, Id id,
-                                                             Id id1, Id id2) {
+  public Response<CollaborationMergeResult> mergeItemVersion(SessionContext context, Id itemId,
+                                                             Id versionId, Id sourceVersionId) {
     throw new UnsupportedOperationException("mergeItemVersion");
   }
 
   @Override
-  public Response<ItemVersionHistory> listItemVersionHistory(SessionContext context, Id id,
-                                                             Id id1) {
-    throw new UnsupportedOperationException("listItemVersionHistory");
+  public Response<CollaborationItemVersionConflict> getItemVersionConflict(SessionContext context,
+                                                                           Id itemId,
+                                                                           Id versionId) {
+    ElementContext elementContext = new ElementContext(itemId, versionId, Id.ZERO);
+
+    Collection<StageEntity<ElementEntity>> conflictedStagedElementDescriptors =
+        elementStageStore.listConflictedDescriptors(context, elementContext);
+
+    CollaborationItemVersionConflict result = new CollaborationItemVersionConflict();
+    for (StageEntity<ElementEntity> stagedElementDescriptor : conflictedStagedElementDescriptors) {
+      if (ROOT_ELEMENTS_PARENT_ID.equals(stagedElementDescriptor.getEntity().getId())) {
+        result.setVersionDataConflict(
+            getVersionDataConflict(context, elementContext, stagedElementDescriptor));
+      } else {
+        result.getElementConflictDescriptors()
+            .add(getElementConflictDescriptor(context, elementContext, stagedElementDescriptor));
+      }
+    }
+    return new Response<>(result);
+  }
+
+  @Override
+  public Response<ItemVersionRevisions> listItemVersionRevisions(SessionContext context, Id itemId,
+                                                                 Id versionId) {
+    return new Response<>(versionPublicStore.listItemVersionRevisions(context, itemId, versionId));
   }
 
   @Override
-  public Response<CollaborationMergeChange> resetItemVersionHistory(SessionContext context,
-                                                                    Id itemId, Id versionId,
-                                                                    String changeRef) {
-    return new Response<>(versionCollaborationStore.resetItemVersionHistory(context, itemId, versionId, changeRef));
+  public Response<Revision> getItemVersionRevision(SessionContext context, Id itemId, Id versionId,
+                                                   Id revisionId) {
+    throw new UnsupportedOperationException(
+        "get revision is not supported in the current cassandra plugin");
+  }
+
+  @Override
+  public Response<CollaborationMergeChange> resetItemVersionRevision(SessionContext context,
+                                                                     Id itemId, Id versionId,
+                                                                     Id revisionId) {
+    throw new UnsupportedOperationException("resetItemVersionRevision function not supported");
+
+  }
+
+  @Override
+  public Response<CollaborationMergeChange> revertItemVersionRevision(SessionContext context,
+                                                                      Id itemId, Id versionId,
+                                                                      Id revisionId) {
+    Optional<ItemVersion> itemVersion = getItemVersion(context, itemId, versionId, revisionId);
+    if (!itemVersion.isPresent()) {
+      throw new RuntimeException(String
+          .format("Item %s, version %s: Cannot revert to revision %s since it is not found",
+              itemId, versionId, revisionId));
+    }
+
+    // TODO: 12/4/2017 force sync is done in order to clear dirty element on private
+    // this is temp solution that should be fixed.
+    forceSyncItemVersion(context, itemId, versionId);
+
+    //updateItemVersion(context, itemId, versionId, itemVersion.get().getData());
+    revertService.revert(context, itemId, versionId, revisionId);
+
+    return new Response<>(new CollaborationMergeChange());
+  }
+
+
+  @Override
+  public Response<Void> commitElements(SessionContext context, Id itemId, Id versionId, String s) {
+    // not needed
+    return new Response(Void.TYPE);
   }
 
   @Override
@@ -119,52 +324,198 @@ public class CassandraCollaborationStorePluginImpl implements CollaborationStore
                                                                  ElementContext elementContext,
                                                                  Namespace namespace,
                                                                  Id elementId) {
-    return new Response<>(
-        elementCollaborationStore.listElements(context, elementContext, elementId));
+    return new Response<>(elementPrivateStore.listSubs(context, elementContext, elementId).stream()
+        .map(elementEntity -> convertToCollaborationElement(elementContext, elementEntity))
+        .collect(Collectors.toList()));
   }
 
   @Override
   public Response<CollaborationElement> getElement(SessionContext context,
                                                    ElementContext elementContext,
                                                    Namespace namespace, Id elementId) {
-    return new Response<>(elementCollaborationStore.getElement(context, elementContext, elementId));
+    return new Response<>(elementPrivateStore.get(context, elementContext, elementId)
+        .map(elementEntity -> convertToCollaborationElement(elementContext, elementEntity))
+        .orElse(null));
+  }
+
+  @Override
+  public Response<CollaborationElementConflict> getElementConflict(SessionContext context,
+                                                                   ElementContext elementContext,
+                                                                   Namespace namespace,
+                                                                   Id elementId) {
+    Optional<StageEntity<ElementEntity>> conflictedStagedElement =
+        elementStageStore
+            .getConflicted(context, elementContext, new ElementEntity(elementId));
+
+    return new Response<>(conflictedStagedElement
+        .map(stagedElement -> getElementConflict(context, elementContext, stagedElement))
+        .orElse(null));
   }
 
   @Override
   public Response<Void> createElement(SessionContext context, CollaborationElement element) {
-    elementCollaborationStore.createElement(context, element);
+    elementPrivateStore.create(context,
+        new ElementContext(element.getItemId(), element.getVersionId()),
+        convertToElementEntity(element));
     return new Response(Void.TYPE);
   }
 
   @Override
   public Response<Void> updateElement(SessionContext context, CollaborationElement element) {
-    elementCollaborationStore.updateElement(context, element);
+    elementPrivateStore.update(context,
+        new ElementContext(element.getItemId(), element.getVersionId()),
+        convertToElementEntity(element));
     return new Response(Void.TYPE);
   }
 
   @Override
   public Response<Void> deleteElement(SessionContext context, CollaborationElement element) {
-    elementCollaborationStore.deleteElement(context, element);
+    elementPrivateStore
+        .delete(context, new ElementContext(element.getItemId(), element.getVersionId()),
+            convertToElementEntity(element));
+
     return new Response(Void.TYPE);
   }
 
   @Override
-  public Response<Void> commitElements(SessionContext context, Id itemId, Id versionId, String s) {
-    // not needed
-    return new Response(Void.TYPE);
+  public Response<CollaborationMergeResult> resolveElementConflict(SessionContext context,
+                                                                   CollaborationElement element,
+                                                                   Resolution resolution) {
+    ElementContext elementContext = new ElementContext(element.getItemId(), element.getVersionId());
+    elementStageStore
+        .resolveConflict(context, elementContext, convertToElementEntity(element), resolution);
+    commitStagingService.commitStaging(context, element.getItemId(), element.getVersionId());
+
+    return new Response<>(new CollaborationMergeResult());
   }
 
   @Override
-  public Response<HealthInfo> checkHealth(SessionContext sessionContext) throws ZusammenException {
+  public Response<ItemVersion> getItemVersion(SessionContext context, Space space, Id itemId,
+                                              Id versionId, Id revisionId) {
+    return new Response<>(getItemVersion(context, itemId, versionId, revisionId).orElse(null));
+  }
 
-    boolean health = elementCollaborationStore.checkHealth(sessionContext);
-    HealthInfo healthInfo ;
-    if (health){
-      healthInfo = new HealthInfo("Collaboration", HealthStatus.UP,"");
-    } else {
-      healthInfo = new HealthInfo("Collaboration", HealthStatus.DOWN,"No Schema Available");
+  @Override
+  public Response<HealthInfo> checkHealth(SessionContext context) throws ZusammenException {
+    HealthInfo healthInfo = versionPublicStore.checkHealth(context)
+        ? new HealthInfo(Module.ZCSP.getDescription(), HealthStatus.UP, "")
+        : new HealthInfo(Module.ZCSP.getDescription(), HealthStatus.DOWN, "No Schema Available");
+
+    return new Response<>(healthInfo);
+  }
+
+  private Optional<ItemVersion> getItemVersion(SessionContext context, Id itemId, Id versionId,
+                                               Id revisionId) {
+    // since revisions are kept only on public - get from there
+    Optional<VersionEntity> versionEntity = versionPublicStore.get(context, itemId, versionId);
+    if (!versionEntity.isPresent()) {
+      return Optional.empty();
+    }
+
+    return elementPublicStore
+        .getDescriptor(context, new ElementContext(itemId, versionId, revisionId),
+            ROOT_ELEMENTS_PARENT_ID)
+        .map(ZusammenPluginUtil::convertToVersionData)
+        .map(itemVersionData -> convertToItemVersion(versionEntity.get(), itemVersionData));
+  }
+
+  private List<ElementEntity> listVersionElements(SessionContext context,
+                                                  ElementContext elementContext) {
+    return elementPrivateStore.listIds(context, elementContext).entrySet().stream() // TODO:
+        // 9/5/2017 parallel
+        .map(entry -> elementPrivateStore.get(context, elementContext, entry.getKey()).get())
+        .collect(Collectors.toList());
+  }
+
+  private void copyElements(SessionContext context,
+                            ElementContext sourceContext, ElementContext targetContext) {
+    listVersionElements(context, sourceContext).forEach(element -> {
+      // publishTime copied as is and dirty is off
+      Date publishTime =
+          elementPrivateStore.getSynchronizationState(context, sourceContext, element.getId())
+              .get().getPublishTime();
+      elementPrivateStore.commitStagedCreate(context, targetContext, element, publishTime);
+    });
+  }
+
+  private ItemVersionDataConflict getVersionDataConflict(SessionContext context,
+                                                         ElementContext elementContext,
+                                                         StageEntity<ElementEntity> stagedElementDescriptor) {
+    ItemVersionDataConflict versionConflict = new ItemVersionDataConflict();
+    versionConflict.setRemoteData(convertToVersionData(stagedElementDescriptor.getEntity()));
+    if (stagedElementDescriptor.getAction() == Action.UPDATE) {
+      versionConflict.setLocalData(getPrivateVersionData(context, elementContext));
     }
-    return new Response<HealthInfo>(healthInfo);
+    return versionConflict;
+  }
 
+  private ItemVersionData getPrivateVersionData(SessionContext context,
+                                                ElementContext elementContext) {
+    return elementPrivateStore.getDescriptor(context, elementContext, ROOT_ELEMENTS_PARENT_ID)
+        .map(ZusammenPluginUtil::convertToVersionData)
+        .orElseThrow(() -> new IllegalStateException("Version must have data"));
+  }
+
+  private ElementConflictDescriptor getElementConflictDescriptor(SessionContext context,
+                                                                 ElementContext elementContext,
+                                                                 StageEntity<ElementEntity> stagedElementDescriptor) {
+    ElementDescriptor elementDescriptorFromStage =
+        convertToElementDescriptor(elementContext, (stagedElementDescriptor.getEntity()));
+
+    ElementConflictDescriptor conflictDescriptor = new ElementConflictDescriptor();
+    switch (stagedElementDescriptor.getAction()) {
+      case CREATE:
+        conflictDescriptor.setRemoteElementDescriptor(elementDescriptorFromStage);
+        break;
+      case UPDATE:
+        conflictDescriptor.setRemoteElementDescriptor(elementDescriptorFromStage);
+        conflictDescriptor.setLocalElementDescriptor(convertToElementDescriptor(elementContext,
+            elementPrivateStore
+                .getDescriptor(context, elementContext, stagedElementDescriptor.getEntity().getId())
+                .orElse(null)));// updated on public while deleted from private
+        break;
+      case DELETE:
+        conflictDescriptor.setLocalElementDescriptor(elementDescriptorFromStage);
+        break;
+      default:
+        break;
+    }
+    return conflictDescriptor;
+  }
+
+  private void addElementsToChangedElements(ElementContext elementContext,
+                                            Collection<ElementEntity> elements,
+                                            Collection<CollaborationElementChange> changedElements,
+                                            Action action) {
+    elements.stream()
+        .map(elementEntity -> convertToElementChange(elementContext, elementEntity, action))
+        .forEach(changedElements::add);
+  }
+
+  private CollaborationElementConflict getElementConflict(SessionContext context,
+                                                          ElementContext entityContext,
+                                                          StageEntity<ElementEntity> stagedElement) {
+    CollaborationElement elementFromStage =
+        convertToCollaborationElement(entityContext, (stagedElement.getEntity()));
+
+    CollaborationElementConflict conflict = new CollaborationElementConflict();
+    switch (stagedElement.getAction()) {
+      case CREATE:
+        conflict.setRemoteElement(elementFromStage);
+        break;
+      case UPDATE:
+        conflict.setRemoteElement(elementFromStage);
+        conflict.setLocalElement(
+            elementPrivateStore.get(context, entityContext, stagedElement.getEntity().getId())
+                .map(element -> convertToCollaborationElement(entityContext, element))
+                .orElse(null));// updated on public while deleted from private
+        break;
+      case DELETE:
+        conflict.setLocalElement(elementFromStage);
+        break;
+      default:
+        break;
+    }
+    return conflict;
   }
 }
\ No newline at end of file