/*
* @(#)$Id: Driver.java 1087 2001-08-18 01:37:50Z Bear $
*
* Copyright 2001 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the proprietary information of Sun Microsystems, Inc.
* Use is subject to license terms.
*
*/
package com.sun.tahiti.compiler;
import java.io.File;
import java.io.OutputStream;
import java.io.IOException;
import java.io.FileOutputStream;
import java.util.Map;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
import com.sun.tahiti.compiler.Controller;
import com.sun.tahiti.compiler.ControllerImpl;
import com.sun.tahiti.compiler.generator.ModelGenerator;
import com.sun.tahiti.compiler.ll.Rules;
import com.sun.tahiti.compiler.ll.RuleSerializer;
import com.sun.tahiti.compiler.ll.RuleGenerator;
import com.sun.tahiti.compiler.sm.MarshallerSerializer;
import com.sun.tahiti.compiler.Symbolizer;
import com.sun.tahiti.grammar.TypeItem;
import com.sun.tahiti.grammar.AnnotatedGrammar;
import com.sun.tahiti.reader.GrammarLoader;
import com.sun.tahiti.util.xml.XSLTUtil;
import com.sun.msv.reader.GrammarReaderController;
import org.apache.xml.serialize.XMLSerializer;
import org.apache.xml.serialize.OutputFormat;
import org.xml.sax.XMLReader;
import org.xml.sax.DocumentHandler;
/**
* Command-line compiler.
*
* @author
* <a href="mailto:kohsuke.kawaguchi@sun.com">Kohsuke KAWAGUCHI</a>
*/
public class Driver
{
private static class OutputMethod {}
private static final OutputMethod java = new OutputMethod();
private static final OutputMethod xml = new OutputMethod();
private static void usage() {
System.err.println(
"Usage: tahiti <options> <grammar file>\n"+
"[OUTPUT OPTIONS]\n"+
" -out xml compiler will produce xml files.\n"+
" -out java compiler will produce java source files.\n"+
" -d <dir> specify output directory.\n"+
"[GENERIC OPTIONS]\n"+
" -package <package name>\n"+
" place java files into the specified package.\n"+
"" );
}
public static void main( String args[] ) throws Exception {
System.exit(run(args));
}
public static int run( String args[] ) throws Exception {
// TODO: where should we obtain the package name
// and the file name of the generated grammar?
OutputMethod out = java;
String grammarFileName=null;
File outDir = new File(".");
for( int i=0; i<args.length; i++ ) {
if( args[i].charAt(0)=='-' ) {
if( args[i].equals("-out") ) {
i++;
if(args.length==i) { usage(); return -1; }
out = null;
if(args[i].equals("xml")) out = xml;
if(args[i].equals("java")) out = java;
if(out==null) { usage(); return -1; }
} else
if( args[i].equals("-d") ) {
i++;
if(args.length==i) { usage(); return -1; }
outDir = new File(args[i]);
// } else
// if( args[i].equals("-log") ) {
// org.apache.log4j.BasicConfigurator.configure(
// new org.apache.log4j.FileAppender(
// new org.apache.log4j.SimpleLayout(),
// System.out )
// );
} else {
System.out.println("unknown option:"+args[i]);
usage();
return -1;
}
} else {
if( grammarFileName!=null ) {
System.err.println("more than one grammar specified");
usage();
return -1;
}
grammarFileName = args[i];
}
}
if( grammarFileName==null ) {
System.err.println("no grammar is specified");
usage();
return -1;
}
SAXParserFactory f = new org.apache.xerces.jaxp.SAXParserFactoryImpl();
f.setNamespaceAware(true);
// parse a grammar file
//-----------------------------------------
System.err.println("parsing a schema...");
GrammarReaderController grammarController =
new com.sun.msv.driver.textui.DebugController(true,true);
AnnotatedGrammar grammar = null;
try {
grammar = GrammarLoader.loadSchema( grammarFileName, grammarController, f );
} catch( org.xml.sax.SAXException e ) {
if(e.getException()!=null)
e.getException().printStackTrace();
throw e;
}
if(grammar==null) {
System.err.println("bailing out");
return -1;
}
// // grammar file will be generated as this name
// String grammarName = g.grammarName; // do not write the extension ".java".
// System.out.println("grammar:"+grammarName);
// generate a grammar file
//-----------------------------------------
System.err.println("generating a grammar file...");
DocumentHandler grammarReceiver = null;
if( out==xml ) {
grammarReceiver = new XMLSerializer(
new FileOutputStream( new File( outDir, "grammar.xml" ) ),
new OutputFormat("xml",null,true) );
} else {
TransformerHandler xsltEngine = XSLTUtil.getTransformer(
Driver.class.getResourceAsStream("grammar2java.xsl"));
xsltEngine.setResult( new StreamResult(
new FileOutputStream( getJavaFile(outDir,grammar.grammarName)) ));
grammarReceiver = new com.sun.msv.writer.ContentHandlerAdaptor(xsltEngine);
}
Rules rules = RuleGenerator.create(grammar);
Symbolizer symbolizer =
RuleSerializer.serialize( grammar, rules, grammarReceiver );
// generate marshallers
//-----------------------------------------
if( out==xml ) {
System.err.println("generating marshallers...");
DocumentHandler marshallerReceiver = null;
marshallerReceiver = new XMLSerializer(
new FileOutputStream( new File( outDir, "marshaller.xml" ) ),
new OutputFormat("xml",null,true) );
MarshallerSerializer.serialize( grammar, symbolizer, grammarController, marshallerReceiver );
}
// the marshaller file is unnecessary when we are generating Java files.
// generate class definitions
//-----------------------------------------
System.err.println("generating class definitions...");
final File od = outDir;
ModelGenerator generator = null;
Controller controller;
if( out==xml ) {
generator = ModelGenerator.xmlGenerator;
controller = new ControllerImpl(grammarController) {
public OutputStream getOutput( TypeItem item ) throws IOException {
return new FileOutputStream(
new File( od, item.getTypeName()+".xml") );
}
};
} else {
generator = ModelGenerator.javaGenerator;
controller = new ControllerImpl(grammarController) {
public OutputStream getOutput( TypeItem item ) throws IOException {
return new FileOutputStream(
getJavaFile( od, item.getTypeName() ) );
}
};
}
generator.generate( grammar, symbolizer, controller );
System.err.println("done.");
return 0;
}
/**
* gets a File object from the specified Java class name.
*
* <p>
* This method creates directories if necessary.
*
* @param javaPath
* it will be something like "abc.def.ghi"
*/
private static File getJavaFile( File parent, String javaPath ) {
File r = new File( parent, javaPath.replace('.','/')+".java" );
new File(r.getParent()).mkdirs();
return r;
}
}