KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > tools > OPP > srcgen > builder > FactoryBuilder


1 // You can redistribute this software and/or modify it under the terms of
2
// the Ozone Library License version 1 published by ozone-db.org.
3
//
4
// The original code and portions created by SMB are
5
// Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
6
//
7
// $Id$
8
package org.ozoneDB.tools.OPP.srcgen.builder;
9
10 import org.ozoneDB.tools.OPP.OPPHelper;
11 import org.ozoneDB.tools.OPP.message.MessageWriter;
12 import org.ozoneDB.tools.OPP.srcgen.ClassBuilder;
13 import org.ozoneDB.tools.OPP.srcgen.BuilderException;
14 import org.ozoneDB.tools.OPP.srcgen.streamfactory.OutputStreamFactory;
15
16 import java.io.*;
17 import java.lang.reflect.Modifier JavaDoc;
18
19 /**
20  * Most of the code was lifted out of the FactoryGenerator written by
21  * Leo Mekenkamp. The FactoryGenerator was in turn based on the ProxyGenerator
22  *
23  * The FactoryBuilder is in fact half of the FactoryGenerate, the
24  * generating part. The rest of the FactoryGenerator had to do with
25  * browsing a class for constructors etc. That part is moved to a
26  * director, thus separating concerns.
27  *
28  * @author <a HREF="http://www.softwarebuero.de/">SMB</a>
29  * @author <a HREF="http://www.medium.net/">Medium.net</a>
30  * @author Per Nyfelt
31  * @author <a HREF="mailto://ozone-db.orgATmekenkampD0Tcom">Leo Mekenkamp</a>
32  * @author Joakim Ohlrogge
33  */

34 public class FactoryBuilder implements ClassBuilder {
35     private OutputStreamFactory outputFactory;
36     private String JavaDoc postfix;
37     private PrintWriter out = null;
38     private String JavaDoc[] interfaces;
39     private MessageWriter msgWriter;
40
41     public FactoryBuilder(OutputStreamFactory outputFactory, String JavaDoc postfix) {
42         this.outputFactory = outputFactory;
43         this.postfix = postfix;
44     }
45
46     private void makeCreateInternal(String JavaDoc implementationClass, String JavaDoc type) {
47         out.println(" private " + type + " createInternal(OzonePersonalMetaData personalMeta, OzoneSharedMetaData sharedMeta, Class[] ctorArgTypes, Object[] ctorArgs) throws Exception {");
48         out.println(" String name = null;");
49         out.println(" int access = OzoneInterface.Public;");
50         out.println(" if (personalMeta != null) {");
51         out.println(" name = personalMeta.getName();");
52         out.println(" }");
53         out.println(" if (sharedMeta != null) {");
54         out.println(" access = sharedMeta.getAccess();");
55         out.println(" }");
56         out.println(" return (" + type + ") getDatabase().createObject(" + implementationClass + ".class, access, name, ctorArgTypes, ctorArgs);");
57         out.println(" }\n");
58     }
59
60     private void makeGlobalHeader(String JavaDoc implementationClass) {
61         out.println("// Factory class generated by ozone's OPP ($Revision$).");
62         out.println("// DO NOT EDIT!\n");
63         if (!OPPHelper.packageName(implementationClass).equals("")) {
64             out.println("package " + OPPHelper.packageName(implementationClass) + ";\n");
65         }
66         out.println("import org.ozoneDB.AbstractFactory;");
67         out.println("import org.ozoneDB.OzonePersonalMetaData;");
68         out.println("import org.ozoneDB.OzoneSharedMetaData;");
69         out.println("import org.ozoneDB.OzoneInterface;");
70         out.println("import org.ozoneDB.OzoneInternalException;");
71         out.println("import org.ozoneDB.OzoneProxy;");
72         out.println("import org.ozoneDB.tools.OPP.OPP;\n");
73     }
74
75     private void makeLocalHeader(String JavaDoc simpleClassName) {
76         out.println("/**");
77         out.println(" * <p>This class is generated by OPP. DO NOT EDIT, for it will be overwritten");
78         out.println(" * the next time OPP is run for <code>" + simpleClassName + "</code>.</p>");
79         out.println(" * <p>Factory pattern class for creating ozone objects.</p>");
80         out.println(" * A factory has a bit of a schizophrenic nature: on the client-side it 'links'");
81         out.println(" * to an ExternalDatabase, while on the server-side it does so to the Database");
82         out.println(" * that holds the instances that the factory creates. Note however that a");
83         out.println(" * factory running inside an Ozone server can also be linked to an External");
84         out.println(" * database outside that server (userclient -> server A -> server B). In that");
85         out.println(" * case such a factory would be 'linked' to an ExternalDatabase.</p>");
86         out.println(" * <p>The idea behind factories is threefold:<ul>\n");
87         out.println(" * <li>provide an abstraction from Ozone specific object creation</li>");
88         out.println(" * <li>facilitate creating objects with non-default constructors</li>");
89         out.println(" * <li>provide (almost) the same interface on the server side and the client");
90         out.println(" * side on object creation</li></ul>");
91         out.println(" * The differences in client side and server side operation are:<ul>");
92         out.println(" * <li>on the server side <code>getDefault()</code> returns a factory that is");
93         out.println(" * creates its objects inside that same server database and on the client side");
94         out.println(" * it returns a factory that creates its objects in the default database</li>");
95         out.println(" * <li>In order to use <code>getDefault()<code> on the client side, you need to");
96         out.println(" * call <code>setDefaultDatabaseUrl(String)</code> to specify the default");
97         out.println(" * database.</li>");
98         out.println(" * In a typical real-world scenario where you connect to only one ozone database");
99         out.println(" * you would call <code>setDefaultDatabaseUrl(String)</code> on the client only");
100         out.println(" * once, and for the rest of the programs lifespan call");
101         out.println(" * <code>" + simpleClassName + ".getDefault().create()</code> methods both on the server and");
102         out.println(" * client sides to create objects.</p>");
103         out.println(" * <p>Note: if you do not have a clue what factories are and how they work, you");
104         out.println(" * should probably brush up on your knowledge of");
105         out.println(" * <a HREF=\"http://www.google.com/search?q=java+design+patterns+GoF\">design patterns</a></p>.");
106         out.println(" * @author <a HREF=\"mailto://ozone-db.orgATmekenkampD0Tcom\">Leo Mekenkamp</a>");
107         out.println(" * @since FIXME(since when?)");
108         out.println(" */\n");
109         out.println("public final class " + simpleClassName + " extends AbstractFactory {\n");
110         out.println(" private static class Info implements org.ozoneDB.FactoryClassInfo {");
111         out.println(" public final void defaultDatabaseUrlChanged() {");
112         out.println(" defaultInstance = null;");
113         out.println(" }");
114         out.println(" }\n");
115         out.println(" static {");
116         out.println(" addFactoryClassInfo(new Info());");
117         out.println(" }\n");
118         out.println(" private static " + simpleClassName + " defaultInstance = null;\n");
119         out.println(" /**");
120         out.println(" * On the client side: returns a factory that is linked to a database");
121         out.println(" * specified by the url passed to <code>setDefaultDatabaseUrl</code>. On the");
122         out.println(" * server side: returns a factory that is linked to the server database.");
123         out.println(" * Note that multiple calls to this method return the same value over and");
124         out.println(" * over again, until <code>setDefaultDatabaseUrl</code> has been called.");
125         out.println(" */");
126         out.println(" public static synchronized " + simpleClassName + " getDefault() throws Exception {");
127         out.println(" if (defaultInstance == null) {");
128         out.println(" defaultInstance = new " + simpleClassName + "();");
129         out.println(" }");
130         out.println(" return defaultInstance;");
131         out.println(" }\n");
132         // constructors
133
out.println(" /**");
134         out.println(" * <p>Default constructor: creates a factory that is liked to the default");
135         out.println(" * database.</p>");
136         out.println(" */");
137         out.println(" public " + simpleClassName + "() throws Exception {");
138         out.println(" }\n");
139         out.println(" /** <p>Creates a factory that creates its objects in the database specified by");
140         out.println(" * <code>url</code>. Note that this constructor can only be used if the database in");
141         out.println(" * question is not opened by this client. Use <code>" + simpleClassName + "()</code> or");
142         out.println(" * <code>" + simpleClassName + "(Factory)</code> to create a factory for an already opened");
143         out.println(" * database. This might seem strange, or even annoying at first, but it is very");
144         out.println(" * logical from an object oriented point of view: you probably want a factory that");
145         out.println(" * creates its objects in the default database, or in the same realm as another");
146         out.println(" * factory you already have created...</p>");
147         out.println(" * @param databaseUrl url defining the remote database (something like");
148         out.println(" * <code>ozone:remote://localhost:3333</code>)");
149         out.println(" */");
150         out.println(" public " + simpleClassName + "(String databaseUrl) throws Exception {");
151         out.println(" super(databaseUrl);");
152         out.println(" }\n");
153         out.println(" /** <p>Creates a factory that creates its objects in the same database as a specific");
154         out.println(" * other fatory does.</p>");
155         out.println(" * @param factory the factory that creates its objects in the same database as the new factory");
156         out.println(" * should");
157         out.println(" */");
158         out.println(" public " + simpleClassName + "(AbstractFactory factory) {");
159         out.println(" super(factory);");
160         out.println(" }\n");
161         out.println(" /**");
162         out.println(" * Gets called automatically to indicate that the default database has been");
163         out.println(" * closed. DO NOT CALL THIS METHOD YOURSELF.");
164         out.println(" */");
165         out.println(" protected void defaultClosed() {");
166         out.println(" defaultInstance = null;");
167         out.println(" }\n");
168     }
169
170     private void makeObjectForHandle(String JavaDoc type) {
171         out.println(" /**");
172         out.println(" * <p>Retrieves an object through its handle. <emp>Do not use this function");
173         out.println(" * unless you are perfectly sure about what you are doing</emp>. See the");
174         out.println(" * examples for some hands-on information on when to use handles. Note that");
175         out.println(" * normally one would use names or just standard java object references.</p>");
176         out.println(" */");
177         out.println(" public " + type + " objectForHandle(String handle) throws Exception {");
178         out.println(" return (" + type + ") getDatabase().objectForHandle(handle);");
179         out.println(" }\n");
180     }
181
182     private void makeObjectForName(String JavaDoc type) {
183         out.println(" /**");
184         out.println(" * <p>Retrieves an object from the database through its name.</p>");
185         out.println(" */");
186         out.println(" public " + type + " objectForName(String name) throws Exception {");
187         out.println(" return (" + type + ") getDatabase().objectForName(name);");
188         out.println(" }\n");
189     }
190
191     public void init(MessageWriter msgWriter) {
192         this.msgWriter = msgWriter;
193     }
194
195     public void beginClass(int modifer, String JavaDoc fullName, String JavaDoc superClass, String JavaDoc interfaces[]) throws BuilderException {
196         msgWriter.startGeneration("Generating factory for: " + fullName);
197         this.interfaces = interfaces;
198         try {
199             out = new PrintWriter(outputFactory.newInstance(fullName + postfix));
200         } catch (IOException e) {
201             throw new BuilderException(e);
202         }
203         makeGlobalHeader(fullName);
204         makeLocalHeader(OPPHelper.simpleClassName(fullName) + postfix);
205         makeObjectForHandle(interfaces[0]);
206         makeObjectForName(interfaces[0]);
207         makeCreateInternal(fullName, interfaces[0]);
208     }
209
210     public void makeConstructor(int modifier, ClassBuilder.Parameter parameters[], String JavaDoc exceptions[]) throws BuilderException {
211         // The original factory srcgen returned instantly when the modifier was private
212
// or protected but generated constructors for public and "package" encapsulation
213
// level.
214
// Since "package" is actually more restrictive than is protected I reconed that
215
// this was simply overlooked in the original factory srcgen thus now only private
216
// causes make method to return instantly.
217
if (Modifier.isPrivate(modifier)) {
218             return;
219         }
220         String JavaDoc mod;
221         // This is not foolproof since the modifier can contain other keywords than
222
// the different protectionlevels. However in the constructor context we can assume
223
// that the modifier is valid can't we?
224
mod = Modifier.toString(modifier);
225         StringBuffer JavaDoc ctorHeader = new StringBuffer JavaDoc();
226         StringBuffer JavaDoc ctorArgTypes = new StringBuffer JavaDoc();
227         StringBuffer JavaDoc ctorArgs = new StringBuffer JavaDoc();
228         for (int i = 0; i < parameters.length; ++i) {
229             String JavaDoc paramType = parameters[i].getType();
230             if (ctorArgTypes.length() > 0) {
231                 ctorArgTypes.append(", ");
232                 ctorHeader.append(", ");
233                 ctorArgs.append(", ");
234             }
235             ctorArgTypes.append(paramType).append(".class");
236             ctorHeader.append(paramType).append(" p").append(i);
237             if (OPPHelper.isPrimitive(paramType)) {
238                 ctorArgs.append("new ").append(OPPHelper.wrappercodeForPrimitive(paramType)).append("(");
239             }
240             ctorArgs.append("p").append(i);
241             if (OPPHelper.isPrimitive(paramType)) {
242                 ctorArgs.append(")");
243             }
244         }
245         out.println(" /**");
246         out.println(" * <p>Creates a new database object</p>");
247         out.println(" */");
248         out.println(" " + mod + " " + interfaces[0] + " create(" + ctorHeader + ") throws Exception {");
249         if (ctorArgTypes.length() == 0) {
250             out.println(" Class[] ctorArgTypes = null;");
251             out.println(" Object[] ctorArgs = null;");
252         } else {
253             out.println(" Class[] ctorArgTypes = new Class[] {" + ctorArgTypes + "};");
254             out.println(" Object[] ctorArgs = new Object[] {" + ctorArgs + "};");
255         }
256         out.println(" return createInternal(null, null, ctorArgTypes, ctorArgs);");
257         out.println(" }\n");
258         // with metadata
259
if (ctorHeader.length() > 0) {
260             ctorHeader.insert(0, ", ");
261         }
262         out.println(" /**");
263         out.println(" * <p>Creates a new database object with given metadata</p>");
264         out.println(" */");
265         out.println(" " + mod + " " + interfaces[0] + " create(OzonePersonalMetaData personalMeta, OzoneSharedMetaData sharedMeta" + ctorHeader + ") throws Exception {");
266         if (ctorArgTypes.length() == 0) {
267             out.println(" Class[] ctorArgTypes = null;");
268             out.println(" Object[] ctorArgs = null;");
269         } else {
270             out.println(" Class[] ctorArgTypes = new Class[] {" + ctorArgTypes + "};");
271             out.println(" Object[] ctorArgs = new Object[] {" + ctorArgs + "};");
272         }
273         out.println(" return createInternal(personalMeta, sharedMeta, ctorArgTypes, ctorArgs);");
274         out.println(" }\n");
275     }
276
277     public void makeMethod(int modifier, String JavaDoc name, ClassBuilder.Parameter parameters[], String JavaDoc returnType, String JavaDoc exceptions[], int lockLevel) throws BuilderException {
278     }
279
280     public void endClass() throws BuilderException {
281         out.println("}");
282         out.close();
283         msgWriter.endGeneration();
284     }
285 }
286
Popular Tags