001: /*
002: * Copyright 2004,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.bsf.util;
018:
019: import java.io.PrintWriter;
020: import java.io.StringReader;
021: import java.io.StringWriter;
022: import java.util.Hashtable;
023: import java.util.Stack;
024: import java.util.Vector;
025:
026: import org.apache.bsf.util.cf.CodeFormatter;
027:
028: /**
029: * A <code>CodeBuffer</code> object is used as a code repository for generated Java code.
030: * It provides buffers which correspond to the various sections of a Java class.
031: *
032: * @author Matthew J. Duftler
033: */
034: public class CodeBuffer {
035: private StringWriter fieldDeclSW = new StringWriter(),
036: methodDeclSW = new StringWriter(),
037: initializerSW = new StringWriter(),
038: constructorSW = new StringWriter(),
039: serviceMethodSW = new StringWriter();
040:
041: private PrintWriter fieldDeclPW = new PrintWriter(fieldDeclSW),
042: methodDeclPW = new PrintWriter(methodDeclSW),
043: initializerPW = new PrintWriter(initializerSW),
044: constructorPW = new PrintWriter(constructorSW),
045: serviceMethodPW = new PrintWriter(serviceMethodSW);
046:
047: private Stack symbolTableStack = new Stack();
048: private Hashtable symbolTable = new Hashtable(),
049: usedSymbolIndices = new Hashtable();
050:
051: private ObjInfo finalStatementInfo;
052: private CodeBuffer parent;
053:
054: {
055: symbolTableStack.push(symbolTable);
056: }
057:
058: // New stuff...
059: private Vector imports = new Vector(),
060: constructorArguments = new Vector(),
061: constructorExceptions = new Vector(),
062: serviceMethodExceptions = new Vector(),
063: implements Vector = new Vector();
064: private String packageName = null, className = "Test",
065: serviceMethodName = "exec", extendsName = null;
066: private Class serviceMethodReturnType = void.class;
067:
068: public CodeBuffer() {
069: }
070:
071: public CodeBuffer(CodeBuffer parent) {
072: this .parent = parent;
073: }
074:
075: public void addConstructorArgument(ObjInfo arg) {
076: constructorArguments.addElement(arg);
077: }
078:
079: public void addConstructorException(String exceptionName) {
080: if (!constructorExceptions.contains(exceptionName)) {
081: constructorExceptions.addElement(exceptionName);
082: }
083: }
084:
085: public void addConstructorStatement(String statement) {
086: constructorPW.println(statement);
087: }
088:
089: public void addFieldDeclaration(String statement) {
090: fieldDeclPW.println(statement);
091: }
092:
093: public void addImplements(String importName) {
094: if (!implements Vector.contains(importName)) {
095: implements Vector.addElement(importName);
096: }
097: }
098:
099: public void addImport(String importName) {
100: if (!imports.contains(importName)) {
101: imports.addElement(importName);
102: }
103: }
104:
105: public void addInitializerStatement(String statement) {
106: initializerPW.println(statement);
107: }
108:
109: public void addMethodDeclaration(String statement) {
110: methodDeclPW.println(statement);
111: }
112:
113: public void addServiceMethodException(String exceptionName) {
114: if (!serviceMethodExceptions.contains(exceptionName)) {
115: serviceMethodExceptions.addElement(exceptionName);
116: }
117: }
118:
119: public void addServiceMethodStatement(String statement) {
120: serviceMethodPW.println(statement);
121: }
122:
123: // Used internally by merge(...).
124: private void appendIfNecessary(PrintWriter pw, StringBuffer buf) {
125: if (buf.length() > 0) {
126: pw.print(buf.toString());
127: }
128: }
129:
130: public String buildNewSymbol(String prefix) {
131: Integer nextNum = getSymbolIndex(prefix);
132:
133: if (nextNum == null) {
134: nextNum = new Integer(0);
135: }
136:
137: int iNextNum = nextNum.intValue();
138: String symbol = prefix + "_" + iNextNum;
139:
140: while (getSymbol(symbol) != null) {
141: iNextNum++;
142: symbol = prefix + "_" + iNextNum;
143: }
144:
145: putSymbolIndex(prefix, new Integer(iNextNum + 1));
146:
147: return symbol;
148: }
149:
150: public void clearSymbolTable() {
151: symbolTable = new Hashtable();
152: symbolTableStack = new Stack();
153: symbolTableStack.push(symbolTable);
154:
155: usedSymbolIndices = new Hashtable();
156: }
157:
158: public String getClassName() {
159: return className;
160: }
161:
162: public Vector getConstructorArguments() {
163: return constructorArguments;
164: }
165:
166: public StringBuffer getConstructorBuffer() {
167: constructorPW.flush();
168:
169: return constructorSW.getBuffer();
170: }
171:
172: public Vector getConstructorExceptions() {
173: return constructorExceptions;
174: }
175:
176: public String getExtends() {
177: return extendsName;
178: }
179:
180: public StringBuffer getFieldBuffer() {
181: fieldDeclPW.flush();
182:
183: return fieldDeclSW.getBuffer();
184: }
185:
186: public ObjInfo getFinalServiceMethodStatement() {
187: return finalStatementInfo;
188: }
189:
190: public Vector getImplements() {
191: return implements Vector;
192: }
193:
194: public Vector getImports() {
195: return imports;
196: }
197:
198: public StringBuffer getInitializerBuffer() {
199: initializerPW.flush();
200:
201: return initializerSW.getBuffer();
202: }
203:
204: public StringBuffer getMethodBuffer() {
205: methodDeclPW.flush();
206:
207: return methodDeclSW.getBuffer();
208: }
209:
210: public String getPackageName() {
211: return packageName;
212: }
213:
214: public StringBuffer getServiceMethodBuffer() {
215: serviceMethodPW.flush();
216:
217: return serviceMethodSW.getBuffer();
218: }
219:
220: public Vector getServiceMethodExceptions() {
221: return serviceMethodExceptions;
222: }
223:
224: public String getServiceMethodName() {
225: return serviceMethodName;
226: }
227:
228: public Class getServiceMethodReturnType() {
229: if (finalStatementInfo != null) {
230: return finalStatementInfo.objClass;
231: } else if (serviceMethodReturnType != null) {
232: return serviceMethodReturnType;
233: } else {
234: return void.class;
235: }
236: }
237:
238: public ObjInfo getSymbol(String symbol) {
239: ObjInfo ret = (ObjInfo) symbolTable.get(symbol);
240:
241: if (ret == null && parent != null)
242: ret = parent.getSymbol(symbol);
243:
244: return ret;
245: }
246:
247: Integer getSymbolIndex(String prefix) {
248: if (parent != null) {
249: return parent.getSymbolIndex(prefix);
250: } else {
251: return (Integer) usedSymbolIndices.get(prefix);
252: }
253: }
254:
255: public Hashtable getSymbolTable() {
256: return symbolTable;
257: }
258:
259: public void merge(CodeBuffer otherCB) {
260: Vector otherImports = otherCB.getImports();
261:
262: for (int i = 0; i < otherImports.size(); i++) {
263: addImport((String) otherImports.elementAt(i));
264: }
265:
266: appendIfNecessary(fieldDeclPW, otherCB.getFieldBuffer());
267: appendIfNecessary(methodDeclPW, otherCB.getMethodBuffer());
268: appendIfNecessary(initializerPW, otherCB.getInitializerBuffer());
269: appendIfNecessary(constructorPW, otherCB.getConstructorBuffer());
270: appendIfNecessary(serviceMethodPW, otherCB
271: .getServiceMethodBuffer());
272:
273: ObjInfo oldRet = getFinalServiceMethodStatement();
274:
275: if (oldRet != null && oldRet.isExecutable()) {
276: addServiceMethodStatement(oldRet.objName + ";");
277: }
278:
279: setFinalServiceMethodStatement(otherCB
280: .getFinalServiceMethodStatement());
281: }
282:
283: public void popSymbolTable() {
284: symbolTableStack.pop();
285: symbolTable = (Hashtable) symbolTableStack.peek();
286: }
287:
288: public void print(PrintWriter out, boolean formatOutput) {
289: if (formatOutput) {
290: new CodeFormatter().formatCode(
291: new StringReader(toString()), out);
292: } else {
293: out.print(toString());
294: }
295:
296: out.flush();
297: }
298:
299: public void pushSymbolTable() {
300: symbolTable = (Hashtable) symbolTableStack
301: .push(new ScriptSymbolTable(symbolTable));
302: }
303:
304: public void putSymbol(String symbol, ObjInfo obj) {
305: symbolTable.put(symbol, obj);
306: }
307:
308: void putSymbolIndex(String prefix, Integer index) {
309: if (parent != null) {
310: parent.putSymbolIndex(prefix, index);
311: } else {
312: usedSymbolIndices.put(prefix, index);
313: }
314: }
315:
316: public void setClassName(String className) {
317: this .className = className;
318: }
319:
320: public void setExtends(String extendsName) {
321: this .extendsName = extendsName;
322: }
323:
324: public void setFinalServiceMethodStatement(
325: ObjInfo finalStatementInfo) {
326: this .finalStatementInfo = finalStatementInfo;
327: }
328:
329: public void setPackageName(String packageName) {
330: this .packageName = packageName;
331: }
332:
333: public void setServiceMethodName(String serviceMethodName) {
334: this .serviceMethodName = serviceMethodName;
335: }
336:
337: public void setServiceMethodReturnType(Class serviceMethodReturnType) {
338: this .serviceMethodReturnType = serviceMethodReturnType;
339: }
340:
341: public void setSymbolTable(Hashtable symbolTable) {
342: this .symbolTable = symbolTable;
343: }
344:
345: public boolean symbolTableIsStacked() {
346: return (symbolTable instanceof ScriptSymbolTable);
347: }
348:
349: public String toString() {
350: StringWriter sw = new StringWriter();
351: PrintWriter pw = new PrintWriter(sw);
352: ObjInfo ret = finalStatementInfo;
353:
354: if (packageName != null && !packageName.equals("")) {
355: pw.println("package " + packageName + ";");
356: pw.println();
357: }
358:
359: if (imports.size() > 0) {
360: for (int i = 0; i < imports.size(); i++) {
361: pw.println("import " + imports.elementAt(i) + ";");
362: }
363:
364: pw.println();
365: }
366:
367: pw
368: .println("public class "
369: + className
370: + (extendsName != null
371: && !extendsName.equals("") ? " extends "
372: + extendsName
373: : "")
374: + (implements Vector.size() > 0 ? " implements "
375: + StringUtils
376: .getCommaListFromVector(implements Vector)
377: : ""));
378: pw.println("{");
379:
380: pw.print(getFieldBuffer().toString());
381:
382: StringBuffer buf = getInitializerBuffer();
383:
384: if (buf.length() > 0) {
385: pw.println();
386: pw.println("{");
387: pw.print(buf.toString());
388: pw.println("}");
389: }
390:
391: buf = getConstructorBuffer();
392:
393: if (buf.length() > 0) {
394: pw.println();
395: pw
396: .println("public "
397: + className
398: + "("
399: + (constructorArguments.size() > 0 ? StringUtils
400: .getCommaListFromVector(constructorArguments)
401: : "")
402: + ")"
403: + (constructorExceptions.size() > 0 ? " throws "
404: + StringUtils
405: .getCommaListFromVector(constructorExceptions)
406: : ""));
407: pw.println("{");
408: pw.print(buf.toString());
409: pw.println("}");
410: }
411:
412: buf = getServiceMethodBuffer();
413:
414: if (buf.length() > 0 || ret != null) {
415: pw.println();
416: pw
417: .println("public "
418: + StringUtils
419: .getClassName(getServiceMethodReturnType())
420: + " "
421: + serviceMethodName
422: + "()"
423: + (serviceMethodExceptions.size() > 0 ? " throws "
424: + StringUtils
425: .getCommaListFromVector(serviceMethodExceptions)
426: : ""));
427: pw.println("{");
428:
429: pw.print(buf.toString());
430:
431: if (ret != null) {
432: if (ret.isValueReturning()) {
433: pw.println();
434: pw.println("return " + ret.objName + ";");
435: } else if (ret.isExecutable()) {
436: pw.println(ret.objName + ";");
437: }
438: }
439:
440: pw.println("}");
441: }
442:
443: pw.print(getMethodBuffer().toString());
444:
445: pw.println("}");
446:
447: pw.flush();
448:
449: return sw.toString();
450: }
451: }
|