From 9168ead7296d27eb457097bfae1db721e2796f35 Mon Sep 17 00:00:00 2001 From: Eike Stepper Date: Sun, 24 Oct 2010 18:40:18 +0000 Subject: [327405] Provide an offline CDOWorkspace with Checkout/Update/Commit workflows https://bugs.eclipse.org/bugs/show_bug.cgi?id=327405 --- .../internal/efs/CDOResourceNodeStore.java | 179 ++++++++++++++++++--- .../workspace/internal/efs/CDOWorkspaceStore.java | 65 ++++++++ 2 files changed, 219 insertions(+), 25 deletions(-) (limited to 'plugins/org.eclipse.emf.cdo.workspace.efs') 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 61dd38469f..51a65056f8 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,15 +10,30 @@ */ 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; import org.eclipse.core.runtime.IProgressMonitor; @@ -27,6 +42,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.util.List; /** @@ -95,31 +111,144 @@ public final class CDOResourceNodeStore extends AbstractResourceNodeStore }.run(); } - // @Override - // public OutputStream openOutputStream(int options, IProgressMonitor monitor) throws CoreException - // { - // return new ResourceNodeRunnable() - // { - // @Override - // protected OutputStream run(CDOResourceNode node) - // { - // ByteArrayOutputStream baos = new ByteArrayOutputStream(); - // CDOResource resource = (CDOResource)node; - // - // try - // { - // resource.save(baos, null); - // } - // catch (Exception ex) - // { - // OM.LOG.error(ex); - // throw WrappedException.wrap(ex); - // } - // - // return new ByteArrayInputStream(baos.toByteArray()); - // } - // }.run(); - // } + @Override + public OutputStream openOutputStream(int options, IProgressMonitor monitor) throws CoreException + { + return new ByteArrayOutputStream() + { + @Override + public void close() throws IOException + { + byte[] bytes = toByteArray(); + InputStream in = new ByteArrayInputStream(bytes); + + XMIResource xmiResource = new XMIResourceImpl(); + xmiResource.load(in, null); + + EList contents = xmiResource.getContents(); + SaveContext saveContext = getWorkspaceStore().getSaveContext(); + handleSavedObjects(contents, xmiResource, saveContext); + + saveContext.save(); + } + }; + } + + protected void handleSavedObjects(EList 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 source = (List)value; + + @SuppressWarnings("unchecked") + List target = (List)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 list = (List)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 caa00da76c..7eb67b98b6 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 @@ -12,6 +12,8 @@ package org.eclipse.emf.cdo.workspace.internal.efs; 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.CommitException; import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.emf.cdo.workspace.CDOWorkspace; import org.eclipse.emf.cdo.workspace.efs.CDOWorkspaceFSUtil; @@ -20,6 +22,7 @@ import org.eclipse.net4j.util.WrappedException; import org.eclipse.net4j.util.io.IOUtil; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.spi.cdo.InternalCDOObject; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.runtime.CoreException; @@ -29,7 +32,9 @@ import java.io.File; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @author Eike Stepper @@ -46,6 +51,8 @@ public final class CDOWorkspaceStore extends AbstractResourceNodeStore private CDOView view; + private SaveContext saveContext; + public CDOWorkspaceStore(String name, File location) { this.name = name; @@ -147,6 +154,16 @@ public final class CDOWorkspaceStore extends AbstractResourceNodeStore return this; } + public SaveContext getSaveContext() + { + if (saveContext == null) + { + saveContext = new SaveContext(); + } + + return saveContext; + } + @Override protected synchronized CDOView getView() { @@ -185,4 +202,52 @@ public final class CDOWorkspaceStore extends AbstractResourceNodeStore } } } + + /** + * @author Eike Stepper + */ + public final class SaveContext + { + private CDOTransaction transaction; + + private Map newObjects = new HashMap(); + + public SaveContext() + { + transaction = workspace.openTransaction(); + } + + public CDOTransaction getTransaction() + { + return transaction; + } + + public void save() + { + try + { + transaction.commit(); + } + catch (CommitException ex) + { + throw WrappedException.wrap(ex); + } + finally + { + saveContext = null; + newObjects = null; + IOUtil.closeSilent(transaction); + } + } + + public void registerNewObject(String fragment, InternalCDOObject object) + { + newObjects.put(fragment, object); + } + + public InternalCDOObject getNewObject(String fragment) + { + return newObjects.get(fragment); + } + } } -- cgit v1.2.3