Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
moclodash
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Erwan BOUSSE
moclodash
Commits
cf54973e
Commit
cf54973e
authored
Jan 23, 2014
by
Erwan Bousse
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
First commit
parents
Changes
15
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1263 additions
and
0 deletions
+1263
-0
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/generator/EMFImpl2PImpl.java
...c/fr/diverse/fancyemfcloning/generator/EMFImpl2PImpl.java
+5
-0
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/generator/FactoryGenerator.java
...r/diverse/fancyemfcloning/generator/FactoryGenerator.java
+5
-0
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/main/Application.java
...ator/src/fr/diverse/fancyemfcloning/main/Application.java
+0
-0
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/tagger/AbstractMetamodelTagger.java
...verse/fancyemfcloning/tagger/AbstractMetamodelTagger.java
+136
-0
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/tagger/ClassTag.java
...rator/src/fr/diverse/fancyemfcloning/tagger/ClassTag.java
+17
-0
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/tagger/MutClassesOnlyMetamodelTagger.java
...fancyemfcloning/tagger/MutClassesOnlyMetamodelTagger.java
+193
-0
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/tagger/WeakMutClassesOnlyMetamodelTagger.java
...yemfcloning/tagger/WeakMutClassesOnlyMetamodelTagger.java
+123
-0
FancyEMFCloning/src/fr/diverse/fancyemfcloning/cloner/Cloner.java
...Cloning/src/fr/diverse/fancyemfcloning/cloner/Cloner.java
+30
-0
FancyEMFCloning/src/fr/diverse/fancyemfcloning/cloner/impl/ClonerImpl.java
...rc/fr/diverse/fancyemfcloning/cloner/impl/ClonerImpl.java
+91
-0
FancyEMFCloning/src/fr/diverse/fancyemfcloning/cloner/impl/DeepCloner.java
...rc/fr/diverse/fancyemfcloning/cloner/impl/DeepCloner.java
+49
-0
FancyEMFCloning/src/fr/diverse/fancyemfcloning/cloner/impl/MutClassesOnlyCloner.java
...rse/fancyemfcloning/cloner/impl/MutClassesOnlyCloner.java
+82
-0
FancyEMFCloning/src/fr/diverse/fancyemfcloning/cloner/impl/WeakMutClassesOnlyCloner.java
...fancyemfcloning/cloner/impl/WeakMutClassesOnlyCloner.java
+17
-0
FancyEMFCloning/src/fr/diverse/fancyemfcloning/customemf/impl/LooseCopier.java
...r/diverse/fancyemfcloning/customemf/impl/LooseCopier.java
+86
-0
FancyEMFCloning/src/fr/diverse/fancyemfcloning/customemf/impl/LooseResource.java
...diverse/fancyemfcloning/customemf/impl/LooseResource.java
+172
-0
FancyEMFCloning/src/fr/diverse/fancyemfcloning/customemf/impl/PotentiallyReadonlyEObject.java
...emfcloning/customemf/impl/PotentiallyReadonlyEObject.java
+257
-0
No files found.
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/generator/EMFImpl2PImpl.java
0 → 100644
View file @
cf54973e
package
fr.diverse.fancyemfcloning.generator
;
public
class
EMFImpl2PImpl
{
}
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/generator/FactoryGenerator.java
0 → 100644
View file @
cf54973e
package
fr.diverse.fancyemfcloning.generator
;
public
class
FactoryGenerator
{
}
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/main/Application.java
0 → 100644
View file @
cf54973e
This diff is collapsed.
Click to expand it.
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/tagger/AbstractMetamodelTagger.java
0 → 100644
View file @
cf54973e
package
fr.diverse.fancyemfcloning.tagger
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.Set
;
import
org.eclipse.emf.ecore.EClass
;
import
org.eclipse.emf.ecore.EObject
;
import
org.eclipse.emf.ecore.EStructuralFeature
;
import
org.eclipse.emf.ecore.resource.Resource
;
public
abstract
class
AbstractMetamodelTagger
{
/**
* Final result of the algorithm, with a tag for each class concerning its
* "mutability".
*/
protected
Map
<
EClass
,
ClassTag
>
tags
;
public
AbstractMetamodelTagger
(
Set
<
Resource
>
metamodel
)
{
tags
=
new
HashMap
<
EClass
,
ClassTag
>();
// Finding all classes of the metamodel
for
(
Resource
resource
:
metamodel
)
for
(
Iterator
<
EObject
>
i
=
resource
.
getAllContents
();
i
.
hasNext
();)
{
EObject
current
=
i
.
next
();
if
(
current
instanceof
EClass
)
tags
.
put
((
EClass
)
current
,
null
);
}
recomputeTags
();
}
protected
boolean
isMutable
(
EClass
c
)
{
return
(
tags
.
get
(
c
)
==
ClassTag
.
completelyMutable
)
||
(
tags
.
get
(
c
)
==
ClassTag
.
partiallyMutable
)
||
(
tags
.
get
(
c
)
==
ClassTag
.
canReachMutable
);
}
protected
static
boolean
isPropertyMutable
(
EStructuralFeature
f
)
{
return
f
.
getName
().
contains
(
"_m"
);
}
/*protected static Set<EClass> findAllLoadedClasses() {
Set<EClass> allLoadedEClasses = new HashSet<EClass>();
for (Object o : EPackage.Registry.INSTANCE.values()) {
EPackage p = (EPackage) o;
if (p.getNsURI() != "http://www.eclipse.org/emf/2002/Ecore") {
for (EClassifier c : p.getEClassifiers()) {
if (c instanceof EClass)
allLoadedEClasses.add((EClass) c);
}
}
}
return allLoadedEClasses;
}*/
/**
* Without looking to the classes that can be reached from a class,
* determine how mutable it is (locally).
*
* @param c
* The class to analyze.
* @return ClassMutability.partiallyMutableOrCanReachMutable if the class
* has both mutable and readonly properties,
* ClassMutability.completelyMutable if the class only has mutable
* properties, ClassMutability.completelyReadonly if the class only
* has readonly properties.
*/
protected
static
ClassTag
findLocalMutability
(
EClass
c
)
{
boolean
hasMutables
=
false
;
boolean
hasReadonlys
=
false
;
for
(
EStructuralFeature
f
:
c
.
getEAllStructuralFeatures
())
{
if
(
isPropertyMutable
(
f
))
hasMutables
=
true
;
else
hasReadonlys
=
true
;
}
if
(
hasMutables
&&
hasReadonlys
)
return
ClassTag
.
partiallyMutable
;
else
if
(
hasMutables
&&
!
hasReadonlys
)
return
ClassTag
.
completelyMutable
;
else
// only readonlys OR no properties at all
return
ClassTag
.
completelyReadonly
;
}
/*
* protected static Set<Set<Resource>> findAllLoadedMetamodels() {
* Set<Set<Resource>> result = new HashSet<Set<Resource>>();
*
* // For each loaded epackage (excepted ecore itself) for (Object o :
* EPackage.Registry.INSTANCE.values()) { EPackage p = (EPackage)o; if
* (p.getNsURI()!="http://www.eclipse.org/emf/2002/Ecore") {
*
*
* // We find or create the metamodel for this package Set<Resource>
* pMetamodel = null; for (Set<Resource> metamodel : result) { if
* (metamodel.contains(p.eResource())) { pMetamodel = metamodel; break; } }
* if (pMetamodel == null){ pMetamodel = new HashSet<Resource>();
* pMetamodel.add(p.eResource()); result.add(pMetamodel); }
*
*
*
* // We look at the content (classes) for(EClassifier c :
* p.getEClassifiers()) { if (c instanceof EClass) { // For each class, we
* check that it does try to access to another resource // If it does, we
* add the resource of the class to the metamodel for (EReference r :
* ((EClass)c).getEAllReferences()) {
* pMetamodel.add(r.getEReferenceType().eResource()); } } } } }
*
* System.out.println("Found metamodels"); return result; }
*/
public
ClassTag
getTagOfEClass
(
EClass
c
)
{
if
(
tags
.
containsKey
(
c
))
{
if
(
tags
.
get
(
c
)==
null
)
System
.
out
.
println
(
"The class "
+
c
.
getName
()
+
" has no tag! Tagging problem?"
);
return
tags
.
get
(
c
);
}
else
{
System
.
out
.
println
(
"The class "
+
c
.
getName
()
+
" is not in the registered metamodel of the cloner!"
);
return
null
;
}
}
public
abstract
void
recomputeTags
();
public
abstract
boolean
mayTagClassesReadonly
();
}
\ No newline at end of file
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/tagger/ClassTag.java
0 → 100644
View file @
cf54973e
package
fr.diverse.fancyemfcloning.tagger
;
/**
* From a cloning kind point of view a class is either
* - completely readonly (no property change change), thus no need to clone it
* - completely mutable (all properties can change), thus must be cloned completely
* - partially mutable (some properties can change) OR can reach a mutable , thus can be cloned partially or completely
* @author ebousse
*
*/
public
enum
ClassTag
{
completelyReadonly
,
completelyMutable
,
partiallyMutable
,
canReachMutable
,
}
\ No newline at end of file
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/tagger/MutClassesOnlyMetamodelTagger.java
0 → 100644
View file @
cf54973e
package
fr.diverse.fancyemfcloning.tagger
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.Stack
;
import
org.eclipse.emf.ecore.EClass
;
import
org.eclipse.emf.ecore.EReference
;
import
org.eclipse.emf.ecore.resource.Resource
;
/**
* This static class allows to tag all the EClasses of a metamodel in order to determine how it can eventaully be
* cloned, for a normal MutableClassesOnly clone.
*
* @author ebousse
*
*/
public
class
MutClassesOnlyMetamodelTagger
extends
AbstractMetamodelTagger
{
public
MutClassesOnlyMetamodelTagger
(
Set
<
Resource
>
metamodel
)
{
super
(
metamodel
);
}
/**
* Very simple class used to model sccs, for clarity.
*
* @author ebousse
*
*/
private
class
StronglyConnectedComponent
{
private
Set
<
EClass
>
classes
;
public
StronglyConnectedComponent
()
{
classes
=
new
HashSet
<
EClass
>();
}
}
// Tarjan variables
private
Map
<
EClass
,
Integer
>
tarjanIndexes
;
private
Map
<
EClass
,
Integer
>
tarjanLowlinks
;
private
Stack
<
EClass
>
tarjanS
;
private
int
tarjanIndex
;
private
Set
<
StronglyConnectedComponent
>
tarjanResult
;
/**
* From https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorith Main operation that
* implements the main operation of the tarjan algorithm. Computes StronglyConnectedComponents, and tags classes in
* each as soon as they are computed.
*
* Note : should we provide a quicker algorithm for tree-shaped metamodels ?
*
* @param vertices
* the EClasses to consider
*/
private
void
tarjanWithTagging
(
Set
<
EClass
>
vertices
)
{
tarjanIndexes
=
new
HashMap
<
EClass
,
Integer
>();
tarjanLowlinks
=
new
HashMap
<
EClass
,
Integer
>();
tarjanS
=
new
Stack
<
EClass
>();
tarjanIndex
=
0
;
tarjanResult
=
new
HashSet
<
StronglyConnectedComponent
>();
for
(
EClass
v
:
vertices
)
{
if
(!
tarjanIndexes
.
containsKey
(
v
))
{
tarjanWithTaggingOnVertex
(
v
);
}
}
}
/**
* Main code of the tarjan algorithm.
*
* @param v
*/
private
void
tarjanWithTaggingOnVertex
(
EClass
v
)
{
// Set the depth index for v to the smallest unused index
tarjanIndexes
.
put
(
v
,
tarjanIndex
);
tarjanLowlinks
.
put
(
v
,
tarjanIndex
);
tarjanIndex
=
tarjanIndex
+
1
;
tarjanS
.
push
(
v
);
// Computing successors
Set
<
EClass
>
successors
=
new
HashSet
<
EClass
>();
for
(
EReference
ref
:
v
.
getEAllReferences
())
successors
.
add
(
ref
.
getEReferenceType
());
// Consider successors of v
for
(
EClass
w
:
successors
)
{
if
(!
tarjanIndexes
.
containsKey
(
w
))
{
// Successor w has not yet been visited; recurse on it
tarjanWithTaggingOnVertex
(
w
);
tarjanLowlinks
.
put
(
v
,
Math
.
min
(
tarjanLowlinks
.
get
(
v
),
tarjanLowlinks
.
get
(
w
)));
}
else
if
(
tarjanS
.
contains
(
w
))
{
// Successor w is in stack S and hence in the current SCC
tarjanLowlinks
.
put
(
v
,
Math
.
min
(
tarjanLowlinks
.
get
(
v
),
tarjanIndexes
.
get
(
w
)));
}
}
// If v is a root node, pop the stack and generate an SCC
if
(
tarjanLowlinks
.
get
(
v
)
==
tarjanIndexes
.
get
(
v
))
{
StronglyConnectedComponent
scc
=
new
StronglyConnectedComponent
();
EClass
w
;
do
{
w
=
tarjanS
.
pop
();
scc
.
classes
.
add
(
w
);
}
while
(
w
!=
v
);
// BONUS (only part not in Tarjan): computing tags
// Possible because Tarjan guarantees that
// "no strongly connected component will be identified before any of its successors."
computeMutabilityOfScc
(
scc
);
// End BONUS
tarjanResult
.
add
(
scc
);
}
}
/**
* To me used as soon as some SCC is found by the Tarjan algorithm. Will iterate over all classes of the SCC, and
* tags them for mutability.
*
* @param scc
* A StronglyConnectedComponent freshly computed in Tarjan.
*/
private
void
computeMutabilityOfScc
(
StronglyConnectedComponent
scc
)
{
Set
<
EClass
>
roWaitingForResult
=
new
HashSet
<
EClass
>();
// Do we know yet if we can reach a mutable somewhere from th scc ?
boolean
hasReachableMutable
=
false
;
// We look at all classes if the scc
for
(
EClass
c
:
scc
.
classes
)
{
// First, if still no mutable found, we look for outgoing edges of the scc
if
(!
hasReachableMutable
)
{
for
(
EReference
ref
:
c
.
getEAllReferences
())
{
EClass
reachableClass
=
ref
.
getEReferenceType
();
// If the reached class is not from the current scc AND
// is mutable, then our scc can reach a mutable
if
(!
scc
.
classes
.
contains
(
reachableClass
))
hasReachableMutable
=
isMutable
(
reachableClass
);
// If we found that we reach a mutable, no need to
// search more
if
(
hasReachableMutable
)
break
;
}
}
// Then we compute locally what we can
ClassTag
localMut
=
findLocalMutability
(
c
);
switch
(
localMut
)
{
case
partiallyMutable:
hasReachableMutable
=
true
;
tags
.
put
(
c
,
ClassTag
.
partiallyMutable
);
break
;
case
completelyMutable:
hasReachableMutable
=
true
;
tags
.
put
(
c
,
ClassTag
.
completelyMutable
);
break
;
case
completelyReadonly:
if
(
hasReachableMutable
)
tags
.
put
(
c
,
ClassTag
.
canReachMutable
);
else
roWaitingForResult
.
add
(
c
);
break
;
}
}
// And finally we compute the readonlys waiting to know if a mut can
// be reached
for
(
EClass
c
:
roWaitingForResult
)
{
if
(
hasReachableMutable
)
tags
.
put
(
c
,
ClassTag
.
canReachMutable
);
else
tags
.
put
(
c
,
ClassTag
.
completelyReadonly
);
}
}
@Override
public
void
recomputeTags
()
{
tarjanWithTagging
(
tags
.
keySet
());
System
.
out
.
println
(
"Computed mutabilities"
);
for
(
EClass
c
:
tags
.
keySet
())
{
System
.
out
.
println
(
c
.
getName
()
+
" : "
+
tags
.
get
(
c
));
}
}
@Override
public
boolean
mayTagClassesReadonly
()
{
return
true
;
}
}
CloningMaterialGenerator/src/fr/diverse/fancyemfcloning/tagger/WeakMutClassesOnlyMetamodelTagger.java
0 → 100644
View file @
cf54973e
package
fr.diverse.fancyemfcloning.tagger
;
import
java.util.HashSet
;
import
java.util.Set
;
import
org.eclipse.emf.ecore.EClass
;
import
org.eclipse.emf.ecore.EReference
;
import
org.eclipse.emf.ecore.resource.Resource
;
public
class
WeakMutClassesOnlyMetamodelTagger
extends
AbstractMetamodelTagger
{
public
WeakMutClassesOnlyMetamodelTagger
(
Set
<
Resource
>
metamodel
)
{
super
(
metamodel
);
}
public
static
class
NoSingleRootException
extends
Exception
{
private
static
final
long
serialVersionUID
=
1L
;
private
Set
<
EClass
>
roots
;
public
NoSingleRootException
(
Set
<
EClass
>
foundRoots
)
{
roots
=
new
HashSet
<
EClass
>();
roots
.
addAll
(
foundRoots
);
}
@Override
public
String
getMessage
()
{
String
message
=
"A single root is required. Roots found: "
;
for
(
EClass
aClass
:
roots
)
message
+=
aClass
.
getName
()
+
", "
;
return
message
.
substring
(
0
,
message
.
length
()
-
2
)
+
"\n"
+
super
.
getMessage
();
}
}
private
EClass
findRoot
()
throws
NoSingleRootException
{
// Preparing result set
Set
<
EClass
>
roots
=
new
HashSet
<
EClass
>();
// Finding all contained classes
Set
<
EClass
>
containedClasses
=
new
HashSet
<
EClass
>();
for
(
EClass
aClass
:
tags
.
keySet
())
for
(
EReference
r
:
aClass
.
getEAllContainments
())
(
containedClasses
).
add
(
r
.
getEReferenceType
());
// Finding root classes, ie not contained classes
for
(
EClass
aClass
:
tags
.
keySet
())
if
(!
containedClasses
.
contains
(
aClass
))
roots
.
add
(
aClass
);
// If there are multiple roots, then we have a problem
if
(
roots
.
size
()
!=
1
)
throw
new
NoSingleRootException
(
roots
);
return
roots
.
iterator
().
next
();
}
/**
* Tags a containment tree of EClasses.
*
* @param root
* The root EClass of the containment tree.
* @return True if this (sub)tree has a mutable. Required for the recursive calls.
* @throws NoSingleRootException
*/
private
boolean
treeTagging
(
EClass
root
)
throws
NoSingleRootException
{
// Is this class mutable or can reach a mutable through containment ?
// At first, false
boolean
hasMutable
=
false
;
// We first make recursive calls looking for mutables at lower levels
// If some contained classes are mutable, we change hasMutable
for
(
EReference
cont
:
root
.
getEAllContainments
())
{
hasMutable
=
hasMutable
||
treeTagging
(
cont
.
getEReferenceType
());
}
// Then depending on the local attributes, we tag the current class
ClassTag
localMut
=
findLocalMutability
(
root
);
switch
(
localMut
)
{
case
partiallyMutable:
hasMutable
=
true
;
tags
.
put
(
root
,
ClassTag
.
partiallyMutable
);
break
;
case
completelyMutable:
hasMutable
=
true
;
tags
.
put
(
root
,
ClassTag
.
completelyMutable
);
break
;
case
completelyReadonly:
if
(
hasMutable
)
tags
.
put
(
root
,
ClassTag
.
canReachMutable
);
else
tags
.
put
(
root
,
ClassTag
.
completelyReadonly
);
break
;
}
// And we return true if the class is considered mutable
return
hasMutable
;
}
@Override
public
void
recomputeTags
()
{
try
{
treeTagging
(
findRoot
());
}
catch
(
NoSingleRootException
e
)
{
System
.
out
.
println
(
e
.
getMessage
());
System
.
out
.
println
(
"No tagging possible for WeakMutClassesOnlyMetamodelTagger."
);
}
System
.
out
.
println
(
"Computed mutabilities:"
);
if
(
tags
.
size
()
==
0
)
System
.
out
.
println
(
"No mutable class!"
);
for
(
EClass
c
:
tags
.
keySet
())
{
System
.
out
.
println
(
c
.
getName
()
+
" : "
+
tags
.
get
(
c
));
}
}
@Override
public
boolean
mayTagClassesReadonly
()
{
// TODO Stub de la méthode généré automatiquement
return
true
;
}
}
FancyEMFCloning/src/fr/diverse/fancyemfcloning/cloner/Cloner.java
0 → 100644
View file @
cf54973e
package
fr.diverse.fancyemfcloning.cloner
;
import
org.eclipse.emf.ecore.EClass
;
import
org.eclipse.emf.ecore.resource.ResourceSet
;
import
fr.diverse.fancyemfcloning.customemf.ClassTag
;
/**
* Defines a class in which a cloning technique is implemented.
* @author ebousse
*
*/
public
interface
Cloner
{
/**
* Considering a model stored in a ResourceSet, computes a clone of the model.
* @param model The model to clone.
* @param folder The folder in which to store the model to clone (at least in its URI).
* @return The cloned model.
*/
public
ResourceSet
clone
(
ResourceSet
model
,
String
folder
);
public
ClassTag
getTagOf
(
EClass
eClass
);
//public ClassTag getTagOf(EClass c);
}
FancyEMFCloning/src/fr/diverse/fancyemfcloning/cloner/impl/ClonerImpl.java
0 → 100644
View file @
cf54973e
package
fr.diverse.fancyemfcloning.cloner.impl
;
import
java.util.Iterator
;
import
org.eclipse.emf.common.util.URI
;
import
org.eclipse.emf.ecore.EClass
;
import
org.eclipse.emf.ecore.EObject
;
import
org.eclipse.emf.ecore.resource.Resource
;
import
org.eclipse.emf.ecore.resource.ResourceSet
;
import
org.eclipse.emf.ecore.resource.impl.ResourceSetImpl
;
import
org.eclipse.emf.ecore.util.EcoreUtil
;
import
fr.diverse.fancyemfcloning.cloner.Cloner
;
import
fr.diverse.fancyemfcloning.customemf.ClassTag
;
import
fr.diverse.fancyemfcloning.customemf.impl.LooseCopier
;
import
fr.diverse.fancyemfcloning.customemf.impl.LooseResource
;
import
fr.diverse.fancyemfcloning.tagger.AbstractMetamodelTagger
;
/**
* Self containing class with the cloning algorithm.
*
* @author ebousse
*
*/
public
class
ClonerImpl
implements
Cloner
{
protected
AbstractMetamodelTagger
tagger
;
public
ClonerImpl
(
AbstractMetamodelTagger
tagger
)
{
this
.
tagger
=
tagger
;
}
@Override
public
ResourceSet
clone
(
ResourceSet
cloned
,
String
folder
)
{
// Creating empty clone resource set
ResourceSet
clone
=
new
ResourceSetImpl
();
// Preparing the copier, which will allow us to copy objects in new
// resources AND to resolve the references in the clone (even between resources)
EcoreUtil
.
Copier
copier
=
new
LooseCopier
();
// new EcoreUtil.Copier();
// Cloning all resources
for
(
Resource
r
:
cloned
.
getResources
())
{
// Getting the complete file name
String
filename
=
r
.
getURI
().
segmentsList
().
get
(
r
.
getURI
().
segmentsList
().
size
()
-
1
);
// Preparing the URI of the new resource (with a specific 'folder')
URI
uri
=
r
.
getURI
().
trimSegments
(
1
).
appendSegment
(
folder
).
appendSegment
(
filename
);
// Creating the new Resource...
Resource
resourceClone
=
null
;
// LooseResource if objects might be shared
if
(
tagger
.
mayTagClassesReadonly
())
{
resourceClone
=
new
LooseResource
(
this
);
resourceClone
.
setURI
(
uri
);
clone
.
getResources
().
add
(
resourceClone
);
}
// Or regular Resource, if not
else
resourceClone
=
clone
.
createResource
(
uri
);
// Copying objects (but not the references, and only tagged mutable ones)
for
(
Iterator
<
EObject
>
i
=
r
.
getAllContents
();
i
.
hasNext
();)
{
EObject
o
=
i
.
next
();
ClassTag
tag
=
tagger
.
getTagOfEClass
(
o
.
eClass
());
if
(
tag
==
ClassTag
.
canReachMutable
||
tag
==
ClassTag
.
completelyMutable
||
tag
==
ClassTag
.
partiallyMutable
)
{
resourceClone
.
getContents
().
add
(
copier
.
copy
(
o
));
}
else
{
resourceClone
.
getContents
().
add
(
o
);
}
}
}
// Resolving references (all of them, even between resources of the clone and
// between the clone and the cloned)
copier
.
copyReferences
();
// Returning the obtained clone
return
clone
;
}