blob: f373fce5bb81f652e945fe135884bab26dd7a5d8 [file] [log] [blame]
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.bsf.util;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;
import org.apache.bsf.util.cf.CodeFormatter;
/**
* A <code>CodeBuffer</code> object is used as a code repository for generated Java code.
* It provides buffers which correspond to the various sections of a Java class.
*
* @author Matthew J. Duftler
*/
public class CodeBuffer
{
private StringWriter fieldDeclSW = new StringWriter(),
methodDeclSW = new StringWriter(),
initializerSW = new StringWriter(),
constructorSW = new StringWriter(),
serviceMethodSW = new StringWriter();
private PrintWriter fieldDeclPW = new PrintWriter(fieldDeclSW),
methodDeclPW = new PrintWriter(methodDeclSW),
initializerPW = new PrintWriter(initializerSW),
constructorPW = new PrintWriter(constructorSW),
serviceMethodPW = new PrintWriter(serviceMethodSW);
private Stack symbolTableStack = new Stack();
private Hashtable symbolTable = new Hashtable(),
usedSymbolIndices = new Hashtable();
private ObjInfo finalStatementInfo;
private CodeBuffer parent;
{
symbolTableStack.push(symbolTable);
}
// New stuff...
private Vector imports = new Vector(),
constructorArguments = new Vector(),
constructorExceptions = new Vector(),
serviceMethodExceptions = new Vector(),
implementsVector = new Vector();
private String packageName = null,
className = "Test",
serviceMethodName = "exec",
extendsName = null;
private Class serviceMethodReturnType = void.class;
public CodeBuffer()
{
}
public CodeBuffer(CodeBuffer parent)
{
this.parent = parent;
}
public void addConstructorArgument(ObjInfo arg)
{
constructorArguments.addElement(arg);
}
public void addConstructorException(String exceptionName)
{
if (!constructorExceptions.contains(exceptionName))
{
constructorExceptions.addElement(exceptionName);
}
}
public void addConstructorStatement(String statement)
{
constructorPW.println(statement);
}
public void addFieldDeclaration(String statement)
{
fieldDeclPW.println(statement);
}
public void addImplements(String importName)
{
if (!implementsVector.contains(importName))
{
implementsVector.addElement(importName);
}
}
public void addImport(String importName)
{
if (!imports.contains(importName))
{
imports.addElement(importName);
}
}
public void addInitializerStatement(String statement)
{
initializerPW.println(statement);
}
public void addMethodDeclaration(String statement)
{
methodDeclPW.println(statement);
}
public void addServiceMethodException(String exceptionName)
{
if (!serviceMethodExceptions.contains(exceptionName))
{
serviceMethodExceptions.addElement(exceptionName);
}
}
public void addServiceMethodStatement(String statement)
{
serviceMethodPW.println(statement);
}
// Used internally by merge(...).
private void appendIfNecessary(PrintWriter pw, StringBuffer buf)
{
if (buf.length() > 0)
{
pw.print(buf.toString());
}
}
public String buildNewSymbol(String prefix)
{
Integer nextNum = getSymbolIndex(prefix);
if (nextNum == null)
{
nextNum = new Integer(0);
}
int iNextNum = nextNum.intValue();
String symbol = prefix + "_" + iNextNum;
while (getSymbol(symbol) != null)
{
iNextNum++;
symbol = prefix + "_" + iNextNum;
}
putSymbolIndex(prefix, new Integer(iNextNum + 1));
return symbol;
}
public void clearSymbolTable()
{
symbolTable = new Hashtable();
symbolTableStack = new Stack();
symbolTableStack.push(symbolTable);
usedSymbolIndices = new Hashtable();
}
public String getClassName()
{
return className;
}
public Vector getConstructorArguments()
{
return constructorArguments;
}
public StringBuffer getConstructorBuffer()
{
constructorPW.flush();
return constructorSW.getBuffer();
}
public Vector getConstructorExceptions()
{
return constructorExceptions;
}
public String getExtends()
{
return extendsName;
}
public StringBuffer getFieldBuffer()
{
fieldDeclPW.flush();
return fieldDeclSW.getBuffer();
}
public ObjInfo getFinalServiceMethodStatement()
{
return finalStatementInfo;
}
public Vector getImplements()
{
return implementsVector;
}
public Vector getImports()
{
return imports;
}
public StringBuffer getInitializerBuffer()
{
initializerPW.flush();
return initializerSW.getBuffer();
}
public StringBuffer getMethodBuffer()
{
methodDeclPW.flush();
return methodDeclSW.getBuffer();
}
public String getPackageName()
{
return packageName;
}
public StringBuffer getServiceMethodBuffer()
{
serviceMethodPW.flush();
return serviceMethodSW.getBuffer();
}
public Vector getServiceMethodExceptions()
{
return serviceMethodExceptions;
}
public String getServiceMethodName()
{
return serviceMethodName;
}
public Class getServiceMethodReturnType()
{
if (finalStatementInfo != null)
{
return finalStatementInfo.objClass;
}
else if (serviceMethodReturnType != null)
{
return serviceMethodReturnType;
}
else
{
return void.class;
}
}
public ObjInfo getSymbol(String symbol)
{
ObjInfo ret = (ObjInfo)symbolTable.get(symbol);
if (ret == null && parent != null)
ret = parent.getSymbol(symbol);
return ret;
}
Integer getSymbolIndex(String prefix)
{
if (parent != null)
{
return parent.getSymbolIndex(prefix);
}
else
{
return (Integer)usedSymbolIndices.get(prefix);
}
}
public Hashtable getSymbolTable()
{
return symbolTable;
}
public void merge(CodeBuffer otherCB)
{
Vector otherImports = otherCB.getImports();
for (int i = 0; i < otherImports.size(); i++)
{
addImport((String)otherImports.elementAt(i));
}
appendIfNecessary(fieldDeclPW, otherCB.getFieldBuffer());
appendIfNecessary(methodDeclPW, otherCB.getMethodBuffer());
appendIfNecessary(initializerPW, otherCB.getInitializerBuffer());
appendIfNecessary(constructorPW, otherCB.getConstructorBuffer());
appendIfNecessary(serviceMethodPW, otherCB.getServiceMethodBuffer());
ObjInfo oldRet = getFinalServiceMethodStatement();
if (oldRet != null && oldRet.isExecutable())
{
addServiceMethodStatement(oldRet.objName + ";");
}
setFinalServiceMethodStatement(otherCB.getFinalServiceMethodStatement());
}
public void popSymbolTable()
{
symbolTableStack.pop();
symbolTable = (Hashtable)symbolTableStack.peek();
}
public void print(PrintWriter out, boolean formatOutput)
{
if (formatOutput)
{
new CodeFormatter().formatCode(new StringReader(toString()), out);
}
else
{
out.print(toString());
}
out.flush();
}
public void pushSymbolTable()
{
symbolTable = (Hashtable)symbolTableStack.push(new ScriptSymbolTable(symbolTable));
}
public void putSymbol(String symbol, ObjInfo obj)
{
symbolTable.put(symbol, obj);
}
void putSymbolIndex(String prefix, Integer index)
{
if (parent != null)
{
parent.putSymbolIndex(prefix, index);
}
else
{
usedSymbolIndices.put(prefix, index);
}
}
public void setClassName(String className)
{
this.className = className;
}
public void setExtends(String extendsName)
{
this.extendsName = extendsName;
}
public void setFinalServiceMethodStatement(ObjInfo finalStatementInfo)
{
this.finalStatementInfo = finalStatementInfo;
}
public void setPackageName(String packageName)
{
this.packageName = packageName;
}
public void setServiceMethodName(String serviceMethodName)
{
this.serviceMethodName = serviceMethodName;
}
public void setServiceMethodReturnType(Class serviceMethodReturnType)
{
this.serviceMethodReturnType = serviceMethodReturnType;
}
public void setSymbolTable(Hashtable symbolTable)
{
this.symbolTable = symbolTable;
}
public boolean symbolTableIsStacked()
{
return (symbolTable instanceof ScriptSymbolTable);
}
public String toString()
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ObjInfo ret = finalStatementInfo;
if (packageName != null && !packageName.equals(""))
{
pw.println("package " + packageName + ";");
pw.println();
}
if (imports.size() > 0)
{
for (int i = 0; i < imports.size(); i++)
{
pw.println("import " + imports.elementAt(i) + ";");
}
pw.println();
}
pw.println("public class " + className +
(extendsName != null && !extendsName.equals("")
? " extends " + extendsName
: "") +
(implementsVector.size() > 0
? " implements " +
StringUtils.getCommaListFromVector(implementsVector)
: "")
);
pw.println("{");
pw.print(getFieldBuffer().toString());
StringBuffer buf = getInitializerBuffer();
if (buf.length() > 0)
{
pw.println();
pw.println("{");
pw.print(buf.toString());
pw.println("}");
}
buf = getConstructorBuffer();
if (buf.length() > 0)
{
pw.println();
pw.println("public " + className + "(" +
(constructorArguments.size() > 0
? StringUtils.getCommaListFromVector(constructorArguments)
: ""
) + ")" +
(constructorExceptions.size() > 0
? " throws " +
StringUtils.getCommaListFromVector(constructorExceptions)
: ""
)
);
pw.println("{");
pw.print(buf.toString());
pw.println("}");
}
buf = getServiceMethodBuffer();
if (buf.length() > 0 || ret != null)
{
pw.println();
pw.println("public " +
StringUtils.getClassName(getServiceMethodReturnType()) + " " +
serviceMethodName + "()" +
(serviceMethodExceptions.size() > 0
? " throws " +
StringUtils.getCommaListFromVector(serviceMethodExceptions)
: ""
)
);
pw.println("{");
pw.print(buf.toString());
if (ret != null)
{
if (ret.isValueReturning())
{
pw.println();
pw.println("return " + ret.objName + ";");
}
else if (ret.isExecutable())
{
pw.println(ret.objName + ";");
}
}
pw.println("}");
}
pw.print(getMethodBuffer().toString());
pw.println("}");
pw.flush();
return sw.toString();
}
}