Commit ce354e76 authored by Erwan Bousse's avatar Erwan Bousse

Major improvement: now inheritance and abstract classes and interfaces are...

Major improvement: now inheritance and abstract classes and interfaces are taken into account. Also error messages are now displayed when generating cloning material
parent eee4fcef
...@@ -41,7 +41,8 @@ public class LightCopierGenerator { ...@@ -41,7 +41,8 @@ public class LightCopierGenerator {
try { try {
// Preparing the output file // Preparing the output file
// File outputDir = new File(srcOutputFolder + "/" + generateFullyQualifiedName(pack, "/"));*/ // File outputDir = new File(srcOutputFolder + "/" +
// generateFullyQualifiedName(pack, "/"));*/
outputDir.mkdirs(); outputDir.mkdirs();
File outputFile = new File(outputDir, className + ".java"); File outputFile = new File(outputDir, className + ".java");
...@@ -69,35 +70,38 @@ public class LightCopierGenerator { ...@@ -69,35 +70,38 @@ public class LightCopierGenerator {
Set<EClass> eClasses = EcoreHelper.findEClasses(metamodel); Set<EClass> eClasses = EcoreHelper.findEClasses(metamodel);
for (EClass c : eClasses) { for (EClass c : eClasses) {
if (tagger.getTagOfEClass(c) == ClassTag.PARTIALLY_SHAREABLE) { if (!c.isAbstract() && !c.isInterface()) {
hasShareable = true;
imports += "import " + EcoreHelper.computeFullyQualifiedName(c) + ";\n"; if (tagger.getTagOfEClass(c) == ClassTag.PARTIALLY_SHAREABLE) {
hasShareable = true;
imports += "import " + EcoreHelper.computeFullyQualifiedName(c) + ";\n";
// We generate its if/elseif lines
if (!firstIf) {
classdef += "else\n";
firstIf = false;
}
classdef += "if (eObject instanceof " + c.getName() + ")\n";
classdef += "return new " + c.getName() + tagger.getSuffix() + "((" + c.getName() + ")"
+ "eObject);\n";
// We generate its if/elseif lines
if (!firstIf) {
classdef += "else\n";
firstIf = false;
} }
classdef += "if (eObject instanceof " + c.getName() + ")\n";
classdef += "return new " + c.getName() + tagger.getSuffix() + "((" + c.getName() + ")"
+ "eObject);\n";
} else if (tagger.getTagOfEClass(c) == ClassTag.COMPLETELY_SHAREABLE) {
hasShareable = true;
else if (tagger.getTagOfEClass(c) == ClassTag.COMPLETELY_SHAREABLE) { imports += "import " + EcoreHelper.computeFullyQualifiedName(c) + ";\n";
hasShareable = true;
imports += "import " + EcoreHelper.computeFullyQualifiedName(c) + ";\n"; // We generate its if/elseif lines
if (!firstIf) {
// We generate its if/elseif lines classdef += "else\n";
if (!firstIf) { firstIf = false;
classdef += "else\n"; }
firstIf = false; classdef += "if (eObject instanceof " + c.getName() + ")\n";
classdef += "return eObject;\n";
} }
classdef += "if (eObject instanceof " + c.getName() + ")\n";
classdef += "return eObject;\n";
} }
} }
......
...@@ -30,8 +30,8 @@ import fr.inria.diverse.cloning.runtime.util.Log; ...@@ -30,8 +30,8 @@ import fr.inria.diverse.cloning.runtime.util.Log;
public class TagsGenerator { public class TagsGenerator {
/** /**
* Generates a java class implementing the MetamodelTags interface, to retrieve at runtine the generate tags of the * Generates a java class implementing the MetamodelTags interface, to
* metamodel classes. * retrieve at runtine the generate tags of the metamodel classes.
* *
* @param pack * @param pack
* The java package in which to generate the class. * The java package in which to generate the class.
...@@ -77,21 +77,20 @@ public class TagsGenerator { ...@@ -77,21 +77,20 @@ public class TagsGenerator {
boolean firstIf = true; boolean firstIf = true;
Set<EClass> eClasses = EcoreHelper.findEClasses(metamodel); Set<EClass> eClasses = EcoreHelper.findEClasses(metamodel);
for (EClass c : eClasses) { for (EClass c : eClasses) {
if (!c.isInterface()) {
//imports += "import " + EcoreHelper.computeFullyQualifiedName(c) + ";\n"; // We generate its if/elseif lines
if (!firstIf) {
// We generate its if/elseif lines classdef += "else\n";
if (!firstIf) { firstIf = false;
classdef += "else\n"; }
firstIf = false;
}
String packageInterfaceName = EcoreHelper.computeFullyQualifiedName(c.getEPackage()) + "."
+ CodeGeneration.firstCharUp(c.getEPackage().getName()) + "Package";
classdef += "if (eClass.equals(" + packageInterfaceName + ".eINSTANCE.get" + c.getName() + "()))\n"; String packageInterfaceName = EcoreHelper.computeFullyQualifiedName(c.getEPackage()) + "."
classdef += "return " + ClassTag.class.getSimpleName() + "." + tagger.getTagOfEClass(c) + ";\n"; + CodeGeneration.firstCharUp(c.getEPackage().getName()) + "Package";
classdef += "if (eClass.equals(" + packageInterfaceName + ".eINSTANCE.get" + c.getName() + "()))\n";
classdef += "return " + ClassTag.class.getSimpleName() + "." + tagger.getTagOfEClass(c) + ";\n";
}
} }
// Default case: call to the super method // Default case: call to the super method
...@@ -115,22 +114,23 @@ public class TagsGenerator { ...@@ -115,22 +114,23 @@ public class TagsGenerator {
// For each class that led to a pimpl // For each class that led to a pimpl
boolean firstIf2 = true; boolean firstIf2 = true;
for (EClass c : eClasses) { for (EClass c : eClasses) {
if (!c.isInterface()) {
for (EStructuralFeature prop : c.getEStructuralFeatures()) { for (EStructuralFeature prop : c.getEStructuralFeatures()) {
// We generate its if/elseif lines // We generate its if/elseif lines
if (!firstIf2) { if (!firstIf2) {
classdef += "else\n"; classdef += "else\n";
firstIf2 = false; firstIf2 = false;
} }
String packageInterfaceName = EcoreHelper.computeFullyQualifiedName(c.getEPackage()) + "."
+ CodeGeneration.firstCharUp(c.getEPackage().getName()) + "Package";
classdef += "if (prop.equals(" + packageInterfaceName + ".eINSTANCE.get" + c.getName() + "_" String packageInterfaceName = EcoreHelper.computeFullyQualifiedName(c.getEPackage()) + "."
+ CodeGeneration.firstCharUp(prop.getName()) + "()))\n"; + CodeGeneration.firstCharUp(c.getEPackage().getName()) + "Package";
classdef += "return " + String.valueOf(tagger.isPropertyShareable(prop)) + ";\n";
classdef += "if (prop.equals(" + packageInterfaceName + ".eINSTANCE.get" + c.getName() + "_"
+ CodeGeneration.firstCharUp(prop.getName()) + "()))\n";
classdef += "return " + String.valueOf(tagger.isPropertyShareable(prop)) + ";\n";
}
} }
} }
// Default case // Default case
...@@ -139,8 +139,7 @@ public class TagsGenerator { ...@@ -139,8 +139,7 @@ public class TagsGenerator {
// end isPropertyMutable method declaration // end isPropertyMutable method declaration
classdef += "}\n"; classdef += "}\n";
// metrics methods declaration // metrics methods declaration
classdef += "public double getShareableClassesRatio() {\n"; classdef += "public double getShareableClassesRatio() {\n";
classdef += "return " + CloningMetrics.computeShareableClassesRatio(metamodel, tagger) + ";\n"; classdef += "return " + CloningMetrics.computeShareableClassesRatio(metamodel, tagger) + ";\n";
...@@ -152,10 +151,12 @@ public class TagsGenerator { ...@@ -152,10 +151,12 @@ public class TagsGenerator {
classdef += "return " + CloningMetrics.computeIsolatedShareablePropertiesRatio(metamodel, tagger) + ";\n"; classdef += "return " + CloningMetrics.computeIsolatedShareablePropertiesRatio(metamodel, tagger) + ";\n";
classdef += "}\n"; classdef += "}\n";
classdef += "public double getShareablePropertiesInPartShareableClassesDensity() {\n"; classdef += "public double getShareablePropertiesInPartShareableClassesDensity() {\n";
classdef += "return " + CloningMetrics.computeShareablePropertiesInPartShareableClassesDensity(metamodel, tagger)+ ";\n"; classdef += "return "
+ CloningMetrics.computeShareablePropertiesInPartShareableClassesDensity(metamodel, tagger) + ";\n";
classdef += "}\n"; classdef += "}\n";
classdef += "public double getShareablePropertiesInShareableClassesDensity() {\n"; classdef += "public double getShareablePropertiesInShareableClassesDensity() {\n";
classdef += "return " + CloningMetrics.computeShareablePropertiesInShareableClassesDensity(metamodel, tagger)+ ";\n"; classdef += "return "
+ CloningMetrics.computeShareablePropertiesInShareableClassesDensity(metamodel, tagger) + ";\n";
classdef += "}\n"; classdef += "}\n";
// end metrics methods declaration // end metrics methods declaration
......
...@@ -19,7 +19,9 @@ import java.util.Set; ...@@ -19,7 +19,9 @@ import java.util.Set;
import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI; import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.EcorePackage;
...@@ -46,7 +48,8 @@ import fr.inria.diverse.cloning.runtime.util.Log; ...@@ -46,7 +48,8 @@ import fr.inria.diverse.cloning.runtime.util.Log;
public class Start { public class Start {
public static void start(Set<File> ecoreFiles, String metamodelName, IJavaProject javaProject, boolean emf) { public static void start(Set<File> ecoreFiles, String metamodelName, IJavaProject javaProject, boolean emf)
throws CoreException {
Log.info("Starting Cloning material generator"); Log.info("Starting Cloning material generator");
try { try {
...@@ -56,7 +59,8 @@ public class Start { ...@@ -56,7 +59,8 @@ public class Start {
rs = EMFCodeGenerator.generate(ecoreFiles, metamodelName, javaProject.getProject()); rs = EMFCodeGenerator.generate(ecoreFiles, metamodelName, javaProject.getProject());
else { else {
// Loading some ecore files in a resource set (= considered metamodel) // Loading some ecore files in a resource set (= considered
// metamodel)
EcoreResourceFactoryImpl fact = new EcoreResourceFactoryImpl(); EcoreResourceFactoryImpl fact = new EcoreResourceFactoryImpl();
if (!EPackage.Registry.INSTANCE.containsKey(EcorePackage.eNS_URI)) { if (!EPackage.Registry.INSTANCE.containsKey(EcorePackage.eNS_URI)) {
EPackage.Registry.INSTANCE.put(EcorePackage.eNS_URI, EcorePackage.eINSTANCE); EPackage.Registry.INSTANCE.put(EcorePackage.eNS_URI, EcorePackage.eINSTANCE);
...@@ -71,7 +75,7 @@ public class Start { ...@@ -71,7 +75,7 @@ public class Start {
Collection<Tagger> taggers = Arrays.asList(new DeepCloningTagger(rs, metamodelName), Collection<Tagger> taggers = Arrays.asList(new DeepCloningTagger(rs, metamodelName),
new ShareFieldsOnlyTagger(rs, metamodelName), new ShareObjOnlyTagger(rs, metamodelName), new ShareFieldsOnlyTagger(rs, metamodelName), new ShareObjOnlyTagger(rs, metamodelName),
new ShareAllTagger(rs, metamodelName)); new ShareAllTagger(rs, metamodelName));
// Discovering the model from the project // Discovering the model from the project
DiscoverJavaModelFromJavaProject discoverer = new DiscoverJavaModelFromJavaProject(); DiscoverJavaModelFromJavaProject discoverer = new DiscoverJavaModelFromJavaProject();
...@@ -84,7 +88,8 @@ public class Start { ...@@ -84,7 +88,8 @@ public class Start {
// Getting the absolute path of the folder // Getting the absolute path of the folder
File emfProjectFolder = javaProject.getProject().getLocation().toFile(); File emfProjectFolder = javaProject.getProject().getLocation().toFile();
// String srcOutputFolder = "/home/ebousse/Dev/modelCloning/emf/SomeMetamodel/src"; // String srcOutputFolder =
// "/home/ebousse/Dev/modelCloning/emf/SomeMetamodel/src";
String srcOutputFolder = new File(emfProjectFolder, "src").getAbsolutePath(); String srcOutputFolder = new File(emfProjectFolder, "src").getAbsolutePath();
// Calling the partial implementations transformer with one tagger // Calling the partial implementations transformer with one tagger
...@@ -97,18 +102,6 @@ public class Start { ...@@ -97,18 +102,6 @@ public class Start {
javaGenerator.doGenerate(null); javaGenerator.doGenerate(null);
toProcess = brandNew; toProcess = brandNew;
} }
//new EMFImpl2PImpl(originalModel, tagger2, true).transform2PImpl(srcOutputFolder);
// // Generating the code from the obtained model
// GenerateJavaExtended javaGenerator = new GenerateJavaExtended(javaModel, new File(srcOutputFolder),
// new ArrayList<Object>());
// javaGenerator.doGenerate(null);
//
// // Generating the code from the obtained model
// GenerateJavaExtended javaGenerator2 = new GenerateJavaExtended(originalModel, new File(srcOutputFolder),
// new ArrayList<Object>());
// javaGenerator2.doGenerate(null);
// Adding a dependency in the manifest // Adding a dependency in the manifest
ManifestEditor manEdit = new ManifestEditor(javaProject.getProject()); ManifestEditor manEdit = new ManifestEditor(javaProject.getProject());
...@@ -119,18 +112,11 @@ public class Start { ...@@ -119,18 +112,11 @@ public class Start {
// Done // Done
Log.info("Done !"); Log.info("Done !");
} catch (DiscoveryException e) { } catch (Exception e) {
// TODO Bloc catch généré automatiquement
e.printStackTrace();
} catch (IOException e) {
// TODO Bloc catch généré automatiquement
e.printStackTrace();
} catch (EMFGenerationException e) {
// TODO Bloc catch généré automatiquement
e.printStackTrace();
} catch (CoreException e) {
// TODO Bloc catch généré automatiquement
e.printStackTrace(); e.printStackTrace();
IStatus status = new Status(IStatus.ERROR, "fr.inria.diverse.cloning.materialgenerator", e.getMessage());
throw new CoreException(status);
} }
} }
} }
...@@ -29,7 +29,8 @@ import fr.inria.diverse.cloning.runtime.util.Log; ...@@ -29,7 +29,8 @@ import fr.inria.diverse.cloning.runtime.util.Log;
public abstract class AbstractTagger implements Tagger { public abstract class AbstractTagger implements Tagger {
/** /**
* Final result of the algorithm, with a tag for each class concerning its "mutability". * Final result of the algorithm, with a tag for each class concerning its
* "mutability".
*/ */
protected Map<EClass, ClassTag> classesTags; protected Map<EClass, ClassTag> classesTags;
...@@ -38,7 +39,6 @@ public abstract class AbstractTagger implements Tagger { ...@@ -38,7 +39,6 @@ public abstract class AbstractTagger implements Tagger {
protected ResourceSet metamodel; protected ResourceSet metamodel;
protected String metamodelname; protected String metamodelname;
@Override @Override
public String getMetamodelName() { public String getMetamodelName() {
...@@ -54,14 +54,17 @@ public abstract class AbstractTagger implements Tagger { ...@@ -54,14 +54,17 @@ public abstract class AbstractTagger implements Tagger {
for (Resource resource : metamodel.getResources()) for (Resource resource : metamodel.getResources())
for (Iterator<EObject> i = resource.getAllContents(); i.hasNext();) { for (Iterator<EObject> i = resource.getAllContents(); i.hasNext();) {
EObject current = i.next(); EObject current = i.next();
if (current instanceof EClass) if (current instanceof EClass) {
classesTags.put((EClass) current, null); EClass currentEClass = (EClass) current;
if (!currentEClass.isInterface())
classesTags.put((EClass) current, null);
}
} }
recomputeTags(); recomputeTags();
} }
public AbstractTagger(Set<Resource> metamodel, String metamodelname) { public AbstractTagger(Set<Resource> metamodel, String metamodelname) {
} }
protected boolean isMutable(EClass c) { protected boolean isMutable(EClass c) {
...@@ -70,17 +73,14 @@ public abstract class AbstractTagger implements Tagger { ...@@ -70,17 +73,14 @@ public abstract class AbstractTagger implements Tagger {
} }
protected static boolean isPropertyDesignedMutable(EStructuralFeature f) { protected static boolean isPropertyDesignedMutable(EStructuralFeature f) {
//return f.getName().endsWith("_m"); // return f.getName().endsWith("_m");
return EcoreHelper.isPropertyDesignedMutable(f); return EcoreHelper.isPropertyDesignedMutable(f);
} }
protected enum PropertiesMutability { protected enum PropertiesMutability {
allMutable, someMutable, noneMutable allMutable, someMutable, noneMutable
} }
@Override @Override
public ClassTag getTagOfEClass(EClass c) { public ClassTag getTagOfEClass(EClass c) {
if (classesTags.containsKey(c)) { if (classesTags.containsKey(c)) {
...@@ -94,7 +94,6 @@ public abstract class AbstractTagger implements Tagger { ...@@ -94,7 +94,6 @@ public abstract class AbstractTagger implements Tagger {
} }
@Override @Override
public ResourceSet getMetamodel() { public ResourceSet getMetamodel() {
return metamodel; return metamodel;
......
...@@ -137,8 +137,8 @@ public class ShareAllTagger extends AbstractTagger { ...@@ -137,8 +137,8 @@ public class ShareAllTagger extends AbstractTagger {
} }
/** /**
* To me used as soon as some SCC is found by the Tarjan algorithm. Will iterate over all classes of the SCC, and * To be 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. * tag them for mutability.
* *
* @param scc * @param scc
* A StronglyConnectedComponent freshly computed in Tarjan. * A StronglyConnectedComponent freshly computed in Tarjan.
......
...@@ -10,13 +10,9 @@ ...@@ -10,13 +10,9 @@
******************************************************************************/ ******************************************************************************/
package fr.inria.diverse.cloning.materialgenerator.tagger.impl; package fr.inria.diverse.cloning.materialgenerator.tagger.impl;
import java.util.Iterator;
import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.ResourceSet;
import fr.inria.diverse.cloning.runtime.common.ClassTag; import fr.inria.diverse.cloning.runtime.common.ClassTag;
...@@ -28,37 +24,32 @@ public class ShareFieldsOnlyTagger extends AbstractTagger { ...@@ -28,37 +24,32 @@ public class ShareFieldsOnlyTagger extends AbstractTagger {
super(metamodel, metamodelname); super(metamodel, metamodelname);
} }
@Override @Override
public void recomputeTags() { public void recomputeTags() {
Log.info("Tagging with ShareFieldsOnlyTagger."); Log.info("Tagging with ShareFieldsOnlyTagger.");
for (Resource res : metamodel.getResources()) { for (EClass next : classesTags.keySet()) {
for (Iterator<EObject> i = res.getAllContents(); i.hasNext();) { EClass c = (EClass) next;
EObject next = i.next(); boolean hasReadonlys = false;
if (next instanceof EClass) { // First attributes
EClass c = (EClass) next; for (EAttribute att : c.getEAllAttributes()) {
boolean hasReadonlys = false; if (isPropertyDesignedMutable(att))
// First attributes propertiesTags.put(att, false);
for (EAttribute att : c.getEAllAttributes()) { else {
if (isPropertyDesignedMutable(att)) propertiesTags.put(att, true);
propertiesTags.put(att, false); hasReadonlys = true;
else {
propertiesTags.put(att, true);
hasReadonlys = true;
}
}
// Then references, all mutable
for (EReference ref : c.getEAllReferences()) {
propertiesTags.put(ref, false);
}
if (hasReadonlys)
classesTags.put(c, ClassTag.PARTIALLY_SHAREABLE);
else
classesTags.put(c, ClassTag.NOT_SHAREABLE);
} }
} }
// Then references, all mutable
for (EReference ref : c.getEAllReferences()) {
propertiesTags.put(ref, false);
}
if (hasReadonlys)
classesTags.put(c, ClassTag.PARTIALLY_SHAREABLE);
else
classesTags.put(c, ClassTag.NOT_SHAREABLE);
} }
Log.info("Computed mutabilities:"); Log.info("Computed mutabilities:");
Log.plusLevel(); Log.plusLevel();
for (EClass c : classesTags.keySet()) { for (EClass c : classesTags.keySet()) {
...@@ -83,7 +74,6 @@ public class ShareFieldsOnlyTagger extends AbstractTagger { ...@@ -83,7 +74,6 @@ public class ShareFieldsOnlyTagger extends AbstractTagger {
return "ShareFieldsOnly"; return "ShareFieldsOnly";
} }
@Override @Override
public boolean mayTagClassesPartShareable() { public boolean mayTagClassesPartShareable() {
return true; return true;
......
...@@ -56,7 +56,7 @@ public class CodeGeneration { ...@@ -56,7 +56,7 @@ public class CodeGeneration {
// instantiate the default code formatter with the given options // instantiate the default code formatter with the given options
final CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(options); final CodeFormatter codeFormatter = ToolFactory