View Javadoc

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++) {  // all structures
67        Structure structure = (Structure) structureList.get(i);
68  
69        fileContent    = new StringBuffer(4096);
70        fieldList      = structure.getFields().getFieldList();
71        Collections.sort(fieldList); // For better Javadoc.
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);    // open file
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"); // Use superclass' properties.
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()) {  // mark primary keys by a green background
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() + "&nbsp;</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) {            // Handle default value.
168         write(" = ");
169         if (type.equals("String")) {          // Deal with String.
170           write("\"" + defaultt + "\"");
171         } else if (type.equals("BigDecimal")) {      // Deal with BigDecimal.
172           write("new " + type + "(\"" + defaultt + "\")");
173         } else {
174           write("new " + type + "(" + defaultt + ")"); // Deal with others.
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