Commit eee4fcef authored by Erwan Bousse's avatar Erwan Bousse
Browse files

Fixing bug in cloning algo in which cloned objects dont have a container yet,...

Fixing bug in cloning algo in which cloned objects dont have a container yet, and adding new feature with the possibility to create readonly clones in which the containment semantics is not ok when shared objects are moved from a container to another (thus should not be moved, thus readonly)
parent b0c2f490
...@@ -32,8 +32,12 @@ public interface Cloner { ...@@ -32,8 +32,12 @@ public interface Cloner {
* folder * folder
* @return The cloned model. * @return The cloned model.
*/ */
public ResourceSet clone(ResourceSet model, String folderName);//,boolean light); public ResourceSet clone(ResourceSet model, String folderName);
public ResourceSet clone(ResourceSet cloned, File outputFolder);//,boolean light); public ResourceSet clone(ResourceSet cloned, File outputFolder);
public ResourceSet clone(ResourceSet cloned, File outputFolder, boolean readOnly);
public ResourceSet clone(ResourceSet cloned, String folderName, boolean readOnly);
} }
...@@ -42,7 +42,7 @@ public class ClonerImpl implements Cloner { ...@@ -42,7 +42,7 @@ public class ClonerImpl implements Cloner {
cloningMaterial = cm; cloningMaterial = cm;
} }
private ResourceSet clone(ResourceSet cloned, File outputFolder, String folderName) {//, boolean light) { private ResourceSet clone(ResourceSet cloned, File outputFolder, String folderName, boolean readOnly) {
// Creating empty clone resource set // Creating empty clone resource set
ResourceSet clone = new ResourceSetImpl(); ResourceSet clone = new ResourceSetImpl();
...@@ -76,7 +76,7 @@ public class ClonerImpl implements Cloner { ...@@ -76,7 +76,7 @@ public class ClonerImpl implements Cloner {
Resource resourceClone = null; Resource resourceClone = null;
// LooseResource if there are readonly objects that might be shared among models // LooseResource if there are readonly objects that might be shared among models
if (tags.mayTagClassesShareable()) { if (tags.mayTagClassesShareable()) {
resourceClone = new LooseResource(tags); resourceClone = new LooseResource(tags,readOnly);
resourceClone.setURI(uri); resourceClone.setURI(uri);
clone.getResources().add(resourceClone); clone.getResources().add(resourceClone);
} }
...@@ -94,7 +94,7 @@ public class ClonerImpl implements Cloner { ...@@ -94,7 +94,7 @@ public class ClonerImpl implements Cloner {
ClassTag tag = tags.getTagOf(o.eClass()); ClassTag tag = tags.getTagOf(o.eClass());
// We only put the copied object in the resource if not contained already // We only put the copied object in the resource if not contained already
if (o.eContainer() == null) { //if (o.eContainer() == null) {
switch (tag) { switch (tag) {
case NOT_SHAREABLE: // here the copier should always produce a regular copy case NOT_SHAREABLE: // here the copier should always produce a regular copy
resourceClone.getContents().add(copier.copy(o)); resourceClone.getContents().add(copier.copy(o));
...@@ -103,10 +103,11 @@ public class ClonerImpl implements Cloner { ...@@ -103,10 +103,11 @@ public class ClonerImpl implements Cloner {
resourceClone.getContents().add(copier.copy(o)); resourceClone.getContents().add(copier.copy(o));
break; break;
case COMPLETELY_SHAREABLE: // no copy, shared object case COMPLETELY_SHAREABLE: // no copy, shared object
resourceClone.getContents().add(o); if (o.eContainer() == null)
resourceClone.getContents().add(o);
break; break;
} }
} else { /*} else {
switch (tag) { switch (tag) {
case NOT_SHAREABLE: // here the copier should always produce a regular copy case NOT_SHAREABLE: // here the copier should always produce a regular copy
copier.copy(o); copier.copy(o);
...@@ -115,9 +116,10 @@ public class ClonerImpl implements Cloner { ...@@ -115,9 +116,10 @@ public class ClonerImpl implements Cloner {
copier.copy(o); copier.copy(o);
break; break;
case COMPLETELY_SHAREABLE: // no copy, shared object case COMPLETELY_SHAREABLE: // no copy, shared object
break; break;
} }
} }*/
} }
} }
...@@ -131,12 +133,23 @@ public class ClonerImpl implements Cloner { ...@@ -131,12 +133,23 @@ public class ClonerImpl implements Cloner {
@Override @Override
public ResourceSet clone(ResourceSet cloned, File outputFolder) {//, boolean light) { public ResourceSet clone(ResourceSet cloned, File outputFolder) {//, boolean light) {
return clone(cloned, outputFolder, "NOTHING");//, light); return clone(cloned, outputFolder, "NOTHING", false);//, light);
} }
@Override @Override
public ResourceSet clone(ResourceSet cloned, String folderName) {//, boolean light) { public ResourceSet clone(ResourceSet cloned, String folderName) {//, boolean light) {
return clone(cloned, null, folderName);//, light); return clone(cloned, null, folderName, false);//, light);
} }
@Override
public ResourceSet clone(ResourceSet cloned, File outputFolder,boolean readOnly) {
return clone(cloned, outputFolder, "NOTHING", readOnly);
}
@Override
public ResourceSet clone(ResourceSet cloned, String folderName,boolean readOnly) {
return clone(cloned,null, folderName,readOnly);
}
} }
...@@ -32,11 +32,12 @@ import fr.inria.diverse.cloning.runtime.util.EcoreHelper; ...@@ -32,11 +32,12 @@ import fr.inria.diverse.cloning.runtime.util.EcoreHelper;
* container, at all time (eContainer). * container, at all time (eContainer).
* *
* @author ebousse * @author ebousse
* *
*/ */
public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Container {// implements public abstract class AbstractShareableEObject extends
// ShareableEObject MinimalEObjectImpl.Container {// implements
// { // ShareableEObject
// {
/** /**
* Internal class to store the context temporarily * Internal class to store the context temporarily
...@@ -119,7 +120,8 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai ...@@ -119,7 +120,8 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai
// LooseResource // LooseResource
boolean toChange = (otherResource != null) boolean toChange = (otherResource != null)
&& (otherResource instanceof LooseResource) && (otherResource instanceof LooseResource)
&& (((LooseResource) (otherResource)).getTags().getTagOf(this.eClass()) == ClassTag.COMPLETELY_SHAREABLE) && (((LooseResource) (otherResource)).getTags().getTagOf(
this.eClass()) == ClassTag.COMPLETELY_SHAREABLE)
&& (otherRS != null) && (otherRS != currentRS); && (otherRS != null) && (otherRS != currentRS);
// If we do change the context // If we do change the context
...@@ -129,37 +131,26 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai ...@@ -129,37 +131,26 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai
ReadonlyContext context = new ReadonlyContext(this); ReadonlyContext context = new ReadonlyContext(this);
// We get the resource set in which "things happen" // We get the resource set in which "things happen"
ResourceSet otherResourceSet = otherEnd.eResource().getResourceSet(); // ResourceSet otherResourceSet =
// otherEnd.eResource().getResourceSet();
// We initialize the maps at the first usage
// if (this.additionnalContainersOrResources == null) {
// additionnalContainersOrResources = new HashMap<ResourceSet,
// Object>(1);
// }
// If we don't have entries for the otherResourceSet,
// we create ones with 'null' (ie not contained in this resource
// yet)
// if
// (!this.additionnalContainersOrResources.containsKey(otherResourceSet))
// {
// this.additionnalContainersOrResources.put(otherResourceSet,
// null);
// }
// We remove ourselves from a resource // We remove ourselves from a resource
if (this.eResource() != null) if (this.eResource() != null)
this.eResource().getContents().remove(this); this.eResource().getContents().remove(this);
// We only load/store another container if we are not manipulated in
// a read-only context
Object container = null;
if (!((LooseResource) (otherResource)).isReadOnly()) {
if (this.additionnalContainersOrResources == null)
container = null;
else
container = this.additionnalContainersOrResources
.get(otherRS);
}
// We temporarily change the container (which might of course erase // We temporarily change the container (which might of course erase
// the resource) // the resource)
Object container;
if (this.additionnalContainersOrResources == null)
container = null;
else
container = this.additionnalContainersOrResources.get(otherResourceSet);
if (container != null) { if (container != null) {
if (container instanceof InternalEObject) { if (container instanceof InternalEObject) {
this.eBasicSetContainer((InternalEObject) container); this.eBasicSetContainer((InternalEObject) container);
...@@ -172,18 +163,6 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai ...@@ -172,18 +163,6 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai
this.setResourceNonInverse(null); this.setResourceNonInverse(null);
} }
/*
* InternalEObject otherCont = (InternalEObject)
* this.additionnalContainersAndResources.get(otherResourceSet)[0];
*
*
* // We temporarily change the resource, if the container was null
* if (otherCont == null) { Resource otherResource = (Resource)
* this.additionnalContainersAndResources.get(otherResourceSet)[1];
* if (otherResource != null) otherResource.getContents().add(this);
* }
*/
// And we return the context for further restore // And we return the context for further restore
return context; return context;
...@@ -200,7 +179,8 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai ...@@ -200,7 +179,8 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai
* *
* @param context * @param context
*/ */
protected void restoreContext(ReadonlyContext context, InternalEObject otherEnd) { protected void restoreContext(ReadonlyContext context,
InternalEObject otherEnd) {
// If null, nothing to restore // If null, nothing to restore
if (context != null) { if (context != null) {
...@@ -214,23 +194,32 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai ...@@ -214,23 +194,32 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai
MetamodelTags tags = null; MetamodelTags tags = null;
if (otherResource != null && otherResource instanceof LooseResource) if (otherResource != null && otherResource instanceof LooseResource)
tags = ((LooseResource) (otherResource)).getTags(); tags = ((LooseResource) (otherResource)).getTags();
// if (tags != null && if (tags != null
// tags.isPropertyShareable(this.eContainmentFeature())) { && !EcoreHelper.isPropertyDesignedMutable(this
if (tags != null && !EcoreHelper.isPropertyDesignedMutable(this.eContainmentFeature())) { .eContainmentFeature())) {
storeContainer = false; storeContainer = false;
} }
if (storeContainer) { // We only store other resources if we are not manipulated in a read
// We initialize the maps at the first usage // only context
if (this.additionnalContainersOrResources == null) { if (!((LooseResource) (otherResource)).isReadOnly()) {
additionnalContainersOrResources = new HashMap<ResourceSet, Object>(1);
} if (storeContainer) {
// We initialize the maps at the first usage
if (this.additionnalContainersOrResources == null) {
additionnalContainersOrResources = new HashMap<ResourceSet, Object>(
1);
}
// We store the current context in our map
if (this.eContainer != null)
this.additionnalContainersOrResources.put(
currentResourceSet, this.eContainer);
else
this.additionnalContainersOrResources.put(
currentResourceSet, this.eResource());
// We store the current context in our map }
if (this.eContainer != null)
this.additionnalContainersOrResources.put(currentResourceSet, this.eContainer);
else
this.additionnalContainersOrResources.put(currentResourceSet, this.eResource());
} }
...@@ -253,14 +242,15 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai ...@@ -253,14 +242,15 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai
* .ecore.InternalEObject, int, java.lang.Class, * .ecore.InternalEObject, int, java.lang.Class,
* org.eclipse.emf.common.notify.NotificationChain) * org.eclipse.emf.common.notify.NotificationChain)
*/ */
public NotificationChain eInverseAdd(InternalEObject otherEnd, int featureID, public NotificationChain eInverseAdd(InternalEObject otherEnd,
Class<?> baseClass, NotificationChain msgs) { int featureID, Class<?> baseClass, NotificationChain msgs) {
// Changing the context // Changing the context
ReadonlyContext context = changeContext(otherEnd); ReadonlyContext context = changeContext(otherEnd);
// Actual call // Actual call
NotificationChain result = super.eInverseAdd(otherEnd, featureID, baseClass, msgs); NotificationChain result = super.eInverseAdd(otherEnd, featureID,
baseClass, msgs);
// Restoring the context // Restoring the context
restoreContext(context, otherEnd); restoreContext(context, otherEnd);
...@@ -278,24 +268,20 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai ...@@ -278,24 +268,20 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai
* .emf.ecore.InternalEObject, int, java.lang.Class, * .emf.ecore.InternalEObject, int, java.lang.Class,
* org.eclipse.emf.common.notify.NotificationChain) * org.eclipse.emf.common.notify.NotificationChain)
*/ */
public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, public NotificationChain eInverseRemove(InternalEObject otherEnd,
Class<?> baseClass, NotificationChain msgs) { int featureID, Class<?> baseClass, NotificationChain msgs) {
// Changing the context // Changing the context
ReadonlyContext context = changeContext(otherEnd); ReadonlyContext context = changeContext(otherEnd);
// Actual call // Actual call
NotificationChain result = super.eInverseRemove(otherEnd, featureID, baseClass, msgs); NotificationChain result = super.eInverseRemove(otherEnd, featureID,
baseClass, msgs);
// handling the removal from the hashmap, if required // handling the removal from the hashmap, if required
Resource otherResource = findResource(otherEnd); Resource otherResource = findResource(otherEnd);
ResourceSet otherRS = findResourceSet(otherEnd); ResourceSet otherRS = findResourceSet(otherEnd);
//MetamodelTags tags = null;
if (otherResource != null && otherResource instanceof LooseResource) { if (otherResource != null && otherResource instanceof LooseResource) {
// tags = ((LooseResource) (otherResource)).getTags();
// if (tags != null &&
// !EcoreHelper.isPropertyDesignedMutable(this.eContainmentFeature()))
// {
this.additionnalContainersOrResources.remove(otherRS); this.additionnalContainersOrResources.remove(otherRS);
if (this.additionnalContainersOrResources.size() == 0) if (this.additionnalContainersOrResources.size() == 0)
this.additionnalContainersOrResources = null; this.additionnalContainersOrResources = null;
...@@ -322,14 +308,4 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai ...@@ -322,14 +308,4 @@ public abstract class AbstractShareableEObject extends MinimalEObjectImpl.Contai
eSetDirectResource(resource); eSetDirectResource(resource);
} }
// @Override
// public Object getContainerOrResourceInContext(ResourceSet context) {
// if (findResourceSet(this) == context)
// return this.eContainer();
// else if (this.additionnalContainersOrResources.containsKey(context))
// return this.additionnalContainersOrResources.get(context);
// else
// return null;
// }
} }
...@@ -45,9 +45,10 @@ public class LooseResource extends XMIResourceImpl { ...@@ -45,9 +45,10 @@ public class LooseResource extends XMIResourceImpl {
* @param c * @param c
* The cloning technique tagger. * The cloning technique tagger.
*/ */
public LooseResource(MetamodelTags t) { public LooseResource(MetamodelTags tags, boolean readOnly) {
this(); this();
this.tags = t; this.tags = tags;
this.readOnly = readOnly;
} }
/** /**
...@@ -74,13 +75,18 @@ public class LooseResource extends XMIResourceImpl { ...@@ -74,13 +75,18 @@ public class LooseResource extends XMIResourceImpl {
private static final long serialVersionUID = 1410188721350066354L; private static final long serialVersionUID = 1410188721350066354L;
private boolean changeResourceOfObject(InternalEObject eObject) {
return (!(LooseResource.this.tags.getTagOf(eObject.eClass()) == ClassTag.COMPLETELY_SHAREABLE));
}
@Override @Override
public NotificationChain inverseAdd(E object, public NotificationChain inverseAdd(E object,
NotificationChain notifications) { NotificationChain notifications) {
InternalEObject eObject = (InternalEObject) object; InternalEObject eObject = (InternalEObject) object;
// We only allow Readonly (from the cloning technique pov) objects // We only allow Readonly (from the cloning technique pov) objects
// to be in multiple resources at once // to be in multiple resources at once
if (!(LooseResource.this.tags.getTagOf(eObject.eClass()) == ClassTag.COMPLETELY_SHAREABLE)) if (changeResourceOfObject(eObject))
notifications = eObject.eSetResource(LooseResource.this,notifications); notifications = eObject.eSetResource(LooseResource.this,notifications);
LooseResource.this.attached(eObject); LooseResource.this.attached(eObject);
return notifications; return notifications;
...@@ -95,7 +101,7 @@ public class LooseResource extends XMIResourceImpl { ...@@ -95,7 +101,7 @@ public class LooseResource extends XMIResourceImpl {
} }
// We only allow Readonly (from the cloning technique pov) objects // We only allow Readonly (from the cloning technique pov) objects
// to be in multiple resources at once // to be in multiple resources at once
if (!(LooseResource.this.tags.getTagOf(eObject.eClass()) == ClassTag.COMPLETELY_SHAREABLE)) if (changeResourceOfObject(eObject))
return eObject.eSetResource(null, notifications); return eObject.eSetResource(null, notifications);
else else
return notifications; return notifications;
...@@ -104,6 +110,7 @@ public class LooseResource extends XMIResourceImpl { ...@@ -104,6 +110,7 @@ public class LooseResource extends XMIResourceImpl {
} }
protected EList<EObject> realContents; protected EList<EObject> realContents;
private boolean readOnly;
@Override @Override
/** /**
...@@ -178,5 +185,9 @@ public class LooseResource extends XMIResourceImpl { ...@@ -178,5 +185,9 @@ public class LooseResource extends XMIResourceImpl {
// Restore the context of all contents // Restore the context of all contents
restoreContext(context); restoreContext(context);
} }
public boolean isReadOnly() {
return readOnly;
}
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment