| 1 | /* | 
| 2 |  *   Copyright (C) Christian Schulte, 2005-206 | 
| 3 |  *   All rights reserved. | 
| 4 |  * | 
| 5 |  *   Redistribution and use in source and binary forms, with or without | 
| 6 |  *   modification, are permitted provided that the following conditions | 
| 7 |  *   are met: | 
| 8 |  * | 
| 9 |  *     o Redistributions of source code must retain the above copyright | 
| 10 |  *       notice, this list of conditions and the following disclaimer. | 
| 11 |  * | 
| 12 |  *     o Redistributions in binary form must reproduce the above copyright | 
| 13 |  *       notice, this list of conditions and the following disclaimer in | 
| 14 |  *       the documentation and/or other materials provided with the | 
| 15 |  *       distribution. | 
| 16 |  * | 
| 17 |  *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | 
| 18 |  *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | 
| 19 |  *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | 
| 20 |  *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, | 
| 21 |  *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
| 22 |  *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
| 23 |  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
| 24 |  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 25 |  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 
| 26 |  *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 27 |  * | 
| 28 |  *   $JOMC: ToolsModelProcessor.java 4829 2014-01-03 04:24:59Z schulte $ | 
| 29 |  * | 
| 30 |  */ | 
| 31 | package org.jomc.tools.modlet; | 
| 32 |   | 
| 33 | import java.lang.reflect.Field; | 
| 34 | import java.text.MessageFormat; | 
| 35 | import java.util.Locale; | 
| 36 | import java.util.ResourceBundle; | 
| 37 | import java.util.logging.Level; | 
| 38 | import org.jomc.model.Dependencies; | 
| 39 | import org.jomc.model.Implementation; | 
| 40 | import org.jomc.model.JavaTypeName; | 
| 41 | import org.jomc.model.Messages; | 
| 42 | import org.jomc.model.ModelObjectException; | 
| 43 | import org.jomc.model.Module; | 
| 44 | import org.jomc.model.Modules; | 
| 45 | import org.jomc.model.Properties; | 
| 46 | import org.jomc.model.Specification; | 
| 47 | import org.jomc.model.Specifications; | 
| 48 | import org.jomc.model.modlet.ModelHelper; | 
| 49 | import org.jomc.modlet.Model; | 
| 50 | import org.jomc.modlet.ModelContext; | 
| 51 | import org.jomc.modlet.ModelException; | 
| 52 | import org.jomc.modlet.ModelProcessor; | 
| 53 | import org.jomc.tools.model.SourceFileType; | 
| 54 | import org.jomc.tools.model.SourceFilesType; | 
| 55 | import org.jomc.tools.model.SourceSectionType; | 
| 56 | import org.jomc.tools.model.SourceSectionsType; | 
| 57 | import static org.jomc.tools.modlet.ToolsModletConstants.ANNOTATIONS_SECTION_NAME; | 
| 58 | import static org.jomc.tools.modlet.ToolsModletConstants.CONSTRUCTORS_HEAD_TEMPLATE; | 
| 59 | import static org.jomc.tools.modlet.ToolsModletConstants.CONSTRUCTORS_SECTION_NAME; | 
| 60 | import static org.jomc.tools.modlet.ToolsModletConstants.CONSTRUCTORS_TAIL_TEMPLATE; | 
| 61 | import static org.jomc.tools.modlet.ToolsModletConstants.DEFAULT_CONSTRUCTOR_SECTION_NAME; | 
| 62 | import static org.jomc.tools.modlet.ToolsModletConstants.DEFAULT_CONSTRUCTOR_TEMPLATE; | 
| 63 | import static org.jomc.tools.modlet.ToolsModletConstants.DEPENDENCIES_SECTION_NAME; | 
| 64 | import static org.jomc.tools.modlet.ToolsModletConstants.DEPENDENCIES_TEMPLATE; | 
| 65 | import static org.jomc.tools.modlet.ToolsModletConstants.DOCUMENTATION_SECTION_NAME; | 
| 66 | import static org.jomc.tools.modlet.ToolsModletConstants.IMPLEMENTATION_ANNOTATIONS_TEMPLATE; | 
| 67 | import static org.jomc.tools.modlet.ToolsModletConstants.IMPLEMENTATION_DOCUMENTATION_TEMPLATE; | 
| 68 | import static org.jomc.tools.modlet.ToolsModletConstants.IMPLEMENTATION_LICENSE_TEMPLATE; | 
| 69 | import static org.jomc.tools.modlet.ToolsModletConstants.IMPLEMENTATION_TEMPLATE; | 
| 70 | import static org.jomc.tools.modlet.ToolsModletConstants.LICENSE_SECTION_NAME; | 
| 71 | import static org.jomc.tools.modlet.ToolsModletConstants.MESSAGES_SECTION_NAME; | 
| 72 | import static org.jomc.tools.modlet.ToolsModletConstants.MESSAGES_TEMPLATE; | 
| 73 | import static org.jomc.tools.modlet.ToolsModletConstants.PROPERTIES_SECTION_NAME; | 
| 74 | import static org.jomc.tools.modlet.ToolsModletConstants.PROPERTIES_TEMPLATE; | 
| 75 | import static org.jomc.tools.modlet.ToolsModletConstants.SPECIFICATION_ANNOTATIONS_TEMPLATE; | 
| 76 | import static org.jomc.tools.modlet.ToolsModletConstants.SPECIFICATION_DOCUMENTATION_TEMPLATE; | 
| 77 | import static org.jomc.tools.modlet.ToolsModletConstants.SPECIFICATION_LICENSE_TEMPLATE; | 
| 78 | import static org.jomc.tools.modlet.ToolsModletConstants.SPECIFICATION_TEMPLATE; | 
| 79 |   | 
| 80 | /** | 
| 81 |  * Object management and configuration tools {@code ModelProcessor} implementation. | 
| 82 |  * | 
| 83 |  * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> | 
| 84 |  * @version $JOMC: ToolsModelProcessor.java 4829 2014-01-03 04:24:59Z schulte $ | 
| 85 |  * @see ModelContext#processModel(org.jomc.modlet.Model) | 
| 86 |  * @since 1.2 | 
| 87 |  */ | 
| 88 | public class ToolsModelProcessor implements ModelProcessor | 
| 89 | { | 
| 90 |   | 
| 91 |     /** | 
| 92 |      * Constant for the name of the model context attribute backing property {@code enabled}. | 
| 93 |      * @see #processModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) | 
| 94 |      * @see ModelContext#getAttribute(java.lang.String) | 
| 95 |      */ | 
| 96 |     public static final String ENABLED_ATTRIBUTE_NAME = "org.jomc.tools.modlet.ToolsModelProcessor.enabledAttribute"; | 
| 97 |   | 
| 98 |     /** | 
| 99 |      * Constant for the name of the system property controlling property {@code defaultEnabled}. | 
| 100 |      * @see #isDefaultEnabled() | 
| 101 |      */ | 
| 102 |     private static final String DEFAULT_ENABLED_PROPERTY_NAME = | 
| 103 |         "org.jomc.tools.modlet.ToolsModelProcessor.defaultEnabled"; | 
| 104 |   | 
| 105 |     /** | 
| 106 |      * Default value of the flag indicating the processor is enabled by default. | 
| 107 |      * @see #isDefaultEnabled() | 
| 108 |      */ | 
| 109 |     private static final Boolean DEFAULT_ENABLED = Boolean.TRUE; | 
| 110 |   | 
| 111 |     /** Flag indicating the processor is enabled by default. */ | 
| 112 |     private static volatile Boolean defaultEnabled; | 
| 113 |   | 
| 114 |     /** Flag indicating the processor is enabled. */ | 
| 115 |     private Boolean enabled; | 
| 116 |   | 
| 117 |     /** | 
| 118 |      * Constant for the name of the model context attribute backing property | 
| 119 |      * {@code modelObjectClasspathResolutionEnabled}. | 
| 120 |      * | 
| 121 |      * @see #processModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) | 
| 122 |      * @see ModelContext#getAttribute(java.lang.String) | 
| 123 |      */ | 
| 124 |     public static final String MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME = | 
| 125 |         "org.jomc.tools.modlet.ToolsModelProcessor.modelObjectClasspathResolutionEnabledAttribute"; | 
| 126 |   | 
| 127 |     /** | 
| 128 |      * Constant for the name of the system property controlling property | 
| 129 |      * {@code defaultModelObjectClasspathResolutionEnabled}. | 
| 130 |      * @see #isDefaultModelObjectClasspathResolutionEnabled() | 
| 131 |      */ | 
| 132 |     private static final String DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_PROPERTY_NAME = | 
| 133 |         "org.jomc.tools.modlet.ToolsModelProcessor.defaultModelObjectClasspathResolutionEnabled"; | 
| 134 |   | 
| 135 |     /** | 
| 136 |      * Default value of the flag indicating model object class path resolution is enabled by default. | 
| 137 |      * @see #isDefaultModelObjectClasspathResolutionEnabled() | 
| 138 |      */ | 
| 139 |     private static final Boolean DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED = Boolean.TRUE; | 
| 140 |   | 
| 141 |     /** Flag indicating model object class path resolution is enabled by default. */ | 
| 142 |     private static volatile Boolean defaultModelObjectClasspathResolutionEnabled; | 
| 143 |   | 
| 144 |     /** Flag indicating model object class path resolution is enabled. */ | 
| 145 |     private Boolean modelObjectClasspathResolutionEnabled; | 
| 146 |   | 
| 147 |     /** | 
| 148 |      * Constant for the name of the model context attribute backing property {@code headComment}. | 
| 149 |      * @see #processModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) | 
| 150 |      * @see ModelContext#getAttribute(java.lang.String) | 
| 151 |      * @since 1.6 | 
| 152 |      */ | 
| 153 |     public static final String HEAD_COMMENT_ATTRIBUTE_NAME = | 
| 154 |         "org.jomc.tools.modlet.ToolsModelProcessor.headCommentAttribute"; | 
| 155 |   | 
| 156 |     /** | 
| 157 |      * Constant for the name of the system property controlling property {@code defaultHeadComment}. | 
| 158 |      * @see #getDefaultHeadComment() | 
| 159 |      * @since 1.6 | 
| 160 |      */ | 
| 161 |     private static final String DEFAULT_HEAD_COMMENT_PROPERTY_NAME = | 
| 162 |         "org.jomc.tools.modlet.ToolsModelProcessor.defaultHeadComment"; | 
| 163 |   | 
| 164 |     /** | 
| 165 |      * Default head comment the processor is applying by default. | 
| 166 |      * @see #getDefaultHeadComment() | 
| 167 |      * @since 1.6 | 
| 168 |      */ | 
| 169 |     private static final String DEFAULT_HEAD_COMMENT = "//"; | 
| 170 |   | 
| 171 |     /** | 
| 172 |      * Head comment the processor is applying by default. | 
| 173 |      * @since 1.6 | 
| 174 |      */ | 
| 175 |     private static volatile String defaultHeadComment; | 
| 176 |   | 
| 177 |     /** | 
| 178 |      * Head comment the processor is applying. | 
| 179 |      * @since 1.6 | 
| 180 |      */ | 
| 181 |     private String headComment; | 
| 182 |   | 
| 183 |     /** | 
| 184 |      * Constant for the name of the model context attribute backing property {@code tailComment}. | 
| 185 |      * @see #processModel(org.jomc.modlet.ModelContext, org.jomc.modlet.Model) | 
| 186 |      * @see ModelContext#getAttribute(java.lang.String) | 
| 187 |      * @since 1.6 | 
| 188 |      */ | 
| 189 |     public static final String TAIL_COMMENT_ATTRIBUTE_NAME = | 
| 190 |         "org.jomc.tools.modlet.ToolsModelProcessor.tailCommentAttribute"; | 
| 191 |   | 
| 192 |     /** | 
| 193 |      * Constant for the name of the system property controlling property {@code defaultTailComment}. | 
| 194 |      * @see #getDefaultTailComment() | 
| 195 |      * @since 1.6 | 
| 196 |      */ | 
| 197 |     private static final String DEFAULT_TAIL_COMMENT_PROPERTY_NAME = | 
| 198 |         "org.jomc.tools.modlet.ToolsModelProcessor.defaultTailComment"; | 
| 199 |   | 
| 200 |     /** | 
| 201 |      * Default tail comment the processor is applying by default. | 
| 202 |      * @see #getDefaultTailComment() | 
| 203 |      * @since 1.6 | 
| 204 |      */ | 
| 205 |     private static final String DEFAULT_TAIL_COMMENT = null; | 
| 206 |   | 
| 207 |     /** | 
| 208 |      * Tail comment the processor is applying by default. | 
| 209 |      * @since 1.6 | 
| 210 |      */ | 
| 211 |     private static volatile String defaultTailComment; | 
| 212 |   | 
| 213 |     /** | 
| 214 |      * Tail comment the processor is applying. | 
| 215 |      * @since 1.6 | 
| 216 |      */ | 
| 217 |     private String tailComment; | 
| 218 |   | 
| 219 |     /** Creates a new {@code ToolsModelProcessor} instance. */ | 
| 220 |     public ToolsModelProcessor() | 
| 221 |     { | 
| 222 |         super(); | 
| 223 |     } | 
| 224 |   | 
| 225 |     /** | 
| 226 |      * Gets a flag indicating the processor is enabled by default. | 
| 227 |      * <p>The default enabled flag is controlled by system property | 
| 228 |      * {@code org.jomc.tools.modlet.ToolsModelProcessor.defaultEnabled} holding a value indicating the processor is | 
| 229 |      * enabled by default. If that property is not set, the {@code true} default is returned.</p> | 
| 230 |      * | 
| 231 |      * @return {@code true}, if the processor is enabled by default; {@code false}, if the processor is disabled by | 
| 232 |      * default. | 
| 233 |      * | 
| 234 |      * @see #setDefaultEnabled(java.lang.Boolean) | 
| 235 |      */ | 
| 236 |     public static boolean isDefaultEnabled() | 
| 237 |     { | 
| 238 |         if ( defaultEnabled == null ) | 
| 239 |         { | 
| 240 |             defaultEnabled = Boolean.valueOf( System.getProperty( DEFAULT_ENABLED_PROPERTY_NAME, | 
| 241 |                                                                   Boolean.toString( DEFAULT_ENABLED ) ) ); | 
| 242 |   | 
| 243 |         } | 
| 244 |   | 
| 245 |         return defaultEnabled; | 
| 246 |     } | 
| 247 |   | 
| 248 |     /** | 
| 249 |      * Sets the flag indicating the processor is enabled by default. | 
| 250 |      * | 
| 251 |      * @param value The new value of the flag indicating the processor is enabled by default or {@code null}. | 
| 252 |      * | 
| 253 |      * @see #isDefaultEnabled() | 
| 254 |      */ | 
| 255 |     public static void setDefaultEnabled( final Boolean value ) | 
| 256 |     { | 
| 257 |         defaultEnabled = value; | 
| 258 |     } | 
| 259 |   | 
| 260 |     /** | 
| 261 |      * Gets a flag indicating the processor is enabled. | 
| 262 |      * | 
| 263 |      * @return {@code true}, if the processor is enabled; {@code false}, if the processor is disabled. | 
| 264 |      * | 
| 265 |      * @see #isDefaultEnabled() | 
| 266 |      * @see #setEnabled(java.lang.Boolean) | 
| 267 |      */ | 
| 268 |     public final boolean isEnabled() | 
| 269 |     { | 
| 270 |         if ( this.enabled == null ) | 
| 271 |         { | 
| 272 |             this.enabled = isDefaultEnabled(); | 
| 273 |         } | 
| 274 |   | 
| 275 |         return this.enabled; | 
| 276 |     } | 
| 277 |   | 
| 278 |     /** | 
| 279 |      * Sets the flag indicating the processor is enabled. | 
| 280 |      * | 
| 281 |      * @param value The new value of the flag indicating the processor is enabled or {@code null}. | 
| 282 |      * | 
| 283 |      * @see #isEnabled() | 
| 284 |      */ | 
| 285 |     public final void setEnabled( final Boolean value ) | 
| 286 |     { | 
| 287 |         this.enabled = value; | 
| 288 |     } | 
| 289 |   | 
| 290 |     /** | 
| 291 |      * Gets a flag indicating model object class path resolution is enabled by default. | 
| 292 |      * <p>The model object class path resolution default enabled flag is controlled by system property | 
| 293 |      * {@code org.jomc.tools.modlet.ToolsModelProcessor.defaultModelObjectClasspathResolutionEnabled} holding a value | 
| 294 |      * indicating model object class path resolution is enabled by default. If that property is not set, the | 
| 295 |      * {@code true} default is returned.</p> | 
| 296 |      * | 
| 297 |      * @return {@code true}, if model object class path resolution is enabled by default; {@code false}, if model object | 
| 298 |      * class path resolution is disabled by default. | 
| 299 |      * | 
| 300 |      * @see #setDefaultModelObjectClasspathResolutionEnabled(java.lang.Boolean) | 
| 301 |      */ | 
| 302 |     public static boolean isDefaultModelObjectClasspathResolutionEnabled() | 
| 303 |     { | 
| 304 |         if ( defaultModelObjectClasspathResolutionEnabled == null ) | 
| 305 |         { | 
| 306 |             defaultModelObjectClasspathResolutionEnabled = Boolean.valueOf( System.getProperty( | 
| 307 |                 DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_PROPERTY_NAME, | 
| 308 |                 Boolean.toString( DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED ) ) ); | 
| 309 |   | 
| 310 |         } | 
| 311 |   | 
| 312 |         return defaultModelObjectClasspathResolutionEnabled; | 
| 313 |     } | 
| 314 |   | 
| 315 |     /** | 
| 316 |      * Sets the flag indicating model object class path resolution is enabled by default. | 
| 317 |      * | 
| 318 |      * @param value The new value of the flag indicating model object class path resolution is enabled by default or | 
| 319 |      * {@code null}. | 
| 320 |      * | 
| 321 |      * @see #isDefaultModelObjectClasspathResolutionEnabled() | 
| 322 |      */ | 
| 323 |     public static void setDefaultModelObjectClasspathResolutionEnabled( final Boolean value ) | 
| 324 |     { | 
| 325 |         defaultModelObjectClasspathResolutionEnabled = value; | 
| 326 |     } | 
| 327 |   | 
| 328 |     /** | 
| 329 |      * Gets a flag indicating model object class path resolution is enabled. | 
| 330 |      * | 
| 331 |      * @return {@code true}, if model object class path resolution is enabled; {@code false}, if model object class path | 
| 332 |      * resolution is disabled. | 
| 333 |      * | 
| 334 |      * @see #isDefaultModelObjectClasspathResolutionEnabled() | 
| 335 |      * @see #setModelObjectClasspathResolutionEnabled(java.lang.Boolean) | 
| 336 |      */ | 
| 337 |     public final boolean isModelObjectClasspathResolutionEnabled() | 
| 338 |     { | 
| 339 |         if ( this.modelObjectClasspathResolutionEnabled == null ) | 
| 340 |         { | 
| 341 |             this.modelObjectClasspathResolutionEnabled = isDefaultModelObjectClasspathResolutionEnabled(); | 
| 342 |         } | 
| 343 |   | 
| 344 |         return this.modelObjectClasspathResolutionEnabled; | 
| 345 |     } | 
| 346 |   | 
| 347 |     /** | 
| 348 |      * Sets the flag indicating model object class path resolution is is enabled. | 
| 349 |      * | 
| 350 |      * @param value The new value of the flag indicating model object class path resolution is enabled or {@code null}. | 
| 351 |      * | 
| 352 |      * @see #isModelObjectClasspathResolutionEnabled() | 
| 353 |      */ | 
| 354 |     public final void setModelObjectClasspathResolutionEnabled( final Boolean value ) | 
| 355 |     { | 
| 356 |         this.modelObjectClasspathResolutionEnabled = value; | 
| 357 |     } | 
| 358 |   | 
| 359 |     /** | 
| 360 |      * Gets the head comment the processor is applying by default. | 
| 361 |      * <p>The default head comment is controlled by system property | 
| 362 |      * {@code org.jomc.tools.modlet.ToolsModelProcessor.defaultHeadComment} holding the head comment the processor is | 
| 363 |      * applying by default. If that property is not set, the {@code //} default is returned.</p> | 
| 364 |      * | 
| 365 |      * @return The head comment the processor is applying by default or {@code null}. | 
| 366 |      * | 
| 367 |      * @see #setDefaultHeadComment(java.lang.String) | 
| 368 |      * @since 1.6 | 
| 369 |      */ | 
| 370 |     public static String getDefaultHeadComment() | 
| 371 |     { | 
| 372 |         if ( defaultHeadComment == null ) | 
| 373 |         { | 
| 374 |             defaultHeadComment = System.getProperty( DEFAULT_HEAD_COMMENT_PROPERTY_NAME, DEFAULT_HEAD_COMMENT ); | 
| 375 |         } | 
| 376 |   | 
| 377 |         return defaultHeadComment; | 
| 378 |     } | 
| 379 |   | 
| 380 |     /** | 
| 381 |      * Sets the head comment the processor is applying by default. | 
| 382 |      * | 
| 383 |      * @param value The new head comment the processor is applying by default or {@code null}. | 
| 384 |      * | 
| 385 |      * @see #getDefaultHeadComment() | 
| 386 |      * @since 1.6 | 
| 387 |      */ | 
| 388 |     public static void setDefaultHeadComment( final String value ) | 
| 389 |     { | 
| 390 |         defaultHeadComment = value; | 
| 391 |     } | 
| 392 |   | 
| 393 |     /** | 
| 394 |      * Gets the head comment the processor is applying. | 
| 395 |      * | 
| 396 |      * @return The head comment the processor is applying or {@code null}. | 
| 397 |      * | 
| 398 |      * @see #getDefaultHeadComment() | 
| 399 |      * @see #setDefaultHeadComment(java.lang.String) | 
| 400 |      * @since 1.6 | 
| 401 |      */ | 
| 402 |     public final String getHeadComment() | 
| 403 |     { | 
| 404 |         if ( this.headComment == null ) | 
| 405 |         { | 
| 406 |             this.headComment = getDefaultHeadComment(); | 
| 407 |         } | 
| 408 |   | 
| 409 |         return this.headComment; | 
| 410 |     } | 
| 411 |   | 
| 412 |     /** | 
| 413 |      * Sets the head comment the processor is applying. | 
| 414 |      * | 
| 415 |      * @param value The new head comment the processor is applying or {@code null}. | 
| 416 |      * | 
| 417 |      * @see #getHeadComment() | 
| 418 |      * @since 1.6 | 
| 419 |      */ | 
| 420 |     public final void setHeadComment( final String value ) | 
| 421 |     { | 
| 422 |         this.headComment = value; | 
| 423 |     } | 
| 424 |   | 
| 425 |     /** | 
| 426 |      * Gets the tail comment the processor is applying by default. | 
| 427 |      * <p>The default tail comment is controlled by system property | 
| 428 |      * {@code org.jomc.tools.modlet.ToolsModelProcessor.defaultTailComment} holding the tail comment the processor is | 
| 429 |      * applying by default. If that property is not set, the {@code null} default is returned.</p> | 
| 430 |      * | 
| 431 |      * @return The tail comment the processor is applying by default or {@code null}. | 
| 432 |      * | 
| 433 |      * @see #setDefaultTailComment(java.lang.String) | 
| 434 |      * @since 1.6 | 
| 435 |      */ | 
| 436 |     public static String getDefaultTailComment() | 
| 437 |     { | 
| 438 |         if ( defaultTailComment == null ) | 
| 439 |         { | 
| 440 |             defaultTailComment = System.getProperty( DEFAULT_TAIL_COMMENT_PROPERTY_NAME, DEFAULT_TAIL_COMMENT ); | 
| 441 |         } | 
| 442 |   | 
| 443 |         return defaultTailComment; | 
| 444 |     } | 
| 445 |   | 
| 446 |     /** | 
| 447 |      * Sets the tail comment the processor is applying by default. | 
| 448 |      * | 
| 449 |      * @param value The new tail comment the processor is applying by default or {@code null}. | 
| 450 |      * | 
| 451 |      * @see #getDefaultTailComment() | 
| 452 |      * @since 1.6 | 
| 453 |      */ | 
| 454 |     public static void setDefaultTailComment( final String value ) | 
| 455 |     { | 
| 456 |         defaultTailComment = value; | 
| 457 |     } | 
| 458 |   | 
| 459 |     /** | 
| 460 |      * Gets the tail comment the processor is applying. | 
| 461 |      * | 
| 462 |      * @return The tail comment the processor is applying or {@code null}. | 
| 463 |      * | 
| 464 |      * @see #getDefaultTailComment() | 
| 465 |      * @see #setDefaultTailComment(java.lang.String) | 
| 466 |      * @since 1.6 | 
| 467 |      */ | 
| 468 |     public final String getTailComment() | 
| 469 |     { | 
| 470 |         if ( this.tailComment == null ) | 
| 471 |         { | 
| 472 |             this.tailComment = getDefaultTailComment(); | 
| 473 |         } | 
| 474 |   | 
| 475 |         return this.tailComment; | 
| 476 |     } | 
| 477 |   | 
| 478 |     /** | 
| 479 |      * Sets the tail comment the processor is applying. | 
| 480 |      * | 
| 481 |      * @param value The new tail comment the processor is applying or {@code null}. | 
| 482 |      * | 
| 483 |      * @see #getTailComment() | 
| 484 |      * @since 1.6 | 
| 485 |      */ | 
| 486 |     public final void setTailComment( final String value ) | 
| 487 |     { | 
| 488 |         this.tailComment = value; | 
| 489 |     } | 
| 490 |   | 
| 491 |     /** | 
| 492 |      * {@inheritDoc} | 
| 493 |      * | 
| 494 |      * @see #isEnabled() | 
| 495 |      * @see #isModelObjectClasspathResolutionEnabled() | 
| 496 |      * @see #getHeadComment() | 
| 497 |      * @see #getTailComment() | 
| 498 |      * @see #ENABLED_ATTRIBUTE_NAME | 
| 499 |      * @see #MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME | 
| 500 |      * @see #HEAD_COMMENT_ATTRIBUTE_NAME | 
| 501 |      * @see #TAIL_COMMENT_ATTRIBUTE_NAME | 
| 502 |      */ | 
| 503 |     public Model processModel( final ModelContext context, final Model model ) throws ModelException | 
| 504 |     { | 
| 505 |         if ( context == null ) | 
| 506 |         { | 
| 507 |             throw new NullPointerException( "context" ); | 
| 508 |         } | 
| 509 |         if ( model == null ) | 
| 510 |         { | 
| 511 |             throw new NullPointerException( "model" ); | 
| 512 |         } | 
| 513 |   | 
| 514 |         Model processed = model; | 
| 515 |   | 
| 516 |         boolean contextEnabled = this.isEnabled(); | 
| 517 |         if ( DEFAULT_ENABLED == contextEnabled && context.getAttribute( ENABLED_ATTRIBUTE_NAME ) instanceof Boolean ) | 
| 518 |         { | 
| 519 |             contextEnabled = (Boolean) context.getAttribute( ENABLED_ATTRIBUTE_NAME ); | 
| 520 |         } | 
| 521 |   | 
| 522 |         boolean contextModelObjectClasspathResolutionEnabled = this.isModelObjectClasspathResolutionEnabled(); | 
| 523 |         if ( contextModelObjectClasspathResolutionEnabled == DEFAULT_MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED | 
| 524 |              && context.getAttribute( MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME ) instanceof Boolean ) | 
| 525 |         { | 
| 526 |             contextModelObjectClasspathResolutionEnabled = | 
| 527 |                 (Boolean) context.getAttribute( MODEL_OBJECT_CLASSPATH_RESOLUTION_ENABLED_ATTRIBUTE_NAME ); | 
| 528 |   | 
| 529 |         } | 
| 530 |   | 
| 531 |         if ( contextEnabled ) | 
| 532 |         { | 
| 533 |             processed = model.clone(); | 
| 534 |             final Modules modules = ModelHelper.getModules( processed ); | 
| 535 |   | 
| 536 |             if ( modules != null ) | 
| 537 |             { | 
| 538 |                 Module classpathModule = null; | 
| 539 |                 if ( contextModelObjectClasspathResolutionEnabled ) | 
| 540 |                 { | 
| 541 |                     classpathModule = modules.getClasspathModule( Modules.getDefaultClasspathModuleName(), | 
| 542 |                                                                   context.getClassLoader() ); | 
| 543 |   | 
| 544 |                     if ( classpathModule != null | 
| 545 |                          && modules.getModule( Modules.getDefaultClasspathModuleName() ) == null ) | 
| 546 |                     { | 
| 547 |                         modules.getModule().add( classpathModule ); | 
| 548 |                     } | 
| 549 |                     else | 
| 550 |                     { | 
| 551 |                         classpathModule = null; | 
| 552 |                     } | 
| 553 |                 } | 
| 554 |   | 
| 555 |                 if ( modules.getSpecifications() != null ) | 
| 556 |                 { | 
| 557 |                     for ( int i = 0, s0 = modules.getSpecifications().getSpecification().size(); i < s0; i++ ) | 
| 558 |                     { | 
| 559 |                         final Specification specification = modules.getSpecifications().getSpecification().get( i ); | 
| 560 |                         final SourceFileType sourceFileType = specification.getAnyObject( SourceFileType.class ); | 
| 561 |                         final SourceFilesType sourceFilesType = specification.getAnyObject( SourceFilesType.class ); | 
| 562 |   | 
| 563 |                         if ( sourceFileType != null ) | 
| 564 |                         { | 
| 565 |                             if ( sourceFileType.getLocation() == null && specification.getClazz() != null ) | 
| 566 |                             { | 
| 567 |                                 // As of 1.2, the 'location' attribute got updated from 'required' to 'optional'. | 
| 568 |                                 sourceFileType.setLocation( new StringBuilder( specification.getClazz().length() + 5 ). | 
| 569 |                                     append( specification.getClazz().replace( '.', '/' ) ).append( ".java" ). | 
| 570 |                                     toString() ); | 
| 571 |   | 
| 572 |                             } | 
| 573 |   | 
| 574 |                             if ( sourceFileType.getHeadComment() == null ) | 
| 575 |                             { | 
| 576 |                                 // As of 1.2, the 'head-comment' and 'tail-comment' attributes got introduced. | 
| 577 |                                 sourceFileType.setHeadComment( "//" ); | 
| 578 |                             } | 
| 579 |                         } | 
| 580 |   | 
| 581 |                         if ( sourceFilesType != null ) | 
| 582 |                         { | 
| 583 |                             this.applyDefaults( context, modules, specification, sourceFilesType ); | 
| 584 |                         } | 
| 585 |                     } | 
| 586 |                 } | 
| 587 |   | 
| 588 |                 if ( modules.getImplementations() != null ) | 
| 589 |                 { | 
| 590 |                     for ( int i = 0, s0 = modules.getImplementations().getImplementation().size(); i < s0; i++ ) | 
| 591 |                     { | 
| 592 |                         final Implementation implementation = modules.getImplementations().getImplementation().get( i ); | 
| 593 |                         final SourceFileType sourceFileType = implementation.getAnyObject( SourceFileType.class ); | 
| 594 |                         final SourceFilesType sourceFilesType = implementation.getAnyObject( SourceFilesType.class ); | 
| 595 |   | 
| 596 |                         if ( sourceFileType != null ) | 
| 597 |                         { | 
| 598 |                             if ( sourceFileType.getLocation() == null && implementation.getClazz() != null ) | 
| 599 |                             { | 
| 600 |                                 // As of 1.2, the 'location' attribute got updated from 'required' to 'optional'. | 
| 601 |                                 sourceFileType.setLocation( new StringBuilder( implementation.getClazz().length() + 5 ). | 
| 602 |                                     append( implementation.getClazz().replace( '.', '/' ) ).append( ".java" ). | 
| 603 |                                     toString() ); | 
| 604 |   | 
| 605 |                             } | 
| 606 |   | 
| 607 |                             if ( sourceFileType.getHeadComment() == null ) | 
| 608 |                             { | 
| 609 |                                 // As of 1.2, the 'head-comment' and 'tail-comment' attributes got introduced. | 
| 610 |                                 sourceFileType.setHeadComment( "//" ); | 
| 611 |                             } | 
| 612 |                         } | 
| 613 |   | 
| 614 |                         if ( sourceFilesType != null ) | 
| 615 |                         { | 
| 616 |                             this.applyDefaults( context, modules, implementation, sourceFilesType ); | 
| 617 |                         } | 
| 618 |                     } | 
| 619 |                 } | 
| 620 |   | 
| 621 |                 if ( classpathModule != null ) | 
| 622 |                 { | 
| 623 |                     modules.getModule().remove( classpathModule ); | 
| 624 |                 } | 
| 625 |             } | 
| 626 |         } | 
| 627 |         else if ( context.isLoggable( Level.FINER ) ) | 
| 628 |         { | 
| 629 |             context.log( Level.FINER, getMessage( "disabled", this.getClass().getSimpleName(), | 
| 630 |                                                   model.getIdentifier() ), null ); | 
| 631 |   | 
| 632 |         } | 
| 633 |   | 
| 634 |         return processed; | 
| 635 |     } | 
| 636 |   | 
| 637 |     /** | 
| 638 |      * Gets the default source code file location for a given specification. | 
| 639 |      * <p>If the specification provides a Java type name, this method returns a Java source code file location based on | 
| 640 |      * that Java type name.</p> | 
| 641 |      * | 
| 642 |      * @param context The context to get the default location with. | 
| 643 |      * @param modules The model to get the default location with. | 
| 644 |      * @param specification The specification to get the default location for. | 
| 645 |      * | 
| 646 |      * @return The default location for {@code specification} or {@code null}. | 
| 647 |      * | 
| 648 |      * @throws NullPointerExeption if {@code context}, {@code modules} or {@code specification} is {@code null}. | 
| 649 |      * | 
| 650 |      * @see SourceFileType#getLocation() | 
| 651 |      * @see Specification#getJavaTypeName() | 
| 652 |      * @since 1.6 | 
| 653 |      */ | 
| 654 |     protected String getDefaultSourceFileLocation( final ModelContext context, final Modules modules, | 
| 655 |                                                    final Specification specification ) | 
| 656 |     { | 
| 657 |         if ( context == null ) | 
| 658 |         { | 
| 659 |             throw new NullPointerException( "context" ); | 
| 660 |         } | 
| 661 |         if ( modules == null ) | 
| 662 |         { | 
| 663 |             throw new NullPointerException( "modules" ); | 
| 664 |         } | 
| 665 |         if ( specification == null ) | 
| 666 |         { | 
| 667 |             throw new NullPointerException( "specification" ); | 
| 668 |         } | 
| 669 |   | 
| 670 |         String location = null; | 
| 671 |   | 
| 672 |         try | 
| 673 |         { | 
| 674 |             if ( specification.getJavaTypeName() != null ) | 
| 675 |             { | 
| 676 |                 location = specification.getJavaTypeName().getQualifiedName().replace( '.', '/' ) + ".java"; | 
| 677 |             } | 
| 678 |         } | 
| 679 |         catch ( final ModelObjectException e ) | 
| 680 |         { | 
| 681 |             context.log( Level.WARNING, getMessage( e ), null ); | 
| 682 |         } | 
| 683 |   | 
| 684 |         return location; | 
| 685 |     } | 
| 686 |   | 
| 687 |     /** | 
| 688 |      * Gets the default source code file location for a given implementation. | 
| 689 |      * <p>If the implementation provides a Java type name, this method returns a Java source code file location based on | 
| 690 |      * that Java type name.</p> | 
| 691 |      * | 
| 692 |      * @param context The context to get the default location with. | 
| 693 |      * @param modules The model to get the default location with. | 
| 694 |      * @param implementation The implementation to get the default location for. | 
| 695 |      * | 
| 696 |      * @return The default location for {@code implementation} or {@code null}. | 
| 697 |      * | 
| 698 |      * @throws NullPointerExeption if {@code context}, {@code modules} or {@code implementation} is {@code null}. | 
| 699 |      * | 
| 700 |      * @see SourceFileType#getLocation() | 
| 701 |      * @see Implementation#getJavaTypeName() | 
| 702 |      * @since 1.6 | 
| 703 |      */ | 
| 704 |     protected String getDefaultSourceFileLocation( final ModelContext context, final Modules modules, | 
| 705 |                                                    final Implementation implementation ) | 
| 706 |     { | 
| 707 |         if ( context == null ) | 
| 708 |         { | 
| 709 |             throw new NullPointerException( "context" ); | 
| 710 |         } | 
| 711 |         if ( modules == null ) | 
| 712 |         { | 
| 713 |             throw new NullPointerException( "modules" ); | 
| 714 |         } | 
| 715 |         if ( implementation == null ) | 
| 716 |         { | 
| 717 |             throw new NullPointerException( "implementation" ); | 
| 718 |         } | 
| 719 |   | 
| 720 |         String location = null; | 
| 721 |   | 
| 722 |         try | 
| 723 |         { | 
| 724 |             if ( implementation.getJavaTypeName() != null ) | 
| 725 |             { | 
| 726 |                 location = implementation.getJavaTypeName().getQualifiedName().replace( '.', '/' ) + ".java"; | 
| 727 |             } | 
| 728 |         } | 
| 729 |         catch ( final ModelObjectException e ) | 
| 730 |         { | 
| 731 |             context.log( Level.WARNING, getMessage( e ), null ); | 
| 732 |         } | 
| 733 |   | 
| 734 |         return location; | 
| 735 |     } | 
| 736 |   | 
| 737 |     /** | 
| 738 |      * Gets the default source section name for a given specification. | 
| 739 |      * <p>If the specification provides a Java type name, this method returns a section name based on that Java type | 
| 740 |      * name.</p> | 
| 741 |      * | 
| 742 |      * @param context The context to get the default section name with. | 
| 743 |      * @param modules The model to get the default section name with. | 
| 744 |      * @param specification The specification to get the default section name for. | 
| 745 |      * | 
| 746 |      * @return The default source section name for {@code specification} or {@code null}. | 
| 747 |      * | 
| 748 |      * @throws NullPointerExeption if {@code context}, {@code modules} or {@code specification} is {@code null}. | 
| 749 |      * | 
| 750 |      * @see SourceSectionType#getName() | 
| 751 |      * @see Specification#getJavaTypeName() | 
| 752 |      * @since 1.6 | 
| 753 |      */ | 
| 754 |     protected String getDefaultSourceSectionName( final ModelContext context, final Modules modules, | 
| 755 |                                                   final Specification specification ) | 
| 756 |     { | 
| 757 |         if ( context == null ) | 
| 758 |         { | 
| 759 |             throw new NullPointerException( "context" ); | 
| 760 |         } | 
| 761 |         if ( modules == null ) | 
| 762 |         { | 
| 763 |             throw new NullPointerException( "modules" ); | 
| 764 |         } | 
| 765 |         if ( specification == null ) | 
| 766 |         { | 
| 767 |             throw new NullPointerException( "specification" ); | 
| 768 |         } | 
| 769 |   | 
| 770 |         String sectionName = null; | 
| 771 |   | 
| 772 |         try | 
| 773 |         { | 
| 774 |             final JavaTypeName javaTypeName = specification.getJavaTypeName(); | 
| 775 |   | 
| 776 |             if ( javaTypeName != null ) | 
| 777 |             { | 
| 778 |                 sectionName = javaTypeName.getName( false ); | 
| 779 |             } | 
| 780 |         } | 
| 781 |         catch ( final ModelObjectException e ) | 
| 782 |         { | 
| 783 |             context.log( Level.WARNING, getMessage( e ), null ); | 
| 784 |         } | 
| 785 |   | 
| 786 |         return sectionName; | 
| 787 |     } | 
| 788 |   | 
| 789 |     /** | 
| 790 |      * Gets the default source section name for a given implementation. | 
| 791 |      * <p>If the implementation provides a Java type name, this method returns a section name based that Java type | 
| 792 |      * name.</p> | 
| 793 |      * | 
| 794 |      * @param context The context to get the default section name with. | 
| 795 |      * @param modules The model to get the default section name with. | 
| 796 |      * @param implementation The implementation to get the default section name for. | 
| 797 |      * | 
| 798 |      * @return The default source section name for {@code implementation} or {@code null}. | 
| 799 |      * | 
| 800 |      * @throws NullPointerExeption if {@code context}, {@code modules} or {@code implementation} is {@code null}. | 
| 801 |      * | 
| 802 |      * @see SourceSectionType#getName() | 
| 803 |      * @see Implementation#getJavaTypeName() | 
| 804 |      * @since 1.6 | 
| 805 |      */ | 
| 806 |     protected String getDefaultSourceSectionName( final ModelContext context, final Modules modules, | 
| 807 |                                                   final Implementation implementation ) | 
| 808 |     { | 
| 809 |         if ( context == null ) | 
| 810 |         { | 
| 811 |             throw new NullPointerException( "context" ); | 
| 812 |         } | 
| 813 |         if ( modules == null ) | 
| 814 |         { | 
| 815 |             throw new NullPointerException( "modules" ); | 
| 816 |         } | 
| 817 |         if ( implementation == null ) | 
| 818 |         { | 
| 819 |             throw new NullPointerException( "implementation" ); | 
| 820 |         } | 
| 821 |   | 
| 822 |         String sectionName = null; | 
| 823 |   | 
| 824 |         try | 
| 825 |         { | 
| 826 |             final JavaTypeName javaTypeName = implementation.getJavaTypeName(); | 
| 827 |   | 
| 828 |             if ( javaTypeName != null ) | 
| 829 |             { | 
| 830 |                 sectionName = javaTypeName.getName( false ); | 
| 831 |             } | 
| 832 |         } | 
| 833 |         catch ( final ModelObjectException e ) | 
| 834 |         { | 
| 835 |             context.log( Level.WARNING, getMessage( e ), null ); | 
| 836 |         } | 
| 837 |   | 
| 838 |         return sectionName; | 
| 839 |     } | 
| 840 |   | 
| 841 |     /** | 
| 842 |      * Updates any optional attributes to default values. | 
| 843 |      * | 
| 844 |      * @param context The context to apply defaults with. | 
| 845 |      * @param modules The model to to apply defaults with. | 
| 846 |      * @param specification The specification corresponding to {@code sourceFilesType}. | 
| 847 |      * @param sourceFilesType The model to update. | 
| 848 |      * | 
| 849 |      * @throws NullPointerException if {@code context}, {@code modules}, {@code specification} or | 
| 850 |      * {@code sourceFilesType} is {@code null}. | 
| 851 |      */ | 
| 852 |     private void applyDefaults( final ModelContext context, final Modules modules, final Specification specification, | 
| 853 |                                 final SourceFilesType sourceFilesType ) | 
| 854 |     { | 
| 855 |         if ( context == null ) | 
| 856 |         { | 
| 857 |             throw new NullPointerException( "context" ); | 
| 858 |         } | 
| 859 |         if ( modules == null ) | 
| 860 |         { | 
| 861 |             throw new NullPointerException( "modules" ); | 
| 862 |         } | 
| 863 |         if ( specification == null ) | 
| 864 |         { | 
| 865 |             throw new NullPointerException( "specification" ); | 
| 866 |         } | 
| 867 |         if ( sourceFilesType == null ) | 
| 868 |         { | 
| 869 |             throw new NullPointerException( "sourceFilesType" ); | 
| 870 |         } | 
| 871 |   | 
| 872 |         String contextHeadComment = this.getHeadComment(); | 
| 873 |         if ( ( DEFAULT_HEAD_COMMENT != null | 
| 874 |                ? DEFAULT_HEAD_COMMENT.equals( contextHeadComment ) | 
| 875 |                : contextHeadComment == null ) | 
| 876 |              && context.getAttribute( HEAD_COMMENT_ATTRIBUTE_NAME ) instanceof String ) | 
| 877 |         { | 
| 878 |             contextHeadComment = (String) context.getAttribute( HEAD_COMMENT_ATTRIBUTE_NAME ); | 
| 879 |         } | 
| 880 |   | 
| 881 |         if ( contextHeadComment != null && contextHeadComment.length() == 0 ) | 
| 882 |         { | 
| 883 |             contextHeadComment = null; | 
| 884 |         } | 
| 885 |   | 
| 886 |         String contextTailComment = this.getTailComment(); | 
| 887 |         if ( ( DEFAULT_TAIL_COMMENT != null | 
| 888 |                ? DEFAULT_TAIL_COMMENT.equals( contextTailComment ) | 
| 889 |                : contextTailComment == null ) | 
| 890 |              && context.getAttribute( TAIL_COMMENT_ATTRIBUTE_NAME ) instanceof String ) | 
| 891 |         { | 
| 892 |             contextTailComment = (String) context.getAttribute( TAIL_COMMENT_ATTRIBUTE_NAME ); | 
| 893 |         } | 
| 894 |   | 
| 895 |         if ( contextTailComment != null && contextTailComment.length() == 0 ) | 
| 896 |         { | 
| 897 |             contextTailComment = null; | 
| 898 |         } | 
| 899 |   | 
| 900 |         for ( int i = 0, s0 = sourceFilesType.getSourceFile().size(); i < s0; i++ ) | 
| 901 |         { | 
| 902 |             final SourceFileType s = sourceFilesType.getSourceFile().get( i ); | 
| 903 |   | 
| 904 |             if ( s.getTemplate() == null ) | 
| 905 |             { | 
| 906 |                 s.setTemplate( SPECIFICATION_TEMPLATE ); | 
| 907 |             } | 
| 908 |             if ( s.getLocation() == null ) | 
| 909 |             { | 
| 910 |                 s.setLocation( this.getDefaultSourceFileLocation( context, modules, specification ) ); | 
| 911 |             } | 
| 912 |             if ( s.getHeadComment() == null ) | 
| 913 |             { | 
| 914 |                 s.setHeadComment( contextHeadComment ); | 
| 915 |             } | 
| 916 |             if ( s.getTailComment() == null ) | 
| 917 |             { | 
| 918 |                 s.setTailComment( contextTailComment ); | 
| 919 |             } | 
| 920 |   | 
| 921 |             this.applyDefaults( context, modules, specification, s.getSourceSections() ); | 
| 922 |         } | 
| 923 |     } | 
| 924 |   | 
| 925 |     /** | 
| 926 |      * Updates any optional attributes to default values. | 
| 927 |      * | 
| 928 |      * @param context The context to apply defaults with. | 
| 929 |      * @param modules The model to to apply defaults with. | 
| 930 |      * @param specification The specification corresponding to {@code sourceSectionsType}. | 
| 931 |      * @param sourceSectionsType The model to update or {@code null}. | 
| 932 |      * | 
| 933 |      * @throws NullPointerException if {@code context}, {@code modules} or {@code specification} is {@code null}. | 
| 934 |      */ | 
| 935 |     private void applyDefaults( final ModelContext context, final Modules modules, final Specification specification, | 
| 936 |                                 final SourceSectionsType sourceSectionsType ) | 
| 937 |     { | 
| 938 |         if ( context == null ) | 
| 939 |         { | 
| 940 |             throw new NullPointerException( "context" ); | 
| 941 |         } | 
| 942 |         if ( modules == null ) | 
| 943 |         { | 
| 944 |             throw new NullPointerException( "modules" ); | 
| 945 |         } | 
| 946 |         if ( specification == null ) | 
| 947 |         { | 
| 948 |             throw new NullPointerException( "specification" ); | 
| 949 |         } | 
| 950 |   | 
| 951 |         try | 
| 952 |         { | 
| 953 |             if ( sourceSectionsType != null ) | 
| 954 |             { | 
| 955 |                 for ( int i = 0, s0 = sourceSectionsType.getSourceSection().size(); i < s0; i++ ) | 
| 956 |                 { | 
| 957 |                     final SourceSectionType s = sourceSectionsType.getSourceSection().get( i ); | 
| 958 |   | 
| 959 |                     if ( LICENSE_SECTION_NAME.equals( s.getName() ) ) | 
| 960 |                     { | 
| 961 |                         if ( !isFieldSet( s, "optional" ) ) | 
| 962 |                         { | 
| 963 |                             s.setOptional( true ); | 
| 964 |                         } | 
| 965 |                         if ( s.getHeadTemplate() == null ) | 
| 966 |                         { | 
| 967 |                             s.setHeadTemplate( SPECIFICATION_LICENSE_TEMPLATE ); | 
| 968 |                         } | 
| 969 |                     } | 
| 970 |   | 
| 971 |                     if ( ANNOTATIONS_SECTION_NAME.equals( s.getName() ) ) | 
| 972 |                     { | 
| 973 |                         if ( s.getHeadTemplate() == null ) | 
| 974 |                         { | 
| 975 |                             s.setHeadTemplate( SPECIFICATION_ANNOTATIONS_TEMPLATE ); | 
| 976 |                         } | 
| 977 |                     } | 
| 978 |   | 
| 979 |                     if ( DOCUMENTATION_SECTION_NAME.equals( s.getName() ) ) | 
| 980 |                     { | 
| 981 |                         if ( !isFieldSet( s, "optional" ) ) | 
| 982 |                         { | 
| 983 |                             s.setOptional( true ); | 
| 984 |                         } | 
| 985 |                         if ( s.getHeadTemplate() == null ) | 
| 986 |                         { | 
| 987 |                             s.setHeadTemplate( SPECIFICATION_DOCUMENTATION_TEMPLATE ); | 
| 988 |                         } | 
| 989 |                     } | 
| 990 |   | 
| 991 |                     final String sectionName = this.getDefaultSourceSectionName( context, modules, specification ); | 
| 992 |   | 
| 993 |                     if ( sectionName != null && sectionName.equals( s.getName() ) ) | 
| 994 |                     { | 
| 995 |                         if ( !isFieldSet( s, "editable" ) ) | 
| 996 |                         { | 
| 997 |                             s.setEditable( true ); | 
| 998 |                         } | 
| 999 |                         if ( !isFieldSet( s, "indentationLevel" ) ) | 
| 1000 |                         { | 
| 1001 |                             s.setIndentationLevel( 1 ); | 
| 1002 |                         } | 
| 1003 |                     } | 
| 1004 |   | 
| 1005 |                     this.applyDefaults( context, modules, specification, s.getSourceSections() ); | 
| 1006 |                 } | 
| 1007 |             } | 
| 1008 |         } | 
| 1009 |         catch ( final NoSuchFieldException e ) | 
| 1010 |         { | 
| 1011 |             throw new AssertionError( e ); | 
| 1012 |         } | 
| 1013 |     } | 
| 1014 |   | 
| 1015 |     /** | 
| 1016 |      * Updates any optional attributes to default values. | 
| 1017 |      * | 
| 1018 |      * @param context The context to apply defaults with. | 
| 1019 |      * @param modules The model to to apply defaults with. | 
| 1020 |      * @param implementation The implementation corresponding to {@code sourceFilesType}. | 
| 1021 |      * @param sourceFilesType The model to update. | 
| 1022 |      * | 
| 1023 |      * @throws NullPointerException if {@code context}, {@code modules}, {@code implementation} or | 
| 1024 |      * {@code sourceFilesType} is {@code null}. | 
| 1025 |      */ | 
| 1026 |     private void applyDefaults( final ModelContext context, final Modules modules, final Implementation implementation, | 
| 1027 |                                 final SourceFilesType sourceFilesType ) | 
| 1028 |     { | 
| 1029 |         if ( context == null ) | 
| 1030 |         { | 
| 1031 |             throw new NullPointerException( "context" ); | 
| 1032 |         } | 
| 1033 |         if ( modules == null ) | 
| 1034 |         { | 
| 1035 |             throw new NullPointerException( "modules" ); | 
| 1036 |         } | 
| 1037 |         if ( implementation == null ) | 
| 1038 |         { | 
| 1039 |             throw new NullPointerException( "implementation" ); | 
| 1040 |         } | 
| 1041 |         if ( sourceFilesType == null ) | 
| 1042 |         { | 
| 1043 |             throw new NullPointerException( "sourceFilesType" ); | 
| 1044 |         } | 
| 1045 |   | 
| 1046 |         String contextHeadComment = this.getHeadComment(); | 
| 1047 |         if ( ( DEFAULT_HEAD_COMMENT != null | 
| 1048 |                ? DEFAULT_HEAD_COMMENT.equals( contextHeadComment ) | 
| 1049 |                : contextHeadComment == null ) | 
| 1050 |              && context.getAttribute( HEAD_COMMENT_ATTRIBUTE_NAME ) instanceof String ) | 
| 1051 |         { | 
| 1052 |             contextHeadComment = (String) context.getAttribute( HEAD_COMMENT_ATTRIBUTE_NAME ); | 
| 1053 |         } | 
| 1054 |   | 
| 1055 |         if ( contextHeadComment != null && contextHeadComment.length() == 0 ) | 
| 1056 |         { | 
| 1057 |             contextHeadComment = null; | 
| 1058 |         } | 
| 1059 |   | 
| 1060 |         String contextTailComment = this.getTailComment(); | 
| 1061 |         if ( ( DEFAULT_TAIL_COMMENT != null | 
| 1062 |                ? DEFAULT_TAIL_COMMENT.equals( contextTailComment ) | 
| 1063 |                : contextTailComment == null ) | 
| 1064 |              && context.getAttribute( TAIL_COMMENT_ATTRIBUTE_NAME ) instanceof String ) | 
| 1065 |         { | 
| 1066 |             contextTailComment = (String) context.getAttribute( TAIL_COMMENT_ATTRIBUTE_NAME ); | 
| 1067 |         } | 
| 1068 |   | 
| 1069 |         if ( contextTailComment != null && contextTailComment.length() == 0 ) | 
| 1070 |         { | 
| 1071 |             contextTailComment = null; | 
| 1072 |         } | 
| 1073 |   | 
| 1074 |         for ( int i = 0, s0 = sourceFilesType.getSourceFile().size(); i < s0; i++ ) | 
| 1075 |         { | 
| 1076 |             final SourceFileType s = sourceFilesType.getSourceFile().get( i ); | 
| 1077 |   | 
| 1078 |             if ( s.getTemplate() == null ) | 
| 1079 |             { | 
| 1080 |                 s.setTemplate( IMPLEMENTATION_TEMPLATE ); | 
| 1081 |             } | 
| 1082 |             if ( s.getLocation() == null ) | 
| 1083 |             { | 
| 1084 |                 s.setLocation( this.getDefaultSourceFileLocation( context, modules, implementation ) ); | 
| 1085 |             } | 
| 1086 |             if ( s.getHeadComment() == null ) | 
| 1087 |             { | 
| 1088 |                 s.setHeadComment( contextHeadComment ); | 
| 1089 |             } | 
| 1090 |             if ( s.getTailComment() == null ) | 
| 1091 |             { | 
| 1092 |                 s.setTailComment( contextTailComment ); | 
| 1093 |             } | 
| 1094 |   | 
| 1095 |             this.applyDefaults( context, modules, implementation, s.getSourceSections() ); | 
| 1096 |         } | 
| 1097 |     } | 
| 1098 |   | 
| 1099 |     /** | 
| 1100 |      * Updates any optional attributes to default values. | 
| 1101 |      * | 
| 1102 |      * @param context The context to apply defaults with. | 
| 1103 |      * @param modules The model to to apply defaults with. | 
| 1104 |      * @param implementation The implementation corresponding to {@code sourceSectionsType}. | 
| 1105 |      * @param sourceSectionsType The model to update or {@code null}. | 
| 1106 |      * | 
| 1107 |      * @throws NullPointerException if {@code context}, {@code modules} or {@code implementation} is {@code null}. | 
| 1108 |      */ | 
| 1109 |     private void applyDefaults( final ModelContext context, final Modules modules, final Implementation implementation, | 
| 1110 |                                 final SourceSectionsType sourceSectionsType ) | 
| 1111 |     { | 
| 1112 |         if ( context == null ) | 
| 1113 |         { | 
| 1114 |             throw new NullPointerException( "context" ); | 
| 1115 |         } | 
| 1116 |         if ( modules == null ) | 
| 1117 |         { | 
| 1118 |             throw new NullPointerException( "modules" ); | 
| 1119 |         } | 
| 1120 |         if ( implementation == null ) | 
| 1121 |         { | 
| 1122 |             throw new NullPointerException( "implementation" ); | 
| 1123 |         } | 
| 1124 |   | 
| 1125 |         final Specifications specifications = modules.getSpecifications( implementation.getIdentifier() ); | 
| 1126 |         final Dependencies dependencies = modules.getDependencies( implementation.getIdentifier() ); | 
| 1127 |         final Messages messages = modules.getMessages( implementation.getIdentifier() ); | 
| 1128 |         final Properties properties = modules.getProperties( implementation.getIdentifier() ); | 
| 1129 |   | 
| 1130 |         try | 
| 1131 |         { | 
| 1132 |             if ( sourceSectionsType != null ) | 
| 1133 |             { | 
| 1134 |                 for ( int i = 0, s0 = sourceSectionsType.getSourceSection().size(); i < s0; i++ ) | 
| 1135 |                 { | 
| 1136 |                     final SourceSectionType s = sourceSectionsType.getSourceSection().get( i ); | 
| 1137 |   | 
| 1138 |                     if ( LICENSE_SECTION_NAME.equals( s.getName() ) ) | 
| 1139 |                     { | 
| 1140 |                         if ( !isFieldSet( s, "optional" ) ) | 
| 1141 |                         { | 
| 1142 |                             s.setOptional( true ); | 
| 1143 |                         } | 
| 1144 |                         if ( s.getHeadTemplate() == null ) | 
| 1145 |                         { | 
| 1146 |                             s.setHeadTemplate( IMPLEMENTATION_LICENSE_TEMPLATE ); | 
| 1147 |                         } | 
| 1148 |                     } | 
| 1149 |   | 
| 1150 |                     if ( ANNOTATIONS_SECTION_NAME.equals( s.getName() ) ) | 
| 1151 |                     { | 
| 1152 |                         if ( s.getHeadTemplate() == null ) | 
| 1153 |                         { | 
| 1154 |                             s.setHeadTemplate( IMPLEMENTATION_ANNOTATIONS_TEMPLATE ); | 
| 1155 |                         } | 
| 1156 |                     } | 
| 1157 |   | 
| 1158 |                     if ( DOCUMENTATION_SECTION_NAME.equals( s.getName() ) ) | 
| 1159 |                     { | 
| 1160 |                         if ( !isFieldSet( s, "optional" ) ) | 
| 1161 |                         { | 
| 1162 |                             s.setOptional( true ); | 
| 1163 |                         } | 
| 1164 |                         if ( s.getHeadTemplate() == null ) | 
| 1165 |                         { | 
| 1166 |                             s.setHeadTemplate( IMPLEMENTATION_DOCUMENTATION_TEMPLATE ); | 
| 1167 |                         } | 
| 1168 |                     } | 
| 1169 |   | 
| 1170 |                     if ( CONSTRUCTORS_SECTION_NAME.equals( s.getName() ) ) | 
| 1171 |                     { | 
| 1172 |                         if ( !isFieldSet( s, "indentationLevel" ) ) | 
| 1173 |                         { | 
| 1174 |                             s.setIndentationLevel( 1 ); | 
| 1175 |                         } | 
| 1176 |                         if ( s.getHeadTemplate() == null ) | 
| 1177 |                         { | 
| 1178 |                             s.setHeadTemplate( CONSTRUCTORS_HEAD_TEMPLATE ); | 
| 1179 |                         } | 
| 1180 |                         if ( s.getTailTemplate() == null ) | 
| 1181 |                         { | 
| 1182 |                             s.setTailTemplate( CONSTRUCTORS_TAIL_TEMPLATE ); | 
| 1183 |                         } | 
| 1184 |                         if ( !isFieldSet( s, "optional" ) ) | 
| 1185 |                         { | 
| 1186 |                             s.setOptional( specifications == null || ( specifications.getSpecification().isEmpty() | 
| 1187 |                                                                        && specifications.getReference().isEmpty() ) ); | 
| 1188 |   | 
| 1189 |                         } | 
| 1190 |                     } | 
| 1191 |   | 
| 1192 |                     if ( DEFAULT_CONSTRUCTOR_SECTION_NAME.equals( s.getName() ) ) | 
| 1193 |                     { | 
| 1194 |                         if ( !isFieldSet( s, "editable" ) ) | 
| 1195 |                         { | 
| 1196 |                             s.setEditable( true ); | 
| 1197 |                         } | 
| 1198 |                         if ( !isFieldSet( s, "indentationLevel" ) ) | 
| 1199 |                         { | 
| 1200 |                             s.setIndentationLevel( 2 ); | 
| 1201 |                         } | 
| 1202 |                         if ( s.getHeadTemplate() == null ) | 
| 1203 |                         { | 
| 1204 |                             s.setHeadTemplate( DEFAULT_CONSTRUCTOR_TEMPLATE ); | 
| 1205 |                         } | 
| 1206 |                     } | 
| 1207 |   | 
| 1208 |                     if ( DEPENDENCIES_SECTION_NAME.equals( s.getName() ) ) | 
| 1209 |                     { | 
| 1210 |                         if ( !isFieldSet( s, "optional" ) ) | 
| 1211 |                         { | 
| 1212 |                             s.setOptional( dependencies == null || dependencies.getDependency().isEmpty() ); | 
| 1213 |                         } | 
| 1214 |                         if ( !isFieldSet( s, "indentationLevel" ) ) | 
| 1215 |                         { | 
| 1216 |                             s.setIndentationLevel( 1 ); | 
| 1217 |                         } | 
| 1218 |                         if ( s.getHeadTemplate() == null ) | 
| 1219 |                         { | 
| 1220 |                             s.setHeadTemplate( DEPENDENCIES_TEMPLATE ); | 
| 1221 |                         } | 
| 1222 |                     } | 
| 1223 |   | 
| 1224 |                     if ( PROPERTIES_SECTION_NAME.equals( s.getName() ) ) | 
| 1225 |                     { | 
| 1226 |                         if ( !isFieldSet( s, "optional" ) ) | 
| 1227 |                         { | 
| 1228 |                             s.setOptional( properties == null || properties.getProperty().isEmpty() ); | 
| 1229 |                         } | 
| 1230 |                         if ( !isFieldSet( s, "indentationLevel" ) ) | 
| 1231 |                         { | 
| 1232 |                             s.setIndentationLevel( 1 ); | 
| 1233 |                         } | 
| 1234 |                         if ( s.getHeadTemplate() == null ) | 
| 1235 |                         { | 
| 1236 |                             s.setHeadTemplate( PROPERTIES_TEMPLATE ); | 
| 1237 |                         } | 
| 1238 |                     } | 
| 1239 |   | 
| 1240 |                     if ( MESSAGES_SECTION_NAME.equals( s.getName() ) ) | 
| 1241 |                     { | 
| 1242 |                         if ( !isFieldSet( s, "optional" ) ) | 
| 1243 |                         { | 
| 1244 |                             s.setOptional( messages == null || messages.getMessage().isEmpty() ); | 
| 1245 |                         } | 
| 1246 |                         if ( !isFieldSet( s, "indentationLevel" ) ) | 
| 1247 |                         { | 
| 1248 |                             s.setIndentationLevel( 1 ); | 
| 1249 |                         } | 
| 1250 |                         if ( s.getHeadTemplate() == null ) | 
| 1251 |                         { | 
| 1252 |                             s.setHeadTemplate( MESSAGES_TEMPLATE ); | 
| 1253 |                         } | 
| 1254 |                     } | 
| 1255 |   | 
| 1256 |                     if ( specifications != null ) | 
| 1257 |                     { | 
| 1258 |                         for ( final Specification specification : specifications.getSpecification() ) | 
| 1259 |                         { | 
| 1260 |                             final String sectionName = | 
| 1261 |                                 this.getDefaultSourceSectionName( context, modules, specification ); | 
| 1262 |   | 
| 1263 |                             if ( sectionName != null && sectionName.equals( s.getName() ) ) | 
| 1264 |                             { | 
| 1265 |                                 if ( !isFieldSet( s, "editable" ) ) | 
| 1266 |                                 { | 
| 1267 |                                     s.setEditable( true ); | 
| 1268 |                                 } | 
| 1269 |                                 if ( !isFieldSet( s, "indentationLevel" ) ) | 
| 1270 |                                 { | 
| 1271 |                                     s.setIndentationLevel( 1 ); | 
| 1272 |                                 } | 
| 1273 |                             } | 
| 1274 |                         } | 
| 1275 |                     } | 
| 1276 |   | 
| 1277 |                     final String sectionName = this.getDefaultSourceSectionName( context, modules, implementation ); | 
| 1278 |   | 
| 1279 |                     if ( sectionName != null && sectionName.equals( s.getName() ) ) | 
| 1280 |                     { | 
| 1281 |                         if ( !isFieldSet( s, "editable" ) ) | 
| 1282 |                         { | 
| 1283 |                             s.setEditable( true ); | 
| 1284 |                         } | 
| 1285 |                         if ( !isFieldSet( s, "indentationLevel" ) ) | 
| 1286 |                         { | 
| 1287 |                             s.setIndentationLevel( 1 ); | 
| 1288 |                         } | 
| 1289 |                     } | 
| 1290 |   | 
| 1291 |                     this.applyDefaults( context, modules, implementation, s.getSourceSections() ); | 
| 1292 |                 } | 
| 1293 |             } | 
| 1294 |         } | 
| 1295 |         catch ( final NoSuchFieldException e ) | 
| 1296 |         { | 
| 1297 |             throw new AssertionError( e ); | 
| 1298 |         } | 
| 1299 |     } | 
| 1300 |   | 
| 1301 |     private static boolean isFieldSet( final Object object, final String fieldName ) throws NoSuchFieldException | 
| 1302 |     { | 
| 1303 |         final Field field = object.getClass().getDeclaredField( fieldName ); | 
| 1304 |         final boolean accessible = field.isAccessible(); | 
| 1305 |   | 
| 1306 |         try | 
| 1307 |         { | 
| 1308 |             field.setAccessible( true ); | 
| 1309 |             return field.get( object ) != null; | 
| 1310 |         } | 
| 1311 |         catch ( final IllegalAccessException e ) | 
| 1312 |         { | 
| 1313 |             throw new AssertionError( e ); | 
| 1314 |         } | 
| 1315 |         finally | 
| 1316 |         { | 
| 1317 |             field.setAccessible( accessible ); | 
| 1318 |         } | 
| 1319 |     } | 
| 1320 |   | 
| 1321 |     private static String getMessage( final Throwable t ) | 
| 1322 |     { | 
| 1323 |         return t != null | 
| 1324 |                ? t.getMessage() != null && t.getMessage().trim().length() > 0 | 
| 1325 |                  ? t.getMessage() | 
| 1326 |                  : getMessage( t.getCause() ) | 
| 1327 |                : null; | 
| 1328 |   | 
| 1329 |     } | 
| 1330 |   | 
| 1331 |     private static String getMessage( final String key, final Object... args ) | 
| 1332 |     { | 
| 1333 |         return MessageFormat.format( ResourceBundle.getBundle( | 
| 1334 |             ToolsModelProcessor.class.getName().replace( '.', '/' ), Locale.getDefault() ).getString( key ), args ); | 
| 1335 |   | 
| 1336 |     } | 
| 1337 |   | 
| 1338 | } |