1 package pl.aislib.tools.mapping.generators;
2
3 import java.io.File;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 import java.io.Writer;
7 import java.util.Collections;
8 import java.util.HashMap;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Set;
13 import java.util.TreeSet;
14
15 import pl.aislib.tools.mapping.Generator;
16 import pl.aislib.tools.mapping.structure.Field;
17 import pl.aislib.tools.mapping.structure.JavaClass;
18 import pl.aislib.tools.mapping.structure.JavaField;
19 import pl.aislib.tools.mapping.structure.Structure;
20
21 /***
22 * <code>BaseX.java</code> generator.
23 *
24 * @author Milosz Tylenda, AIS.PL (milosz@ais.pl)
25 * $Revision: 1.16 $
26 */
27 public class BeanGenerator extends Generator {
28
29 /*** Mapping: short name to full class name. */
30 private static final Map LONG_CLASS_NAMES = new HashMap(3);
31
32 static {
33 LONG_CLASS_NAMES.put("BigDecimal", "java.math.BigDecimal");
34 LONG_CLASS_NAMES.put("Timestamp", "java.sql.Timestamp");
35 LONG_CLASS_NAMES.put("Array", "java.sql.Array");
36 }
37
38 /*** List containing Field objects from Structure. */
39 private List fieldList;
40
41 /*** Buffer to store content of a generated file. */
42 private StringBuffer fileContent;
43
44 /*** Whether to generate support for PropertyChange? */
45 private boolean propertyChangeSupport;
46
47 private File initDirectory(File destinationDir) throws IOException {
48 File objectsDir = new File(destinationDir.getPath() + File.separator + objectsSubdir);
49 if (!objectsDir.exists()) {
50 objectsDir.mkdirs();
51 }
52 File baseDir = new File(objectsDir.getPath() + File.separator + "base");
53 if (!baseDir.exists()) {
54 baseDir.mkdirs();
55 }
56 return baseDir;
57 }
58
59 private Writer initWriter(String className, File baseDir) throws IOException {
60 return new FileWriter(baseDir.getPath() + File.separator + "Base" + className + ".java");
61 }
62
63 public void generate() throws IOException {
64 File baseDir = initDirectory(destinationDir);
65 List structureList = database.getStructureList();
66 for (int i = 0, size = structureList.size() ; i < size ; i++) {
67 Structure structure = (Structure) structureList.get(i);
68
69 fileContent = new StringBuffer(4096);
70 fieldList = structure.getFields().getFieldList();
71 Collections.sort(fieldList);
72 propertyChangeSupport = structure.getJavaClass().isPropertyChangeSupport();
73
74 JavaClass javaClass = structure.getJavaClass();
75 putPackage();
76 putImports();
77 putClassJavadoc(structure);
78 putClassBegin(javaClass);
79 putProperties();
80 putGetSet();
81 putPropertyChangeCode();
82 putToString(structure);
83 putClassEnd();
84
85 Writer writer = initWriter(javaClass.getName(), baseDir);
86 writer.write(fileContent.toString());
87 writer.close();
88 }
89 log(structureList.size() + " BaseX class(es) generated");
90 }
91
92 private void putPackage() {
93 write("package " + packageName + "." + objectsSubpackage + ".base;\n\n");
94 }
95
96 private void putImports() {
97 Set usedClasses = new TreeSet();
98 usedClasses.add("java.io.Serializable");
99 if (propertyChangeSupport) {
100 usedClasses.add("java.beans.PropertyChangeSupport");
101 usedClasses.add("java.beans.PropertyChangeListener");
102 }
103
104 for (int i = 0, size = fieldList.size() ; i < size ; i++) {
105 Field field = (Field) fieldList.get(i);
106 JavaField javaField = field.getJavaField();
107 String type = javaField.getType();
108 String longName = (String) LONG_CLASS_NAMES.get(type);
109 if (longName != null) {
110 usedClasses.add(longName);
111 }
112 }
113
114 for (Iterator iter = usedClasses.iterator() ; iter.hasNext() ; ) {
115 String longName = (String) iter.next();
116 write("import " + longName + ";\n");
117 }
118 write("\n");
119 }
120
121 private void putClassJavadoc(Structure structure) {
122 String className = structure.getJavaClass().getName();
123 String pcSupport = "";
124 if (propertyChangeSupport) {
125 pcSupport =", with PropertyChange support";
126 }
127 write("/**\n");
128 write(" * Counterpart of <code>" + structure.getName() + "</code> structure" + pcSupport + ".\n");
129 write(" * This class was generated by BeanGenerator.<br><br>\n");
130 write(" * <table border=\"1\">\n");
131 write(" * <caption>Base" + className + " fields</caption>\n");
132 write(" * <tr>\n");
133 write(" * <th>Java name</th><th>Java type</th>");
134 write("<th>Java default</th><th>Structure field name</th><th>SQL column</th>\n");
135 write(" * </tr>\n");
136 for (int i = 0, size = fieldList.size() ; i < size ; i++) {
137 Field field = (Field) fieldList.get(i);
138 if (field.isPrimaryKey()) {
139 write(" * <tr bgcolor=\"#00FF00\">\n");
140 } else {
141 write(" * <tr>\n");
142 }
143 write(" * <td>" + field.getJavaField().getName() + "</td>\n");
144 write(" * <td><code>" + field.getJavaField().getType() + "</code></td>\n");
145 write(" * <td>" + field.getJavaField().getDefault() + " </td>\n");
146 write(" * <td>" + field.getName() + "</td>\n");
147 write(" * <td>" + field.getSqlField().getName() + "</td>\n");
148 write(" * </tr>\n");
149 }
150 write(" * </table>\n");
151 write(" * @author BeanGenerator\n");
152 write(" */\n");
153 }
154
155 private void putClassBegin(JavaClass javaClass) {
156 write("public abstract class Base" + javaClass.getName() + " implements Serializable {\n\n");
157 }
158
159 private void putProperties() {
160 for (int i = 0, size = fieldList.size() ; i < size ; i++) {
161 Field field = (Field) fieldList.get(i);
162 JavaField javaField = field.getJavaField();
163 String type = javaField.getType();
164 String name = javaField.getName();
165 String defaultt = javaField.getDefault();
166 write(" private " + type + " " + name);
167 if (defaultt.length() > 0) {
168 write(" = ");
169 if (type.equals("String")) {
170 write("\"" + defaultt + "\"");
171 } else if (type.equals("BigDecimal")) {
172 write("new " + type + "(\"" + defaultt + "\")");
173 } else {
174 write("new " + type + "(" + defaultt + ")");
175 }
176 }
177 write(";\n");
178 }
179 write("\n");
180 }
181
182 private void putGetSet() {
183 for (int i = 0, size = fieldList.size() ; i < size ; i++) {
184 Field field = (Field) fieldList.get(i);
185 JavaField javaField = field.getJavaField();
186 String type = javaField.getType();
187 String name = javaField.getName();
188 String fieldName = field.getName();
189 write(" /**\n");
190 write(" * Gets the value of <code>" + fieldName + "</code> field.\n");
191 write(" * @return the value of <code>" + fieldName + "</code> field\n");
192 write(" */\n");
193 write(" public " + type + " " + Utils.getter(name) + " {\n");
194 write(" return " + name + ";\n");
195 write(" }\n\n");
196 write(" /**\n");
197 write(" * Sets the " + type + " value of <code>" + fieldName + "</code> field.\n");
198 write(" * @param _" + name + " the new value for <code>" + fieldName + "</code> field\n");
199 write(" */\n");
200 write(" public void set" + Utils.capitalize(name) + "(" + type + " _" + name + ") {\n");
201 if (propertyChangeSupport) {
202 write(" if (pcs != null) {\n");
203 write(" pcs.firePropertyChange(\"" + name + "\", " + name + ", _" + name + ");\n");
204 write(" }\n");
205 }
206 write(" " + name + " = _" + name + ";\n");
207 write(" }\n\n");
208 }
209 }
210
211 private void putToString(Structure structure) {
212 int fieldsSize = fieldList.size();
213 write(" /**\n");
214 write(" * Returns property names and values contained in this object.\n");
215 write(" * @return Property names and values contained in this object\n");
216 write(" */\n");
217 write(" public String toString() {\n");
218 write(" return \"" + structure.getName() + "\"");
219
220 if (fieldsSize > 0) {
221 write(" + \": \"");
222 }
223
224 for (int i = 0 ; i < fieldsSize ; i++) {
225 Field field = (Field) fieldList.get(i);
226 JavaField javaField = field.getJavaField();
227 String name = javaField.getName();
228 String fieldName = field.getName();
229 write(" +\n");
230 write(" \"" + fieldName + ": \" + " + name);
231 if (i < (fieldsSize - 1)) {
232 write(" + \", \"");
233 }
234 }
235 write(";\n");
236 write(" }\n\n");
237 }
238
239 private void putPropertyChangeCode() {
240 if (!propertyChangeSupport) {
241 return;
242 }
243 write(" private PropertyChangeSupport pcs;\n\n");
244 write(" /**\n");
245 write(" * Adds a PropertyChangeListener to the listener list. The listener is registered for all properties.\n");
246 write(" * @param listener the PropertyChangeListener to be added\n");
247 write(" */\n");
248 write(" public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {\n");
249 write(" if (pcs == null) {\n");
250 write(" pcs = new PropertyChangeSupport(this);\n");
251 write(" }\n");
252 write(" pcs.addPropertyChangeListener(listener);\n");
253 write(" }\n\n");
254 write(" /**\n");
255 write(" * Adds a PropertyChangeListener for a specific property.\n");
256 write(" * The listener will be invoked only when that specific property changes its value.\n");
257 write(" * @param propertyName the name of the property to listen on\n");
258 write(" * @param listener the PropertyChangeListener to be added\n");
259 write(" */\n");
260 write(" public synchronized void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {\n");
261 write(" if (pcs == null) {\n");
262 write(" pcs = new PropertyChangeSupport(this);\n");
263 write(" }\n");
264 write(" pcs.addPropertyChangeListener(propertyName, listener);\n");
265 write(" }\n\n");
266 write(" /**\n");
267 write(" * Removes a PropertyChangeListener from the listener list.\n");
268 write(" * This removes a PropertyChangeListener that was registered for all properties.\n");
269 write(" * @param listener the PropertyChangeListener to be removed\n");
270 write(" */\n");
271 write(" public void removePropertyChangeListener(PropertyChangeListener listener) {\n");
272 write(" if (pcs == null) {\n");
273 write(" return;\n");
274 write(" }\n");
275 write(" pcs.removePropertyChangeListener(listener);\n");
276 write(" }\n\n");
277 write(" /**\n");
278 write(" * Removes a PropertyChangeListener for a specific property.\n");
279 write(" * @param propertyName the name of the property that was listened on\n");
280 write(" * @param listener the PropertyChangeListener to be removed\n");
281 write(" */\n");
282 write(" public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {\n");
283 write(" if (pcs == null) {\n");
284 write(" return;\n");
285 write(" }\n");
286 write(" pcs.removePropertyChangeListener(propertyName, listener);\n");
287 write(" }\n\n");
288 write(" /**\n");
289 write(" * Checks if there are any listeners for a specific property.\n");
290 write(" * @param propertyName the property name\n");
291 write(" * @return true if there are one or more listeners for the given property\n");
292 write(" */\n");
293 write(" public boolean hasListeners(String propertyName) {\n");
294 write(" if (pcs == null) {\n");
295 write(" return false;\n");
296 write(" }\n");
297 write(" return pcs.hasListeners(propertyName);\n");
298 write(" }\n\n");
299 write(" /**\n");
300 write(" * Reports a bound property update to any registered listeners.\n");
301 write(" * No event is fired if oldValue and newValue are equal and non-null.\n");
302 write(" * @param propertyName the programmatic name of the property that was changed\n");
303 write(" * @param oldValue the old value of the property\n");
304 write(" * @param newValue the new value of the property\n");
305 write(" */\n");
306 write(" protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {\n");
307 write(" if (pcs == null) {\n");
308 write(" return;\n");
309 write(" }\n");
310 write(" pcs.firePropertyChange(propertyName, oldValue, newValue);\n");
311 write(" }\n\n");
312 }
313
314 private void putClassEnd() {
315 write("}\n");
316 }
317
318 private void write(String s) {
319 fileContent.append(s);
320 }
321
322 }
323
324 /***
325 * $Log: BeanGenerator.java,v $
326 * Revision 1.16 2004/08/11 12:41:01 wswiatek
327 * Database and map handlers location are now parametrizable.
328 * Maven plugin version changed to 1.0.1
329 *
330 * Revision 1.15 2004/01/19 14:40:45 milosz
331 * JavaField.getDefault method no longer returns null.
332 *
333 * Revision 1.14 2003/10/29 11:47:02 pikus
334 * use ant logger where possible
335 *
336 * Revision 1.13 2003/09/15 12:35:04 milosz
337 * Support for propertyChangeSupport in JavaClass added.
338 *
339 * Revision 1.12 2003/09/15 10:20:35 milosz
340 * Refactoring: Total rewrite.
341 *
342 * Revision 1.11 2003/07/11 13:08:14 milosz
343 * objectsSubpackage property added.
344 *
345 * Revision 1.10 2003/05/26 08:36:03 pikus
346 * cleanup imports
347 *
348 * Revision 1.9 2003/05/20 10:44:13 milosz
349 * Added displaying of SQL column to Javadoc.
350 *
351 * Revision 1.8 2003/02/12 10:31:31 milosz
352 * No more unspecified order of imports; imports are sorted now.
353 *
354 * Revision 1.7 2002/12/03 14:10:06 milosz
355 * JavaDoc table is sorted: primary keys first, other fields by JavaClass.name.
356 *
357 * Revision 1.6 2002/11/20 09:19:03 wswiatek
358 * Changed oracle.sql.ARRAY to java.sql.Array.
359 * Removed very funny local variable.
360 *
361 * Revision 1.5 2002/11/14 13:03:15 milosz
362 * Default values for String and BigDecimal are generated correctly.
363 *
364 * Revision 1.4 2002/10/08 08:27:10 milosz
365 * Generators became AntTasks(?). Ufff...
366 *
367 * Revision 1.3 2002/10/04 13:22:04 milosz
368 * Minor fix.
369 *
370 * Revision 1.2 2002/10/04 13:07:22 milosz
371 * Reaching old mapping's functionality.
372 *
373 */
374