// Copyright 2002-2006, FreeHEP.
package org.freehep.aid.cli;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import org.freehep.aid.parser.AidParser;
import org.freehep.rtti.Generator;
import org.freehep.rtti.IClass;
import org.freehep.rtti.IPackage;
import org.freehep.rtti.RTTI;
import org.freehep.util.argv.ArgumentFormatException;
import org.freehep.util.argv.ArgumentParser;
import org.freehep.util.argv.BooleanOption;
import org.freehep.util.argv.ListParameter;
import org.freehep.util.argv.MissingArgumentException;
import org.freehep.util.argv.StringOption;
import org.freehep.util.argv.StringParameter;
import org.freehep.util.io.ConditionalInputStream;
/**
* @author Mark Donszelmann
* @version $Id: Aid.java 8584 2006-08-10 23:06:37Z duns $
*/
public class Aid {
private static final String aidDescription = "Abstract Interface Definition compiler";
private static RTTI rtti;
public static RTTI getRTTI() {
return rtti;
}
public int run(String[] args) throws Exception {
rtti = new RTTI();
BooleanOption help = new BooleanOption("-help", "-h", "Show this help page", true);
BooleanOption version = new BooleanOption("-version", "-v", "Show product version", true);
BooleanOption rtti = new BooleanOption("-rtti", "-r", "Print RTTI to stdout");
BooleanOption noGenerate = new BooleanOption("-nogenerate", "-n", "Do not generate any code");
StringOption directory = new StringOption("-directory", "-d", "output dir", ".", "Output into directory instead of current directory");
StringOption property = new StringOption("-property", "-p", "property directory", ".", "Read user property files from directory instead of current directory");
BooleanOption force = new BooleanOption("-force", "-f", "Force overwriting of output files");
BooleanOption ignore = new BooleanOption("-ignore", "-i", "Ignore errors from the parser");
BooleanOption verbose = new BooleanOption("-verbose", "-V", "Verbose");
StringParameter generatorParameter = new StringParameter("generator", "A generator, one of JavaInterfaceGenerator, JavaClassGenerator, CPPHeaderGenerator, PythonClassGenerator, ...");
ListParameter files = new ListParameter("files", "AID files");
Properties mavenProperties = new Properties();
InputStream is = Aid.class.getResourceAsStream("/META-INF/maven/org.freehep/freehep-aid/pom.properties");
if (is != null) mavenProperties.load(is);
String versionNumber = "("+mavenProperties.getProperty("version", "undefined")+")";
String aid = "AID - "+aidDescription+" "+versionNumber;
ArgumentParser cl = new ArgumentParser(aid);
cl.add(help);
cl.add(version);
cl.add(rtti);
cl.add(noGenerate);
cl.add(directory);
cl.add(property);
cl.add(force);
cl.add(ignore);
cl.add(verbose);
cl.add(generatorParameter);
cl.add(files);
try {
List extra = cl.parse(args);
if( !extra.isEmpty() || help.getValue()) {
cl.printUsage( System.out );
return 0;
}
if (version.getValue()) {
System.out.println(aid);
return 0;
}
} catch (MissingArgumentException mae) {
System.out.println(mae.getMessage());
return 0;
} catch (ArgumentFormatException afe) {
System.out.println(afe.getMessage());
return 0;
}
String generatorName = generatorParameter.getValue();
Generator generator = null;
try {
String propDir = property.getValue();
// generate output
Class cls = null;
try {
cls = Class.forName(generatorName);
} catch (ClassNotFoundException cnfe) {
cls = Class.forName("org.freehep.aid."+generatorName);
}
Constructor constructor = cls.getConstructor(new Class[] { java.lang.String.class });
generator = (Generator)constructor.newInstance(new Object[] { propDir });
} catch (ClassNotFoundException cnfe) {
System.err.println("ERROR: Generator class '"+generatorName+"' does not exist.");
return 1;
} catch (ClassCastException cce) {
System.err.println("ERROR: Generator class '"+generatorName+"' does not implement org.freehep.jaco.generator.Generator.");
return 1;
} catch (NoSuchMethodException nsme) {
System.err.println("ERROR: Generator class '"+generatorName+"' does not define a constructor with one String argument.");
return 1;
} catch (InstantiationException ie) {
System.err.println("ERROR: Generator class '"+generatorName+"' cannot be instantiated.");
return 1;
} catch (IllegalAccessException iae) {
System.err.println("ERROR: Generator class '"+generatorName+"' cannot be accessed.");
return 1;
} catch (InvocationTargetException ite) {
System.err.println("ERROR: Generator class '"+generatorName+"' cannot be invoked.");
ite.printStackTrace();
return 1;
}
// parse files, skip first argument as it is the generator
AidParser parser;
for (Iterator i=files.getValue().iterator(); i.hasNext(); ) {
String filename = (String)i.next();
try {
if (verbose.getValue()) System.out.println("Parsing AID: "+filename);
InputStream in = new java.io.FileInputStream(filename);
InputStream cin = new ConditionalInputStream(in, generator.getProperties());
parser = new AidParser(cin);
parser.parse();
cin.close();
in.close();
} catch (java.io.FileNotFoundException e) {
System.err.println("ERROR: File " + filename + " not found.");
if (!ignore.getValue()) return 1;
// } catch (ParseException e) {
// System.err.println("ERROR: Encountered errors during parse.");
// System.err.println(e.getMessage());
// if (!ignore.getValue()) return 1;
} catch (Exception e) {
System.err.println("ERROR: "+e);
if (!ignore.getValue()) return 1;
}
}
// check to print out rtti
if (rtti.getValue()) {
System.out.println(Aid.getRTTI().toString());
}
// only generate
if (noGenerate.getValue()) {
System.out.println("No code generated.");
return 0;
}
try {
IPackage[] p = Aid.getRTTI().getPackages();
boolean stop = false;
for (int i=0; i<p.length; i++) {
IClass[] c = p[i].getClasses();
for (int j=0; (j<c.length) && !stop; j++ ) {
stop = writeClass(generator, c[j], directory.getValue(), force.getValue(), verbose.getValue());
}
}
} catch (IOException ioe) {
System.err.println(ioe);
return 1;
} catch (Exception e) {
System.err.println(e);
e.printStackTrace();
return 1;
}
return 0;
}
// return true if we want to stop
private boolean writeClass(Generator generator, IClass clazz,
String outDir, boolean overwrite, boolean verbose) throws IOException {
File dir = new File(outDir+"/"+generator.directory(clazz));
dir.mkdirs();
File file = new File(dir, generator.filename(clazz));
// Check if we are overwriting a class which was already generated by us
if (!overwrite) {
if (file.exists()) {
BufferedReader reader = new BufferedReader(new FileReader(file));
boolean found = false;
// look in first 5 lines
for (int i=0; !found && (i<5); i++) {
String line = reader.readLine();
if ((line != null) && (line.indexOf("AID-GENERATED") >= 0)) {
found = true;
}
}
if (!found) throw new IOException("Non AID-GENERATED file exists '"+file+"', cannot overwrite, use -force option");
reader.close();
}
}
if (verbose) System.out.println("Generating: "+file);
boolean stop = generator.print(file, clazz);
return stop;
}
public static void runMain(String[] args) throws Exception {
Aid aid = new Aid();
aid.run(args);
}
public static void main(String[] args) {
try {
Aid aid = new Aid();
System.exit(aid.run(args));
} catch (Exception e) {
System.err.println(e);
System.exit(1);
}
}
}