Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.sdmlib.models.classes.logic.GenClassModel Maven / Gradle / Ivy
Go to download
SDMLib is a light weight modeling library. SDMLib intentionally comes without any tool or editor.
package org.sdmlib.models.classes.logic;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.sdmlib.CGUtil;
import org.sdmlib.StrUtil;
import org.sdmlib.codegen.LocalVarTableEntry;
import org.sdmlib.codegen.Parser;
import org.sdmlib.codegen.StatementEntry;
import org.sdmlib.codegen.SymTabEntry;
import org.sdmlib.codegen.util.StatementEntrySet;
import org.sdmlib.models.SDMLibIdMap;
import org.sdmlib.models.classes.ClassModel;
import org.sdmlib.models.objects.GenericAttribute;
import org.sdmlib.models.objects.GenericLink;
import org.sdmlib.models.objects.GenericObject;
import org.sdmlib.storyboards.Storyboard;
import de.uniks.networkparser.IdMap;
import de.uniks.networkparser.graph.Annotation;
import de.uniks.networkparser.graph.Association;
import de.uniks.networkparser.graph.AssociationTypes;
import de.uniks.networkparser.graph.Attribute;
import de.uniks.networkparser.graph.Cardinality;
import de.uniks.networkparser.graph.Clazz;
import de.uniks.networkparser.graph.Clazz.ClazzType;
import de.uniks.networkparser.graph.DataType;
import de.uniks.networkparser.graph.GraphMember;
import de.uniks.networkparser.graph.GraphUtil;
import de.uniks.networkparser.graph.Literal;
import de.uniks.networkparser.graph.Method;
import de.uniks.networkparser.graph.Modifier;
import de.uniks.networkparser.graph.Parameter;
import de.uniks.networkparser.graph.Throws;
import de.uniks.networkparser.graph.util.AssociationSet;
import de.uniks.networkparser.interfaces.SendableEntityCreator;
import de.uniks.networkparser.list.SimpleList;
import de.uniks.networkparser.list.SimpleSet;
public class GenClassModel implements ClassModelAdapter
{
public static final String UTILPATH = ".util";
ClassModel model;
private LinkedHashMap handledClazzes = new LinkedHashMap();
private AssociationSet associations = null;
private HashMap> generators = new HashMap>();
private DIFF showDiff = DIFF.NONE;
private List ignoreDiff;
public enum DIFF
{
NONE, DIFF, FULL
};
public boolean addToAssociations(Association value)
{
boolean changed = false;
if (value != null)
{
if (this.associations == null)
{
this.associations = new AssociationSet();
}
changed = this.associations.add(value);
}
return changed;
}
public boolean removeFromAssociations(Association value)
{
boolean changed = false;
if ((this.associations != null) && (value != null))
{
changed = this.associations.remove(value);
}
return changed;
}
public AssociationSet getAssociations()
{
if (this.associations == null)
{
return new AssociationSet();
}
return this.associations;
}
public GenClazzEntity getOrCreate(Clazz clazz) {
if(clazz.getType()==ClazzType.ENUMERATION) {
return getOrCreateEnum(clazz);
} else {
return getOrCreateClazz(clazz);
}
}
private GenClass getOrCreateClazz(Clazz clazz)
{
if (generators.containsKey(clazz))
{
return (GenClass) generators.get(clazz);
}
Generator gen = new GenClass().withModel(clazz);
generators.put(clazz, gen);
return (GenClass) gen;
}
private GenEnumeration getOrCreateEnum(Clazz enumeration)
{
if (generators.containsKey(enumeration))
{
return (GenEnumeration) generators.get(enumeration);
}
Generator gen = new GenEnumeration().withModel(enumeration);
generators.put(enumeration, gen);
return (GenEnumeration) gen;
}
@Override
public GenClass getClazz(String name) {
for(Iterator>> iterator = generators.entrySet().iterator();iterator.hasNext();){
Entry> item = iterator.next();
if(item.getKey().getName().equals(name)) {
return (GenClass)item.getValue();
}
}
return null;
}
public GenMethod getOrCreate(Method method)
{
if (generators.containsKey(method))
{
return (GenMethod) generators.get(method);
}
Generator gen = new GenMethod().withModel(method);
generators.put(method, gen);
return (GenMethod) gen;
}
public GenAttribute getOrCreate(Attribute attribute)
{
if (generators.containsKey(attribute))
{
return (GenAttribute) generators.get(attribute);
}
Generator gen = new GenAttribute().withModel(attribute);
generators.put(attribute, gen);
return (GenAttribute) gen;
}
public GenAnnotation getOrCreate(Annotation annotation)
{
if (generators.containsKey(annotation))
{
return (GenAnnotation) generators.get(annotation);
}
Generator gen = new GenAnnotation().withModel(annotation);
generators.put(annotation, gen);
return (GenAnnotation) gen;
}
public GenAssociation getOrCreate(Association association)
{
if (generators.containsKey(association))
{
return (GenAssociation) generators.get(association);
}
Generator gen = new GenAssociation().withModel(association);
generators.put(association, gen);
return (GenAssociation) gen;
}
public boolean generate(String rootDir)
{
resetParsers();
fixClassModel(rootDir);
addHelperClassesForUnknownAttributeTypes();
for (Clazz clazz : model.getClazzes()) {
getOrCreate(clazz).generate(rootDir, rootDir);
}
// for (Enumeration enumeration : model.getEnumerations())
// {
// getOrCreate(enumeration).generate(rootDir, rootDir);
// }
//
// for (Clazz clazz : model.getClazzes())
// {
// getOrCreate(clazz).generate(rootDir, rootDir);
// }
for (Association assoc : getAssociations())
{
getOrCreate(assoc).generate(rootDir, rootDir);
getOrCreate(assoc.getOther()).generate(rootDir, rootDir);
}
Exception e = new RuntimeException();
attributNameConsistenceCheck(e, rootDir);
// Write all
if (getShowDiff() != DIFF.NONE)
{
int count = 0;
for (Clazz clazz : model.getClazzes())
{
if(clazz.getType()==ClazzType.CLAZZ) {
count += getOrCreateClazz(clazz).printAll(getShowDiff(), this.ignoreDiff);
}
}
System.out.println("Totalchanges of all Files: " + count);
}
// perhabs there is already generated and compiled code from previous run.
// Try to do coverage of model code
this.doCoverageOfModelCode();
this.addJavadocReferences(rootDir);
return true;
}
private void addJavadocReferences(String rootDir)
{
// find method that called ClassModel.generate()
Exception e = new RuntimeException();
StackTraceElement[] stackTrace = e.getStackTrace();
StackTraceElement callEntry = null;
// find first method above ClassModel.generate()
int i = 1;
while (true)
{
callEntry = stackTrace[i];
if (callEntry.getClassName().equals(GenClassModel.class.getName())
|| callEntry.getClassName().equals(ClassModel.class.getName()))
{
i++;
continue;
}
else
{
break;
}
}
String classModelConstructionClass = callEntry.getClassName();
// search for a subdirectory containing the javaTestFile of the
// execution directory and search for the subdi
File projectDir = new File(".");
Storyboard story = new Storyboard();
story.setJavaTestFileName(classModelConstructionClass.replaceAll("\\.", "/") + ".java");
if (story.searchDirectoryTree(projectDir))
{
// found it
// add javadoc references to all generated model classes
for (Clazz clazz : this.model.getClazzes())
{
if (clazz.isExternal()) continue;
String fullClazzFileName = rootDir + "/" + clazz.getName(false).replaceAll("\\.", "/") + ".java";
story.addReferenceToJavaDoc(fullClazzFileName, Parser.CLASS + ":" + CGUtil.shortClassName(clazz.getName()), story.getJavaTestFileName().substring(3));
}
System.out.println();
}
}
private void fixClassModel(String rootDir)
{
Clazz[] classes = model.getClazzes().toArray(new Clazz[model.getClazzes().size()]);
HashSet visited = new HashSet();
for (Clazz item : classes)
{
fixClassModel(item, visited, rootDir);
}
}
private void fixClassModel(Clazz item, HashSet visited, String rootDir)
{
for (Clazz entity : item.getInterfaces(false))
{
if (entity.getClassModel() == null)
{
if (visited.add(entity))
{
fixClassModel(entity, visited, rootDir);
}
entity.setClassModel(model);
}
}
for (Clazz entity : item.getSuperClazzes(false))
{
if (entity.getClassModel() == null)
{
if (visited.add(entity))
{
fixClassModel(entity, visited, rootDir);
}
entity.setClassModel(model);
}
}
for (Clazz entity : item.getKidClazzes(false))
{
if (entity.getClassModel() == null)
{
entity.setClassModel(model);
if (visited.add(entity))
{
fixClassModel(entity, visited, rootDir);
}
}
}
for (Association role : item.getAssociations())
{
Clazz clazz = role.getOtherClazz();
if (clazz.getClassModel() == null)
{
clazz.setClassModel(model);
if (visited.add(clazz))
{
fixClassModel(clazz, visited, rootDir);
}
}
this.addToAssociations(role);
}
// Fix the Clazz
if(item.getType() == ClazzType.ENUMERATION) {
SimpleSet literals = item.getValues();
SimpleSet attributes = item.getAttributes();
for(Literal literal : literals) {
int no = 0;
SimpleList values = literal.getValues();
if(values != null) {
for(Object value : values) {
if(value != null) {
String type = value.getClass().getName();
if(attributes.size()>no) {
Attribute attribute = attributes.get(no);
if(attribute.getType().getName(false).equals(type)) {
// Everthing is ok
} else {
attribute.with(DataType.OBJECT);
}
} else {
Attribute attribute = new Attribute("value"+no, DataType.create(type));
attributes.add(attribute);
item.with(attribute);
}
}
no++;
}
}
}
GenClazzEntity orCreate = getOrCreate(item);
Parser orCreateParser = orCreate.getOrCreateParser(rootDir);
orCreateParser.indexOf(Parser.CLASS_END);
Method constructor = new Method(item.getName()).with(DataType.create(""));
String constructorBody = "";
for(Attribute attribute : attributes) {
constructor.with(new Parameter(attribute.getType()).with(attribute.getName()));
constructorBody += " this." + attribute.getName() + " = " + attribute.getName() + ";\n" ;
}
constructor.withBody(constructorBody);
constructor.with(Modifier.PACKAGE);
item.with(constructor);
}
}
private SimpleSet getAllTypes() {
SimpleSet collection = new SimpleSet();
for(Clazz clazz : this.model.getClazzes()) {
for(Attribute attribute : clazz.getAttributes()) {
collection.add(attribute.getType());
}
}
return collection;
}
public void addHelperClassesForUnknownAttributeTypes()
{
// for attribute types like java.util.Date we add a class with that name
// and mark it as wrapped. This generates the required DateSet class.
for (DataType item : getAllTypes())
{
String typeName = item.getName(false);
// seems to be a non trivial type. We should have a clazz with that
// type
// it may be an instance of a generic type like ArrayList, cut
// off generic part
int pos = typeName.indexOf('<');
if (pos >= 0)
{
typeName = typeName.substring(0, pos);
}
pos = typeName.indexOf('[');
if (pos >= 0)
{
typeName = typeName.substring(0, pos);
}
if (!CGUtil.isPrimitiveType(typeName))
{
Clazz clazz = this.model.getClazz(typeName);
if (clazz == null)
{
// class is missing, create it.
if (typeName.indexOf(".") >= 0)
{
model.createClazz(typeName).withExternal(true);
}
else
{
model.createClazz(typeName);
}
}
}
}
}
private void attributNameConsistenceCheck(Exception e, String rootDir)
{
StackTraceElement[] stackTrace = e.getStackTrace();
StackTraceElement secondStackTraceElement = stackTrace[1];
String fileName = secondStackTraceElement.getFileName();
String className = secondStackTraceElement.getClassName();
String methodName = secondStackTraceElement.getMethodName();
int callMethodLineNumber = secondStackTraceElement.getLineNumber();
int i = 2;
while (ClassModel.class.getName().equals(className))
{
secondStackTraceElement = stackTrace[i];
fileName = secondStackTraceElement.getFileName();
className = secondStackTraceElement.getClassName();
methodName = secondStackTraceElement.getMethodName();
callMethodLineNumber = secondStackTraceElement.getLineNumber();
i++;
}
// FIXME ALEX SCHAUEN
Clazz modelCreationClass = new ClassModel().with(".").getGenerator().getOrCreateClazz(className);
Parser parser = getOrCreateClazz(modelCreationClass).getOrCreateParser(rootDir);
parser.indexOf(Parser.CLASS_END);
String signature = "method:" + methodName + "(";
ArrayList symTabEntries = parser.getSymTabEntriesFor(signature);
SymTabEntry symTabEntry = null;
for (SymTabEntry symTabEnt : symTabEntries)
{
long startPos = parser.getLineIndexOf(symTabEnt.getStartPos());
long endPos = parser.getLineIndexOf(symTabEnt.getEndPos());
if (startPos <= callMethodLineNumber && endPos >= callMethodLineNumber)
{
symTabEntry = symTabEnt;
}
}
LinkedHashMap localVarTable = null;
if (symTabEntry != null)
{
parser.parseMethodBody(symTabEntry);
localVarTable = parser.getLocalVarTable();
}
for (Clazz clazz : model.getClazzes())
{
HashMap attributs = new HashMap();
HashSet duplicateEntries = new HashSet();
for (Attribute attr : clazz.getAttributes())
{
String name = attr.getName();
if (attributs.containsKey(name))
{
duplicateEntries.add(attr);
duplicateEntries.add(attributs.get(name));
}
attributs.put(name, attr);
}
SimpleSet roles = GraphUtil.getOtherAssociations(clazz);
for (Association role : roles)
{
String name = role.getName();
if (name == null)
{
name = "";
}
if (name.equals(role.getOther().getName()))
{
// no problem,
continue;
}
if (role.getType()==AssociationTypes.EDGE || role.getType()==AssociationTypes.GENERALISATION)
{
// uni directional assoc, name is not used, no problem
continue;
}
if (attributs.containsKey(name))
{
duplicateEntries.add(role);
duplicateEntries.add(attributs.get(name));
}
attributs.put(name, role);
}
for (Object object : duplicateEntries)
{
if (object instanceof Attribute)
{
Attribute attribute = (Attribute) object;
String position = defPositionAsString(parser, localVarTable, attribute.getName(), attribute.getType(),
attribute.getClazz().getName(false));
System.out.println("in " + fileName + ": duplicate name found in definition for attribute"
+ attribute.getClazz() + "\n " + position + "\n Attribute " + attribute);
GraphUtil.removeYou(attribute);
}
else if (object instanceof Association)
{
Association role = (Association) object;
String position = defPositionAsString(parser, localVarTable, role.getName(), DataType.create("NONE"), role
.getClazz().getName(false));
System.out.println("in " + fileName + " duplicate name found in definition for " + role.getClazz()
+ "\n " + position + "\n Role " + role);
System.out.println(parser.getLineForPos((int) defPosition(parser, localVarTable, role.getName(),
DataType.create("NONE"), role.getClazz().getName(false))));
GraphUtil.removeYou(role);
}
}
}
}
private String defPositionAsString(Parser parser, LinkedHashMap localVarTable,
String name, DataType attrType, String clazzType)
{
String position = "";
if (localVarTable != null)
{
for (LocalVarTableEntry entry : localVarTable.values())
{
if (entry.getType() != null && entry.getType().equals("Clazz"))
{
String type = entry.getInitSequence().get(0).get(1).replace("\"", "");
if (clazzType.endsWith(type))
{
CharSequence subSequence = parser.getText().subSequence(entry.getStartPos(), entry.getEndPos() + 1);
String subSequenceString = subSequence.toString();
Pattern fileName = Pattern.compile("\"" + name + "\"\\s*,\\s*\"" + attrType + "\"");
Matcher matcher = fileName.matcher(subSequenceString);
int indexOf = 0;
while (matcher.find())
{
String group = matcher.group(0);
indexOf = subSequenceString.indexOf(group);
}
position = "at line " + parser.getLineIndexOf(entry.getStartPos() + indexOf) + " ";
}
}
}
}
return position;
}
private long defPosition(Parser parser, LinkedHashMap localVarTable, String name,
DataType attrType, String clazzType)
{
long position = 0;
if (localVarTable != null)
{
for (LocalVarTableEntry entry : localVarTable.values())
{
if (entry.getType() != null && entry.getType().equals("Clazz"))
{
String type = entry.getInitSequence().get(0).get(1).replace("\"", "");
if (clazzType.endsWith(type))
{
CharSequence subSequence = parser.getText().subSequence(entry.getStartPos(), entry.getEndPos() + 1);
String subSequenceString = subSequence.toString();
Pattern fileName = Pattern.compile("\"" + name + "\"\\s*,\\s*\"" + attrType + "\"");
Matcher matcher = fileName.matcher(subSequenceString);
int indexOf = 0;
while (matcher.find())
{
String group = matcher.group(0);
indexOf = subSequenceString.indexOf(group);
}
position = entry.getStartPos() + indexOf;
}
}
}
}
return position;
}
private void writeToFile(Clazz modelCreationClass)
{
getOrCreateClazz(modelCreationClass).printFile();
}
private void resetParsers()
{
for (Clazz clazz : this.model.getClazzes())
{
getOrCreate(clazz).setParser(null);
}
}
public void setModel(ClassModel value)
{
if (this.model != value)
{
// ClassModel oldValue = this.model;
// if (this.model != null)
// {
// this.model = null;
// oldValue.setGenerator(null);
// }
this.model = value;
// if (value != null)
// {
// value.setGenerator(this);
// }
}
}
public Clazz getOrCreateClazz(String className)
{
for (Clazz clazz : getModel().getClazzes())
{
if (StrUtil.stringEquals(clazz.getName(false), className))
{
return clazz;
}
}
Clazz clazz = getModel().createClazz(className);
return clazz;
}
public ClassModel getModel()
{
return model;
}
public void insertModelCreationCodeHere(String rootDir, String newMethod)
{
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
// StackTraceElement firstStackTraceElement = stackTrace[0];
// String callMethodName = firstStackTraceElement.getMethodName();
StackTraceElement secondStackTraceElement = stackTrace[1];
String className = secondStackTraceElement.getClassName();
insertModelCreationCodeHere(rootDir, className, newMethod);
}
public void insertModelCreationCodeHere(String rootDir, String className, String newMethod)
{
Clazz modelCreationClass = getOrCreateClazz(className);
modelCreationClass.getClassModel().without(modelCreationClass);
GenClass modelCreationGenerator = getOrCreateClazz(modelCreationClass);
Parser modelCreationParser = modelCreationGenerator.getOrCreateParser(rootDir);
modelCreationParser.indexOf(Parser.CLASS_END);
String signature = Parser.METHOD + ":" + newMethod + "(";
ArrayList symTabEntriesFor = modelCreationParser.getSymTabEntriesFor(signature);
int currentInsertPos = modelCreationParser.indexOf(Parser.CLASS_BODY);
if (symTabEntriesFor.size() < 1)
{
// int currentInsertPos = symTabEntry.getEndPos() + 2;
currentInsertPos = modelCreationParser.insert(currentInsertPos, " @Test\n public void " + newMethod
+ "() {\n"
+ " ClassModel clazzModel = new ClassModel(\"" + model.getName() + "\");\n");
modelCreationParser.insert(currentInsertPos, " }\n");
}
else
{
SymTabEntry symTabEntry = symTabEntriesFor.get(0);
currentInsertPos = symTabEntry.getBodyStartPos() + 2;
}
modelCreationParser.indexOf(Parser.CLASS_END);
TreeSet sortedClazz = new TreeSet(new Comparator()
{
@Override
public int compare(Clazz o1, Clazz o2)
{
return o1.getName(false).compareTo(o2.getName(false));
}
});
currentInsertPos = insertNewCreationClasses(modelCreationClass, signature, currentInsertPos,
rootDir, sortedClazz);
completeImports();
writeToFile(modelCreationClass);
}
public void insertModelCreationCodeHere(String rootDir)
{
// String fileName = null;
String className = null;
String methodName = null;
String callMethodName = null;
// int callMethodLineNumber = -1;
Exception e = new RuntimeException();
StackTraceElement[] stackTrace = e.getStackTrace();
StackTraceElement firstStackTraceElement = stackTrace[0];
callMethodName = firstStackTraceElement.getMethodName();
StackTraceElement secondStackTraceElement = stackTrace[1];
// fileName = secondStackTraceElement.getFileName();
className = secondStackTraceElement.getClassName();
methodName = secondStackTraceElement.getMethodName();
int callMethodLineNumber = secondStackTraceElement.getLineNumber();
// parse the model creation file
Clazz modelCreationClass = getOrCreateClazz(className);
modelCreationClass.getClassModel().without(modelCreationClass);
String signature = Parser.METHOD + ":" + methodName + "(";
GenClass modelCreationGenerator = getOrCreateClazz(modelCreationClass);
Parser modelCreationParser = modelCreationGenerator.getOrCreateParser(rootDir);
modelCreationParser.indexOf(Parser.CLASS_END);
SymTabEntry symTabEntry = modelCreationParser.getMethodEntryWithLineNumber(signature, callMethodLineNumber);
if (symTabEntry == null)
{
System.out.println("call method for model creation code not found");
return;
}
// insert code
int currentInsertPos = modelCreationParser.methodCallIndexOf(Parser.NAME_TOKEN + ":model",
symTabEntry.getBodyStartPos(), symTabEntry.getEndPos());
if (currentInsertPos > 0)
{
currentInsertPos = modelCreationParser.indexOfInMethodBody(Parser.NAME_TOKEN + ":;", currentInsertPos + 1,
symTabEntry.getEndPos() - 1) + 1;
}
else
{
currentInsertPos = symTabEntry.getBodyStartPos() + 2;
currentInsertPos = modelCreationParser.insert(currentInsertPos,
" ClassModel clazzModel = new ClassModel(\"" + model.getName() + "\");");
}
currentInsertPos = completeCreationClasses(callMethodName, modelCreationClass, signature, currentInsertPos,
rootDir);
currentInsertPos = insertNewCreationClasses(callMethodName, modelCreationClass, signature, currentInsertPos,
rootDir);
completeImports();
writeToFile(modelCreationClass);
}
private void completeImports()
{
for (String className : imports.keySet())
{
GenClass genClass = imports.get(className);
genClass.insertImport(className);
}
imports.clear();
}
private int completeCreationClasses(String callMethodName, Clazz modelCreationClass, String signature,
int currentInsertPos, String rootDir)
{
refreshMethodScan(signature, modelCreationClass, rootDir);
for (Clazz clazz : model.getClazzes())
{
if(clazz.getType()!=ClazzType.CLAZZ) {
continue;
}
String modelClassName = clazz.getName(false);
Parser parser = getOrCreateClazz(modelCreationClass)
.getParser();
LocalVarTableEntry entry = findInLocalVarTable(
parser
.getLocalVarTable(),
modelClassName);
if (entry != null)
{
// check code for clazz
handledClazzes.put(modelClassName, clazz);
// getOrCreate(clazz).getOrCreateParser(rootDir);
currentInsertPos = checkCodeForClazz(entry, signature, callMethodName, modelCreationClass,
refreshMethodScan(signature, modelCreationClass, rootDir), clazz, handledClazzes, currentInsertPos,
rootDir);
}
writeToFile(modelCreationClass);
}
return currentInsertPos;
}
private SymTabEntry refreshMethodScan(String signature, Clazz clazz, String rootDir)
{
SymTabEntry symTabEntry = null;
rescanCode(clazz, rootDir);
Map symTab = getOrCreateClazz(clazz).getOrCreateParser(rootDir).getSymTab();
for (String key : symTab.keySet())
{
if (key.startsWith(signature))
{
symTabEntry = symTab.get(key);
break;
}
}
getOrCreateClazz(clazz).getParser().parseMethodBody(symTabEntry);
return symTabEntry;
}
private void rescanCode(Clazz clazz, String rootDir)
{
getOrCreateClazz(clazz).getOrCreateParser(rootDir).indexOf(Parser.CLASS_END);
}
private int checkCodeForClazz(LocalVarTableEntry entry, String signature, String callMethodName,
Clazz modelCreationClass, SymTabEntry symTabEntry, Clazz clazz,
LinkedHashMap handledClazzes, int currentInsertPos, String rootDir)
{
// rescanCode(modelCreationClass, rootDir);
Parser modelCreationClassParser = getOrCreateClazz(modelCreationClass).getParser();
// check has superclass
if (clazz.getSuperClass() != null && !checkSuper(clazz, entry, "withSuperClazz"))
{
String token = Parser.NAME_TOKEN + ":" + entry.getName();
int methodCallStartPos = modelCreationClassParser.methodCallIndexOf(token, symTabEntry.getBodyStartPos(),
symTabEntry.getEndPos());
token = Parser.NAME_TOKEN + ":;";
currentInsertPos = modelCreationClassParser.indexOfInMethodBody(token, methodCallStartPos,
symTabEntry.getEndPos());
// set interface
currentInsertPos = insertCreationCode("\n /*set superclass*/", currentInsertPos, modelCreationClass);
currentInsertPos = insertCreationCode("\n", currentInsertPos, modelCreationClass);
StringBuilder text = new StringBuilder(" .withSuperClazz(superClassName)");
CGUtil.replaceAll(text, "superClassName",
StrUtil.downFirstChar(CGUtil.shortClassName(clazz.getSuperClass().getName(false))) + "Class");
currentInsertPos = insertCreationCode(text, currentInsertPos, modelCreationClass);
currentInsertPos++;
symTabEntry = refreshMethodScan(signature, modelCreationClass, rootDir);
// FIXME ALEX NICHT NOTWENDIG ODER
// getOrCreate(clazz).isFileHasChanged();
}
// check is interface
else if (GraphUtil.isInterface(clazz) && !isInterface(entry))
{
String token = Parser.NAME_TOKEN + ":" + entry.getName();
int methodCallStartPos = modelCreationClassParser.methodCallIndexOf(token, symTabEntry.getBodyStartPos(),
symTabEntry.getEndPos());
token = Parser.NAME_TOKEN + ":;";
currentInsertPos = modelCreationClassParser.indexOfInMethodBody(token, methodCallStartPos,
symTabEntry.getEndPos());
// set interface
currentInsertPos = insertCreationCode("\n /*set interface*/", currentInsertPos, modelCreationClass);
currentInsertPos = insertCreationCode("\n", currentInsertPos, modelCreationClass);
StringBuilder text = new StringBuilder(" .withInterface(true)");
currentInsertPos = insertCreationCode(text, currentInsertPos, modelCreationClass);
currentInsertPos++;
symTabEntry = refreshMethodScan(signature, modelCreationClass, rootDir);
// FIXME ALEX NICHT NOTWENDIG ODER
// getOrCreate(clazz).isFileHasChanged();
}
// check has interfaces
for (Clazz interfaze : clazz.getInterfaces(false))
{
if (!checkSuper(interfaze, entry, "withInterfaces"))
{
// writeToFile(modelCreationClass);
// find insert position
String token = Parser.NAME_TOKEN + ":" + entry.getName();
int methodCallStartPos = modelCreationClassParser.methodCallIndexOf(token, symTabEntry.getBodyStartPos(),
symTabEntry.getEndPos());
token = Parser.NAME_TOKEN + ":;";
currentInsertPos = modelCreationClassParser.indexOfInMethodBody(token, methodCallStartPos,
symTabEntry.getEndPos());
// add attribut
currentInsertPos = insertCreationCode("\n /*add interface*/", currentInsertPos, modelCreationClass);
currentInsertPos = insertCreationCode("\n", currentInsertPos, modelCreationClass);
StringBuilder text = new StringBuilder(" .withSuperClazz(interfaceName)");
CGUtil.replaceAll(text, "interfaceName",
StrUtil.downFirstChar(CGUtil.shortClassName(interfaze.getName(false))) + "Class");
currentInsertPos = insertCreationCode(text, currentInsertPos, modelCreationClass);
currentInsertPos++;
}
// set insert position to next line
currentInsertPos++;
symTabEntry = refreshMethodScan(signature, modelCreationClass, rootDir);
}
// check code for attribut
SimpleSet clazzAttributes = clazz.getAttributes();
for (Attribute attribute : clazzAttributes)
{
if (!hasAttribute(attribute, entry, rootDir) && !"PropertyChangeSupport".equals(attribute.getType()))
{
writeToFile(modelCreationClass);
// find insert position
String tokenString = entry.getInitSequence().get(0).get(0);
if (tokenString.endsWith(".withAssoc"))
{
boolean found = false;
// attributes belong to a separate
// playerClass.withAttributes(...) statement
for (StatementEntry stat : modelCreationClassParser.getCurrentStatement().getParent().getBodyStats())
{
String token = stat.getTokenList().get(0);
if (token.equals(entry.getName() + ".withAttribute") ||
token.equals(entry.getName() + ".with(new Attribute"))
{
// here we are
currentInsertPos = stat.getEndPos() - 1;
found = true;
break;
}
}
if (!found)
{
// there is no class.withAttributes(...) yet. Create one
StringBuilder text = new StringBuilder(
"\n" +
"\n" +
" classVar.withAttributes(\n" +
" \"name\", \"type\");"
);
CGUtil.replaceAll(text,
"classVar", entry.getName(),
"name", attribute.getName(),
"type", attribute.getType());
currentInsertPos = insertCreationCode(text.toString(), entry.getEndPos() + 2, modelCreationClass);
symTabEntry = refreshMethodScan(signature, clazz, rootDir);
continue;
}
}
else
{
String token = Parser.NAME_TOKEN + ":" + entry.getName();
int methodCallStartPos = modelCreationClassParser.methodCallIndexOf(token,
symTabEntry.getBodyStartPos(), symTabEntry.getEndPos());
token = Parser.NAME_TOKEN + ":;";
currentInsertPos = modelCreationClassParser.indexOfInMethodBody(token, methodCallStartPos,
symTabEntry.getEndPos());
}
// add attribute
StringBuilder text = new StringBuilder(
"\n" +
" /*add attribut*/\n" +
" .with(new Attribute(\"name\", DataType.create(\"type\")) )");
// + " \"name\", \"type\"");
CGUtil.replaceAll(text,
"name", attribute.getName(),
"type", attribute.getType().getName(false));
currentInsertPos = insertCreationCode(text.toString(), currentInsertPos, modelCreationClass);
GenClass genCreationClass = getOrCreateClazz(modelCreationClass);
addImportForClazz(Attribute.class.getName(), genCreationClass);
currentInsertPos++;
}
// set insert position to next line
currentInsertPos += 2;
symTabEntry = refreshMethodScan(signature, modelCreationClass, rootDir);
}
// check code for method
SimpleSet methods = clazz.getMethods();
for (Method method : methods)
{
currentInsertPos = tryToInsertMethod(symTabEntry, method, currentInsertPos, modelCreationClass);
symTabEntry = refreshMethodScan(signature, modelCreationClass, rootDir);
}
// check code for assoc
LinkedHashSet roles = new LinkedHashSet();
if (!clazz.getAssociations().isEmpty())
roles.addAll(clazz.getAssociations());
for (Association assoc : roles)
{
String sourceClassName = assoc.getClazz().getName(false);
String targetClassName = assoc.getOtherClazz().getName(false);
if (handledClazzes.containsKey(sourceClassName) && handledClazzes.containsKey(targetClassName))
{
symTabEntry = refreshMethodScan(signature, modelCreationClass, rootDir);
int indexOfSourceClassPos = positionOfClazzDecl(sourceClassName, modelCreationClass);
int indexOfTargetClassPos = positionOfClazzDecl(targetClassName, modelCreationClass);
int resultPos = Math.max(indexOfSourceClassPos, indexOfTargetClassPos) + 3;
currentInsertPos = Math.max(resultPos, currentInsertPos);
currentInsertPos = tryToInsertAssoc(symTabEntry, assoc, currentInsertPos, modelCreationClass);
}
}
return currentInsertPos;
}
private LocalVarTableEntry findInLocalVarTable(LinkedHashMap localVarTable, String name)
{
for (LocalVarTableEntry entry : localVarTable.values())
{
if ("Clazz".equals(entry.getType()))
{
if (entry.getInitSequence() == null)
continue;
ArrayList initSequence = entry.getInitSequence().get(0);
if (initSequence.size() >= 2 &&
(initSequence.get(0).startsWith("new")
|| initSequence.get(0).startsWith("model.createClazz")
|| initSequence.get(0).endsWith(".createClassAndAssoc")))
{
String className = initSequence.get(1).replaceAll("\"", "");
if (StrUtil.stringEquals(name, className) || name.endsWith("." + className))
{
return entry;
}
}
}
}
return null;
}
private int positionOfClazzDecl(String sourceClassName, Clazz clazz)
{
LinkedHashMap localVarTable = getOrCreateClazz(clazz).getParser().getLocalVarTable();
for (String localVarTableEntityName : localVarTable.keySet())
{
LocalVarTableEntry localVarTableEntry = localVarTable.get(localVarTableEntityName);
ArrayList arrayList = localVarTableEntry.getInitSequence().get(0);
String string = "";
if (arrayList.size() > 1)
{
string = arrayList.get(1).replaceAll("\"", "");
if (sourceClassName.equals(string) || sourceClassName.endsWith("." + string))
{
return localVarTableEntry.getEndPos();
}
}
}
return -1;
}
private int tryToInsertAssoc(SymTabEntry symTabEntry, Association assoc, int currentInsertPos, Clazz modelCreationClass)
{
Parser parser = getOrCreateClazz(modelCreationClass).getParser();
parser.parseMethodBody(symTabEntry);
boolean assocIsNew = true;
LinkedHashMap localVarTable = parser.getLocalVarTable();
for (String string : localVarTable.keySet())
{
LocalVarTableEntry localVarTableEntry = localVarTable.get(string);
if ("Clazz".equals(localVarTableEntry.getType()))
{
ArrayList> sequence = localVarTableEntry.getInitSequence();
for (ArrayList subSequence : sequence)
{
if ("withAssoc".equals(subSequence.get(0)))
{
String className = sequence.get(0).get(1);
if (compareAssocDecl(assoc, subSequence, className, localVarTable))
{
assocIsNew = false;
break;
}
}
}
}
else if (string.startsWith("Association_"))
{
if (compareAssocDecl(assoc, localVarTableEntry))
{
assocIsNew = false;
break;
}
}
}
for (StatementEntry stat : getOrCreateClazz(modelCreationClass).getParser().getStatementList().getBodyStats())
{
if (stat.getTokenList().get(0).endsWith(".withAssoc")
|| stat.getTokenList().get(0).endsWith(".createClassAndAssoc"))
{
// looks like sourceClass.withAssoc(targetClass, "targetRole",
// targetCard, "sourceRole", sourceCard);
// ensure source class name
String classVar = CGUtil.packageName(stat.getTokenList().get(0));
LocalVarTableEntry localVarTableEntry = localVarTable.get(classVar);
String classNameFromText = localVarTableEntry.getInitSequence().get(0).get(1).replaceAll("\"", "");
String classNameFromAssoc = assoc.getClazz().getName(false);
if (StrUtil.stringEquals(classNameFromText, classNameFromAssoc)
|| classNameFromAssoc.endsWith("." + classNameFromText))
{
// ensure target class name
classVar = stat.getTokenList().get(2);
localVarTableEntry = localVarTable.get(classVar);
if (stat.getTokenList().get(0).endsWith(".withAssoc"))
classNameFromText = localVarTableEntry.getInitSequence().get(0).get(1).replaceAll("\"", "");
else
classNameFromText = stat.getTokenList().get(2).replaceAll("\"", ""); //
classNameFromAssoc = assoc.getOtherClazz().getName(false);
if (StrUtil.stringEquals(classNameFromText, classNameFromAssoc)
|| classNameFromAssoc.endsWith("." + classNameFromText))
{
// ensure target role name
String tokenRoleName1 = stat.getTokenList().get(4).replaceAll("\"", "");
String assocRoleName1 = assoc.getOther().getName();
String tokenRoleName2 = stat.getTokenList().get(8).replaceAll("\"", "");
String assocRoleName2 = assoc.getName();
if (stringsPairwiseEquals(tokenRoleName1, assocRoleName1, tokenRoleName2, assocRoleName2))
{
// found it
assocIsNew = false;
break;
}
}
}
}
}
if (assocIsNew)
{
String name = assoc.getClazz().getName(true) + "Class";
name = StrUtil.downFirstChar(name);
LocalVarTableEntry localVarTableEntry = localVarTable.get(name);
int insertPos = localVarTableEntry.getEndPos() + 3;
insertPos = currentInsertPos;
currentInsertPos = insertCreationCode(" /* add assoc */", insertPos, modelCreationClass);
currentInsertPos = insertCreationAssociationCode(assoc, currentInsertPos, modelCreationClass, symTabEntry);
}
return currentInsertPos;
}
private boolean stringsPairwiseEquals(String string1, String string2, String string3,
String string4)
{
if (StrUtil.stringEquals(string1, string2) && StrUtil.stringEquals(string3, string4)
|| StrUtil.stringEquals(string1, string3) && StrUtil.stringEquals(string2, string4)
|| StrUtil.stringEquals(string1, string4) && StrUtil.stringEquals(string2, string3))
return true;
return false;
}
private boolean compareAssocDecl(Association assoc, ArrayList subSequence, String className,
LinkedHashMap localVarTable)
{
String sourceInitSequence = subSequence.get(7).replaceAll("\"", "") + "|" + className.replaceAll("\"", "");
String targetClassName = subSequence.get(1);
for (String key : localVarTable.keySet())
{
if (key.equals(targetClassName))
{
LocalVarTableEntry entry = localVarTable.get(key);
ArrayList> initSequence = entry.getInitSequence();
targetClassName = initSequence.get(0).get(1);
}
}
String targetInitSequence = subSequence.get(2).replaceAll("\"", "") + "|" + targetClassName.replaceAll("\"", "");
String sourceSequence = assoc.getName() + "|" + assoc.getClazz().getName(false);
String targetSequence = assoc.getOther().getName() + "|" + assoc.getOtherClazz().getName(false);
if ((sourceInitSequence.equals(sourceSequence) && targetInitSequence.equals(targetSequence))
|| (targetInitSequence.equals(sourceSequence) && sourceInitSequence.equals(targetSequence)))
return true;
return false;
}
private boolean compareAssocDecl(Association assoc, LocalVarTableEntry localVarTableEntry)
{
if (compareAssocs(assoc, localVarTableEntry.getInitSequence()))
{
return true;
}
return false;
}
private boolean compareAssocs(Association assoc, ArrayList> initSequence)
{
String sourceInitSequence = findInitSequenceAsString(".withSource", initSequence);
sourceInitSequence = cutCardinality(sourceInitSequence);
String targetInitSequence = findInitSequenceAsString(".withTarget", initSequence);
targetInitSequence = cutCardinality(targetInitSequence);
String sourceSequence = getInitSequenceAsString(".withSource", assoc);
sourceSequence = cutCardinality(sourceSequence);
String targetSequence = getInitSequenceAsString(".withTarget", assoc);
targetSequence = cutCardinality(targetSequence);
if ((sourceInitSequence.equals(sourceSequence) && targetInitSequence.equals(targetSequence))
|| (targetInitSequence.equals(sourceSequence) && sourceInitSequence.equals(targetSequence)))
return true;
return false;
}
private String cutCardinality(String sourceInitSequence)
{
sourceInitSequence = sourceInitSequence.substring(0, sourceInitSequence.lastIndexOf(','));
return sourceInitSequence;
}
private String getInitSequenceAsString(String string, Association assoc)
{
String sequence = string + "(";
Association role = null;
if (".withSource".equals(string))
role = assoc;
else if (".withTarget".equals(string))
role = assoc.getOther();
else
return null;
sequence += "\"" + role.getName() + "\"";
String shortClassName = role.getClazz().getName(true);
String clazzString = StrUtil.downFirstChar(shortClassName) + "Class";
sequence += "," + clazzString + ",";
sequence += "\"" + role.getCardinality().getValue() + "\"" + ")";
return sequence;
}
private String findInitSequenceAsString(String searchString, ArrayList> initSequence)
{
for (ArrayList sequence : initSequence)
{
String sequenceString = "";
for (String string : sequence)
{
sequenceString += string;
}
if (sequenceString.startsWith(searchString))
{
return sequenceString;
}
}
return null;
}
private int tryToInsertMethod(SymTabEntry symTabEntry, Method method, int currentInsertPos, Clazz modelCreationClass)
{
Parser parser = getOrCreateClazz(modelCreationClass).getParser();
parser.parseMethodBody(symTabEntry);
boolean methodIsNew = true;
LinkedHashMap localVarTable = parser.getLocalVarTable();
for (LocalVarTableEntry localVarTableEntry : localVarTable.values())
{
if (compareMethodDecl(method, localVarTableEntry, modelCreationClass))
{
currentInsertPos = localVarTableEntry.getEndPos() + 2;
// Parser parser = getOrCreate(modelCreationClass).getParser();
// System.out.println("line: "+parser.getLineIndexOf(currentInsertPos));
// System.out.println(parser.getLineForPos(currentInsertPos));
methodIsNew = false;
break;
}
}
if (methodIsNew && !isSDMLibMethod(method))
{
String name = CGUtil.shortClassName(method.getClazz().getName(false)) + "Class";
name = StrUtil.downFirstChar(name);
LocalVarTableEntry localVarTableEntry = localVarTable.get(name);
if (localVarTableEntry == null)
return currentInsertPos;
int insertPos = localVarTableEntry.getEndPos() + 1;
currentInsertPos = insertCreationCode("\n /* add method */", insertPos, modelCreationClass);
currentInsertPos = insertCreationMethodCode(method, currentInsertPos, modelCreationClass, symTabEntry);
writeToFile(modelCreationClass);
}
return currentInsertPos;
}
private boolean isSDMLibMethod(Method method)
{
return (method.getName().startsWith("get") && method.getName().endsWith("Transitive"));
}
private boolean compareMethodDecl(Method method, LocalVarTableEntry localVarTableEntry, Clazz modelCreationClass)
{
String shortClassName = CGUtil.shortClassName(method.getClazz().getName(false));
// String signature = method.getSignature(true);
// String methodClass = "";
// String methodSignature = "";
ArrayList> initSequence = localVarTableEntry.getInitSequence();
// the first method call should be model.createClazz()
ArrayList init = initSequence.get(0);
if (init.size() != 2)
return false;
if (!init.get(0).endsWith(".createClazz"))
return false;
String initClassName = init.get(1);
initClassName = initClassName.substring(1, initClassName.length() - 1);
if (!shortClassName.equals(CGUtil.shortClassName(initClassName)))
return false;
for (int i = 1; i < initSequence.size(); i++)
{
init = initSequence.get(i);
if ("withMethod".equals(init.get(0)) && ("\"" + method.getName() + "\"").equals(init.get(1)))
{
// looks good, do we need to check more?
if (init.size() <= 7 && method.getParameter().size() == 0)
return true;
// there should be more:
if (init.size() >= 4)
{
String dataType = init.get(3);
String searchType = method.getReturnType().toString();
if (!dataType.equals(searchType))
return false;
// boolean found = false;
try
{
int j = 6;
Iterator paramIter = method.getParameter().iterator();
while (j < init.size() && paramIter.hasNext())
{
Parameter searchParam = paramIter.next();
String token = init.get(j);
if (!token.equals("["))
return false;
j++;
token = init.get(j);
if (!token.equals("new"))
return false;
j++;
token = init.get(j);
if (!token.equals("Parameter"))
return false;
j++;
token = init.get(j);
if (!token.equals(searchParam.getType().toString()))
{
if (!token.equals("DataType.ref")
|| !init.get(j + 1).equals(("\"" + searchParam.getType().getName(false) + "\"")))
return false;
else
{
j++;
}
}
// this parameter matches
j = j + 3;
if (j == init.size() && !paramIter.hasNext())
{
return true;
}
}
}
catch (Exception e)
{
}
}
}
}
return false;
}
protected String parseDataType(String typeString, Clazz modelCreationClass)
{
String type = "";
if (typeString.startsWith("DataType.ref"))
{
String typeSplit = typeString.substring("DataType.ref".length() + 1, typeString.length() - 1);
// DataType.create("String")
if (typeSplit.startsWith("\""))
{
typeSplit = typeSplit.replaceAll("\"", "");
typeSplit = typeSplit.toUpperCase();
return "DataType." + typeSplit;
}
// DataType.create(objectname)
else
{
LocalVarTableEntry tableEntry = getOrCreateClazz(modelCreationClass).getParser()
.getLocalVarEntriesFor(typeSplit);
if (tableEntry != null)
{
String className = tableEntry.getInitSequence().get(0).get(1).replaceAll("\"", "");
className = className.toUpperCase();
return "DataType." + className;
}
}
}
// DataType.STRING
else if (typeString.startsWith("DataType."))
{
// TODO : parse primitive types
}
return type;
}
private int createAndInsertCodeForNewClazz(Clazz modelCreationClass, SymTabEntry symTabEntry,
Clazz clazz, LinkedHashMap handledClazzes,
int currentInsertPos)
{
String modelClassName = clazz.getName(false);
String classModelName = clazz.getClassModel().getName();
if (modelClassName.startsWith(classModelName))
{
modelClassName = modelClassName.replaceFirst(classModelName + ".", "");
}
// no creation code yet. Insert it.
currentInsertPos = insertCreationClassCode(currentInsertPos, modelClassName, modelCreationClass, symTabEntry);
// check interface attr
if (GraphUtil.isInterface(clazz))
{
currentInsertPos = insertCreationIsInterfaceCode(currentInsertPos, modelCreationClass, symTabEntry);
currentInsertPos = insertCreationCode("\n", currentInsertPos, modelCreationClass);
}
// insert code for superclass
Clazz superClass = clazz.getSuperClass();
if (superClass != null)
{
currentInsertPos = insertCreationSuperClassCode(currentInsertPos, superClass.getName(false),
modelCreationClass, symTabEntry);
currentInsertPos = insertCreationCode("\n", currentInsertPos, modelCreationClass);
}
// insert code for interfaces
for (Clazz interfaze : clazz.getInterfaces(false))
{
if (interfaze != null)
{
currentInsertPos = insertCreationInterfaceCode(currentInsertPos, interfaze.getName(false),
modelCreationClass, symTabEntry);
currentInsertPos = insertCreationCode("\n", currentInsertPos, modelCreationClass);
}
}
// insert code for new Attr()
SimpleSet clazzAttributes = clazz.getAttributes();
TreeSet sortedAttributes = new TreeSet(new Comparator()
{
@Override
public int compare(Attribute o1, Attribute o2)
{
return o1.getName().compareTo(o2.getName());
}
});
for (Attribute attribute : clazzAttributes)
{
sortedAttributes.add(attribute);
}
for (Attribute attribute : sortedAttributes)
{
if (!"PropertyChangeSupport".equals(attribute.getType()))
{
currentInsertPos = insertCreationAttributeCode(attribute,
currentInsertPos, modelCreationClass, symTabEntry);
currentInsertPos = insertCreationCode("\n", currentInsertPos,
modelCreationClass);
}
}
currentInsertPos = 1 + insertCreationCode(";", currentInsertPos - 1, modelCreationClass);
// insert code for new Method()
SimpleSet methods = clazz.getMethods();
TreeSet sortedMethods = new TreeSet(new Comparator()
{
@Override
public int compare(Method o1, Method o2)
{
return o1.getName().compareTo(o2.getName());
}
});
for (Method method : methods)
{
sortedMethods.add(method);
}
for (Method method : sortedMethods)
{
currentInsertPos = insertCreationMethodCode(method, currentInsertPos, modelCreationClass, symTabEntry);
}
// insert code for new Assoc
// LinkedHashSet roles = new LinkedHashSet();
TreeSet roles = new TreeSet(new Comparator()
{
@Override
public int compare(Association o1, Association o2)
{
return o1.getOther().getName().compareTo(o2.getOther().getName());
}
});
if (!clazz.getAssociations().isEmpty())
{
for (Association role : clazz.getAssociations())
{
roles.add(role);
}
}
currentInsertPos = handleAssocs(roles, currentInsertPos, modelCreationClass, symTabEntry, handledClazzes);
return currentInsertPos;
}
// FIXME private int searchForQualifiedNamePosition(String methodCall, int
// methodEndPos, Parser parser)
// {
// Set methodBodyQualifiedNames =
// parser.getMethodBodyQualifiedNames();
// for (String qualifiedName : methodBodyQualifiedNames)
// {
// if (qualifiedName.contains(methodCall))
// {
// int callPos = parser.getMethodBodyQualifiedNamesMap().get(qualifiedName);
// String substring = parser.getFileBody().substring(callPos, methodEndPos);
// return callPos + substring.indexOf(';') + 1;
// }
// }
// return -1;
// }
private int handleAssocs(TreeSet assoc, int currentInsertPos, Clazz modelCreationClass,
SymTabEntry symTabEntry, LinkedHashMap handledClazzes)
{
ArrayList handledAssocs = new ArrayList();
for (Association firstRole : assoc)
{
Association secondRole;
if (firstRole.getOther() != firstRole)
secondRole = firstRole.getOther();
else
secondRole = firstRole;
String secondClassName = secondRole.getClazz().getName(false);
if (handledClazzes.containsKey(secondClassName))
{
handledAssocs.add(firstRole);
currentInsertPos = insertCreationAssociationCode(firstRole, currentInsertPos, modelCreationClass, symTabEntry);
}
writeToFile(modelCreationClass);
}
return currentInsertPos;
}
private int insertNewCreationClasses(String callMethodName, Clazz modelCreationClass, String signature,
int currentInsertPos, String rootDir)
{
return insertNewCreationClasses(modelCreationClass, signature, currentInsertPos, rootDir,
new LinkedHashSet());
}
private int insertNewCreationClasses(Clazz modelCreationClass, String signature,
int currentInsertPos, String rootDir, Set clazzQueue)
{
// find last creation code position
for (Clazz clazz : model.getClazzes())
{
clazzQueue.add(clazz);
}
boolean format = false;
while (!clazzQueue.isEmpty())
{
Clazz clazz = clazzQueue.iterator().next();
clazzQueue.remove(clazz);
String modelClassName = clazz.getName(false);
Parser parser = getOrCreateClazz(modelCreationClass).getParser().parse();
ArrayList symTabEntry = parser.getSymTabEntriesFor(signature);
parser.parseMethodBody(symTabEntry.get(0));
LocalVarTableEntry entry = findInLocalVarTable(getOrCreateClazz(modelCreationClass).getParser().getLocalVarTable(),
modelClassName);
if (entry == null)
{
// insert code for new Clazz()
if (!checkDependencies(clazz))
{
clazzQueue.add(clazz);
}
else
{
if (!format)
{
currentInsertPos = insertCreationCode("\n", currentInsertPos, modelCreationClass);
format = true;
}
handledClazzes.put(modelClassName, clazz);
currentInsertPos = createAndInsertCodeForNewClazz(modelCreationClass,
refreshMethodScan(signature, modelCreationClass, rootDir), clazz, handledClazzes, currentInsertPos);
}
writeToFile(modelCreationClass);
}
}
return currentInsertPos;
}
private boolean checkDependencies(Clazz clazz)
{
ArrayList dependencies = new ArrayList();
if (clazz.getSuperClass() != null)
dependencies.add(clazz.getSuperClass());
if (clazz.getInterfaces(false) != null)
dependencies.addAll(clazz.getInterfaces(false));
for (Clazz depClazz : dependencies)
{
if (handledClazzes.get(depClazz.getName(false)) == null)
{
return false;
}
}
return true;
}
// private boolean assocHasHandled(Association assoc, ArrayList handledAssocs)
// {
// Association source = assoc;
// Association target = assoc.getOther();
//
// for (Association association : handledAssocs)
// {
//
// Association source2 = association;
// Association target2 = association.getOther();
//
// if (compareRoles(source, target2) && compareRoles(target, source2))
// return true;
//
// }
// return false;
// }
private int insertCreationClassCode(int currentInsertPos, String modelClassName, Clazz modelCreationClass,
SymTabEntry symTabEntry)
{
StringBuilder text = new StringBuilder("\n Clazz localVar = clazzModel.createClazz(\"className\")\n");
Parser parser = getOrCreateClazz(modelCreationClass).getParser();
LinkedHashMap localVarTable = parser.getLocalVarTable();
for (String key : localVarTable.keySet())
{
LocalVarTableEntry localVarTableEntry = localVarTable.get(key);
if ("ClassModel".equals(localVarTableEntry.getType()))
{
String classmodelName = localVarTableEntry.getName();
CGUtil.replaceAll(text, "clazzModel", classmodelName);
break;
}
}
CGUtil.replaceAll(text, "localVar", StrUtil.downFirstChar(CGUtil.shortClassName(modelClassName)) + "Class",
"className", modelClassName);
currentInsertPos = checkImport(Clazz.class.getName(), currentInsertPos, modelCreationClass, symTabEntry);
return insertCreationCode(text, currentInsertPos, modelCreationClass);
}
private int insertCreationSuperClassCode(int currentInsertPos, String superClassName, Clazz modelCreationClass,
SymTabEntry symTabEntry)
{
StringBuilder text = new StringBuilder(" .withSuperClazz(superClassName)");
CGUtil.replaceAll(text, "superClassName", StrUtil.downFirstChar(CGUtil.shortClassName(superClassName)) + "Class");
return insertCreationCode(text, currentInsertPos, modelCreationClass);
}
private int insertCreationInterfaceCode(int currentInsertPos, String interfaceName, Clazz modelCreationClass,
SymTabEntry symTabEntry)
{
StringBuilder text = new StringBuilder(" .withSuperClazz(interfaceName)");
CGUtil.replaceAll(text, "interfaceName", StrUtil.downFirstChar(CGUtil.shortClassName(interfaceName)) + "Class");
return insertCreationCode(text, currentInsertPos, modelCreationClass);
}
private int insertCreationIsInterfaceCode(int currentInsertPos, Clazz modelCreationClass, SymTabEntry symTabEntry)
{
StringBuilder text = new StringBuilder(" .withInterface(true)");
return insertCreationCode(text, currentInsertPos, modelCreationClass);
}
private int insertCreationAttributeCode(Attribute attribute, int currentInsertPos, Clazz modelCreationClass,
SymTabEntry symTabEntry)
{
GenClass genCreationClass = getOrCreateClazz(modelCreationClass);
Parser parser = genCreationClass.getParser();
// has init value
String initialization = attribute.getValue();
if (initialization != null)
{
initialization = ".withInitialization(\"" + initialization + "\")";
}
else
{
initialization = "";
}
StringBuilder result = parser.replaceAll(currentInsertPos,
" .with(new Attribute(\"attributeName\", DataType.create(\"attributeType\")) attributeInit)",
"attributeType", attribute.getType().getName(false),
"attributeName", attribute.getName(),
"attributeInit", initialization);
addImportForClazz(Attribute.class.getName(), genCreationClass);
return currentInsertPos + result.length();
}
HashMap imports = new HashMap<>();
private void addImportForClazz(String className, GenClass genCreationClass)
{
imports.put(className, genCreationClass);
}
private int insertCreationMethodCode(Method method, int currentInsertPos, Clazz modelCreationClass,
SymTabEntry symTabEntry)
{
String methodName = method.getName();
if (methodName.startsWith("get") && methodName.endsWith("Transitive"))
{
String part = methodName.substring("get".length(), methodName.length() - "Transitive".length());
Clazz clazz = method.getClazz();
for (Association role : clazz.getAssociations())
{
if (role.getName().toLowerCase().equals(part.toLowerCase()))
return currentInsertPos;
}
}
Parser parser = getOrCreateClazz(modelCreationClass).getParser();
String clazzName = method.getClazz().getName(false);
clazzName = StrUtil.downFirstChar(CGUtil.shortClassName(clazzName)) + "Class";
StringBuilder paString = new StringBuilder();
for (Parameter parameter : method.getParameter())
{
paString.append(", new Parameter(" + parameter.getType().toString() + ")");
}
StringBuilder result = parser.replaceAll(currentInsertPos - 2, "\n" +
" .withMethod(\"METHODNAME\", Return_TypePARAMETERS)",
"Return_Type", method.getReturnType().toString(),
"PARAMETERS", paString.toString(),
"METHODNAME", methodName);
currentInsertPos = checkImport(Method.class.getName(), currentInsertPos, modelCreationClass, symTabEntry);
currentInsertPos += result.length();
if (paString.length() > 0)
{
currentInsertPos = checkImport(Parameter.class.getName(), currentInsertPos, modelCreationClass, symTabEntry);
}
return currentInsertPos;
}
private int checkImport(String newImport, int currentInsertPos, Clazz modelCreationClass, SymTabEntry symTabEntry)
{
getOrCreateClazz(modelCreationClass).getParser().indexOf(Parser.CLASS_END);
Map symTab = getOrCreateClazz(modelCreationClass).getParser().getSymTab();
LinkedHashMap result = new LinkedHashMap();
for (String key : symTab.keySet())
{
if (key.startsWith(Parser.IMPORT) && (key.endsWith("." + newImport) || key.endsWith(".ClassModel")))
{
String path = key.replace(Parser.IMPORT + ":", "");
int lastIndexOf = path.lastIndexOf('.') + 1;
String name = path.substring(lastIndexOf);
String pathString = path.substring(0, lastIndexOf - 1);
result.put(name, pathString);
}
}
if (!result.containsKey(newImport) && result.containsKey("ClassModel") )
{
String symTabEntryName = result.get("ClassModel");
int endOfImports = getOrCreateClazz(modelCreationClass).getParser().getEndOfImports() + 1;
String importString;
if(newImport.indexOf(".") < 1) {
importString = "\n" + Parser.IMPORT + " " + symTabEntryName + "." + newImport + ";";
} else {
importString = "\n" + Parser.IMPORT + " " + newImport + ";";
}
insertCreationCode(importString, endOfImports, modelCreationClass);
currentInsertPos += importString.length();
}
return currentInsertPos;
}
private int insertCreationAssociationCode(Association assoc, int currentInsertPos, Clazz modelCreationClass,
SymTabEntry symTabEntry)
{
StringBuilder text = new StringBuilder(
"\n sourceClazz.withAssoc(targetClazz, \"targetName\", targetCard, \"sourceName\", sourceCard);\n");
Association source = assoc;
Association target = assoc.getOther();
if (source.getName().compareTo(target.getName()) < 1)
{
Association tempRole = source;
source = target;
target = tempRole;
}
String sourceCard = "Card." + source.getCardinality().getValue().toUpperCase();
String sourceName = source.getName();
String sourceClazz = StrUtil.downFirstChar(source.getClazz().getName(true)) + "Class";
String targetCard = "Card." + target.getCardinality().getValue().toUpperCase();
String targetName = target.getName();
String targetClazz = StrUtil.downFirstChar(target.getClazz().getName(true)) + "Class";
CGUtil.replaceAll(text,
"sourceName", sourceName,
"sourceClazz", sourceClazz,
"sourceCard", sourceCard,
"targetName", targetName,
"targetClazz", targetClazz,
"targetCard", targetCard);
currentInsertPos = checkImport(Association.class.getName(), currentInsertPos, modelCreationClass, symTabEntry);
GenClass genCreationClass = getOrCreateClazz(modelCreationClass);
addImportForClazz(Cardinality.class.getName(), genCreationClass);
return insertCreationCode(text, currentInsertPos, modelCreationClass);
}
private boolean checkSuper(Clazz clazz, LocalVarTableEntry entry, String classType)
{
ArrayList> initSequence = entry.getInitSequence();
for (ArrayList sequencePart : initSequence)
{
if (classType.equals(sequencePart.get(0)))
{
return true;
}
}
return false;
}
private boolean isInterface(LocalVarTableEntry entry)
{
ArrayList> initSequence = entry.getInitSequence();
for (ArrayList sequencePart : initSequence)
{
if ("withInterface".equals(sequencePart.get(0)))
{
return true;
}
}
return false;
}
private int insertCreationCode(StringBuilder text, int insertPos, Clazz modelCreationClass)
{
getOrCreateClazz(modelCreationClass).getParser().insert(insertPos, text.toString());
return insertPos + text.length();
}
private int insertCreationCode(String string, int insertPos, Clazz modelCreationClass)
{
StringBuilder text = new StringBuilder(string);
return insertCreationCode(text, insertPos, modelCreationClass);
}
public String getMemberType(String currentType, String varName)
{
String result = null;
for (Clazz clazz : model.getClazzes())
{
String name = CGUtil.shortClassName(clazz.getName(false));
if (StrUtil.stringEquals(name, currentType))
{
for (Attribute attr : clazz.getAttributes())
{
if (StrUtil.stringEquals(attr.getName(), varName))
{
return attr.getType().getName(false);
}
}
for (Association role : clazz.getAssociations())
{
role = role.getOther();
if (StrUtil.stringEquals(role.getName(), varName))
{
// currentTypeCard = role.getCard();
return role.getClazz().getName(true);
}
}
}
}
return result;
}
public ClassModel learnFromGenericObjects(String packageName, GenericObject root)
{
// collect all objects and links
LinkedHashSet allObjects = new LinkedHashSet();
LinkedList todoObjects = new LinkedList();
LinkedHashSet allLinks = new LinkedHashSet();
todoObjects.add(root);
while (!todoObjects.isEmpty())
{
GenericObject currentObject = todoObjects.pop();
allObjects.add(currentObject);
allLinks.addAll(currentObject.getOutgoingLinks());
allLinks.addAll(currentObject.getIncommingLinks());
todoObjects.addAll(currentObject.getOutgoingLinks().getTgt().minus(allObjects));
todoObjects.addAll(currentObject.getIncommingLinks().getSrc().minus(allObjects));
}
// now derive classes from node types
for (GenericObject currentObject : allObjects)
{
if (currentObject.getType() != null)
{
Clazz currentClazz = this.getOrCreateClazz(packageName + "." + currentObject.getType());
// add attribute declarations
for (GenericAttribute attr : currentObject.getAttrs())
{
Attribute attrDecl = null;
int attrPos = currentClazz.getAttributes().indexOf(attr);
if (attrPos >= 0) {
attrDecl = currentClazz.getAttributes().get(attrPos);
}
if (attrDecl == null) {
attrDecl = currentClazz.createAttribute(attr.getName(), DataType.OBJECT);
}
learnAttrType(attr, attrDecl);
}
}
}
LinkedHashSet alreadyUsedLabels = new LinkedHashSet();
// now derive assocs from links
for (GenericLink currentLink : allLinks)
{
String sourceType = currentLink.getSrc().getType();
if (sourceType == null)
continue;
String targetType = currentLink.getTgt().getType();
if (targetType == null)
continue;
String sourceLabel = currentLink.getSrcLabel();
if (sourceLabel == null)
{
sourceLabel = StrUtil.downFirstChar(sourceType) + "s";
}
String targetLabel = currentLink.getTgtLabel();
if (targetLabel == null)
{
targetLabel = StrUtil.downFirstChar(sourceType) + "s";
}
// search for an assoc with similar srcClazz, srcLabel, tgtClass,
// tgtLabel
Association currentAssoc = null;
for (Association assoc : this.getAssociations())
{
if (sourceType.equals(CGUtil.shortClassName(assoc.getClazz().getName()))
&& targetType.equals(CGUtil.shortClassName(assoc.getOtherClazz().getName()))
&& sourceLabel.equals(assoc.getName())
&& targetLabel.equals(assoc.getOther().getName()))
{
// found old one
currentAssoc = assoc;
break;
}
}
if (currentAssoc == null)
{
// need to create a new one
Association other = new Association(getOrCreateClazz(packageName + "." + targetType))
.with(Cardinality.ONE).with(targetLabel);
currentAssoc = new Association(this.getOrCreateClazz(packageName + "." + sourceType))
.with(Cardinality.ONE)
.with(sourceLabel)
.with(other);
this.addToAssociations(currentAssoc);
}
if (alreadyUsedLabels.contains(currentLink.getSrc().hashCode() + ":" + targetLabel))
{
currentAssoc.getOther().with(Cardinality.MANY);
}
if (alreadyUsedLabels.contains(currentLink.getTgt().hashCode() + ":" + sourceLabel))
{
currentAssoc.with(Cardinality.MANY);
}
alreadyUsedLabels.add(currentLink.getSrc().hashCode() + ":" + targetLabel);
alreadyUsedLabels.add(currentLink.getTgt().hashCode() + ":" + sourceLabel);
}
return this.getModel();
}
private void learnAttrType(GenericAttribute attr, Attribute attrDecl)
{
String valueString = attr.getValue();
DataType attrType = DataType.STRING;
try
{
Integer.parseInt(valueString);
attrType = DataType.INT;
}
catch (NumberFormatException e)
{
try
{
Double.parseDouble(valueString);
attrType = DataType.DOUBLE;
}
catch (NumberFormatException e1)
{
try
{
DateFormat.getDateInstance().parse(valueString);
attrType = DataType.create("java.util.Date");
}
catch (ParseException e2)
{
try
{
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-mm-dd'T'hh:mm:ss");
simpleDateFormat.parse(valueString);
attrType = DataType.create("java.util.Date");
}
catch (ParseException e3)
{
}
}
}
}
String typeOrder = "Object int double java.util.Date String";
if (typeOrder.indexOf(attrDecl.getType().getName(false)) < typeOrder.indexOf(attrType.getName(false)))
{
attrDecl.with(attrType);
}
}
private boolean compareRoles(Association first, Association second)
{
Clazz firstClass = first.getClazz();
String firstName = first.getName();
String firstCard = first.getCardinality().getValue();
Clazz secondClass = second.getClazz();
String secondName = second.getName();
String secondCard = second.getCardinality().getValue();
if (firstClass == secondClass && firstName.equals(secondName) && firstCard.equals(secondCard))
return true;
return false;
}
public Clazz findClass(String partnerClassName)
{
for (Clazz partnerClass : model.getClazzes())
{
String shortClassName = CGUtil.shortClassName(partnerClass.getName(false));
if (partnerClassName.equals(shortClassName))
{
return partnerClass;
}
}
return null;
}
public String findPartnerClassName(String partnerTypeName)
{
String partnerClassName;
int openAngleBracket = partnerTypeName.indexOf("<");
int closeAngleBracket = partnerTypeName.indexOf(">");
if (openAngleBracket > -1 && closeAngleBracket > openAngleBracket)
{
partnerClassName = partnerTypeName.substring(openAngleBracket + 1, closeAngleBracket);
}
else if (partnerTypeName.endsWith("Set"))
{
// TODO: should check for superclass ModelSet
partnerClassName = partnerTypeName.substring(0, partnerTypeName.length() - 3);
}
else
{
partnerClassName = partnerTypeName;
}
return partnerClassName;
}
// ==========================================================================
private ArrayList searchForJavaFiles(String path)
{
ArrayList javaFiles = new ArrayList();
File file = new File(path);
if (file.exists() && file.isDirectory())
{
File[] listFiles = file.listFiles(new FilenameFilter()
{
@Override
public boolean accept(File file, String string)
{
return string.toLowerCase().endsWith(".java");
}
});
Collections.addAll(javaFiles, listFiles);
File[] directory = file.listFiles(new FilenameFilter()
{
@Override
public boolean accept(File file, String string)
{
return file.isDirectory();
}
});
for (File dir : directory)
{
javaFiles.addAll(searchForJavaFiles(dir.getPath()));
}
}
javaFiles.sort(new Comparator()
{
@Override
public int compare(File file1, File file2)
{
return file1.getAbsolutePath().compareTo(file2.getAbsolutePath());
}
});
return javaFiles;
}
public void updateFromCode(String includePathes, String packages)
{
File projectRootFolder = new File(".");
updateFromCode(includePathes, packages, projectRootFolder);
}
/*
* usage for maven project model.updateFromCode("java", "org.package.name",
* new File((new
* File(this.getClass().getResource(".").getPath())).getParentFile
* ().getParent() + "/src/main/" ));
*/
public void updateFromCode(String includePathes, String packages, File projectRoot)
{
// find java files in parent directory
if (projectRoot != null)
{
ArrayList javaFiles = searchForJavaFiles(includePathes, packages, projectRoot);
addJavaFilesToClasses(packages, projectRoot, javaFiles);
if (model.getClazzes().isEmpty())
{
System.out.println("no class files found !!!! END");
return;
}
// parse each java file
for (Iterator i = model.getClazzes().iterator(); i.hasNext();)
{
Clazz clazz = i.next();
handleMember(clazz, includePathes, projectRoot);
}
}
// add model creation code at invocation place, if not yet there
}
private Clazz handleMember(Clazz clazz, String rootDir, File projectRoot)
{
// System.out.println("parse " + clazz.getName(false));
Parser parser = getOrCreateClazz(clazz).getOrCreateParser(projectRoot.getAbsolutePath() + "//" + rootDir);
parser.indexOf(Parser.CLASS_END);
if (isHelperClass(parser))
{
GraphUtil.removeYou(clazz);
}
// FIXME
// set class or interface
// if (Parser.INTERFACE.equals(parser.getClassType()))
// {
// clazz.setInterface(true);
// }
LinkedHashMap symTab = new LinkedHashMap();
for (String key : parser.getSymTab().keySet())
{
symTab.put(key, parser.getSymTab().get(key));
}
for (String memberName : symTab.keySet())
{
addMemberToModel(clazz, parser, memberName, projectRoot + "/" + rootDir);
}
return clazz;
}
private boolean isSDMLibClass(Clazz clazz)
{
String className = clazz.getName(false);
String sDMLibClasses =
"org.sdmlib.serialization.EntityFactory "
+ "org.sdmlib.models.pattern.PatternObject "
+ "org.sdmlib.models.pattern.util.PatternObjectCreator "
+ "org.sdmlib.models.modelsets.SDMSet "
+ "org.sdmlib.serialization.PropertyChangeInterface";
if (sDMLibClasses.indexOf(className) >= 0)
{
return true;
}
return false;
}
private boolean isHelperClass(Parser parser)
{
String className = parser.getClassName();
// is creatorcreator class
if ("CreatorCreator".equals(className))
{
return true;
}
// is creator class
if (className.endsWith("Creator")
&& isClassExtends("EntityFactory PatternObjectCreator", parser))
{
return true;
}
// is PO class
if (isClassExtends("PatternObject", parser))
{
return true;
}
// is Set class
if (isClassExtends("SDMSet", parser))
{
return true;
}
return false;
}
private boolean isClassExtends(String extendsString, Parser parser)
{
for (String extendClass : extendsString.split(" "))
{
if (parser.getSymTabEntriesFor("extends:" + extendClass).size() > 0)
return true;
}
return false;
}
private void addMemberToModel(Clazz clazz, Parser parser, String memberName, String rootDir)
{
//add annotations
if(memberName.startsWith("annotation")) {
addMemberAsAnnotation(clazz, memberName, parser);
}
// add new methods
if (memberName.startsWith(Parser.METHOD))
{
addMemberAsMethod(clazz, memberName, parser);
}
// add new attributes
else if (memberName.startsWith(Parser.ATTRIBUTE))
{
String[] split = memberName.split(":");
String attrName = split[1];
SymTabEntry symTabEntry = parser.getSymTab().get(memberName);
if (symTabEntry != null)
addMemberAsAttribut(clazz, attrName, symTabEntry, rootDir);
}
// add super classes
if (memberName.startsWith(Parser.EXTENDS))
{
if (GraphUtil.isInterface(clazz))
{
addMemberAsInterface(clazz, memberName, parser);
}
else
{
addMemberAsSuperClass(clazz, memberName, parser);
}
}
else if (memberName.startsWith(Parser.IMPLEMENTS))
{
addMemberAsInterface(clazz, memberName, parser);
}
}
private void addMemberAsAnnotation(Clazz clazz, String memberName, Parser parser)
{
String[] split = memberName.split(":");
clazz.with(new Annotation(split[1]));
}
private void addMemberAsAttribut(Clazz clazz, String attrName, SymTabEntry symTabEntry, String rootDir)
{
// filter public static final constances
String modifiers = symTabEntry.getModifiers();
if ((modifiers.indexOf("public") >= 0 || modifiers.indexOf("private") >= 0) && modifiers.indexOf("static") >= 0
&& modifiers.indexOf("final") >= 0)
{
// ignore
return;
}
String type = symTabEntry.getType();
// include arrays
type = type.replace("[]", "");
if (CGUtil.isPrimitiveType(type))
{
if (!classContainsAttribut(clazz, attrName, symTabEntry.getType()))
{
new Attribute(attrName, DataType.create(symTabEntry.getType())).with(clazz);
}
}
else
{
// handle complex attributes
handleComplexAttr(clazz, attrName, symTabEntry, rootDir);
}
}
private void handleComplexAttr(Clazz clazz, String attrName, SymTabEntry symTabEntry, String rootDir)
{
String memberName = symTabEntry.getMemberName();
String partnerTypeName = symTabEntry.getType();
String partnerClassName = findPartnerClassName(partnerTypeName);
Clazz partnerClass = model.getClazz(partnerTypeName);
if (partnerClass == null)
return;
Cardinality card = findRoleCard(partnerTypeName);
String setterPrefix = "set";
if (Cardinality.MANY.equals(card))
{
setterPrefix = "addTo";
}
String name = StrUtil.upFirstChar(memberName);
Parser parser = getOrCreateClazz(clazz).getParser().parse();
SymTabEntry addToSymTabEntry = parser.getSymTab().get(
Parser.METHOD + ":" + setterPrefix + name + "(" + partnerClassName + ")");
if (addToSymTabEntry == null && "addTo".equals(setterPrefix))
{
addToSymTabEntry = parser.getSymTab().get(
Parser.METHOD + ":" + "with" + name + "(" + partnerClassName + "...)");
}
// type is unknown
if (addToSymTabEntry == null)
{
new Attribute(memberName, DataType.create(partnerTypeName))
.with(clazz);
return;
}
parser.parseMethodBody(addToSymTabEntry);
LinkedHashSet methodBodyQualifiedNames = new LinkedHashSet();
for (String key : parser.getMethodBodyQualifiedNames())
{
methodBodyQualifiedNames.add(key);
}
boolean done = false;
for (String qualifiedName : methodBodyQualifiedNames)
{
if (qualifiedName.startsWith("value.set"))
{
handleAssoc(clazz, rootDir, memberName, card, partnerClassName, partnerClass,
qualifiedName.substring("value.set".length()));
done = true;
}
else if (qualifiedName.startsWith("value.with") || qualifiedName.startsWith("item.with"))
{
handleAssoc(clazz, rootDir, memberName, card, partnerClassName, partnerClass,
qualifiedName.substring("value.with".length()));
done = true;
}
else if (qualifiedName.startsWith("value.addTo"))
{
handleAssoc(clazz, rootDir, memberName, card, partnerClassName, partnerClass,
qualifiedName.substring("value.addTo".length()));
done = true;
}
}
if (!done)
{
// did not find reverse role, add as attribute
new Attribute(memberName, DataType.create(partnerTypeName))
.with(clazz);
}
// // remove getter with setter or addTo removeFrom removeAllFrom without
// for (String memberName : memberNames)
// {
// // remove getter with setter or addTo removeFrom removeAllFrom without
// findAndRemoveMethods(
// clazz,
// memberName,
// "get set with without addTo create removeFrom removeAllFrom iteratorOf hasIn sizeOf removePropertyChange addPropertyChange");
// findAndRemoveAttributs(clazz, "listeners");
// }
}
private void handleAssoc(Clazz clazz, String rootDir, String memberName, Cardinality card,
String partnerClassName, Clazz partnerClass, String partnerAttrName)
{
partnerAttrName = StrUtil.downFirstChar(partnerAttrName);
GenClass partnerGenClass = getOrCreateClazz(partnerClass);
Parser partnerParser = partnerGenClass.getOrCreateParser(rootDir);
String searchString = Parser.ATTRIBUTE + ":" + partnerAttrName;
int attributePosition = partnerParser.indexOf(searchString);
if (attributePosition > -1)
{
Cardinality partnerCard = findRoleCard(partnerParser, searchString);
tryToCreateAssoc(clazz, memberName, card, partnerClassName, partnerClass, partnerAttrName, partnerCard);
}
}
private void tryToCreateAssoc(Clazz clazz, String memberName, Cardinality card, String partnerClassName,
Clazz partnerClass, String partnerAttrName, Cardinality partnerCard)
{
Association sourceRole = new Association(clazz).with(partnerCard).with(partnerAttrName);
Association targetRole = new Association(partnerClass).with(card).with(memberName);
if (!assocWithRolesExists(sourceRole, targetRole))
{
sourceRole.with(targetRole);
clazz.with(sourceRole);
}
}
private boolean assocWithRolesExists(Association source, Association target)
{
for (Association assoc : getAssociations())
{
if (compareRoles(source, target, assoc) || compareRoles(target, source, assoc))
return true;
}
return false;
}
private boolean compareRoles(Association source, Association target, Association assoc)
{
return compareRoles(assoc, source) && compareRoles(assoc.getOther(), target);
}
private Cardinality findRoleCard(Parser partnerParser, String searchString)
{
String partnerTypeName;
SymTabEntry partnerSymTabEntry = partnerParser.getSymTab().get(searchString);
partnerTypeName = partnerSymTabEntry.getType();
return findRoleCard(partnerTypeName);
}
private Cardinality findRoleCard(String partnerTypeName)
{
Cardinality partnerCard = Cardinality.ONE;
int _openAngleBracket = partnerTypeName.indexOf("<");
int _closeAngleBracket = partnerTypeName.indexOf(">");
if (_openAngleBracket > 1 && _closeAngleBracket > _openAngleBracket)
{
// partner to many
partnerCard = Cardinality.MANY;
}
else if (partnerTypeName.endsWith("Set") && partnerTypeName.length() > 3)
{
// it might be a ModelSet. Look if it starts with a clazz name
String prefix = partnerTypeName.substring(0, partnerTypeName.length() - 3);
for (Clazz clazz : model.getClazzes())
{
if (prefix.equals(CGUtil.shortClassName(clazz.getName())))
{
partnerCard = Cardinality.MANY;
break;
}
}
}
return partnerCard;
}
private void addMemberAsSuperClass(Clazz clazz, String memberName, Parser parser)
{
Clazz memberClass = findMemberClass(clazz, memberName, parser);
if (memberClass == null)
{
// probably an internal class
return;
}
// ignore helperclasses
if (isSDMLibClass(memberClass))
{
GraphUtil.removeYou(memberClass);
return;
}
if (memberClass != null)
clazz.withSuperClazz(memberClass);
}
private void addMemberAsInterface(Clazz clazz, String memberName, Parser parser)
{
Clazz memberClass = findMemberClass(clazz, memberName, parser);
// ignore helperclasses
if (isSDMLibClass(memberClass))
{
GraphUtil.removeYou(memberClass);
return;
}
//FIXME
if (memberClass != null)
{
// memberClass.withInterface(true);
clazz.withSuperClazz(memberClass);
}
}
private Clazz findMemberClass(Clazz clazz, String memberName, Parser parser)
{
String[] split = memberName.split(":");
String signature = split[1];
Map symTab = parser.getSymTab();
for (String key : symTab.keySet())
{
String importName = symTab.get(key).getMemberName();
if (key.startsWith(Parser.IMPORT + ":") && importName.endsWith(signature))
{
Clazz modelClass = findClassInModel(importName);
if (modelClass != null)
{
return modelClass;
}
else
{
Clazz externClass = model.createClazz(importName).withExternal(true);
return externClass;
}
}
else if (key.startsWith(Parser.IMPORT + ":") && importName.endsWith("*"))
{
// might work
importName = importName.substring(0, importName.length() - 1) + signature;
Clazz modelClass = findClassInModel(importName);
if (modelClass != null)
{
return modelClass;
}
}
}
String name = clazz.getName(false);
int lastIndex = name.lastIndexOf('.');
name = name.substring(0, lastIndex + 1) + signature;
return findClassInModel(name);
}
private Clazz findClassInModel(String name)
{
SimpleSet classes = model.getClazzes();
for (Clazz eClazz : classes)
{
if (eClazz.getName(false).equals(name))
{
return eClazz;
}
}
return null;
}
private void addMemberAsMethod(Clazz clazz, String memberName, Parser parser)
{
SymTabEntry symTabEntry = parser.getSymTab().get(memberName);
// TODO: FIX Parser has no symTableEntries
if (symTabEntry == null)
{
parser.parse();
symTabEntry = parser.getSymTab().get(memberName);
}
String fullSignature = symTabEntry.getType();
String[] split = fullSignature.split(":");
String signature = split[1];
// filter internal generated methods
String filterString = "get(String) set(String,Object) getPropertyChangeSupport() removeYou()"
+
" addPropertyChangeListener(PropertyChangeListener) removePropertyChangeListener(PropertyChangeListener)"
+
" addPropertyChangeListener(String,PropertyChangeListener) removePropertyChangeListener(String,PropertyChangeListener)"
+ "toString()";
if (filterString.indexOf(signature) < 0 && !isGetterSetter(signature, parser, clazz)
&& isNewMethod(signature, clazz))
{
int part = signature.indexOf("(");
String[] params = signature.substring(part + 1, signature.length() - 1).split(",");
Method method = new Method(signature.substring(0, part))
.withParent(clazz)
.with(DataType.create(split[2]));
for (String param : params)
{
if (param != null && param.length() > 0)
{
method.with(new Parameter(DataType.create(param)));
}
}
if (!symTabEntry.getAnnotations().isEmpty())
{
method.with(new Annotation(symTabEntry.getAnnotations()));
}
method.with(new Throws(symTabEntry.getThrowsTags()));
method.withBody(parser.getFileBody().substring(symTabEntry.getBodyStartPos(), symTabEntry.getEndPos()+1));
}
}
private boolean isGetterSetter(String signature, Parser parser, Clazz clazz)
{
Map symTab = parser.getSymTab();
List attributeKeys = new ArrayList<>();
for (String key : symTab.keySet())
{
if (key.startsWith("attribute:"))
{
attributeKeys.add(key);
}
// TODO: check type hierarchy
}
// method starts with: with set get ...
if (signature.startsWith("with")
|| signature.startsWith("set")
|| signature.startsWith("get")
|| signature.startsWith("add")
|| signature.startsWith("remove")
|| signature.startsWith("create"))
{
// is class attribute
for (String attrKey : attributeKeys)
{
SymTabEntry symTabEntry = symTab.get(attrKey);
String attrName = symTabEntry.getMemberName();
String signName = signature.substring(0, signature.indexOf("("));
if (signName.toLowerCase().endsWith(attrName.toLowerCase()))
{
return true;
}
}
}
return false;
}
private boolean isNewMethod(String memberName, Clazz clazz)
{
for (Method method : clazz.getMethods())
{
if (method.getName(false).equals(memberName))
return false;
}
return true;
}
private ArrayList searchForJavaFiles(String includePathes, String packageString, File projectRoot)
{
ArrayList javaFiles = new ArrayList();
String[] packages = packageString.split("\\s+");
String[] includes = includePathes.split("\\s+");
for (String pAckage : packages)
{
String packagepath = pAckage.replace('.', '/');
for (String include : includes)
{
String newPath = projectRoot.getPath() + "/" + include + "/" + packagepath;
javaFiles.addAll(searchForJavaFiles(newPath));
}
}
return javaFiles;
}
private void addJavaFilesToClasses(String packageString, File srcFolder, ArrayList javaFiles)
{
String[] packages = packageString.split("\\s+");
for (File file : javaFiles)
{
String filePath = file.getAbsolutePath();
filePath = filePath.replace(srcFolder.getAbsolutePath(), "");
filePath = filePath.replace(File.separatorChar, '.').substring(1);
filePath = filePath.substring(0, filePath.length() - 5);
addClassToClasses(filePath, packages);
}
}
private void addClassToClasses(String filePath, String[] packages)
{
int pos = filePath.indexOf('.');
// split off source folder
String rootDir="";
// boolean commonPrefix=false;
for (String packageName : packages)
{
pos = filePath.indexOf(packageName) - 1;
if (pos == -1) { // It is 0 - 1
// pos = 0;
// commonPrefix = true;
}
break;
}
if(pos > 0) {
rootDir = filePath.substring(0, pos);
}
filePath = filePath.substring(pos + 1);
if (commonPrefix(filePath, packages))
{
if (!classExists(filePath))
{
Clazz clazz = model.createClazz(filePath);
getOrCreateClazz(clazz).withFilePath(rootDir);
}
return;
}
}
private boolean commonPrefix(String filePath, String[] packages)
{
for (String p : packages)
{
if (filePath.startsWith(p))
{
return true;
}
}
return false;
}
private boolean classContainsAttribut(Clazz clazz, String attrName, String type)
{
for (Attribute attr : clazz.getAttributes())
{
if (attrName.equals(attr.getName()) && type.equals(attr.getType()))
return true;
}
return false;
}
private boolean classExists(String filePath)
{
for (Clazz clazz : model.getClazzes())
{
if (clazz.getName(false).equals(filePath))
return true;
}
return false;
}
private boolean hasAttribute(Attribute attribute, LocalVarTableEntry entry, String rootDir)
{
String name = attribute.getName();
ArrayList> initSequence = entry.getInitSequence();
for (ArrayList sequencePart : initSequence)
{
ArrayList isAttribute = partIsAttribute(sequencePart);
if (isAttribute != null)
{
String sequencePartName = isAttribute.get(0).replace("\"", "");
if (StrUtil.stringEquals(name, sequencePartName))
{
// check only for attr name, user may have changed attr type, do
// not overwrite this.
// if (sequencePart.size() > 6 &&
// "DataType.ref".equals(isAttribute.get(1)) ) {
// String typeString =
// type.toString().substring(type.toString().indexOf(".")+1);
// String sequencePartType = sequencePart.get(1).replaceAll("\"",
// "").toUpperCase();
// if (!sequencePartType.equals(typeString))
// System.out.println("warning: " +
// attribute.getClazz().getName()+":attribute \"" + name
// +"\" has different type "+sequencePartType +"!="+ typeString);
// }
// && StrUtil.stringEquals(type, sequencePartType))
return true;
}
}
else if ("model.createClazz".equals(sequencePart.get(0)))
{
// initialization with varargs
int pos = 2;
while (pos + 1 < sequencePart.size())
{
String attrName = sequencePart.get(pos).replace("\"", "");
// String typeName = sequencePart.get(pos + 1).replace("\"", "");
if (StrUtil.stringEquals(name, attrName))
{
return true;
}
pos += 2;
}
}
}
// there may be separate clazz.withAttributes(...) statements
String withAttrCall = entry.getName() + ".with";
String attrNameQuoted = "\"" + name + "\"";
GenClass orCreate = getOrCreateClazz(attribute.getClazz());
Parser parser = orCreate.getOrCreateParser(rootDir);
parser.parse();
StatementEntry currentStatement = parser.getCurrentStatement();
if (currentStatement == null)
return false;
StatementEntry parent = currentStatement.getParent();
StatementEntrySet bodyStats = parent.getBodyStats();
for (StatementEntry stat : bodyStats)
{
String firstToken = stat.getTokenList().get(0);
if (StrUtil.stringEquals(withAttrCall, firstToken))
{
int i = 2;
while (i < stat.getTokenList().size())
{
if (StrUtil.stringEquals(attrNameQuoted, stat.getTokenList().get(i)))
{
// this attribute is already created in model creation code
return true;
}
i++;
}
}
}
return false;
}
private ArrayList partIsAttribute(ArrayList sequencePart)
{
ArrayList attributeSequence = new ArrayList<>();
if ("with".equals(sequencePart.get(0))
&& "[".equals(sequencePart.get(1))
&& "new".equals(sequencePart.get(2))
&& "Attribute".equals(sequencePart.get(3)))
{
attributeSequence.add(sequencePart.get(4));
attributeSequence.add(sequencePart.get(6));
return attributeSequence;
}
if ("withAttribute".equals(sequencePart.get(0)))
{
attributeSequence.add(sequencePart.get(1));
attributeSequence.add(sequencePart.get(5));
return attributeSequence;
}
return null;
}
public void testGeneratedCode() {
String rootDir = "src/test/java";
removeAllGeneratedCode(rootDir, rootDir, rootDir);
getModel().generate(rootDir);
}
public void removeAllGeneratedCode(String rootDir, String srcDir, String helpersDir)
{
turnRemoveCallToComment(rootDir);
// now remove class file, creator file, and modelset file for each class
// and the CreatorCreator
for (Clazz clazz : model.getClazzes())
{
try
{
removeAllCodeForClass(srcDir, helpersDir, clazz);
}
catch (Exception e)
{
}
}
String path = helpersDir + "/" + (model.getName() + UTILPATH).replaceAll("\\.", "/") + "/";
String fileName = path + "CreatorCreator.java";
deleteFile(fileName);
}
public void turnRemoveCallToComment(String rootDir)
{
int codeLineNumber = -1;
String className = null;
// first find the call to this method and make it a comment, to avoid
// undesired execution on later runs.
try
{
throw new RuntimeException();
}
catch (Exception e)
{
StackTraceElement[] stackTrace = e.getStackTrace();
StackTraceElement callEntry = stackTrace[2];
codeLineNumber = callEntry.getLineNumber();
className = callEntry.getClassName();
}
// open java file and find code line
String fileName = rootDir + "/" + className.replaceAll("\\.", "/") + ".java";
File file = new File(fileName);
if (file.exists())
{
try
{
BufferedReader in = new BufferedReader(new FileReader(file));
String line = "";
int lineNo = 0;
StringBuilder buf = new StringBuilder();
while (true)
{
line = in.readLine();
if (line == null)
break;
lineNo++;
if (lineNo == codeLineNumber && line.indexOf("//") == -1)
{
int pos = 0;
while (pos < line.length() && Character.isWhitespace(line.charAt(pos)))
{
pos++;
}
line = line.substring(0, pos) + "// " + line.substring(pos);
}
buf.append(line).append('\n');
}
in.close();
FileWriter fileWriter = new FileWriter(file);
fileWriter.write(buf.toString());
fileWriter.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
public void removeAllCodeForClass(String srcDir, String helpersDir,
Clazz clazz)
{
String className;
String fileName;
String packageName;
className = clazz.getName(false);
int pos = className.lastIndexOf('.');
packageName = className.substring(0, pos);
// class file
fileName = srcDir + "/" + className.replaceAll("\\.", "/") + ".java";
deleteFile(fileName);
String path = helpersDir + "/" + (packageName + UTILPATH).replaceAll("\\.", "/") + "/";
// creator file
fileName = path + CGUtil.shortClassName(className) + "Creator.java";
deleteFile(fileName);
// modelset file
fileName = path + CGUtil.shortClassName(className) + "Set.java";
deleteFile(fileName);
// pattern object file
fileName = path + CGUtil.shortClassName(className) + "PO.java";
deleteFile(fileName);
// pattern object creator file
fileName = path + CGUtil.shortClassName(className) + "POCreator.java";
deleteFile(fileName);
// // CreatorCreator in that package
// fileName = path + "CreatorCreator.java";
// deleteFile(fileName);
}
private void deleteFile(String fileName)
{
File file;
file = new File(fileName);
if (file.exists())
{
file.delete();
}
}
public DIFF getShowDiff()
{
return showDiff;
}
public GenClassModel withShowDiff(DIFF showDiff)
{
this.showDiff = showDiff;
return this;
}
public GenClassModel withIgnoreClazz(String name)
{
if (this.ignoreDiff == null)
{
this.ignoreDiff = new ArrayList();
}
this.ignoreDiff.add(name);
return this;
}
public void doCoverageOfModelCode()
{
// try to create example object structure and use storyboard to do
// coverage
Clazz firstClazz = this.getModel().getClazzes().first();
try
{
// try to load creator class
String creatorClassName = CGUtil.helperClassName(firstClazz.getName(false), "Creator");
Class> creatorClass = Class.forName(creatorClassName);
java.lang.reflect.Method method = creatorClass.getMethod("createIdMap", String.class);
// IdMap map = (IdMap) method.invoke(null, "t");
IdMap map = new SDMLibIdMap("t");
Object largestModelRoot = null;
// now loop through model classes and create two objects for each class
// using the corresponding creator class
for (Clazz clazz : model.getClazzes())
{
try
{
SendableEntityCreator creator = map.getCreator(clazz.getName(false), true);
Object object1 = creator.getSendableInstance(false);
if (largestModelRoot == null)
{
largestModelRoot = object1;
}
map.getId(object1);
// try to add some attribute values
for (Attribute attr : clazz.getAttributes())
{
// for number and string attributes "42" might work.
try
{
creator.setValue(object1, attr.getName(), "42", "");
}
catch (Exception g)
{
}
}
// try to add role values
for (Association role : clazz.getAssociations())
{
role = role.getOther();
Clazz partnerClazz = role.getClazz();
SendableEntityCreator partnerCreator = map.getCreator(partnerClazz.getName(false), true);
Object partnerObject = partnerCreator.getSendableInstance(false);
map.getId(partnerObject);
creator.setValue(object1, role.getName(), partnerObject, "");
try
{
java.lang.reflect.Method createMethod = object1.getClass().getMethod(
"create" + StrUtil.upFirstChar(role.getName()));
createMethod.invoke(object1);
}
catch (Exception g)
{
}
}
}
catch (Exception f)
{
}
}
// now ask the storyboad to do the coverage things
Storyboard story = new Storyboard("coverage");
story.coverSetAndPOClasses(map);
story.coverSeldomModelMethods(map);
story.coverage4GeneratedModelCode(largestModelRoot);
}
catch (Exception e)
{
// e.printStackTrace();
}
}
/**
* Removes the associated class from the current model and deletes
* the generated code from the model and util classes.
* This includes the set, creator and pattern object classes, that are associated with the class.
*
*
* @param rootDir root directory, where the code of the associated class is located
*/
public void removeFromModelAndCode(Clazz model, String rootDir) {
for (Association role : model.getAssociations()) {
Clazz clazz = role.getOtherClazz();
GenClass partnerClass = this.getOrCreateClazz(clazz);
String helperClassName = CGUtil.helperClassName(model.getName(false), "Set");
String helpPoClassName = CGUtil.helperClassName(model.getName(false), "PO");
Parser partnerParser = partnerClass.getParser();
partnerClass.removeFragment(partnerParser, Parser.IMPORT + ":" + model.getName(false));
partnerClass.removeFragment(partnerParser, Parser.IMPORT + ":" + helperClassName);
Parser partnerSetParser = partnerClass.getOrCreateParserForModelSetFile(rootDir);
partnerClass.removeFragment(partnerSetParser, Parser.IMPORT + ":" + model.getName(false));
partnerClass.removeFragment(partnerSetParser, Parser.IMPORT + ":" + helperClassName);
Parser partnerPOParser = partnerClass.getOrCreateParserForPatternObjectFile(rootDir);
partnerClass.removeFragment(partnerPOParser, Parser.IMPORT + ":" + model.getName(false));
partnerClass.removeFragment(partnerPOParser, Parser.IMPORT + ":" + helpPoClassName);
partnerClass.removeFragment(partnerPOParser, Parser.IMPORT + ":" + helperClassName);
Parser partnerCreatorParser = partnerClass.getOrCreateParserForCreatorClass(rootDir);
partnerClass.removeFragment(partnerCreatorParser, Parser.IMPORT + ":" + model.getName(false));
partnerClass.removeFragment(partnerCreatorParser, Parser.IMPORT + ":" + helperClassName);
//FIXME role.removeFromModelAndCode(rootDir);
}
GenClass genClass = this.getOrCreateClazz(model);
genClass.removeGeneratedCode(rootDir);
}
public GenClass getGenerator(Object generator, String name)
{
return getClazz(name);
}
}