Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2010-10-25 05:22:36 -0400
committerEike Stepper2010-10-25 05:22:36 -0400
commit033dd286f0682ac1cdf4c15bdeb6216d4c92dfcc (patch)
treebdc3fda7b597baedb43a2f43a57178ac5e448e86 /plugins/org.eclipse.emf.cdo.workspace.efs
parent4d4bb77ff090a9894eb79d6e308cf34bc2251c2e (diff)
downloadcdo-033dd286f0682ac1cdf4c15bdeb6216d4c92dfcc.tar.gz
cdo-033dd286f0682ac1cdf4c15bdeb6216d4c92dfcc.tar.xz
cdo-033dd286f0682ac1cdf4c15bdeb6216d4c92dfcc.zip
[327405] Provide an offline CDOWorkspace with Checkout/Update/Commit workflows
https://bugs.eclipse.org/bugs/show_bug.cgi?id=327405
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.workspace.efs')
-rw-r--r--plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/AbstractResourceNodeStore.java3
-rw-r--r--plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/CDOResourceNodeStore.java132
-rw-r--r--plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/CDOWorkspaceStore.java341
3 files changed, 331 insertions, 145 deletions
diff --git a/plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/AbstractResourceNodeStore.java b/plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/AbstractResourceNodeStore.java
index 03bf640fb0..951416d3f8 100644
--- a/plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/AbstractResourceNodeStore.java
+++ b/plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/AbstractResourceNodeStore.java
@@ -71,12 +71,13 @@ public abstract class AbstractResourceNodeStore extends AbstractFileStore
protected IFileInfo run(CDOResourceNode node)
{
boolean exists = node != null;
+ boolean directory = exists && isDirectory(node);
FileInfo info = new FileInfo(getName());
info.setExists(exists);
info.setLength(EFS.NONE);
info.setLastModified(EFS.NONE);
- info.setDirectory(exists && isDirectory(node));
+ info.setDirectory(directory);
info.setAttribute(EFS.ATTRIBUTE_READ_ONLY, false);
info.setAttribute(EFS.ATTRIBUTE_HIDDEN, false);
return info;
diff --git a/plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/CDOResourceNodeStore.java b/plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/CDOResourceNodeStore.java
index 51a65056f8..cd1c2a69da 100644
--- a/plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/CDOResourceNodeStore.java
+++ b/plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/CDOResourceNodeStore.java
@@ -10,29 +10,18 @@
*/
package org.eclipse.emf.cdo.workspace.internal.efs;
-import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.id.CDOIDUtil;
-import org.eclipse.emf.cdo.common.model.CDOClassInfo;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.eresource.CDOResourceFolder;
import org.eclipse.emf.cdo.eresource.CDOResourceNode;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
-import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.workspace.internal.efs.CDOWorkspaceStore.SaveContext;
import org.eclipse.emf.cdo.workspace.internal.efs.bundle.OM;
import org.eclipse.net4j.util.WrappedException;
-import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EReference;
-import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.InternalEObject;
-import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
-import org.eclipse.emf.spi.cdo.InternalCDOObject;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.CoreException;
@@ -125,131 +114,12 @@ public final class CDOResourceNodeStore extends AbstractResourceNodeStore
XMIResource xmiResource = new XMIResourceImpl();
xmiResource.load(in, null);
- EList<EObject> contents = xmiResource.getContents();
SaveContext saveContext = getWorkspaceStore().getSaveContext();
- handleSavedObjects(contents, xmiResource, saveContext);
-
- saveContext.save();
+ saveContext.save(xmiResource, getPath());
}
};
}
- protected void handleSavedObjects(EList<EObject> contents, XMIResource xmiResource, SaveContext saveContext)
- {
- for (EObject eObject : contents)
- {
- handleSavedObject((InternalEObject)eObject, xmiResource, saveContext);
- handleSavedObjects(eObject.eContents(), xmiResource, saveContext);
- }
- }
-
- protected void handleSavedObject(InternalEObject eObject, XMIResource xmiResource, SaveContext saveContext)
- {
- InternalCDOObject cdoObject = getCDOObject(eObject, xmiResource, saveContext, true);
-
- CDOClassInfo classInfo = cdoObject.cdoRevision().getClassInfo();
- for (EStructuralFeature feature : classInfo.getAllPersistentFeatures())
- {
- boolean reference = feature instanceof EReference;
- Object value = eObject.eGet(feature);
- if (feature.isMany())
- {
- @SuppressWarnings("unchecked")
- List<Object> source = (List<Object>)value;
-
- @SuppressWarnings("unchecked")
- List<Object> target = (List<Object>)cdoObject.eGet(feature);
- target.clear();
-
- for (Object element : source)
- {
- if (reference)
- {
- element = getCDOObject((InternalEObject)element, xmiResource, saveContext, false);
- }
-
- target.add(element);
- }
- }
- else
- {
- if (reference)
- {
- value = getCDOObject((InternalEObject)value, xmiResource, saveContext, false);
- }
-
- cdoObject.eSet(feature, value);
- }
- }
- }
-
- private InternalCDOObject getCDOObject(InternalEObject eObject, XMIResource xmiResource, SaveContext saveContext,
- boolean createOnDemand)
- {
- if (eObject == null)
- {
- return null;
- }
-
- String fragment = xmiResource.getID(eObject);
- InternalCDOObject cdoObject = null;
-
- try
- {
- CDOID id = CDOIDUtil.read(fragment);
- cdoObject = (InternalCDOObject)saveContext.getTransaction().getObject(id);
- }
- catch (Exception ex)
- {
- //$FALL-THROUGH$
- }
-
- if (cdoObject == null)
- {
- cdoObject = saveContext.getNewObject(fragment);
- }
-
- if (cdoObject == null)
- {
- if (createOnDemand)
- {
- EObject eContainer = eObject.eContainer();
- if (eContainer == null)
- {
- // TODO: implement CDOResourceNodeStore.getCDOObject(eObject, xmiResource, saveContext, createOnDemand)
- throw new UnsupportedOperationException();
- }
-
- InternalCDOObject cdoContainer = getCDOObject((InternalEObject)eContainer, xmiResource, saveContext, false);
- EObject newInstance = EcoreUtil.create(eObject.eClass());
-
- EReference containmentFeature = eObject.eContainmentFeature();
- if (containmentFeature.isMany())
- {
- @SuppressWarnings("unchecked")
- List<Object> list = (List<Object>)cdoContainer.eGet(containmentFeature);
- list.add(newInstance);
- }
- else
- {
- cdoContainer.eSet(containmentFeature, newInstance);
- }
-
- cdoObject = (InternalCDOObject)CDOUtil.getCDOObject(newInstance);
- saveContext.registerNewObject(fragment, cdoObject);
- }
- else
- {
- // saveContext.registerForwardReference(fragment, cdoObject);
-
- // TODO: implement CDOResourceNodeStore.getCDOObject(eObject, xmiResource, saveContext, createOnDemand)
- throw new UnsupportedOperationException();
- }
- }
-
- return cdoObject;
- }
-
@Override
public void delete(int options, IProgressMonitor monitor) throws CoreException
{
diff --git a/plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/CDOWorkspaceStore.java b/plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/CDOWorkspaceStore.java
index 7eb67b98b6..fa612fabf0 100644
--- a/plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/CDOWorkspaceStore.java
+++ b/plugins/org.eclipse.emf.cdo.workspace.efs/src/org/eclipse/emf/cdo/workspace/internal/efs/CDOWorkspaceStore.java
@@ -10,9 +10,14 @@
*/
package org.eclipse.emf.cdo.workspace.internal.efs;
+import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.common.id.CDOIDUtil;
+import org.eclipse.emf.cdo.common.model.CDOClassInfo;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.eresource.CDOResourceNode;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
+import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.workspace.CDOWorkspace;
@@ -21,7 +26,14 @@ import org.eclipse.emf.cdo.workspace.efs.CDOWorkspaceFSUtil;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.io.IOUtil;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.spi.cdo.InternalCDOObject;
import org.eclipse.core.filesystem.IFileStore;
@@ -32,9 +44,13 @@ import java.io.File;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
/**
* @author Eike Stepper
@@ -208,21 +224,295 @@ public final class CDOWorkspaceStore extends AbstractResourceNodeStore
*/
public final class SaveContext
{
- private CDOTransaction transaction;
+ private CDOTransaction transaction = workspace.openTransaction();
private Map<String, InternalCDOObject> newObjects = new HashMap<String, InternalCDOObject>();
+ private Map<String, List<ForwardReference>> forwardReferences = new HashMap<String, List<ForwardReference>>();
+
+ private XMIResource xmiResource;
+
public SaveContext()
{
- transaction = workspace.openTransaction();
}
- public CDOTransaction getTransaction()
+ public void save(XMIResource xmiResource, String cdoPath)
+ {
+ this.xmiResource = xmiResource;
+
+ try
+ {
+ CDOResource cdoResource = transaction.getResource(cdoPath);
+ saveContents(xmiResource.getContents(), cdoResource.getContents());
+ }
+ finally
+ {
+ this.xmiResource = null;
+ done();
+ }
+ }
+
+ private void saveContents(EList<EObject> xmiContents, EList<EObject> cdoContents)
+ {
+ int size = xmiContents.size();
+ for (int i = 0; i < size; i++)
+ {
+ EObject xmiObject = xmiContents.get(i);
+ CDOObject cdoObject = getCDOObjectByXMIID(xmiObject);
+ if (cdoObject == null)
+ {
+ cdoObject = createNewCDOObject(xmiObject);
+ cdoContents.add(i, cdoObject);
+ }
+ else
+ {
+ int index = cdoContents.indexOf(cdoObject);
+ if (index != -1)
+ {
+ cdoContents.move(i, index);
+ }
+ else
+ {
+ cdoContents.add(i, cdoObject);
+ }
+ }
+
+ saveObject((InternalEObject)xmiObject, (InternalCDOObject)cdoObject);
+ }
+
+ shortenList(cdoContents, size);
+ }
+
+ private void saveObject(InternalEObject xmiObject, InternalCDOObject cdoObject)
+ {
+ CDOClassInfo classInfo = cdoObject.cdoRevision().getClassInfo();
+ for (EStructuralFeature feature : classInfo.getAllPersistentFeatures())
+ {
+ Object xmiValue = xmiObject.eGet(feature);
+ if (feature instanceof EReference)
+ {
+ EReference reference = (EReference)feature;
+ if (reference.isContainment())
+ {
+ if (reference.isMany())
+ {
+ // Many-valued containment reference
+ @SuppressWarnings("unchecked")
+ EList<EObject> xmiContents = (EList<EObject>)xmiValue;
+
+ @SuppressWarnings("unchecked")
+ EList<EObject> cdoContents = (EList<EObject>)cdoObject.eGet(reference);
+
+ saveContents(xmiContents, cdoContents);
+ }
+ else
+ {
+ // Single-valued containment reference
+ InternalCDOObject cdoValue = getCDOObjectByXMIID((EObject)xmiValue);
+ if (cdoValue == null)
+ {
+ cdoValue = createNewCDOObject((EObject)xmiValue);
+ }
+
+ cdoObject.eSet(reference, cdoValue);
+ saveObject((InternalEObject)xmiValue, cdoValue);
+ }
+ }
+ else
+ {
+ if (reference.isMany())
+ {
+ // Many-valued cross reference
+ @SuppressWarnings("unchecked")
+ EList<EObject> xmiElements = (EList<EObject>)xmiValue;
+
+ @SuppressWarnings("unchecked")
+ EList<EObject> cdoElements = (EList<EObject>)cdoObject.eGet(reference);
+
+ int size = xmiElements.size();
+ for (int i = 0; i < size; i++)
+ {
+ InternalEObject xmiElement = (InternalEObject)xmiElements.get(i);
+ String href = xmiResource.getURIFragment(xmiElement);
+ InternalCDOObject cdoElement = getCDOObjectByHREF(href);
+ if (cdoElement == null)
+ {
+ registerForwardReference(cdoObject, reference, i, href);
+
+ InternalCDOObject dummy = createNewCDOObject(xmiElement);
+ cdoElements.add(i, dummy);
+ }
+ else
+ {
+ int index = cdoElements.indexOf(cdoElement);
+ if (index != -1)
+ {
+ cdoElements.move(i, index);
+ }
+ else
+ {
+ cdoElements.add(i, cdoElement);
+ }
+ }
+ }
+
+ shortenList(cdoElements, size);
+ }
+ else
+ {
+ // Single-valued cross reference
+ String href = xmiResource.getURIFragment((EObject)xmiValue);
+ CDOObject cdoValue = getCDOObjectByHREF(href);
+ if (cdoValue == null)
+ {
+ registerForwardReference(cdoObject, reference, -1, href);
+ }
+
+ cdoObject.eSet(reference, cdoValue);
+ }
+ }
+ }
+ else
+ {
+ EAttribute attribute = (EAttribute)feature;
+ if (attribute.isMany())
+ {
+ // Many-valued attribute
+ @SuppressWarnings("unchecked")
+ EList<Object> xmiElements = (EList<Object>)xmiValue;
+
+ @SuppressWarnings("unchecked")
+ EList<Object> cdoElements = (EList<Object>)cdoObject.eGet(attribute);
+ cdoElements.clear();
+
+ int size = xmiElements.size();
+ for (int i = 0; i < size; i++)
+ {
+ Object xmiElement = xmiElements.get(i);
+ cdoElements.add(xmiElement);
+ }
+ }
+ else
+ {
+ // Single-valued attribute
+ cdoObject.eSet(attribute, xmiValue);
+ }
+ }
+ }
+ }
+
+ private InternalCDOObject getCDOObjectByXMIID(EObject xmiObject)
+ {
+ String xmiID = xmiResource.getID(xmiObject);
+ if (xmiID != null)
+ {
+ try
+ {
+ CDOID id = CDOIDUtil.read(xmiID);
+ if (!CDOIDUtil.isNull(id))
+ {
+ return (InternalCDOObject)transaction.getObject(id);
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ //$FALL-THROUGH$
+ }
+ }
+
+ return null;
+ }
+
+ private InternalCDOObject createNewCDOObject(EObject xmiObject)
+ {
+ // Create new object
+ EObject newInstance = EcoreUtil.create(xmiObject.eClass());
+ InternalCDOObject cdoObject = (InternalCDOObject)CDOUtil.getCDOObject(newInstance);
+
+ // Remember new object
+ String fragment = xmiResource.getURIFragment(xmiObject);
+ newObjects.put(fragment, cdoObject);
+
+ return cdoObject;
+ }
+
+ private void shortenList(EList<EObject> list, int size)
{
- return transaction;
+ int remove = list.size() - size;
+ while (remove-- != 0)
+ {
+ list.remove(list.size() - 1);
+ }
}
- public void save()
+ private InternalCDOObject getCDOObjectByHREF(String href)
+ {
+ InternalCDOObject cdoObject = null;
+
+ try
+ {
+ CDOID id = CDOIDUtil.read(href);
+ cdoObject = (InternalCDOObject)transaction.getObject(id);
+ }
+ catch (Exception ex)
+ {
+ //$FALL-THROUGH$
+ }
+
+ if (cdoObject == null)
+ {
+ cdoObject = newObjects.get(href);
+ }
+
+ return cdoObject;
+ }
+
+ private void done()
+ {
+ if (resolveForwardReferences())
+ {
+ commit();
+ }
+ }
+
+ private void registerForwardReference(InternalCDOObject cdoObject, EReference reference, int index, String href)
+ {
+ List<ForwardReference> list = forwardReferences.get(href);
+ if (list == null)
+ {
+ list = new ArrayList<ForwardReference>();
+ forwardReferences.put(href, list);
+ }
+
+ list.add(new ForwardReference(cdoObject, reference, index));
+ }
+
+ private boolean resolveForwardReferences()
+ {
+ Set<Entry<String, List<ForwardReference>>> entrySet = forwardReferences.entrySet();
+ for (Iterator<Entry<String, List<ForwardReference>>> it = entrySet.iterator(); it.hasNext();)
+ {
+ Entry<String, List<ForwardReference>> entry = it.next();
+ String href = entry.getKey();
+
+ InternalCDOObject target = getCDOObjectByHREF(href);
+ if (target != null)
+ {
+ List<ForwardReference> list = entry.getValue();
+ for (ForwardReference forwardReference : list)
+ {
+ forwardReference.resolve(target);
+ }
+
+ it.remove();
+ }
+ }
+
+ return forwardReferences.isEmpty();
+ }
+
+ private void commit()
{
try
{
@@ -234,20 +524,45 @@ public final class CDOWorkspaceStore extends AbstractResourceNodeStore
}
finally
{
- saveContext = null;
- newObjects = null;
IOUtil.closeSilent(transaction);
+ transaction = null;
+ forwardReferences = null;
+ newObjects = null;
+ saveContext = null;
}
}
- public void registerNewObject(String fragment, InternalCDOObject object)
+ /**
+ * @author Eike Stepper
+ */
+ public final class ForwardReference
{
- newObjects.put(fragment, object);
- }
+ private final InternalCDOObject cdoObject;
- public InternalCDOObject getNewObject(String fragment)
- {
- return newObjects.get(fragment);
+ private final EReference reference;
+
+ private final int index;
+
+ public ForwardReference(InternalCDOObject cdoObject, EReference reference, int index)
+ {
+ this.cdoObject = cdoObject;
+ this.reference = reference;
+ this.index = index;
+ }
+
+ public void resolve(InternalCDOObject target)
+ {
+ if (reference.isMany())
+ {
+ @SuppressWarnings("unchecked")
+ EList<EObject> list = (EList<EObject>)cdoObject.eGet(reference);
+ list.set(index, target);
+ }
+ else
+ {
+ cdoObject.eSet(reference, target);
+ }
+ }
}
}
}

Back to the top