KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mchange > v2 > codegen > bean > SimplePropertyBeanGenerator


1 /*
2  * Distributed as part of c3p0 v.0.9.1
3  *
4  * Copyright (C) 2005 Machinery For Change, Inc.
5  *
6  * Author: Steve Waldman <swaldman@mchange.com>
7  *
8  * This library is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License version 2.1, as
10  * published by the Free Software Foundation.
11  *
12  * This software is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this software; see the file LICENSE. If not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */

22
23
24 package com.mchange.v2.codegen.bean;
25
26 import java.io.*;
27 import java.util.*;
28 import com.mchange.v2.log.*;
29 import java.lang.reflect.Modifier JavaDoc;
30 import com.mchange.v1.lang.ClassUtils;
31 import com.mchange.v2.codegen.CodegenUtils;
32 import com.mchange.v2.codegen.IndentedWriter;
33
34 public class SimplePropertyBeanGenerator implements PropertyBeanGenerator
35 {
36     private final static MLogger logger = MLog.getLogger( SimplePropertyBeanGenerator.class );
37
38     private boolean inner = false;
39     private int java_version = 130; //1.3.0
40
private boolean force_unmodifiable = false;
41     private String JavaDoc generatorName = this.getClass().getName();
42
43     // helper vars for generate method
44
protected ClassInfo info;
45     protected Property[] props;
46     protected IndentedWriter iw;
47
48     protected Set generalImports;
49     protected Set specificImports;
50     protected Set interfaceNames;
51
52     protected Class JavaDoc superclassType;
53     protected List interfaceTypes;
54     protected Class JavaDoc[] propertyTypes;
55
56     protected List generatorExtensions = new ArrayList();
57
58     public synchronized void setInner( boolean inner )
59     { this.inner = inner; }
60
61     public synchronized boolean isInner()
62     { return inner; }
63
64     /**
65      * @param version a three digit number -- for example Java 1.3.1 is 131
66      */

67     public synchronized void setJavaVersion(int version)
68     { this.java_version = java_version; }
69
70     public synchronized int getJavaVersion()
71     { return java_version; }
72
73     public synchronized void setGeneratorName(String JavaDoc generatorName)
74     { this.generatorName = generatorName; }
75
76     public synchronized String JavaDoc getGeneratorName()
77     { return generatorName; }
78
79     public synchronized void setForceUnmodifiable(boolean force_unmodifiable)
80     { this.force_unmodifiable = force_unmodifiable; }
81
82     public synchronized boolean isForceUnmodifiable()
83     { return force_unmodifiable; }
84
85     public synchronized void addExtension( GeneratorExtension ext )
86     { generatorExtensions.add( ext ); }
87
88     public synchronized void removeExtension( GeneratorExtension ext )
89     { generatorExtensions.remove( ext ); }
90
91     public synchronized void generate( ClassInfo info, Property[] props, Writer w) throws IOException
92     {
93     this.info = info;
94     this.props = props;
95     Arrays.sort( props, BeangenUtils.PROPERTY_COMPARATOR );
96     this.iw = ( w instanceof IndentedWriter ? (IndentedWriter) w : new IndentedWriter(w));
97
98     this.generalImports = new TreeSet();
99     if ( info.getGeneralImports() != null )
100         generalImports.addAll( Arrays.asList( info.getGeneralImports() ) );
101
102     this.specificImports = new TreeSet();
103     if ( info.getSpecificImports() != null )
104         specificImports.addAll( Arrays.asList( info.getSpecificImports() ) );
105
106     this.interfaceNames = new TreeSet();
107     if ( info.getInterfaceNames() != null )
108         interfaceNames.addAll( Arrays.asList( info.getInterfaceNames() ) );
109
110     addInternalImports();
111     addInternalInterfaces();
112
113     resolveTypes();
114
115     if (! inner )
116         {
117         writeHeader();
118         iw.println();
119         }
120
121     writeClassDeclaration();
122     iw.println('{');
123     iw.upIndent();
124
125     writeCoreBody();
126
127     iw.downIndent();
128     iw.println('}');
129     }
130
131     protected void resolveTypes()
132     {
133     String JavaDoc[] gen = (String JavaDoc[]) generalImports.toArray( new String JavaDoc[ generalImports.size() ] );
134     String JavaDoc[] spc = (String JavaDoc[]) specificImports.toArray( new String JavaDoc[ specificImports.size() ] );
135
136     if ( info.getSuperclassName() != null )
137         {
138         try
139             { superclassType = ClassUtils.forName( info.getSuperclassName(), gen, spc ); }
140         catch ( Exception JavaDoc e )
141             {
142 // System.err.println("WARNING: " + this.getClass().getName() + " could not resolve " +
143
// "superclass '" + info.getSuperclassName() + "'.");
144
if ( logger.isLoggable( MLevel.WARNING ) )
145                 logger.warning(this.getClass().getName() + " could not resolve superclass '" + info.getSuperclassName() + "'.");
146
147             superclassType = null;
148             }
149         }
150
151     interfaceTypes = new ArrayList( interfaceNames.size() );
152     for ( Iterator ii = interfaceNames.iterator(); ii.hasNext(); )
153         {
154         String JavaDoc name = (String JavaDoc) ii.next();
155         try
156             { interfaceTypes.add( ClassUtils.forName( name , gen, spc ) ); }
157         catch ( Exception JavaDoc e )
158             {
159 // System.err.println("WARNING: " + this.getClass().getName() + " could not resolve " +
160
// "interface '" + name + "'.");
161

162             if ( logger.isLoggable( MLevel.WARNING ) )
163                 logger.warning(this.getClass().getName() + " could not resolve interface '" + name + "'.");
164
165             interfaceTypes.add( null );
166             }
167         }
168
169     propertyTypes = new Class JavaDoc[ props.length ];
170     for ( int i = 0, len = props.length; i < len; ++i )
171         {
172         String JavaDoc name = props[i].getSimpleTypeName();
173         try
174             { propertyTypes[i] = ClassUtils.forName( name , gen, spc ); }
175         catch ( Exception JavaDoc e )
176             {
177 // e.printStackTrace();
178
// System.err.println("WARNING: " + this.getClass().getName() + " could not resolve " +
179
// "property type '" + name + "'.");
180

181             if ( logger.isLoggable( MLevel.WARNING ) )
182                 logger.log( MLevel.WARNING, this.getClass().getName() + " could not resolve property type '" + name + "'.", e);
183
184             propertyTypes[i] = null;
185             }
186         }
187     }
188
189     protected void addInternalImports()
190     {
191     if (boundProperties())
192         {
193         specificImports.add("java.beans.PropertyChangeEvent");
194         specificImports.add("java.beans.PropertyChangeSupport");
195         specificImports.add("java.beans.PropertyChangeListener");
196         }
197     if (constrainedProperties())
198         {
199         specificImports.add("java.beans.PropertyChangeEvent");
200         specificImports.add("java.beans.PropertyVetoException");
201         specificImports.add("java.beans.VetoableChangeSupport");
202         specificImports.add("java.beans.VetoableChangeListener");
203         }
204
205     for (Iterator ii = generatorExtensions.iterator(); ii.hasNext(); )
206         {
207         GeneratorExtension ge = (GeneratorExtension) ii.next();
208         specificImports.addAll( ge.extraSpecificImports() );
209         generalImports.addAll( ge.extraGeneralImports() );
210         }
211     }
212
213     protected void addInternalInterfaces()
214     {
215     for (Iterator ii = generatorExtensions.iterator(); ii.hasNext(); )
216         {
217         GeneratorExtension ge = (GeneratorExtension) ii.next();
218         interfaceNames.addAll( ge.extraInterfaceNames() );
219         }
220     }
221
222     protected void writeCoreBody() throws IOException
223     {
224     writeJavaBeansChangeSupport();
225     writePropertyVariables();
226     writeOtherVariables();
227     iw.println();
228
229     writeGetterSetterPairs();
230     if ( boundProperties() )
231         {
232         iw.println();
233         writeBoundPropertyEventSourceMethods();
234         }
235     if ( constrainedProperties() )
236         {
237         iw.println();
238         writeConstrainedPropertyEventSourceMethods();
239         }
240     writeInternalUtilityFunctions();
241     writeOtherFunctions();
242
243     writeOtherClasses();
244
245     String JavaDoc[] completed_intfc_names = (String JavaDoc[]) interfaceNames.toArray( new String JavaDoc[ interfaceNames.size() ] );
246     String JavaDoc[] completed_gen_imports = (String JavaDoc[]) generalImports.toArray( new String JavaDoc[ generalImports.size() ] );
247     String JavaDoc[] completed_spc_imports = (String JavaDoc[]) specificImports.toArray( new String JavaDoc[ specificImports.size() ] );
248     ClassInfo completedClassInfo = new SimpleClassInfo( info.getPackageName(),
249                                 info.getModifiers(),
250                                 info.getClassName(),
251                                 info.getSuperclassName(),
252                                 completed_intfc_names,
253                                 completed_gen_imports,
254                                 completed_spc_imports );
255     for (Iterator ii = generatorExtensions.iterator(); ii.hasNext(); )
256         {
257         GeneratorExtension ext = (GeneratorExtension) ii.next();
258         iw.println();
259         ext.generate( completedClassInfo, superclassType, props, propertyTypes, iw );
260         }
261     }
262
263     protected void writeInternalUtilityFunctions() throws IOException
264     {
265     iw.println("private boolean eqOrBothNull( Object a, Object b )");
266     iw.println("{");
267     iw.upIndent();
268
269     iw.println("return");
270     iw.upIndent();
271     iw.println("a == b ||");
272     iw.println("(a != null && a.equals(b));");
273     iw.downIndent();
274
275     iw.downIndent();
276     iw.println("}");
277     }
278
279     protected void writeConstrainedPropertyEventSourceMethods() throws IOException
280     {
281     iw.println("public void addVetoableChangeListener( VetoableChangeListener vcl )");
282     iw.println("{ vcs.addVetoableChangeListener( vcl ); }");
283     iw.println();
284     
285     iw.println("public void removeVetoableChangeListener( VetoableChangeListener vcl )");
286     iw.println("{ vcs.removeVetoableChangeListener( vcl ); }");
287     iw.println();
288
289     if (java_version >= 140)
290         {
291         iw.println("public VetoableChangeListener[] getVetoableChangeListeners()");
292         iw.println("{ return vcs.getPropertyChangeListeners(); }");
293         }
294     }
295
296     protected void writeBoundPropertyEventSourceMethods() throws IOException
297     {
298     iw.println("public void addPropertyChangeListener( PropertyChangeListener pcl )");
299     iw.println("{ pcs.addPropertyChangeListener( pcl ); }");
300     iw.println();
301     
302     iw.println("public void addPropertyChangeListener( String propName, PropertyChangeListener pcl )");
303     iw.println("{ pcs.addPropertyChangeListener( propName, pcl ); }");
304     iw.println();
305     
306     iw.println("public void removePropertyChangeListener( PropertyChangeListener pcl )");
307     iw.println("{ pcs.removePropertyChangeListener( pcl ); }");
308     iw.println();
309
310     iw.println("public void removePropertyChangeListener( String propName, PropertyChangeListener pcl )");
311     iw.println("{ pcs.removePropertyChangeListener( propName, pcl ); }");
312     iw.println();
313
314     if (java_version >= 140)
315         {
316         iw.println("public PropertyChangeListener[] getPropertyChangeListeners()");
317         iw.println("{ return pcs.getPropertyChangeListeners(); }");
318         }
319     }
320
321     protected void writeJavaBeansChangeSupport() throws IOException
322     {
323     if ( boundProperties() )
324         {
325         iw.println("protected PropertyChangeSupport pcs = new PropertyChangeSupport( this );");
326         iw.println();
327         iw.println("protected PropertyChangeSupport getPropertyChangeSupport()");
328         iw.println("{ return pcs; }");
329         
330         }
331     if ( constrainedProperties() )
332         {
333         iw.println("protected VetoableChangeSupport vcs = new VetoableChangeSupport( this );");
334         iw.println();
335         iw.println("protected VetoableChangeSupport getVetoableChangeSupport()");
336         iw.println("{ return vcs; }");
337         }
338     }
339
340     protected void writeOtherVariables() throws IOException //hook method for subclasses
341
{}
342
343     protected void writeOtherFunctions() throws IOException //hook method for subclasses
344
{}
345
346     protected void writeOtherClasses() throws IOException //hook method for subclasses
347
{}
348
349     protected void writePropertyVariables() throws IOException
350     {
351     for (int i = 0, len = props.length; i < len; ++i)
352         writePropertyVariable( props[i] );
353     }
354
355     protected void writePropertyVariable( Property prop ) throws IOException
356     {
357     BeangenUtils.writePropertyVariable( prop, iw );
358 // iw.print( CodegenUtils.getModifierString( prop.getVariableModifiers() ) );
359
// iw.print( ' ' + prop.getSimpleTypeName() + ' ' + prop.getName());
360
// String dflt = prop.getDefaultValueExpression();
361
// if (dflt != null)
362
// iw.print( " = " + dflt );
363
// iw.println(';');
364
}
365
366     /**
367      * @deprecated
368      */

369     protected void writePropertyMembers() throws IOException
370     { throw new InternalError JavaDoc("writePropertyMembers() deprecated and removed. please us writePropertyVariables()."); }
371
372     /**
373      * @deprecated
374      */

375     protected void writePropertyMember( Property prop ) throws IOException
376     { throw new InternalError JavaDoc("writePropertyMember() deprecated and removed. please us writePropertyVariable()."); }
377
378     protected void writeGetterSetterPairs() throws IOException
379     {
380     for (int i = 0, len = props.length; i < len; ++i)
381         {
382         writeGetterSetterPair( props[i], propertyTypes[i] );
383         if ( i != len - 1) iw.println();
384         }
385     }
386
387     protected void writeGetterSetterPair( Property prop, Class JavaDoc propType ) throws IOException
388     {
389     writePropertyGetter( prop, propType );
390     
391     if (! prop.isReadOnly() && ! force_unmodifiable)
392         {
393         iw.println();
394         writePropertySetter( prop, propType );
395         }
396     }
397
398     protected void writePropertyGetter( Property prop, Class JavaDoc propType ) throws IOException
399     {
400     BeangenUtils.writePropertyGetter( prop, this.getGetterDefensiveCopyExpression( prop, propType ), iw );
401
402 // String pfx = ("boolean".equals( prop.getSimpleTypeName() ) ? "is" : "get" );
403
// iw.print( CodegenUtils.getModifierString( prop.getGetterModifiers() ) );
404
// iw.println(' ' + prop.getSimpleTypeName() + ' ' + pfx + BeangenUtils.capitalize( prop.getName() ) + "()");
405
// String retVal = getGetterDefensiveCopyExpression( prop, propType );
406
// if (retVal == null) retVal = prop.getName();
407
// iw.println("{ return " + retVal + "; }");
408
}
409
410
411 // boolean changeMarked( Property prop )
412
// { return prop.isBound() || prop.isConstrained(); }
413

414     protected void writePropertySetter( Property prop, Class JavaDoc propType ) throws IOException
415     {
416     BeangenUtils.writePropertySetter( prop, this.getSetterDefensiveCopyExpression( prop, propType ), iw );
417
418 // iw.print( CodegenUtils.getModifierString( prop.getSetterModifiers() ) );
419
// iw.print(" void set" + BeangenUtils.capitalize( prop.getName() ) + "( " + prop.getSimpleTypeName() + ' ' + prop.getName() + " )");
420
// if ( prop.isConstrained() )
421
// iw.println(" throws PropertyVetoException");
422
// else
423
// iw.println();
424
// String setVal = getSetterDefensiveCopyExpression( prop, propType );
425
// if (setVal == null) setVal = prop.getName();
426
// iw.println('{');
427
// iw.upIndent();
428

429
430 // if ( changeMarked( prop ) )
431
// {
432
// iw.println( prop.getSimpleTypeName() + " oldVal = this." + prop.getName() + ';');
433

434 // String oldValExpr = "oldVal";
435
// String newValExpr = prop.getName();
436
// String changeCheck;
437
// if ( propType != null && propType.isPrimitive() ) //sometimes the type can't be resolved. if so, it ain't primitive.
438
// {
439
// // PropertyChange support already has overrides
440
// // for boolean and int
441
// if (propType == byte.class)
442
// {
443
// oldValExpr = "new Byte( "+ oldValExpr +" )";
444
// newValExpr = "new Byte( "+ newValExpr +" )";
445
// }
446
// else if (propType == char.class)
447
// {
448
// oldValExpr = "new Character( "+ oldValExpr +" )";
449
// newValExpr = "new Character( "+ newValExpr +" )";
450
// }
451
// else if (propType == short.class)
452
// {
453
// oldValExpr = "new Short( "+ oldValExpr +" )";
454
// newValExpr = "new Short( "+ newValExpr +" )";
455
// }
456
// else if (propType == float.class)
457
// {
458
// oldValExpr = "new Float( "+ oldValExpr +" )";
459
// newValExpr = "new Float( "+ newValExpr +" )";
460
// }
461
// else if (propType == double.class)
462
// {
463
// oldValExpr = "new Double( "+ oldValExpr +" )";
464
// newValExpr = "new Double( "+ newValExpr +" )";
465
// }
466

467 // changeCheck = "oldVal != " + prop.getName();
468
// }
469
// else
470
// changeCheck = "! eqOrBothNull( oldVal, " + prop.getName() + " )";
471

472 // if ( prop.isConstrained() )
473
// {
474
// iw.println("if ( " + changeCheck + " )");
475
// iw.upIndent();
476
// iw.println("vcs.fireVetoableChange( \"" + prop.getName() + "\", " + oldValExpr + ", " + newValExpr + " );");
477
// iw.downIndent();
478
// }
479

480 // iw.println("this." + prop.getName() + " = " + setVal + ';');
481

482 // if ( prop.isBound() )
483
// {
484
// iw.println("if ( " + changeCheck + " )");
485
// iw.upIndent();
486
// iw.println("pcs.firePropertyChange( \"" + prop.getName() + "\", " + oldValExpr + ", " + newValExpr + " );");
487
// iw.downIndent();
488
// }
489
// }
490
// else
491
// iw.println("this." + prop.getName() + " = " + setVal + ';');
492

493 // iw.downIndent();
494
// iw.println('}');
495
}
496
497     protected String JavaDoc getGetterDefensiveCopyExpression( Property prop, Class JavaDoc propType )
498     { return prop.getDefensiveCopyExpression(); }
499     
500     protected String JavaDoc getSetterDefensiveCopyExpression( Property prop, Class JavaDoc propType )
501     { return prop.getDefensiveCopyExpression(); }
502     
503     protected String JavaDoc getConstructorDefensiveCopyExpression( Property prop, Class JavaDoc propType )
504     { return prop.getDefensiveCopyExpression(); }
505
506     protected void writeHeader() throws IOException
507     {
508     writeBannerComments();
509     iw.println();
510     iw.println("package " + info.getPackageName() + ';');
511     iw.println();
512     writeImports();
513     }
514
515     protected void writeBannerComments() throws IOException
516     {
517     iw.println("/*");
518     iw.println(" * This class autogenerated by " + generatorName + '.');
519     iw.println(" * DO NOT HAND EDIT!");
520     iw.println(" */");
521     }
522
523     protected void writeImports() throws IOException
524     {
525     for ( Iterator ii = generalImports.iterator(); ii.hasNext(); )
526         iw.println("import " + ii.next() + ".*;");
527     for ( Iterator ii = specificImports.iterator(); ii.hasNext(); )
528         iw.println("import " + ii.next() + ";");
529     }
530
531     protected void writeClassDeclaration() throws IOException
532     {
533     iw.print( CodegenUtils.getModifierString( info.getModifiers() ) + " class " + info.getClassName() );
534     String JavaDoc superclassName = info.getSuperclassName();
535     if (superclassName != null)
536         iw.print( " extends " + superclassName );
537     if (interfaceNames.size() > 0)
538         {
539         iw.print(" implements ");
540         boolean first = true;
541         for (Iterator ii = interfaceNames.iterator(); ii.hasNext(); )
542             {
543             if (first)
544                 first = false;
545             else
546                 iw.print(", ");
547                 
548             iw.print( (String JavaDoc) ii.next() );
549             }
550         }
551     iw.println();
552     }
553
554     boolean boundProperties()
555     { return BeangenUtils.hasBoundProperties( props ); }
556
557     boolean constrainedProperties()
558     { return BeangenUtils.hasConstrainedProperties( props ); }
559
560     public static void main( String JavaDoc[] argv )
561     {
562     try
563         {
564         ClassInfo info = new SimpleClassInfo("test",
565                              Modifier.PUBLIC,
566                              argv[0],
567                              null,
568                              null,
569                              new String JavaDoc[] {"java.awt"},
570                              null);
571         
572         Property[] props =
573             {
574             new SimpleProperty( "number",
575                         "int",
576                         null,
577                         "7",
578                         false,
579                         true,
580                         false
581                         ),
582             new SimpleProperty( "fpNumber",
583                         "float",
584                         null,
585                         null,
586                         true,
587                         true,
588                         false
589                         ),
590             new SimpleProperty( "location",
591                         "Point",
592                         "new Point( location.x, location.y )",
593                         "new Point( 0, 0 )",
594                         false,
595                         true,
596                         true
597                         )
598             };
599
600         FileWriter fw = new FileWriter( argv[0] + ".java" );
601         SimplePropertyBeanGenerator g = new SimplePropertyBeanGenerator();
602         g.addExtension( new SerializableExtension() );
603         g.generate(info, props, fw );
604         fw.flush();
605         fw.close();
606         }
607     catch ( Exception JavaDoc e )
608         { e.printStackTrace(); }
609     }
610 }
611
Popular Tags