// Copyright 2002-2005, FreeHEP.
package org.freehep.aid;
import java.io.*;
import java.util.*;
import org.freehep.rtti.*;
import org.freehep.util.*;
import org.freehep.util.io.*;
/**
* @author Mark Donszelmann
* @version $Id: AbstractJavaGenerator.java 8584 2006-08-10 23:06:37Z duns $
*/
public abstract class AbstractJavaGenerator extends AbstractGenerator {
protected static final String language = "java";
protected UserProperties importProperties = new UserProperties();
protected UserProperties typeProperties = new UserProperties();
protected UserProperties valueProperties = new UserProperties();
protected UserProperties templateProperties = new UserProperties();
protected UserProperties primitiveProperties = new UserProperties();
private Map/*<Id, Type>*/ template;
public AbstractJavaGenerator(String propDir) {
super();
AidUtil.loadProperties(properties, getClass(), propDir, "aid.java.properties");;
AidUtil.loadProperties(importProperties, getClass(), propDir, "aid.imports."+language+".properties");
AidUtil.loadProperties(typeProperties, getClass(), propDir, "aid.types."+language+".properties");
AidUtil.loadProperties(valueProperties, getClass(), propDir, "aid.values."+language+".properties");
AidUtil.loadProperties(templateProperties, getClass(), propDir, "aid.templates."+language+".properties");
AidUtil.loadProperties(primitiveProperties, getClass(), propDir, "aid.primitives."+language+".properties");
}
public String directory(IClass clazz) {
String directory = clazz.getPackageName();
return directory.replace('.',File.separatorChar);
}
public abstract String filename(IClass clazz);
protected boolean isClass(IClass clazz) {
return clazz.isClass();
}
public boolean print(File file, IClass clazz) throws IOException {
IndentPrintWriter out = new IndentPrintWriter(new PrintWriter(new BufferedWriter(new FileWriter(file))));
out.setIndentString(" ");
// these go in separate files
printEnumFields(file, clazz);
printHeader(out, clazz);
printImportStatements(out, clazz);
printClassHeader(out, clazz);
String[] concrete = getConcrete(clazz);
if (concrete == null) {
printClassMembers(out, clazz, null);
} else {
for (int i=0; i<concrete.length; i++) {
StringBuffer innerClassName = new StringBuffer();
String[] templateVars = concrete[i].split(",");
for (int j=0; j<templateVars.length; j++) {
String varName = templateVars[j].trim();
innerClassName.append(primitiveProperties.getProperty(varName, varName));
}
out.println();
out.indent();
out.println("/**");
out.println("/* Template Instantiated Interface: "+clazz.getName()+"<"+concrete[i].trim()+">");
out.println("*/");
out.print("public static interface ");
out.print(innerClassName.toString());
out.print(" extends ");
out.print(clazz.getName());
out.println(" {");
printClassMembers(out, clazz, concrete[i]);
out.println("} //"+clazz.getName()+"."+innerClassName.toString());
out.outdent();
out.println();
}
}
printEOCComments(out, clazz);
out.println("} // class or interface");
printEOPComments(out, clazz);
printEOFComments(out, clazz);
out.println();
out.close();
return false;
}
private void printHeader(IndentPrintWriter out, IClass clazz) {
warning(out);
out.println();
String[] packageComments = clazz.getPackageComments(language);
for (int i=0; i<packageComments.length; i++) {
out.println(packageComments[i]);
}
String packageName = getPackageName(clazz);
if (!packageName.equals("")) {
out.println("package "+packageName+";");
}
}
private void printEnumFields(File file, IClass clazz) throws IOException {
IField[] enums = clazz.getEnumFields();
for (int i=0; i<enums.length; i++) {
IndentPrintWriter eout = new IndentPrintWriter(new BufferedWriter(new FileWriter(
new File(file.getParentFile(), enums[i].getNamedType().getType().getName()+".java"))));
printHeader(eout, clazz);
printField(eout, enums[i], false);
eout.close();
}
}
private void printClassMembers(IndentPrintWriter out, IClass clazz, String concrete) {
template = getTemplateMap(clazz.getTemplateParameters(), concrete);
IMethod[] methods = clazz.getMethods();
if (methods.length > 0) out.println();
for (int i=0; i<methods.length; i++) {
if (i!= 0) out.println();
printMethod(out, clazz, methods[i], concrete != null);
}
IField[] fields = clazz.getFields();
if (fields.length > 0) out.println();
for (int i=0; i<fields.length; i++) {
if (i!= 0) out.println();
printField(out, fields[i], true);
}
}
protected abstract void printClassHeader(IndentPrintWriter out, IClass clazz);
protected void printEOCComments(IndentPrintWriter out, IClass clazz) {
}
protected void printEOPComments(IndentPrintWriter out, IClass clazz) {
}
protected void printEOFComments(IndentPrintWriter out, IClass clazz) {
}
protected void printImportStatements(IndentPrintWriter out, IClass clazz) {
SortedSet imports = new TreeSet();
String packageName = clazz.getPackageName();
String[] interfaces = clazz.getInterfaces();
for (int i=0; i<interfaces.length; i++) {
importFrom(interfaces[i], packageName, imports);
}
IMethod[] methods = clazz.getMethods();
for (int m=0; m<methods.length; m++) {
// check return type
importFrom(methods[m].getReturnType(), packageName, imports);
INamedType[] parameterTypes = methods[m].getParameterTypes();
for (int p=0; p<parameterTypes.length; p++) {
importFrom(parameterTypes[p].getType(), packageName, imports);
}
String[] exceptionTypes = methods[m].getExceptionTypes();
for (int e=0; e<exceptionTypes.length; e++) {
importFrom(exceptionTypes[e], packageName, imports);
}
}
IField[] fields = clazz.getFields();
for (int i=0; i<fields.length; i++) {
IType type = fields[i].getNamedType().getType();
importFrom(type, packageName, imports);
}
out.println();
for (Iterator i = imports.iterator(); i.hasNext(); ) {
out.println("import "+i.next()+";");
}
}
protected void importFrom(IType type, String packageName, SortedSet imports) {
if (type.isPrimitive()) return;
importFrom(type.getName(), packageName, imports);
}
protected void importFrom(String name, String packageName, SortedSet imports) {
if (name == null) return;
name = typeProperties.getProperty(name, name);
String importName = importProperties.getProperty(name, null);
if ((importName != null) &&
!importName.equals("") &&
!importName.equals("java.lang."+name) &&
!importName.equals(packageName+"."+name)) {
imports.add(importName);
}
}
protected void printMethod(IndentPrintWriter out, IClass clazz, IMethod method, boolean useFullyQualifiedNames) {
printMethod(out, clazz, method, useFullyQualifiedNames, method.getParameterTypes().length);
}
protected void printMethod(IndentPrintWriter out, IClass clazz, IMethod method, boolean useFullyQualifiedNames, int noOfParameters) {
INamedType[] parameterTypes = method.getParameterTypes();
if (noOfParameters > 0) {
String init = parameterTypes[noOfParameters-1].getInit();
if (init != null) init = valueProperties.getProperty(init, init);
if ((init != null) && !init.equals("")) {
printMethod(out, clazz, method, useFullyQualifiedNames,noOfParameters-1);
}
}
printMethodComments(out, method, noOfParameters);
printMethodHeader(out, clazz, method, useFullyQualifiedNames, noOfParameters);
printMethodBody(out, clazz, method, noOfParameters);
}
protected void printMethodComments(IndentPrintWriter out, IMethod method, int noOfParameters) {
}
protected void printMethodHeader(IndentPrintWriter out, IClass clazz, IMethod method, boolean useFullyQualifiedNames, int noOfParameters) {
out.print(" public ");
INamedType[] parameterTypes = method.getParameterTypes();
if (isClass(clazz) && (noOfParameters == parameterTypes.length)) out.print("abstract ");
Map methodTemplate = template;
// for templates
String[] templateParameters = method.getTemplateParameters();
if (templateParameters.length > 0) {
// make sure we know we have templates
methodTemplate = new HashMap();
String[] concrete = getConcrete(clazz);
if (concrete == null) {
// use templates
out.print(" <");
out.print(templateParameters[0]);
for (int i=1; i<templateParameters.length; i++) {
out.print(", ");
out.print(templateParameters[i]);
}
out.print("> ");
} else {
System.err.println("Cannot use templated methods in concrete template interfaces");
System.exit(1);
}
}
out.print(type(method.getReturnType(), methodTemplate, useFullyQualifiedNames));
out.print(" ");
out.print(method.getName());
out.print("(");
for (int i=0; i<noOfParameters; i++) {
out.print(namedType(parameterTypes[i], methodTemplate, useFullyQualifiedNames));
if (i<noOfParameters-1) out.print(", ");
}
out.print(")");
String[] exceptionTypes = method.getExceptionTypes();
if (exceptionTypes.length > 0) {
out.print(" throws ");
for (int i=0; i<exceptionTypes.length; i++) {
out.print(exceptionTypes[i]);
if (i<exceptionTypes.length-1) out.print(", ");
}
}
}
protected void printMethodBody(IndentPrintWriter out, IClass clazz, IMethod method, int noOfParameters) {
INamedType[] parameterTypes = method.getParameterTypes();
if (!isClass(clazz) || (noOfParameters == parameterTypes.length)) {
out.println(";");
} else {
out.println(" {");
out.print(" ");
if (!method.getReturnType().isVoid()) out.print("return ");
out.print(method.getName()+"(");
for (int i=0; i<noOfParameters; i++) {
out.print(parameterTypes[i].getName());
out.print(", ");
}
String init = parameterTypes[noOfParameters].getInit();
init = valueProperties.getProperty(init, init);
out.print(init);
out.println(");");
out.println(" }");
}
}
protected void printField(IndentPrintWriter out, IField field, boolean innerClass) {
}
protected String namedType(INamedType namedType, Map/*<Id, Type>*/ template, boolean useFullyQualifiedNames) {
return type(namedType.getType(), template, useFullyQualifiedNames)+" "+namedType.getName();
}
protected String type(IType type, Map/*<Id, Type>*/ template, boolean useFullyQualifiedNames) {
return type(type, 0, template, useFullyQualifiedNames);
}
private String type(IType type, int nesting, Map/*<Id, Type>*/ template, boolean useFullyQualifiedNames) {
IType[] types = type.getTypes();
StringBuffer s = new StringBuffer();
String typeName = type.isEnumeration() ? "int" : type.getName();
if (typeName.equals("[]")) {
s.append(type(types[0], template, useFullyQualifiedNames));
} else {
String javaType = typeProperties.getProperty(typeName, typeName);
if (template != null) {
String templateType = (String)template.get(javaType);
javaType = (templateType != null) ? templateType : javaType;
}
if (useFullyQualifiedNames) javaType = importProperties.getProperty(javaType, javaType);
s.append(javaType);
if (types.length > 0) {
if ((template == null) || (template.size() == 0)) {
// generate templated version
// print subtypes in comments, except if the template type was empty
if (!javaType.equals("")) {
if ((nesting == 0) && (template == null)) s.append("/*");
s.append("<");
}
s.append(type(types[0], nesting+1, template, useFullyQualifiedNames));
for (int i=1; i<types.length; i++) {
s.append(", ");
s.append(type(types[i], nesting+1, template, useFullyQualifiedNames));
}
if (!javaType.equals("")) {
s.append(">");
if ((nesting == 0) && (template == null)) s.append("*/");
}
} else {
// generate instantiated version (one level only)
s.append(".");
for (int i=0; i<types.length; i++) {
String varName = (String)template.get(types[i].getName());
s.append(primitiveProperties.getProperty(varName, varName));
}
}
}
}
for (int i=0; i<type.getDimension(); i++) s.append("[]");
return s.toString();
}
private String getPackageName(IClass clazz) {
String packageName = clazz.getPackageName();
if (!packageName.equals("")) packageName = typeProperties.getProperty(packageName, packageName);
return packageName;
}
protected String[] getConcrete(IClass clazz) {
String concrete = templateProperties.getProperty(getPackageName(clazz)+"."+clazz.getName(), null);
if (concrete == null) return null;
return concrete.split(";");
}
protected Map getTemplateMap(String[] templateParameters, String concrete) {
Map/*<Id, Type>*/ template = null;
if (templateParameters.length > 0) {
template = new HashMap();
if (concrete != null) {
String[] templateVars = concrete.split(",");
if (templateVars.length != templateParameters.length) {
System.err.println("Number of template variables ("+templateVars.length+") not equal to number of template parameters ("+templateParameters.length+")");
System.exit(1);
}
for (int j=0; j<templateVars.length; j++) {
template.put(templateParameters[j], templateVars[j].trim());
}
}
}
return template;
}
}