001: /*
002: * sqlc 1
003: * SQL Compiler
004: * Copyright (C) 2003 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz/products/sqlc/index.html
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.codegen;
024:
025: import java.util.ArrayList;
026: import java.util.Collection;
027: import java.util.HashSet;
028: import java.util.Iterator;
029: import java.util.Properties;
030: import java.util.Set;
031:
032: import org.apache.bcel.Constants;
033: import org.apache.bcel.classfile.Utility;
034: import org.apache.bcel.generic.ClassGen;
035: import org.apache.bcel.generic.InstructionList;
036: import org.apache.bcel.generic.MethodGen;
037: import org.apache.bcel.generic.Type;
038:
039: import biz.hammurapi.codegen.JavaTokenTypes;
040:
041: import antlr.collections.AST;
042: import biz.hammurapi.util.Parameter;
043:
044: /**
045: * @author Pavel Vlasov
046: * @version $Revision: 1.7 $
047: */
048: public class Interface extends ClassGeneratorBase {
049:
050: /**
051: * Constructor
052: * @param definition E.g. <CODE>public interface C extends a.b.A, a.b.c.d.B</CODE> Superinterfaces names shall be fully qualified.
053: * @param description
054: * @param listener
055: * @throws GenerationException
056: */
057: public Interface(String definition, String description,
058: GenerationListener listener) throws GenerationException {
059: this .listener = listener;
060: AST ast = typeDefinition(definition);
061: if (ast == null) {
062: throw new GenerationException("Cannot parse definition: "
063: + definition);
064: }
065:
066: if (ast.getType() == JavaTokenTypes.INTERFACE_DEF) {
067: Set modifiers = new HashSet();
068: String name = null;
069: Collection super Interfaces = new ArrayList();
070: for (AST node = ast.getFirstChild(); node != null; node = node
071: .getNextSibling()) {
072: switch (node.getType()) {
073: case JavaTokenTypes.MODIFIERS:
074: for (AST child = node.getFirstChild(); child != null; child = child
075: .getNextSibling()) {
076: modifiers.add(child.getText());
077: }
078: break;
079: case JavaTokenTypes.IDENT:
080: name = node.getText();
081: break;
082: case JavaTokenTypes.DOT:
083: name = toString(node);
084: break;
085: case JavaTokenTypes.EXTENDS_CLAUSE:
086: for (AST interfaceNode = node.getFirstChild(); interfaceNode != null; interfaceNode = interfaceNode
087: .getNextSibling()) {
088: super Interfaces.add(toString(interfaceNode));
089: }
090: break;
091: default:
092: throw new GenerationException("Unexpected node: "
093: + node);
094: }
095: }
096:
097: cg = new ClassGen(
098: name,
099: "java.lang.Object",
100: description == null ? "<generated>" : description,
101: modifiers(modifiers) | Constants.ACC_INTERFACE,
102: (String[]) super Interfaces
103: .toArray(new String[super Interfaces.size()]));
104:
105: if (listener != null) {
106: listener.onClass(cg, description);
107: }
108: } else {
109: throw new GenerationException("Invalid node type "
110: + ast.getType() + " in definition '" + definition
111: + "'");
112: }
113: }
114:
115: /**
116: *
117: * @param definition E.g. <CODE>public void setX(int x)</CODE> All types shall be fully qualified.
118: * @param parameters Collection of {@link biz.hammurapi.util.Parameter} Parameters to be appended to parameters in definition. Can be null.
119: * @param description
120: * @return
121: * @throws GenerationException
122: */
123: public MethodGen addMethod(String definition,
124: Collection parameters, String description,
125: Properties attributes) throws GenerationException {
126: AST ast = field(definition);
127: if (ast.getType() == JavaTokenTypes.METHOD_DEF) {
128: Set modifiers = new HashSet();
129: String name = null;
130: String returnType = null;
131: Collection throwsList = new ArrayList();
132: Collection allParameters = new ArrayList();
133: class ParameterImpl implements Parameter {
134:
135: private String type;
136: private String name;
137:
138: ParameterImpl(String name, String type) {
139: this .name = name;
140: this .type = type;
141: }
142:
143: public String getName() {
144: return name;
145: }
146:
147: public String getType() {
148: return type;
149: }
150:
151: }
152:
153: for (AST node = ast.getFirstChild(); node != null; node = node
154: .getNextSibling()) {
155: switch (node.getType()) {
156: case JavaTokenTypes.MODIFIERS:
157: for (AST child = node.getFirstChild(); child != null; child = child
158: .getNextSibling()) {
159: modifiers.add(child.getText());
160: }
161: break;
162: case JavaTokenTypes.IDENT:
163: case JavaTokenTypes.INIT:
164: name = node.getText();
165: break;
166: case JavaTokenTypes.TYPE:
167: returnType = toString(node.getFirstChild());
168: break;
169: case JavaTokenTypes.PARAMETERS:
170: for (AST pnode = node.getFirstChild(); pnode != null; pnode = pnode
171: .getNextSibling()) {
172: for (AST ppnode = pnode.getFirstChild(); ppnode != null; ppnode = pnode
173: .getNextSibling()) {
174: String pname = null;
175: String ptype = null;
176: switch (ppnode.getType()) {
177: case JavaTokenTypes.IDENT:
178: pname = node.getText();
179: break;
180: case JavaTokenTypes.TYPE:
181: ptype = toString(ppnode.getFirstChild());
182: break;
183: default:
184: throw new GenerationException(
185: "Unexpected node: "
186: + ppnode.getText());
187: }
188: allParameters.add(new ParameterImpl(pname,
189: ptype));
190: }
191: }
192: break;
193: case JavaTokenTypes.LITERAL_throws:
194: for (AST tnode = node.getFirstChild(); tnode != null; tnode = tnode
195: .getNextSibling()) {
196: throwsList.add(toString(tnode));
197: }
198: break;
199:
200: default:
201: throw new GenerationException("Unexpected node: "
202: + node);
203: }
204: }
205:
206: if (parameters != null) {
207: allParameters.addAll(parameters);
208: }
209:
210: Collection signature = new ArrayList();
211: signature.add(name);
212: Iterator pit = allParameters.iterator();
213: while (pit.hasNext()) {
214: signature.add(((Parameter) pit.next()).getType());
215: }
216:
217: if (checkMethod(signature, returnType, throwsList)) {
218: Type[] args = new Type[allParameters.size()];
219: String[] argNames = new String[args.length];
220: pit = allParameters.iterator();
221: for (int i = 0; pit.hasNext(); i++) {
222: Parameter p = (Parameter) pit.next();
223: args[i] = Type.getType(Utility.getSignature(p
224: .getType()));
225: argNames[i] = p.getName();
226: }
227:
228: InstructionList emptyInstructionList = new InstructionList();
229: MethodGen mg = new MethodGen(
230: Constants.ACC_PUBLIC | Constants.ACC_ABSTRACT
231: | modifiers(modifiers),
232: java2BcelType(returnType), args, argNames,
233: name, cg.getClassName(), emptyInstructionList,
234: cg.getConstantPool());
235:
236: Iterator thit = throwsList.iterator();
237: while (thit.hasNext()) {
238: mg.addException((String) thit.next());
239: }
240:
241: cg.addMethod(mg.getMethod());
242:
243: emptyInstructionList.dispose();
244:
245: if (listener != null
246: && (cg.isPublic() || cg.isProtected())) {
247: listener.onMethod(cg.getClassName(), mg.toString(),
248: description, attributes);
249: }
250:
251: return mg;
252: }
253: return null;
254: }
255: throw new GenerationException("Invalid node type "
256: + ast.getType() + " in definition '" + definition + "'");
257: }
258:
259: /**
260: * Creates a public static final field of specified name and type.
261: * @param name
262: * @param type
263: * @param description
264: * @param attributes
265: * @throws GenerationException
266: */
267: public void addField(String name, String type, String description,
268: Properties attributes) throws GenerationException {
269: addField("public static final " + type + " " + name,
270: description, attributes);
271: }
272: }
|