001/* 002 * Copyright (C) 2005 Christian Schulte <cs@schulte.it> 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions 007 * are met: 008 * 009 * o Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 012 * o Redistributions in binary form must reproduce the above copyright 013 * notice, this list of conditions and the following disclaimer in 014 * the documentation and/or other materials provided with the 015 * distribution. 016 * 017 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 018 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 019 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 020 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, 021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 022 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 023 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 024 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 026 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 027 * 028 * $JOMC: ToolsModelProvider.java 5135 2016-04-08 13:53:07Z schulte $ 029 * 030 */ 031package org.jomc.tools.modlet; 032 033import java.lang.reflect.Field; 034import java.text.MessageFormat; 035import java.util.ArrayList; 036import java.util.HashMap; 037import java.util.HashSet; 038import java.util.Locale; 039import java.util.Map; 040import java.util.ResourceBundle; 041import java.util.Set; 042import java.util.logging.Level; 043import javax.xml.bind.JAXBElement; 044import javax.xml.namespace.QName; 045import org.jomc.model.Dependencies; 046import org.jomc.model.Implementation; 047import org.jomc.model.InheritanceModel; 048import org.jomc.model.JavaTypeName; 049import org.jomc.model.Messages; 050import org.jomc.model.ModelObjectException; 051import org.jomc.model.Module; 052import org.jomc.model.Modules; 053import org.jomc.model.Properties; 054import org.jomc.model.Specification; 055import org.jomc.model.Specifications; 056import org.jomc.model.modlet.ModelHelper; 057import org.jomc.modlet.Model; 058import org.jomc.modlet.ModelContext; 059import org.jomc.modlet.ModelException; 060import org.jomc.modlet.ModelProvider; 061import org.jomc.tools.model.ObjectFactory; 062import org.jomc.tools.model.SourceFileType; 063import org.jomc.tools.model.SourceFilesType; 064import org.jomc.tools.model.SourceSectionType; 065import org.jomc.tools.model.SourceSectionsType; 066import static org.jomc.tools.modlet.ToolsModletConstants.ANNOTATIONS_SECTION_NAME; 067import static org.jomc.tools.modlet.ToolsModletConstants.CONSTRUCTORS_HEAD_TEMPLATE; 068import static org.jomc.tools.modlet.ToolsModletConstants.CONSTRUCTORS_SECTION_NAME; 069import static org.jomc.tools.modlet.ToolsModletConstants.CONSTRUCTORS_TAIL_TEMPLATE; 070import static org.jomc.tools.modlet.ToolsModletConstants.DEFAULT_CONSTRUCTOR_SECTION_NAME; 071import static org.jomc.tools.modlet.ToolsModletConstants.DEFAULT_CONSTRUCTOR_TEMPLATE; 072import static org.jomc.tools.modlet.ToolsModletConstants.DEPENDENCIES_SECTION_NAME; 073import static org.jomc.tools.modlet.ToolsModletConstants.DEPENDENCIES_TEMPLATE; 074import static org.jomc.tools.modlet.ToolsModletConstants.DOCUMENTATION_SECTION_NAME; 075import static org.jomc.tools.modlet.ToolsModletConstants.IMPLEMENTATION_ANNOTATIONS_TEMPLATE; 076import static org.jomc.tools.modlet.ToolsModletConstants.IMPLEMENTATION_DOCUMENTATION_TEMPLATE; 077import static org.jomc.tools.modlet.ToolsModletConstants.IMPLEMENTATION_LICENSE_TEMPLATE; 078import static org.jomc.tools.modlet.ToolsModletConstants.IMPLEMENTATION_TEMPLATE; 079import static org.jomc.tools.modlet.ToolsModletConstants.LICENSE_SECTION_NAME; 080import static org.jomc.tools.modlet.ToolsModletConstants.MESSAGES_SECTION_NAME; 081import static org.jomc.tools.modlet.ToolsModletConstants.MESSAGES_TEMPLATE; 082import static org.jomc.tools.modlet.ToolsModletConstants.PROPERTIES_SECTION_NAME; 083import static org.jomc.tools.modlet.ToolsModletConstants.PROPERTIES_TEMPLATE; 084import static org.jomc.tools.modlet.ToolsModletConstants.SPECIFICATION_ANNOTATIONS_TEMPLATE; 085import static org.jomc.tools.modlet.ToolsModletConstants.SPECIFICATION_DOCUMENTATION_TEMPLATE; 086import static org.jomc.tools.modlet.ToolsModletConstants.SPECIFICATION_LICENSE_TEMPLATE; 087import static org.jomc.tools.modlet.ToolsModletConstants.SPECIFICATION_TEMPLATE; 088 089/** 090 * Object management and configuration tools {@code ModelProvider} implementation. 091 * 092 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 093 * @version $JOMC: ToolsModelProvider.java 5135 2016-04-08 13:53:07Z schulte $ 094 * @see ModelContext#findModel(java.lang.String) 095 * @since 1.2 096 */ 097public class ToolsModelProvider implements ModelProvider 098{ 099 100 /** 101 * Constant for the qualified name of {@code source-files} elements. 102 */ 103 private static final QName SOURCE_FILES_QNAME = new ObjectFactory().createSourceFiles( null ).getName(); 104 105 /** 106 * Constant for the name of the model context attribute backing property {@code enabled}. 107 * 108 * @see #findModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) 109 * @see ModelContext#getAttribute(java.lang.String) 110 */ 111 public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.tools.modlet.ToolsModelProvider.enabledAttribute"; 112 113 /** 114 * Constant for the name of the system property controlling property {@code defaultEnabled}. 115 * 116 * @see #isDefaultEnabled() 117 */ 118 private static final String DEFAULT_ENABLED_PROPERTY_NAME = 119 "org.jomc.tools.modlet.ToolsModelProvider.defaultEnabled"; 120 121 /** 122 * Default value of the flag indicating the provider is enabled by default. 123 * 124 * @see #isDefaultEnabled() 125 */ 126 private static final Boolean DEFAULT_ENABLED = Boolean.TRUE; 127 128 /** 129 * Flag indicating the provider is enabled by default. 130 */ 131 private static volatile Boolean defaultEnabled; 132 133 /** 134 * Flag indicating the provider is enabled. 135 */ 136 private Boolean enabled; 137 138 /** 139 * Constant for the name of the model context attribute backing property 140 * {@code modelObjectClasspathResolutionEnabled}. 141 * 142 * @see #findModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) 143 * @see ModelContext#getAttribute(java.lang.String) 144 */ 145 public static final String MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME = 146 "org.jomc.tools.modlet.ToolsModelProvider.modelObjectClasspathResolutionEnabledAttribute"; 147 148 /** 149 * Constant for the name of the system property controlling property 150 * {@code defaultModelObjectClasspathResolutionEnabled}. 151 * 152 * @see #isDefaultModelObjectClasspathResolutionEnabled() 153 */ 154 private static final String DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_PROPERTY_NAME = 155 "org.jomc.tools.modlet.ToolsModelProvider.defaultModelObjectClasspathResolutionEnabled"; 156 157 /** 158 * Default value of the flag indicating model object class path resolution is enabled by default. 159 * 160 * @see #isDefaultModelObjectClasspathResolutionEnabled() 161 */ 162 private static final Boolean DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED = Boolean.TRUE; 163 164 /** 165 * Flag indicating model object class path resolution is enabled by default. 166 */ 167 private static volatile Boolean defaultModelObjectClasspathResolutionEnabled; 168 169 /** 170 * Flag indicating model object class path resolution is enabled. 171 */ 172 private Boolean modelObjectClasspathResolutionEnabled; 173 174 /** 175 * Constant for the name of the model context attribute backing property {@code headComment}. 176 * 177 * @see #findModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) 178 * @see ModelContext#getAttribute(java.lang.String) 179 * @since 1.6 180 */ 181 public static final String HEAD_COMMENT_ATTRIBUTE_NAME = 182 "org.jomc.tools.modlet.ToolsModelProvider.headCommentAttribute"; 183 184 /** 185 * Constant for the name of the system property controlling property {@code defaultHeadComment}. 186 * 187 * @see #getDefaultHeadComment() 188 * @since 1.6 189 */ 190 private static final String DEFAULT_HEAD_COMMENT_PROPERTY_NAME = 191 "org.jomc.tools.modlet.ToolsModelProvider.defaultHeadComment"; 192 193 /** 194 * Default head comment the provider is providing by default. 195 * 196 * @see #getDefaultHeadComment() 197 * @since 1.6 198 */ 199 private static final String DEFAULT_HEAD_COMMENT = "//"; 200 201 /** 202 * Head comment the provider is providing by default. 203 * 204 * @since 1.6 205 */ 206 private static volatile String defaultHeadComment; 207 208 /** 209 * Head comment the provider is providing. 210 * 211 * @since 1.6 212 */ 213 private String headComment; 214 215 /** 216 * Constant for the name of the model context attribute backing property {@code tailComment}. 217 * 218 * @see #findModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) 219 * @see ModelContext#getAttribute(java.lang.String) 220 * @since 1.6 221 */ 222 public static final String TAIL_COMMENT_ATTRIBUTE_NAME = 223 "org.jomc.tools.modlet.ToolsModelProvider.tailCommentAttribute"; 224 225 /** 226 * Constant for the name of the system property controlling property {@code defaultTailComment}. 227 * 228 * @see #getDefaultTailComment() 229 * @since 1.6 230 */ 231 private static final String DEFAULT_TAIL_COMMENT_PROPERTY_NAME = 232 "org.jomc.tools.modlet.ToolsModelProvider.defaultTailComment"; 233 234 /** 235 * Default tail comment the provider is providing by default. 236 * 237 * @see #getDefaultTailComment() 238 * @since 1.6 239 */ 240 private static final String DEFAULT_TAIL_COMMENT = null; 241 242 /** 243 * Tail comment the provider is providing by default. 244 * 245 * @since 1.6 246 */ 247 private static volatile String defaultTailComment; 248 249 /** 250 * Tail comment the provider is providing. 251 * 252 * @since 1.6 253 */ 254 private String tailComment; 255 256 /** 257 * Creates a new {@code ToolsModelProvider} instance. 258 */ 259 public ToolsModelProvider() 260 { 261 super(); 262 } 263 264 /** 265 * Gets a flag indicating the provider is enabled by default. 266 * <p> 267 * The default enabled flag is controlled by system property 268 * {@code org.jomc.tools.modlet.ToolsModelProvider.defaultEnabled} holding a value indicating the provider is 269 * enabled by default. If that property is not set, the {@code true} default is returned. 270 * </p> 271 * 272 * @return {@code true}, if the provider is enabled by default; {@code false}, if the provider is disabled by 273 * default. 274 * 275 * @see #setDefaultEnabled(java.lang.Boolean) 276 */ 277 public static boolean isDefaultEnabled() 278 { 279 if ( defaultEnabled == null ) 280 { 281 defaultEnabled = Boolean.valueOf( System.getProperty( DEFAULT_ENABLED_PROPERTY_NAME, 282 Boolean.toString( DEFAULT_ENABLED ) ) ); 283 284 } 285 286 return defaultEnabled; 287 } 288 289 /** 290 * Sets the flag indicating the provider is enabled by default. 291 * 292 * @param value The new value of the flag indicating the provider is enabled by default or {@code null}. 293 * 294 * @see #isDefaultEnabled() 295 */ 296 public static void setDefaultEnabled( final Boolean value ) 297 { 298 defaultEnabled = value; 299 } 300 301 /** 302 * Gets a flag indicating the provider is enabled. 303 * 304 * @return {@code true}, if the provider is enabled; {@code false}, if the provider is disabled. 305 * 306 * @see #isDefaultEnabled() 307 * @see #setEnabled(java.lang.Boolean) 308 */ 309 public final boolean isEnabled() 310 { 311 if ( this.enabled == null ) 312 { 313 this.enabled = isDefaultEnabled(); 314 } 315 316 return this.enabled; 317 } 318 319 /** 320 * Sets the flag indicating the provider is enabled. 321 * 322 * @param value The new value of the flag indicating the provider is enabled or {@code null}. 323 * 324 * @see #isEnabled() 325 */ 326 public final void setEnabled( final Boolean value ) 327 { 328 this.enabled = value; 329 } 330 331 /** 332 * Gets a flag indicating model object class path resolution is enabled by default. 333 * <p> 334 * The model object class path resolution default enabled flag is controlled by system property 335 * {@code org.jomc.tools.modlet.ToolsModelProvider.defaultModelObjectClasspathResolutionEnabled} holding a value 336 * indicating model object class path resolution is enabled by default. If that property is not set, the 337 * {@code true} default is returned. 338 * </p> 339 * 340 * @return {@code true}, if model object class path resolution is enabled by default; {@code false}, if model object 341 * class path resolution is disabled by default. 342 * 343 * @see #setDefaultModelObjectClasspathResolutionEnabled(java.lang.Boolean) 344 */ 345 public static boolean isDefaultModelObjectClasspathResolutionEnabled() 346 { 347 if ( defaultModelObjectClasspathResolutionEnabled == null ) 348 { 349 defaultModelObjectClasspathResolutionEnabled = Boolean.valueOf( System.getProperty( 350 DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_PROPERTY_NAME, 351 Boolean.toString( DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED ) ) ); 352 353 } 354 355 return defaultModelObjectClasspathResolutionEnabled; 356 } 357 358 /** 359 * Sets the flag indicating model object class path resolution is enabled by default. 360 * 361 * @param value The new value of the flag indicating model object class path resolution is enabled by default or 362 * {@code null}. 363 * 364 * @see #isDefaultModelObjectClasspathResolutionEnabled() 365 */ 366 public static void setDefaultModelObjectClasspathResolutionEnabled( final Boolean value ) 367 { 368 defaultModelObjectClasspathResolutionEnabled = value; 369 } 370 371 /** 372 * Gets a flag indicating model object class path resolution is enabled. 373 * 374 * @return {@code true}, if model object class path resolution is enabled; {@code false}, if model object class path 375 * resolution is disabled. 376 * 377 * @see #isDefaultModelObjectClasspathResolutionEnabled() 378 * @see #setModelObjectClasspathResolutionEnabled(java.lang.Boolean) 379 */ 380 public final boolean isModelObjectClasspathResolutionEnabled() 381 { 382 if ( this.modelObjectClasspathResolutionEnabled == null ) 383 { 384 this.modelObjectClasspathResolutionEnabled = isDefaultModelObjectClasspathResolutionEnabled(); 385 } 386 387 return this.modelObjectClasspathResolutionEnabled; 388 } 389 390 /** 391 * Sets the flag indicating model object class path resolution is is enabled. 392 * 393 * @param value The new value of the flag indicating model object class path resolution is enabled or {@code null}. 394 * 395 * @see #isModelObjectClasspathResolutionEnabled() 396 */ 397 public final void setModelObjectClasspathResolutionEnabled( final Boolean value ) 398 { 399 this.modelObjectClasspathResolutionEnabled = value; 400 } 401 402 /** 403 * Gets the head comment the provider is providing by default. 404 * <p> 405 * The default head comment is controlled by system property 406 * {@code org.jomc.tools.modlet.ToolsModelProvider.defaultHeadComment} holding the head comment the provider is 407 * providing by default. If that property is not set, the {@code //} default is returned. 408 * </p> 409 * 410 * @return The head comment the provider is providing by default or {@code null}. 411 * 412 * @see #setDefaultHeadComment(java.lang.String) 413 * @since 1.6 414 */ 415 public static String getDefaultHeadComment() 416 { 417 if ( defaultHeadComment == null ) 418 { 419 defaultHeadComment = System.getProperty( DEFAULT_HEAD_COMMENT_PROPERTY_NAME, DEFAULT_HEAD_COMMENT ); 420 } 421 422 return defaultHeadComment; 423 } 424 425 /** 426 * Sets the head comment the provider is providing by default. 427 * 428 * @param value The new head comment the provider is providing by default or {@code null}. 429 * 430 * @see #getDefaultHeadComment() 431 * @since 1.6 432 */ 433 public static void setDefaultHeadComment( final String value ) 434 { 435 defaultHeadComment = value; 436 } 437 438 /** 439 * Gets the head comment the provider is providing. 440 * 441 * @return The head comment the provider is providing or {@code null}. 442 * 443 * @see #getDefaultHeadComment() 444 * @see #setDefaultHeadComment(java.lang.String) 445 * @since 1.6 446 */ 447 public final String getHeadComment() 448 { 449 if ( this.headComment == null ) 450 { 451 this.headComment = getDefaultHeadComment(); 452 } 453 454 return this.headComment; 455 } 456 457 /** 458 * Sets the head comment the provider is providing. 459 * 460 * @param value The new head comment the provider is providing or {@code null}. 461 * 462 * @see #getHeadComment() 463 * @since 1.6 464 */ 465 public final void setHeadComment( final String value ) 466 { 467 this.headComment = value; 468 } 469 470 /** 471 * Gets the tail comment the provider is providing by default. 472 * <p> 473 * The default tail comment is controlled by system property 474 * {@code org.jomc.tools.modlet.ToolsModelProvider.defaultTailComment} holding the tail comment the provider is 475 * providing by default. If that property is not set, the {@code null} default is returned. 476 * </p> 477 * 478 * @return The tail comment the provider is providing by default or {@code null}. 479 * 480 * @see #setDefaultTailComment(java.lang.String) 481 * @since 1.6 482 */ 483 public static String getDefaultTailComment() 484 { 485 if ( defaultTailComment == null ) 486 { 487 defaultTailComment = System.getProperty( DEFAULT_TAIL_COMMENT_PROPERTY_NAME, DEFAULT_TAIL_COMMENT ); 488 } 489 490 return defaultTailComment; 491 } 492 493 /** 494 * Sets the tail comment the provider is providing by default. 495 * 496 * @param value The new tail comment the provider is providing by default or {@code null}. 497 * 498 * @see #getDefaultTailComment() 499 * @since 1.6 500 */ 501 public static void setDefaultTailComment( final String value ) 502 { 503 defaultTailComment = value; 504 } 505 506 /** 507 * Gets the tail comment the provider is providing. 508 * 509 * @return The tail comment the provider is providing or {@code null}. 510 * 511 * @see #getDefaultTailComment() 512 * @see #setDefaultTailComment(java.lang.String) 513 * @since 1.6 514 */ 515 public final String getTailComment() 516 { 517 if ( this.tailComment == null ) 518 { 519 this.tailComment = getDefaultTailComment(); 520 } 521 522 return this.tailComment; 523 } 524 525 /** 526 * Sets the tail comment the provider is providing. 527 * 528 * @param value The new tail comment the provider is providing or {@code null}. 529 * 530 * @see #getTailComment() 531 * @since 1.6 532 */ 533 public final void setTailComment( final String value ) 534 { 535 this.tailComment = value; 536 } 537 538 /** 539 * {@inheritDoc} 540 * 541 * @see #isEnabled() 542 * @see #isModelObjectClasspathResolutionEnabled() 543 * @see #getHeadComment() 544 * @see #getTailComment() 545 * @see #ENABLED_ATTRIBUTE_NAME 546 * @see #MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME 547 * @see #HEAD_COMMENT_ATTRIBUTE_NAME 548 * @see #TAIL_COMMENT_ATTRIBUTE_NAME 549 */ 550 public Model findModel( final ModelContext context, final Model model ) throws ModelException 551 { 552 if ( context == null ) 553 { 554 throw new NullPointerException( "context" ); 555 } 556 if ( model == null ) 557 { 558 throw new NullPointerException( "model" ); 559 } 560 561 Model provided = null; 562 563 boolean contextEnabled = this.isEnabled(); 564 if ( DEFAULT_ENABLED == contextEnabled && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean ) 565 { 566 contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME ); 567 } 568 569 boolean contextModelObjectClasspathResolutionEnabled = this.isModelObjectClasspathResolutionEnabled(); 570 if ( contextModelObjectClasspathResolutionEnabled == DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED 571 && context.getAttribute( MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME ) instanceof Boolean ) 572 { 573 contextModelObjectClasspathResolutionEnabled = 574 (Boolean) context.getAttribute( MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME ); 575 576 } 577 578 if ( contextEnabled ) 579 { 580 provided = model.clone(); 581 final Modules modules = ModelHelper.getModules( provided ); 582 583 if ( modules != null ) 584 { 585 Module classpathModule = null; 586 if ( contextModelObjectClasspathResolutionEnabled ) 587 { 588 classpathModule = modules.getClasspathModule( Modules.getDefaultClasspathModuleName(), 589 context.getClassLoader() ); 590 591 if ( classpathModule != null 592 && modules.getModule( Modules.getDefaultClasspathModuleName() ) == null ) 593 { 594 modules.getModule().add( classpathModule ); 595 } 596 else 597 { 598 classpathModule = null; 599 } 600 } 601 602 if ( modules.getSpecifications() != null ) 603 { 604 for ( int i = 0, s0 = modules.getSpecifications().getSpecification().size(); i < s0; i++ ) 605 { 606 final Specification specification = modules.getSpecifications().getSpecification().get( i ); 607 final SourceFileType sourceFileType = specification.getAnyObject( SourceFileType.class ); 608 final SourceFilesType sourceFilesType = specification.getAnyObject( SourceFilesType.class ); 609 610 if ( sourceFileType == null && specification.isClassDeclaration() ) 611 { 612 final SourceFilesType defaultSourceFiles = 613 this.getDefaultSourceFilesType( context, modules, specification ); 614 615 if ( sourceFilesType != null ) 616 { 617 this.overwriteSourceFiles( sourceFilesType, defaultSourceFiles, true ); 618 } 619 else 620 { 621 specification.getAny().add( 622 new ObjectFactory().createSourceFiles( defaultSourceFiles ) ); 623 624 } 625 } 626 } 627 } 628 629 if ( modules.getImplementations() != null ) 630 { 631 final Map<Implementation, SourceFilesType> userSourceFiles = 632 new HashMap<Implementation, SourceFilesType>( 633 modules.getImplementations().getImplementation().size() ); 634 635 InheritanceModel imodel = new InheritanceModel( modules ); 636 637 for ( int i = 0, s0 = modules.getImplementations().getImplementation().size(); i < s0; i++ ) 638 { 639 final Implementation implementation = modules.getImplementations().getImplementation().get( i ); 640 final SourceFileType sourceFileType = implementation.getAnyObject( SourceFileType.class ); 641 final SourceFilesType sourceFilesType = implementation.getAnyObject( SourceFilesType.class ); 642 643 if ( sourceFileType == null ) 644 { 645 if ( sourceFilesType != null ) 646 { 647 userSourceFiles.put( implementation, sourceFilesType ); 648 } 649 else if ( implementation.isClassDeclaration() ) 650 { 651 final SourceFilesType defaultSourceFiles = 652 this.getDefaultSourceFilesType( context, modules, implementation ); 653 654 boolean finalAncestor = false; 655 656 final Set<InheritanceModel.Node<JAXBElement<?>>> sourceFilesNodes = 657 imodel.getJaxbElementNodes( implementation.getIdentifier(), SOURCE_FILES_QNAME ); 658 659 for ( final InheritanceModel.Node<JAXBElement<?>> sourceFilesNode : sourceFilesNodes ) 660 { 661 if ( sourceFilesNode.getModelObject().getValue() instanceof SourceFilesType ) 662 { 663 final SourceFilesType ancestorSourceFiles = 664 (SourceFilesType) sourceFilesNode.getModelObject().getValue(); 665 666 this.overwriteSourceFiles( defaultSourceFiles, ancestorSourceFiles, false ); 667 668 if ( ancestorSourceFiles.isFinal() ) 669 { 670 finalAncestor = true; 671 } 672 } 673 } 674 675 if ( !finalAncestor ) 676 { 677 implementation.getAny().add( 678 new ObjectFactory().createSourceFiles( defaultSourceFiles ) ); 679 680 } 681 } 682 } 683 } 684 685 for ( final Map.Entry<Implementation, SourceFilesType> e : userSourceFiles.entrySet() ) 686 { 687 this.overwriteSourceFiles( e.getValue(), this.getDefaultSourceFilesType( 688 context, modules, e.getKey() ), true ); 689 690 } 691 692 imodel = new InheritanceModel( modules ); 693 694 for ( int i = 0, s0 = modules.getImplementations().getImplementation().size(); i < s0; i++ ) 695 { 696 final Implementation implementation = modules.getImplementations().getImplementation().get( i ); 697 final SourceFilesType sourceFilesType = implementation.getAnyObject( SourceFilesType.class ); 698 699 if ( sourceFilesType != null && !userSourceFiles.containsKey( implementation ) ) 700 { 701 boolean override = false; 702 703 final Set<InheritanceModel.Node<JAXBElement<?>>> sourceFilesNodes = 704 imodel.getJaxbElementNodes( implementation.getIdentifier(), SOURCE_FILES_QNAME ); 705 706 for ( final InheritanceModel.Node<JAXBElement<?>> e : sourceFilesNodes ) 707 { 708 if ( !e.getOverriddenNodes().isEmpty() ) 709 { 710 override = true; 711 break; 712 } 713 } 714 715 if ( override ) 716 { 717 sourceFilesType.setOverride( override ); 718 } 719 } 720 } 721 } 722 723 if ( classpathModule != null ) 724 { 725 modules.getModule().remove( classpathModule ); 726 } 727 } 728 } 729 else if ( context.isLoggable( Level.FINER ) ) 730 { 731 context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName(), 732 model.getIdentifier() ), null ); 733 734 } 735 736 return provided; 737 } 738 739 /** 740 * Gets the default source code file location for a given specification. 741 * <p> 742 * If the specification provides a Java type name, this method returns a Java source code file location based on 743 * that Java type name. 744 * </p> 745 * 746 * @param context The context to get the default location with. 747 * @param modules The model to get the default location with. 748 * @param specification The specification to get the default location for. 749 * 750 * @return The default location for {@code specification} or {@code null}. 751 * 752 * @throws NullPointerException if {@code context}, {@code modules} or {@code specification} is {@code null}. 753 * 754 * @see #getDefaultSourceFilesType(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Specification) 755 * @see SourceFileType#getLocation() 756 * @see Specification#getJavaTypeName() 757 * @since 1.6 758 */ 759 protected String getDefaultSourceFileLocation( final ModelContext context, final Modules modules, 760 final Specification specification ) 761 { 762 if ( context == null ) 763 { 764 throw new NullPointerException( "context" ); 765 } 766 if ( modules == null ) 767 { 768 throw new NullPointerException( "modules" ); 769 } 770 if ( specification == null ) 771 { 772 throw new NullPointerException( "specification" ); 773 } 774 775 String location = null; 776 777 try 778 { 779 if ( specification.getJavaTypeName() != null ) 780 { 781 location = specification.getJavaTypeName().getQualifiedName().replace( '.', '/' ) + ".java"; 782 } 783 } 784 catch ( final ModelObjectException e ) 785 { 786 context.log( Level.WARNING, getMessage( e ), null ); 787 } 788 789 return location; 790 } 791 792 /** 793 * Gets the default source code file location for a given implementation. 794 * <p> 795 * If the implementation provides a Java type name, this method returns a Java source code file location based on 796 * that Java type name. 797 * </p> 798 * 799 * @param context The context to get the default location with. 800 * @param modules The model to get the default location with. 801 * @param implementation The implementation to get the default location for. 802 * 803 * @return The default location for {@code implementation} or {@code null}. 804 * 805 * @throws NullPointerException if {@code context}, {@code modules} or {@code implementation} is {@code null}. 806 * 807 * @see #getDefaultSourceFilesType(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Implementation) 808 * @see SourceFileType#getLocation() 809 * @see Implementation#getJavaTypeName() 810 * @since 1.6 811 */ 812 protected String getDefaultSourceFileLocation( final ModelContext context, final Modules modules, 813 final Implementation implementation ) 814 { 815 if ( context == null ) 816 { 817 throw new NullPointerException( "context" ); 818 } 819 if ( modules == null ) 820 { 821 throw new NullPointerException( "modules" ); 822 } 823 if ( implementation == null ) 824 { 825 throw new NullPointerException( "implementation" ); 826 } 827 828 String location = null; 829 830 try 831 { 832 if ( implementation.getJavaTypeName() != null ) 833 { 834 location = implementation.getJavaTypeName().getQualifiedName().replace( '.', '/' ) + ".java"; 835 } 836 } 837 catch ( final ModelObjectException e ) 838 { 839 context.log( Level.WARNING, getMessage( e ), null ); 840 } 841 842 return location; 843 } 844 845 /** 846 * Gets the default source section name for a given specification. 847 * <p> 848 * If the specification provides a Java type name, this method returns a section name based on that Java type 849 * name. 850 * </p> 851 * 852 * @param context The context to get the default section name with. 853 * @param modules The model to get the default section name with. 854 * @param specification The specification to get the default section name for. 855 * 856 * @return The default source section name for {@code specification} or {@code null}. 857 * 858 * @throws NullPointerException if {@code context}, {@code modules} or {@code specification} is {@code null}. 859 * 860 * @see #getDefaultSourceFilesType(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Specification) 861 * @see SourceSectionType#getName() 862 * @see Specification#getJavaTypeName() 863 * @since 1.6 864 */ 865 protected String getDefaultSourceSectionName( final ModelContext context, final Modules modules, 866 final Specification specification ) 867 { 868 if ( context == null ) 869 { 870 throw new NullPointerException( "context" ); 871 } 872 if ( modules == null ) 873 { 874 throw new NullPointerException( "modules" ); 875 } 876 if ( specification == null ) 877 { 878 throw new NullPointerException( "specification" ); 879 } 880 881 String sectionName = null; 882 883 try 884 { 885 final JavaTypeName javaTypeName = specification.getJavaTypeName(); 886 887 if ( javaTypeName != null ) 888 { 889 sectionName = javaTypeName.getName( false ); 890 } 891 } 892 catch ( final ModelObjectException e ) 893 { 894 context.log( Level.WARNING, getMessage( e ), null ); 895 } 896 897 return sectionName; 898 } 899 900 /** 901 * Gets the default source section name for a given implementation. 902 * <p> 903 * If the implementation provides a Java type name, this method returns a section name based that Java type 904 * name. 905 * </p> 906 * 907 * @param context The context to get the default section name with. 908 * @param modules The model to get the default section name with. 909 * @param implementation The implementation to get the default section name for. 910 * 911 * @return The default source section name for {@code implementation} or {@code null}. 912 * 913 * @throws NullPointerException if {@code context}, {@code modules} or {@code implementation} is {@code null}. 914 * 915 * @see #getDefaultSourceFilesType(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Implementation) 916 * @see SourceSectionType#getName() 917 * @see Implementation#getJavaTypeName() 918 * @since 1.6 919 */ 920 protected String getDefaultSourceSectionName( final ModelContext context, final Modules modules, 921 final Implementation implementation ) 922 { 923 if ( context == null ) 924 { 925 throw new NullPointerException( "context" ); 926 } 927 if ( modules == null ) 928 { 929 throw new NullPointerException( "modules" ); 930 } 931 if ( implementation == null ) 932 { 933 throw new NullPointerException( "implementation" ); 934 } 935 936 String sectionName = null; 937 938 try 939 { 940 final JavaTypeName javaTypeName = implementation.getJavaTypeName(); 941 942 if ( javaTypeName != null ) 943 { 944 sectionName = javaTypeName.getName( false ); 945 } 946 } 947 catch ( final ModelObjectException e ) 948 { 949 context.log( Level.WARNING, getMessage( e ), null ); 950 } 951 952 return sectionName; 953 } 954 955 /** 956 * Creates a new default source files model for a given specification. 957 * 958 * @param context The context to create a new default source files model with. 959 * @param modules The model to create a new default source files model with. 960 * @param specification The specification to create a new default source files model for. 961 * 962 * @return A new default source files model for {@code specification}. 963 * 964 * @throws NullPointerException if {@code context}, {@code modules} or {@code specification} is {@code null}. 965 * 966 * @see #getDefaultSourceFileLocation(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Specification) 967 * @see #getDefaultSourceSectionName(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Specification) 968 * @since 1.6 969 */ 970 protected SourceFilesType getDefaultSourceFilesType( final ModelContext context, final Modules modules, 971 final Specification specification ) 972 { 973 if ( context == null ) 974 { 975 throw new NullPointerException( "context" ); 976 } 977 if ( modules == null ) 978 { 979 throw new NullPointerException( "modules" ); 980 } 981 if ( specification == null ) 982 { 983 throw new NullPointerException( "specification" ); 984 } 985 986 String contextHeadComment = this.getHeadComment(); 987 if ( ( DEFAULT_HEAD_COMMENT != null 988 ? DEFAULT_HEAD_COMMENT.equals( contextHeadComment ) 989 : contextHeadComment == null ) 990 && context.getAttribute( HEAD_COMMENT_ATTRIBUTE_NAME ) instanceof String ) 991 { 992 contextHeadComment = (String) context.getAttribute( HEAD_COMMENT_ATTRIBUTE_NAME ); 993 } 994 995 if ( contextHeadComment != null && contextHeadComment.length() == 0 ) 996 { 997 contextHeadComment = null; 998 } 999 1000 String contextTailComment = this.getTailComment(); 1001 if ( ( DEFAULT_TAIL_COMMENT != null 1002 ? DEFAULT_TAIL_COMMENT.equals( contextTailComment ) 1003 : contextTailComment == null ) 1004 && context.getAttribute( TAIL_COMMENT_ATTRIBUTE_NAME ) instanceof String ) 1005 { 1006 contextTailComment = (String) context.getAttribute( TAIL_COMMENT_ATTRIBUTE_NAME ); 1007 } 1008 1009 if ( contextTailComment != null && contextTailComment.length() == 0 ) 1010 { 1011 contextTailComment = null; 1012 } 1013 1014 final Set<String> uniqueSectionNames = new HashSet<String>( 16 ); 1015 final Set<String> sectionNames = new HashSet<String>( 16 ); 1016 sectionNames.add( LICENSE_SECTION_NAME ); 1017 sectionNames.add( ANNOTATIONS_SECTION_NAME ); 1018 sectionNames.add( DOCUMENTATION_SECTION_NAME ); 1019 1020 final SourceFilesType sourceFilesType = new SourceFilesType(); 1021 final SourceFileType sourceFileType = new SourceFileType(); 1022 sourceFilesType.getSourceFile().add( sourceFileType ); 1023 1024 sourceFileType.setIdentifier( "Default" ); 1025 sourceFileType.setLocation( this.getDefaultSourceFileLocation( context, modules, specification ) ); 1026 1027 sourceFileType.setTemplate( SPECIFICATION_TEMPLATE ); 1028 sourceFileType.setHeadComment( contextHeadComment ); 1029 sourceFileType.setTailComment( contextTailComment ); 1030 sourceFileType.setSourceSections( new SourceSectionsType() ); 1031 1032 SourceSectionType s = new SourceSectionType(); 1033 s.setName( LICENSE_SECTION_NAME ); 1034 s.setHeadTemplate( SPECIFICATION_LICENSE_TEMPLATE ); 1035 s.setOptional( true ); 1036 sourceFileType.getSourceSections().getSourceSection().add( s ); 1037 1038 s = new SourceSectionType(); 1039 s.setName( ANNOTATIONS_SECTION_NAME ); 1040 s.setHeadTemplate( SPECIFICATION_ANNOTATIONS_TEMPLATE ); 1041 sourceFileType.getSourceSections().getSourceSection().add( s ); 1042 1043 s = new SourceSectionType(); 1044 s.setName( DOCUMENTATION_SECTION_NAME ); 1045 s.setHeadTemplate( SPECIFICATION_DOCUMENTATION_TEMPLATE ); 1046 s.setOptional( true ); 1047 sourceFileType.getSourceSections().getSourceSection().add( s ); 1048 1049 final String sectionName = this.getDefaultSourceSectionName( context, modules, specification ); 1050 1051 if ( sectionName != null ) 1052 { 1053 if ( sectionNames.add( sectionName ) ) 1054 { 1055 s = new SourceSectionType(); 1056 s.setName( sectionName ); 1057 s.setIndentationLevel( 1 ); 1058 s.setEditable( true ); 1059 sourceFileType.getSourceSections().getSourceSection().add( s ); 1060 } 1061 else if ( uniqueSectionNames.add( sectionName ) ) 1062 { 1063 final Module module = modules.getModuleOfSpecification( specification.getIdentifier() ); 1064 context.log( Level.WARNING, getMessage( "specificationSectionNameUniqueness", 1065 specification.getIdentifier(), 1066 module.getName(), 1067 sourceFileType.getIdentifier(), 1068 sectionName ), 1069 null ); 1070 1071 } 1072 } 1073 1074 return sourceFilesType; 1075 } 1076 1077 /** 1078 * Creates a new default source files model for a given implementation. 1079 * 1080 * @param context The context to create a new default source files model with. 1081 * @param modules The model to create a new default source files model with. 1082 * @param implementation The implementation to create a new default source files model for. 1083 * 1084 * @return A new default source files model for {@code implementation}. 1085 * 1086 * @throws NullPointerException if {@code context}, {@code modules} or {@code implementation} is {@code null}. 1087 * 1088 * @see #getDefaultSourceFileLocation(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Implementation) 1089 * @see #getDefaultSourceSectionName(org.jomc.modlet.ModelContext, org.jomc.model.Modules, org.jomc.model.Implementation) 1090 * @since 1.6 1091 */ 1092 protected SourceFilesType getDefaultSourceFilesType( final ModelContext context, final Modules modules, 1093 final Implementation implementation ) 1094 { 1095 if ( context == null ) 1096 { 1097 throw new NullPointerException( "context" ); 1098 } 1099 if ( modules == null ) 1100 { 1101 throw new NullPointerException( "modules" ); 1102 } 1103 if ( implementation == null ) 1104 { 1105 throw new NullPointerException( "implementation" ); 1106 } 1107 1108 String contextHeadComment = this.getHeadComment(); 1109 if ( ( DEFAULT_HEAD_COMMENT != null 1110 ? DEFAULT_HEAD_COMMENT.equals( contextHeadComment ) 1111 : contextHeadComment == null ) 1112 && context.getAttribute( HEAD_COMMENT_ATTRIBUTE_NAME ) instanceof String ) 1113 { 1114 contextHeadComment = (String) context.getAttribute( HEAD_COMMENT_ATTRIBUTE_NAME ); 1115 } 1116 1117 if ( contextHeadComment != null && contextHeadComment.length() == 0 ) 1118 { 1119 contextHeadComment = null; 1120 } 1121 1122 String contextTailComment = this.getTailComment(); 1123 if ( ( DEFAULT_TAIL_COMMENT != null 1124 ? DEFAULT_TAIL_COMMENT.equals( contextTailComment ) 1125 : contextTailComment == null ) 1126 && context.getAttribute( TAIL_COMMENT_ATTRIBUTE_NAME ) instanceof String ) 1127 { 1128 contextTailComment = (String) context.getAttribute( TAIL_COMMENT_ATTRIBUTE_NAME ); 1129 } 1130 1131 if ( contextTailComment != null && contextTailComment.length() == 0 ) 1132 { 1133 contextTailComment = null; 1134 } 1135 1136 final Set<String> uniqueSectionNames = new HashSet<String>( 16 ); 1137 final ArrayList<String> sectionNames = new ArrayList<String>( 16 ); 1138 sectionNames.add( LICENSE_SECTION_NAME ); 1139 sectionNames.add( ANNOTATIONS_SECTION_NAME ); 1140 sectionNames.add( DOCUMENTATION_SECTION_NAME ); 1141 sectionNames.add( CONSTRUCTORS_SECTION_NAME ); 1142 sectionNames.add( DEFAULT_CONSTRUCTOR_SECTION_NAME ); 1143 sectionNames.add( DEPENDENCIES_SECTION_NAME ); 1144 sectionNames.add( PROPERTIES_SECTION_NAME ); 1145 sectionNames.add( MESSAGES_SECTION_NAME ); 1146 1147 final SourceFilesType sourceFilesType = new SourceFilesType(); 1148 final SourceFileType sourceFileType = new SourceFileType(); 1149 sourceFilesType.getSourceFile().add( sourceFileType ); 1150 1151 final Specifications specifications = modules.getSpecifications( implementation.getIdentifier() ); 1152 final Dependencies dependencies = modules.getDependencies( implementation.getIdentifier() ); 1153 final Messages messages = modules.getMessages( implementation.getIdentifier() ); 1154 final Properties properties = modules.getProperties( implementation.getIdentifier() ); 1155 1156 sourceFileType.setIdentifier( "Default" ); 1157 sourceFileType.setLocation( this.getDefaultSourceFileLocation( context, modules, implementation ) ); 1158 1159 sourceFileType.setTemplate( IMPLEMENTATION_TEMPLATE ); 1160 sourceFileType.setHeadComment( contextHeadComment ); 1161 sourceFileType.setTailComment( contextTailComment ); 1162 sourceFileType.setSourceSections( new SourceSectionsType() ); 1163 1164 SourceSectionType s = new SourceSectionType(); 1165 s.setName( LICENSE_SECTION_NAME ); 1166 s.setHeadTemplate( IMPLEMENTATION_LICENSE_TEMPLATE ); 1167 s.setOptional( true ); 1168 sourceFileType.getSourceSections().getSourceSection().add( s ); 1169 1170 s = new SourceSectionType(); 1171 s.setName( ANNOTATIONS_SECTION_NAME ); 1172 s.setHeadTemplate( IMPLEMENTATION_ANNOTATIONS_TEMPLATE ); 1173 sourceFileType.getSourceSections().getSourceSection().add( s ); 1174 1175 s = new SourceSectionType(); 1176 s.setName( DOCUMENTATION_SECTION_NAME ); 1177 s.setHeadTemplate( IMPLEMENTATION_DOCUMENTATION_TEMPLATE ); 1178 s.setOptional( true ); 1179 sourceFileType.getSourceSections().getSourceSection().add( s ); 1180 1181 if ( specifications != null ) 1182 { 1183 sectionNames.ensureCapacity( sectionNames.size() + specifications.getSpecification().size() ); 1184 1185 for ( final Specification specification : specifications.getSpecification() ) 1186 { 1187 final String sectionName = this.getDefaultSourceSectionName( context, modules, specification ); 1188 1189 if ( sectionName != null ) 1190 { 1191 if ( !sectionNames.contains( sectionName ) ) 1192 { 1193 sectionNames.add( sectionName ); 1194 1195 s = new SourceSectionType(); 1196 s.setName( sectionName ); 1197 s.setIndentationLevel( 1 ); 1198 s.setEditable( true ); 1199 sourceFileType.getSourceSections().getSourceSection().add( s ); 1200 } 1201 else if ( uniqueSectionNames.add( sectionName ) ) 1202 { 1203 final Module module = modules.getModuleOfImplementation( implementation.getIdentifier() ); 1204 context.log( Level.WARNING, getMessage( "implementationSectionNameUniqueness", 1205 implementation.getIdentifier(), 1206 module.getName(), 1207 sourceFileType.getIdentifier(), 1208 sectionName ), 1209 null ); 1210 1211 } 1212 } 1213 } 1214 } 1215 1216 final String sectionName = this.getDefaultSourceSectionName( context, modules, implementation ); 1217 1218 if ( sectionName != null ) 1219 { 1220 if ( !sectionNames.contains( sectionName ) ) 1221 { 1222 sectionNames.add( sectionName ); 1223 1224 s = new SourceSectionType(); 1225 s.setName( sectionName ); 1226 s.setIndentationLevel( 1 ); 1227 s.setEditable( true ); 1228 sourceFileType.getSourceSections().getSourceSection().add( s ); 1229 } 1230 else if ( uniqueSectionNames.add( sectionName ) ) 1231 { 1232 final Module module = modules.getModuleOfImplementation( implementation.getIdentifier() ); 1233 context.log( Level.WARNING, getMessage( "implementationSectionNameUniqueness", 1234 implementation.getIdentifier(), 1235 module.getName(), 1236 sourceFileType.getIdentifier(), 1237 sectionName ), 1238 null ); 1239 1240 } 1241 } 1242 1243 s = new SourceSectionType(); 1244 s.setName( CONSTRUCTORS_SECTION_NAME ); 1245 s.setIndentationLevel( 1 ); 1246 s.setHeadTemplate( CONSTRUCTORS_HEAD_TEMPLATE ); 1247 s.setTailTemplate( CONSTRUCTORS_TAIL_TEMPLATE ); 1248 s.setOptional( specifications == null || ( specifications.getSpecification().isEmpty() 1249 && specifications.getReference().isEmpty() ) ); 1250 1251 s.setSourceSections( new SourceSectionsType() ); 1252 sourceFileType.getSourceSections().getSourceSection().add( s ); 1253 1254 final SourceSectionType defaultCtor = new SourceSectionType(); 1255 defaultCtor.setName( DEFAULT_CONSTRUCTOR_SECTION_NAME ); 1256 defaultCtor.setIndentationLevel( 2 ); 1257 defaultCtor.setHeadTemplate( DEFAULT_CONSTRUCTOR_TEMPLATE ); 1258 defaultCtor.setEditable( true ); 1259 s.getSourceSections().getSourceSection().add( defaultCtor ); 1260 1261 s = new SourceSectionType(); 1262 s.setName( DEPENDENCIES_SECTION_NAME ); 1263 s.setIndentationLevel( 1 ); 1264 s.setHeadTemplate( DEPENDENCIES_TEMPLATE ); 1265 s.setOptional( dependencies == null || dependencies.getDependency().isEmpty() ); 1266 sourceFileType.getSourceSections().getSourceSection().add( s ); 1267 1268 s = new SourceSectionType(); 1269 s.setName( PROPERTIES_SECTION_NAME ); 1270 s.setIndentationLevel( 1 ); 1271 s.setHeadTemplate( PROPERTIES_TEMPLATE ); 1272 s.setOptional( properties == null || properties.getProperty().isEmpty() ); 1273 sourceFileType.getSourceSections().getSourceSection().add( s ); 1274 1275 s = new SourceSectionType(); 1276 s.setName( MESSAGES_SECTION_NAME ); 1277 s.setIndentationLevel( 1 ); 1278 s.setHeadTemplate( MESSAGES_TEMPLATE ); 1279 s.setOptional( messages == null || messages.getMessage().isEmpty() ); 1280 sourceFileType.getSourceSections().getSourceSection().add( s ); 1281 1282 return sourceFilesType; 1283 } 1284 1285 /** 1286 * Overwrites a list of source code files with another list of source code files. 1287 * 1288 * @param targetSourceFiles The list to overwrite. 1289 * @param sourceSourceFiles The list to overwrite with. 1290 * @param preserveExisting {@code true}, to preserve existing attributes of source code files and sections; 1291 * {@code false}, to overwrite existing attributes of source code files and sections. 1292 * 1293 * @throws NullPointerException if {@code targetSourceFiles} or {@code sourceSourceFiles} is {@code null}. 1294 */ 1295 private void overwriteSourceFiles( final SourceFilesType targetSourceFiles, final SourceFilesType sourceSourceFiles, 1296 final boolean preserveExisting ) 1297 { 1298 if ( targetSourceFiles == null ) 1299 { 1300 throw new NullPointerException( "targetSourceFiles" ); 1301 } 1302 if ( sourceSourceFiles == null ) 1303 { 1304 throw new NullPointerException( "sourceSourceFiles" ); 1305 } 1306 1307 try 1308 { 1309 for ( final SourceFileType s : sourceSourceFiles.getSourceFile() ) 1310 { 1311 final SourceFileType targetSourceFile = targetSourceFiles.getSourceFile( s.getIdentifier() ); 1312 1313 if ( targetSourceFile != null ) 1314 { 1315 this.overwriteSourceFile( targetSourceFile, s, preserveExisting ); 1316 } 1317 } 1318 } 1319 catch ( final NoSuchFieldException e ) 1320 { 1321 throw new AssertionError( e ); 1322 } 1323 } 1324 1325 /** 1326 * Overwrites a source code file with another source code file. 1327 * 1328 * @param targetSourceFile The source code file to overwrite. 1329 * @param sourceSourceFile The source code file to overwrite with. 1330 * @param preserveExisting {@code true}, to preserve existing attributes of the given source code file and sections; 1331 * {@code false}, to overwrite existing attributes of the given source code file and sections. 1332 * 1333 * @throws NullPointerException if {@code targetSourceFile} or {@code sourceSourceFile} is {@code null}. 1334 */ 1335 private void overwriteSourceFile( final SourceFileType targetSourceFile, final SourceFileType sourceSourceFile, 1336 final boolean preserveExisting ) 1337 throws NoSuchFieldException 1338 { 1339 if ( targetSourceFile == null ) 1340 { 1341 throw new NullPointerException( "targetSourceFile" ); 1342 } 1343 if ( sourceSourceFile == null ) 1344 { 1345 throw new NullPointerException( "sourceSourceFile" ); 1346 } 1347 1348 if ( !preserveExisting ) 1349 { 1350 targetSourceFile.setIdentifier( sourceSourceFile.getIdentifier() ); 1351 targetSourceFile.setLocation( sourceSourceFile.getLocation() ); 1352 targetSourceFile.setTemplate( sourceSourceFile.getTemplate() ); 1353 targetSourceFile.setHeadComment( sourceSourceFile.getHeadComment() ); 1354 targetSourceFile.setTailComment( sourceSourceFile.getTailComment() ); 1355 1356 if ( isFieldSet( sourceSourceFile, "_final" ) ) 1357 { 1358 targetSourceFile.setFinal( sourceSourceFile.isFinal() ); 1359 } 1360 if ( isFieldSet( sourceSourceFile, "modelVersion" ) ) 1361 { 1362 targetSourceFile.setModelVersion( sourceSourceFile.getModelVersion() ); 1363 } 1364 if ( isFieldSet( sourceSourceFile, "override" ) ) 1365 { 1366 targetSourceFile.setOverride( sourceSourceFile.isOverride() ); 1367 } 1368 } 1369 1370 if ( sourceSourceFile.getSourceSections() != null ) 1371 { 1372 if ( targetSourceFile.getSourceSections() == null ) 1373 { 1374 targetSourceFile.setSourceSections( new SourceSectionsType() ); 1375 } 1376 1377 this.overwriteSourceSections( targetSourceFile.getSourceSections(), sourceSourceFile.getSourceSections(), 1378 preserveExisting ); 1379 1380 } 1381 } 1382 1383 /** 1384 * Overwrites source code file sections with other source code file sections. 1385 * 1386 * @param targetSourceSections The source code file sections to overwrite. 1387 * @param sourceSourceSections The source code file sections to overwrite with. 1388 * @param preserveExisting {@code true}, to preserve existing attributes of the given source code file sections; 1389 * {@code false}, to overwrite existing attributes of the given source code file sections. 1390 * 1391 * @throws NullPointerException if {@code targetSourceSections} or {@code sourceSourceSections} is {@code null}. 1392 */ 1393 private void overwriteSourceSections( final SourceSectionsType targetSourceSections, 1394 final SourceSectionsType sourceSourceSections, 1395 final boolean preserveExisting ) throws NoSuchFieldException 1396 { 1397 if ( targetSourceSections == null ) 1398 { 1399 throw new NullPointerException( "targetSourceSections" ); 1400 } 1401 if ( sourceSourceSections == null ) 1402 { 1403 throw new NullPointerException( "sourceSourceSections" ); 1404 } 1405 1406 for ( final SourceSectionType sourceSection : sourceSourceSections.getSourceSection() ) 1407 { 1408 SourceSectionType targetSection = null; 1409 1410 for ( final SourceSectionType t : targetSourceSections.getSourceSection() ) 1411 { 1412 if ( sourceSection.getName().equals( t.getName() ) ) 1413 { 1414 targetSection = t; 1415 break; 1416 } 1417 } 1418 1419 if ( targetSection != null ) 1420 { 1421 if ( !preserveExisting ) 1422 { 1423 targetSection.setName( sourceSection.getName() ); 1424 targetSection.setHeadTemplate( sourceSection.getHeadTemplate() ); 1425 targetSection.setTailTemplate( sourceSection.getTailTemplate() ); 1426 1427 if ( isFieldSet( sourceSection, "editable" ) ) 1428 { 1429 targetSection.setEditable( sourceSection.isEditable() ); 1430 } 1431 if ( isFieldSet( sourceSection, "indentationLevel" ) ) 1432 { 1433 targetSection.setIndentationLevel( sourceSection.getIndentationLevel() ); 1434 } 1435 if ( isFieldSet( sourceSection, "modelVersion" ) ) 1436 { 1437 targetSection.setModelVersion( sourceSection.getModelVersion() ); 1438 } 1439 if ( isFieldSet( sourceSection, "optional" ) ) 1440 { 1441 targetSection.setOptional( sourceSection.isOptional() ); 1442 } 1443 } 1444 } 1445 else 1446 { 1447 targetSection = sourceSection.clone(); 1448 targetSourceSections.getSourceSection().add( targetSection ); 1449 } 1450 1451 if ( sourceSection.getSourceSections() != null ) 1452 { 1453 if ( targetSection.getSourceSections() == null ) 1454 { 1455 targetSection.setSourceSections( new SourceSectionsType() ); 1456 } 1457 1458 this.overwriteSourceSections( targetSection.getSourceSections(), sourceSection.getSourceSections(), 1459 preserveExisting ); 1460 } 1461 } 1462 } 1463 1464 private static boolean isFieldSet( final Object object, final String fieldName ) throws NoSuchFieldException 1465 { 1466 final Field field = getField( object.getClass(), fieldName ); 1467 1468 if ( field == null ) 1469 { 1470 throw new NoSuchFieldException( fieldName ); 1471 } 1472 1473 final boolean accessible = field.isAccessible(); 1474 1475 try 1476 { 1477 field.setAccessible( true ); 1478 return field.get( object ) != null; 1479 } 1480 catch ( final IllegalAccessException e ) 1481 { 1482 throw new AssertionError( e ); 1483 } 1484 finally 1485 { 1486 field.setAccessible( accessible ); 1487 } 1488 } 1489 1490 private static Field getField( final Class<?> clazz, final String name ) 1491 { 1492 if ( clazz != null ) 1493 { 1494 try 1495 { 1496 return clazz.getDeclaredField( name ); 1497 } 1498 catch ( final NoSuchFieldException e ) 1499 { 1500 return getField( clazz.getSuperclass(), name ); 1501 } 1502 } 1503 1504 return null; 1505 } 1506 1507 private static String getMessage( final Throwable t ) 1508 { 1509 return t != null 1510 ? t.getMessage() != null && t.getMessage().trim().length() > 0 1511 ? t.getMessage() 1512 : getMessage( t.getCause() ) 1513 : null; 1514 1515 } 1516 1517 private static String getMessage( final String key, final Object... args ) 1518 { 1519 return MessageFormat.format( ResourceBundle.getBundle( 1520 ToolsModelProvider.class.getName().replace( '.', '/' ), Locale.getDefault() ).getString( key ), args ); 1521 1522 } 1523 1524}