1 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 ; 18 19 34 public class FactoryBuilder implements ClassBuilder { 35 private OutputStreamFactory outputFactory; 36 private String postfix; 37 private PrintWriter out = null; 38 private String [] interfaces; 39 private MessageWriter msgWriter; 40 41 public FactoryBuilder(OutputStreamFactory outputFactory, String postfix) { 42 this.outputFactory = outputFactory; 43 this.postfix = postfix; 44 } 45 46 private void makeCreateInternal(String implementationClass, String 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 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 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 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 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 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 fullName, String superClass, String 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 exceptions[]) throws BuilderException { 211 if (Modifier.isPrivate(modifier)) { 218 return; 219 } 220 String mod; 221 mod = Modifier.toString(modifier); 225 StringBuffer ctorHeader = new StringBuffer (); 226 StringBuffer ctorArgTypes = new StringBuffer (); 227 StringBuffer ctorArgs = new StringBuffer (); 228 for (int i = 0; i < parameters.length; ++i) { 229 String 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 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 name, ClassBuilder.Parameter parameters[], String returnType, String 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 |