1 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 ; 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; private boolean force_unmodifiable = false; 41 private String generatorName = this.getClass().getName(); 42 43 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 superclassType; 53 protected List interfaceTypes; 54 protected Class [] 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 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 generatorName) 74 { this.generatorName = generatorName; } 75 76 public synchronized String 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 [] gen = (String []) generalImports.toArray( new String [ generalImports.size() ] ); 134 String [] spc = (String []) specificImports.toArray( new String [ specificImports.size() ] ); 135 136 if ( info.getSuperclassName() != null ) 137 { 138 try 139 { superclassType = ClassUtils.forName( info.getSuperclassName(), gen, spc ); } 140 catch ( Exception e ) 141 { 142 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 name = (String ) ii.next(); 155 try 156 { interfaceTypes.add( ClassUtils.forName( name , gen, spc ) ); } 157 catch ( Exception e ) 158 { 159 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 [ props.length ]; 170 for ( int i = 0, len = props.length; i < len; ++i ) 171 { 172 String name = props[i].getSimpleTypeName(); 173 try 174 { propertyTypes[i] = ClassUtils.forName( name , gen, spc ); } 175 catch ( Exception e ) 176 { 177 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 [] completed_intfc_names = (String []) interfaceNames.toArray( new String [ interfaceNames.size() ] ); 246 String [] completed_gen_imports = (String []) generalImports.toArray( new String [ generalImports.size() ] ); 247 String [] completed_spc_imports = (String []) specificImports.toArray( new String [ 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 {} 342 343 protected void writeOtherFunctions() throws IOException {} 345 346 protected void writeOtherClasses() throws IOException {} 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 } 365 366 369 protected void writePropertyMembers() throws IOException 370 { throw new InternalError ("writePropertyMembers() deprecated and removed. please us writePropertyVariables()."); } 371 372 375 protected void writePropertyMember( Property prop ) throws IOException 376 { throw new InternalError ("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 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 propType ) throws IOException 399 { 400 BeangenUtils.writePropertyGetter( prop, this.getGetterDefensiveCopyExpression( prop, propType ), iw ); 401 402 } 409 410 411 414 protected void writePropertySetter( Property prop, Class propType ) throws IOException 415 { 416 BeangenUtils.writePropertySetter( prop, this.getSetterDefensiveCopyExpression( prop, propType ), iw ); 417 418 429 430 434 467 472 480 482 493 } 496 497 protected String getGetterDefensiveCopyExpression( Property prop, Class propType ) 498 { return prop.getDefensiveCopyExpression(); } 499 500 protected String getSetterDefensiveCopyExpression( Property prop, Class propType ) 501 { return prop.getDefensiveCopyExpression(); } 502 503 protected String getConstructorDefensiveCopyExpression( Property prop, Class 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 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 ) 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 [] argv ) 561 { 562 try 563 { 564 ClassInfo info = new SimpleClassInfo("test", 565 Modifier.PUBLIC, 566 argv[0], 567 null, 568 null, 569 new String [] {"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 e ) 608 { e.printStackTrace(); } 609 } 610 } 611 | Popular Tags |