Source code: com/aendvari/satyr/tools/ComponentGenerator.java
1 /*
2 * ComponentGenerator.java
3 *
4 * Copyright (c) 2001, 2002 Aendvari, Ltd. All Rights Reserved.
5 *
6 * See the file LICENSE for terms of use.
7 *
8 */
9
10 package com.aendvari.satyr.tools;
11
12 import java.io.*;
13
14 import java.util.Collection;
15 import java.util.Iterator;
16
17 import com.aendvari.cerberus.component.assembly.*;
18 import com.aendvari.cerberus.component.descriptor.*;
19 import com.aendvari.cerberus.component.descriptor.parser.*;
20
21 import com.aendvari.common.model.*;
22 import com.aendvari.common.model.osm.*;
23
24 /**
25 * <p>Generates classes and message listener stubs described in assembly descriptor.</p>
26 *
27 * @author Trevor Milne
28 *
29 */
30
31 public class ComponentGenerator
32 {
33 public static void main(String args[])
34 {
35 // check parameters
36 if (args.length != 2)
37 {
38 System.err.println("usage: ComponentGenerator assembly source");
39 System.err.println();
40 System.exit(1);
41 }
42
43 // read source directory
44 File rootSource = new File(args[1]);
45
46 if (!rootSource.exists() || !rootSource.isDirectory())
47 {
48 System.err.println("Could not access '" + args[1] + "'.");
49 System.exit(1);
50 }
51
52 // get full path
53 String sourcePath = null;
54
55 try
56 {
57 sourcePath = rootSource.getCanonicalPath();
58 }
59 catch (IOException exception)
60 {
61 System.err.println("Could not determine source path.");
62 System.exit(1);
63 }
64
65 try
66 {
67 // open assembly descriptor
68 File assemblyFile = new File(args[0]);
69 FileInputStream inputStream = new FileInputStream(assemblyFile);
70
71 // parse the descriptor
72 AssemblyParser parser = new AssemblyParser();
73 AssemblyDescriptor assembly = parser.parse(inputStream);
74
75 // retrieve the definitions
76 Collection definitions = assembly.getDefinitions();
77
78 // generate classes for components
79 Iterator definitionIterator = definitions.iterator();
80
81 while (definitionIterator.hasNext())
82 {
83 ComponentDefinition definition = (ComponentDefinition)definitionIterator.next();
84
85 // generator component class
86 generateComponent(definition, sourcePath);
87 }
88 }
89 catch (IOException ioException)
90 {
91 System.err.println("Could not read '" + args[0] + "'.");
92 }
93 catch (ParserException parserException)
94 {
95 System.err.println(parserException);
96 }
97 }
98
99 /**
100 * Generates a java class file containing method stubs for the supplied component.
101 *
102 * @param definition The {@link ComponentDefinition} of the component.
103 * @param sourcePath The base directory of the java class packages.
104 *
105 * @exception IOException A I/O error occured.
106 *
107 */
108
109 protected static void generateComponent(ComponentDefinition definition, String sourcePath)
110 throws IOException
111 {
112 String definitionClass = definition.getBackingClass();
113
114 // create full class file path
115 String classPath =
116 sourcePath + File.separator +
117 definitionClass.replace('.', File.separatorChar) + ".java";
118
119 // extract class name
120 int nameIndex = definitionClass.lastIndexOf('.');
121 String className = definitionClass.substring(nameIndex + 1, definitionClass.length());
122
123 // extract package name
124 String packageName = definitionClass.substring(0, nameIndex);
125
126 // create output object
127 File outputFile = new File(classPath);
128
129 System.out.println("Generating " + definition.getBackingClass() + "...");
130
131 // check for existing output
132 if (outputFile.exists())
133 {
134 System.err.println("Class already exists, skipping.");
135 return;
136 }
137
138 // create output file
139 outputFile.createNewFile();
140
141 // create output stream
142 FileOutputStream outputStream = new FileOutputStream(outputFile);
143 PrintWriter outputWriter = new PrintWriter(outputStream);
144
145 // file header
146 outputWriter.println("/*");
147 outputWriter.print(" * ");
148 outputWriter.print(className);
149 outputWriter.println(".java");
150 outputWriter.println(" *");
151 outputWriter.println(" */");
152 outputWriter.println();
153
154 // package
155 outputWriter.print("package ");
156 outputWriter.print(packageName);
157 outputWriter.println(";");
158 outputWriter.println();
159
160 // imports
161 outputWriter.println("import com.aendvari.cerberus.component.assembly.AssembledComponent;");
162 outputWriter.println("import com.aendvari.cerberus.component.assembly.AssemblyContext;");
163 outputWriter.println();
164 outputWriter.println("import com.aendvari.cerberus.component.descriptor.ComponentDescriptor;");
165 outputWriter.println();
166 outputWriter.println("import com.aendvari.hermes.broker.*;");
167 outputWriter.println();
168
169 // generate class
170 generateClass(className, definition, outputWriter);
171
172 // end file
173 outputWriter.println();
174
175 outputWriter.flush();
176 outputStream.close();
177 }
178
179 /**
180 * Generates the java implementation.
181 *
182 * @param className The name of the class to generate.
183 * @param definition The {@link ComponentDefinition} of the component.
184 * @param outputWriter The output stream to write the java source to.
185 *
186 * @exception IOException A I/O error occured.
187 *
188 */
189
190 protected static void generateClass(String className, ComponentDefinition definition, PrintWriter outputWriter)
191 throws IOException
192 {
193 // class comment
194 outputWriter.println("/**");
195
196 if (definition.getDescription() != null)
197 {
198 outputWriter.print(" * <p>");
199 outputWriter.print(definition.getDescription());
200 outputWriter.println("</p>");
201 }
202 else
203 {
204 outputWriter.print(" * <p>Implementation of the ");
205 outputWriter.print(definition.getName());
206 outputWriter.print(" component");
207 outputWriter.println(".</p>");
208 }
209
210 outputWriter.println(" *");
211 outputWriter.print(" * @author ");
212 outputWriter.println(ComponentGenerator.class);
213 outputWriter.println(" *");
214 outputWriter.println(" */");
215 outputWriter.println();
216
217 // class definition
218 outputWriter.print("public class ");
219 outputWriter.print(className);
220 outputWriter.println(" implements AssembledComponent");
221 outputWriter.println("{");
222
223 // output attributes
224 outputWriter.println(" /** Contains the definition for this component. */");
225 outputWriter.println(" protected ComponentDescriptor descriptor;");
226 outputWriter.println();
227
228 Iterator attributeIterator = definition.getAttributes().iterator();
229
230 while (attributeIterator.hasNext())
231 {
232 ComponentAttribute attribute = (ComponentAttribute)attributeIterator.next();
233
234 // output description
235 if (attribute.getDescription() != null)
236 {
237 // output description from definition
238 outputWriter.print(" /** ");
239 outputWriter.print(attribute.getDescription());
240 outputWriter.println(" */");
241 }
242 else
243 {
244 // output default description
245 outputWriter.print(" /** Contains the value of the '");
246 outputWriter.print(attribute.getName());
247 outputWriter.println("' component attribute. */");
248 }
249
250 // output declaration
251 outputWriter.print(" protected String ");
252 outputWriter.print(attribute.getName());
253 outputWriter.println(";");
254
255 outputWriter.println();
256 }
257
258 // generate createComponent() method
259 generateCreateComponent(definition, outputWriter);
260
261 // generate message listener classes
262 Iterator messageIterator = definition.getMessages().iterator();
263
264 while (messageIterator.hasNext())
265 {
266 ComponentMessage message = (ComponentMessage)messageIterator.next();
267
268 // only subscribe to receive messages
269 if (message.getType() != ComponentMessage.Type.Receive)
270 {
271 continue;
272 }
273
274 // output space between classes
275 outputWriter.println();
276
277 // generate listener class
278 generateMessageListener(message, outputWriter);
279 }
280
281 // end class
282 outputWriter.println("}");
283 }
284
285 /**
286 * Generates the createComponent() method. Listeners and attributes are extracted.
287 *
288 * @param definition The {@link ComponentDefinition} of the component.
289 * @param outputWriter The output stream to write the java source to.
290 *
291 * @exception IOException A I/O error occured.
292 *
293 */
294
295 protected static void generateCreateComponent(ComponentDefinition definition, PrintWriter outputWriter)
296 throws IOException
297 {
298 // comment
299 outputWriter.println(" /**");
300 outputWriter.println(" * Creates the component based on the provided descriptor.");
301 outputWriter.println(" *");
302 outputWriter.println(" * @param context The {@link AssemblyContext} for this component.");
303 outputWriter.println(" * @param descriptor The {@link ComponentDescriptor} for this component.");
304 outputWriter.println(" *");
305 outputWriter.println(" */");
306 outputWriter.println();
307
308 // declaration
309 outputWriter.println(" public void createComponent(AssemblyContext context, ComponentDescriptor descriptor)");
310 outputWriter.println(" {");
311
312 // body
313
314 // message broker connection
315 outputWriter.println(" // create a connection to the message broker");
316 outputWriter.println(" MessageBrokerConnection connection = context.getMessageBroker().createConnection();");
317 outputWriter.println();
318
319 // descriptor
320 outputWriter.println(" // store the component descriptor");
321 outputWriter.println(" this.descriptor = descriptor;");
322 outputWriter.println();
323
324 // attributes
325 outputWriter.println(" // retrieve attribute values");
326
327 Iterator attributeIterator = definition.getAttributes().iterator();
328
329 while (attributeIterator.hasNext())
330 {
331 ComponentAttribute attribute = (ComponentAttribute)attributeIterator.next();
332
333 // output code
334 outputWriter.print(" ");
335 outputWriter.print(attribute.getName());
336 outputWriter.print(" = descriptor.getAttribute(\"");
337 outputWriter.print(attribute.getName());
338 outputWriter.println("\").getValue();");
339 }
340
341 outputWriter.println();
342
343 // messages
344 outputWriter.println(" // subscribe to receive message topics");
345
346 Iterator messageIterator = definition.getMessages().iterator();
347
348 while (messageIterator.hasNext())
349 {
350 ComponentMessage message = (ComponentMessage)messageIterator.next();
351
352 // only subscribe to receive messages
353 if (message.getType() != ComponentMessage.Type.Receive)
354 {
355 continue;
356 }
357
358 // create name of message listener
359 String listenerName =
360 Character.toUpperCase(message.getName().charAt(0)) +
361 message.getName().substring(1) +
362 "Listener";
363
364 // output code
365 outputWriter.print(" connection.subscribe(descriptor.getMessage(\"");
366 outputWriter.print(message.getName());
367 outputWriter.print("\").getTopic(), new ");
368 outputWriter.print(listenerName);
369 outputWriter.println("());");
370 }
371
372 // end method
373 outputWriter.println(" }");
374 }
375
376 /**
377 * Generates a message listener internal class.
378 *
379 * @param message The {@link ComponentMessage} to generate code for.
380 * @param outputWriter The output stream to write the java source to.
381 *
382 * @exception IOException A I/O error occured.
383 *
384 */
385
386 protected static void generateMessageListener(ComponentMessage message, PrintWriter outputWriter)
387 throws IOException
388 {
389 // class comment
390 outputWriter.println(" /**");
391 outputWriter.print(" * <p>");
392
393 // output description
394 if (message.getDescription() != null)
395 {
396 // output description from definition
397 outputWriter.print(message.getDescription());
398 }
399 else
400 {
401 // output default comment
402 outputWriter.print("Listens for \"");
403 outputWriter.print(message.getName());
404 outputWriter.print("\" messages.");
405 }
406
407 outputWriter.println("</p>");
408 outputWriter.println(" *");
409 outputWriter.print(" * @author ");
410 outputWriter.println(ComponentGenerator.class);
411 outputWriter.println(" *");
412 outputWriter.println(" */");
413 outputWriter.println();
414
415 // class definition
416
417 // create name of message listener
418 String listenerName =
419 Character.toUpperCase(message.getName().charAt(0)) +
420 message.getName().substring(1) +
421 "Listener";
422
423 // output declaration
424 outputWriter.print(" protected class ");
425 outputWriter.print(listenerName);
426 outputWriter.println(" implements MessageListener");
427 outputWriter.println(" {");
428
429 // output onMessage() method
430 outputWriter.println(" /**");
431 outputWriter.println(" * Receives a message from the {@link MessageBroker}.");
432 outputWriter.println(" *");
433 outputWriter.println(" * @param message The {@link Message} received.");
434 outputWriter.println(" *");
435 outputWriter.println(" */");
436 outputWriter.println();
437 outputWriter.println(" public void onMessage(Message message)");
438 outputWriter.println(" {");
439 outputWriter.println(" }");
440
441 // end class
442 outputWriter.println(" }");
443 }
444 }
445