001/* 002 * Copyright (C) Christian Schulte, 2005-206 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: JomcTool.java 4709 2013-01-02 06:17:48Z schulte $ 029 * 030 */ 031package org.jomc.tools; 032 033import java.io.BufferedReader; 034import java.io.ByteArrayInputStream; 035import java.io.ByteArrayOutputStream; 036import java.io.FileNotFoundException; 037import java.io.IOException; 038import java.io.InputStream; 039import java.io.InputStreamReader; 040import java.io.OutputStreamWriter; 041import java.io.Reader; 042import java.io.StringReader; 043import java.lang.ref.Reference; 044import java.lang.ref.SoftReference; 045import java.lang.reflect.InvocationTargetException; 046import java.net.URL; 047import java.text.DateFormat; 048import java.text.Format; 049import java.text.MessageFormat; 050import java.text.ParseException; 051import java.text.SimpleDateFormat; 052import java.util.ArrayList; 053import java.util.Calendar; 054import java.util.Collections; 055import java.util.Enumeration; 056import java.util.HashMap; 057import java.util.List; 058import java.util.Locale; 059import java.util.Map; 060import java.util.ResourceBundle; 061import java.util.Set; 062import java.util.concurrent.ConcurrentHashMap; 063import java.util.concurrent.CopyOnWriteArrayList; 064import java.util.concurrent.CopyOnWriteArraySet; 065import java.util.logging.Level; 066import javax.activation.MimeTypeParseException; 067import org.apache.commons.io.IOUtils; 068import org.apache.commons.lang.StringEscapeUtils; 069import org.apache.commons.lang.StringUtils; 070import org.apache.velocity.Template; 071import org.apache.velocity.VelocityContext; 072import org.apache.velocity.app.VelocityEngine; 073import org.apache.velocity.exception.ParseErrorException; 074import org.apache.velocity.exception.ResourceNotFoundException; 075import org.apache.velocity.exception.VelocityException; 076import org.apache.velocity.runtime.RuntimeConstants; 077import org.apache.velocity.runtime.RuntimeServices; 078import org.apache.velocity.runtime.log.LogChute; 079import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; 080import org.apache.velocity.runtime.resource.loader.URLResourceLoader; 081import org.jomc.model.Argument; 082import org.jomc.model.Dependency; 083import org.jomc.model.Implementation; 084import org.jomc.model.InheritanceModel; 085import org.jomc.model.JavaIdentifier; 086import org.jomc.model.JavaTypeName; 087import org.jomc.model.Message; 088import org.jomc.model.ModelObject; 089import org.jomc.model.ModelObjectException; 090import org.jomc.model.Modules; 091import org.jomc.model.Multiplicity; 092import org.jomc.model.Property; 093import org.jomc.model.Specification; 094import org.jomc.model.SpecificationReference; 095import org.jomc.model.Text; 096import org.jomc.model.Texts; 097import org.jomc.model.modlet.ModelHelper; 098import org.jomc.modlet.Model; 099 100/** 101 * Base tool class. 102 * 103 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 104 * @version $JOMC: JomcTool.java 4709 2013-01-02 06:17:48Z schulte $ 105 */ 106public class JomcTool 107{ 108 109 /** Listener interface. */ 110 public abstract static class Listener 111 { 112 113 /** Creates a new {@code Listener} instance. */ 114 public Listener() 115 { 116 super(); 117 } 118 119 /** 120 * Gets called on logging. 121 * 122 * @param level The level of the event. 123 * @param message The message of the event or {@code null}. 124 * @param throwable The throwable of the event or {@code null}. 125 * 126 * @throws NullPointerException if {@code level} is {@code null}. 127 */ 128 public void onLog( final Level level, final String message, final Throwable throwable ) 129 { 130 if ( level == null ) 131 { 132 throw new NullPointerException( "level" ); 133 } 134 } 135 136 } 137 138 /** Empty byte array. */ 139 private static final byte[] NO_BYTES = 140 { 141 }; 142 143 /** The prefix of the template location. */ 144 private static final String TEMPLATE_PREFIX = 145 JomcTool.class.getPackage().getName().replace( '.', '/' ) + "/templates/"; 146 147 /** Constant for the default template profile. */ 148 private static final String DEFAULT_TEMPLATE_PROFILE = "jomc-java"; 149 150 /** 151 * Constant for the name of the template profile property specifying a parent template profile name. 152 * @since 1.3 153 */ 154 private static final String PARENT_TEMPLATE_PROFILE_PROPERTY_NAME = "parent-template-profile"; 155 156 /** 157 * Constant for the name of the template profile property specifying the template encoding. 158 * @since 1.3 159 */ 160 private static final String TEMPLATE_ENCODING_PROFILE_PROPERTY_NAME = "template-encoding"; 161 162 /** 163 * The default encoding to use for reading templates. 164 * @since 1.3 165 */ 166 private String defaultTemplateEncoding; 167 168 /** The default template profile. */ 169 private static volatile String defaultTemplateProfile; 170 171 /** 172 * The log level events are logged at by default. 173 * @see #getDefaultLogLevel() 174 */ 175 private static final Level DEFAULT_LOG_LEVEL = Level.WARNING; 176 177 /** The default log level. */ 178 private static volatile Level defaultLogLevel; 179 180 /** The model of the instance. */ 181 private Model model; 182 183 /** The {@code VelocityEngine} of the instance. */ 184 private VelocityEngine velocityEngine; 185 186 /** 187 * Flag indicating the default {@code VelocityEngine}. 188 * @since 1.2.4 189 */ 190 private boolean defaultVelocityEngine; 191 192 /** 193 * The location to search for templates in addition to searching the class path. 194 * @since 1.2 195 */ 196 private URL templateLocation; 197 198 /** The encoding to use for reading files. */ 199 private String inputEncoding; 200 201 /** The encoding to use for writing files. */ 202 private String outputEncoding; 203 204 /** 205 * The template parameters. 206 * @since 1.2 207 */ 208 private Map<String, Object> templateParameters; 209 210 /** The template profile of the instance. */ 211 private String templateProfile; 212 213 /** The indentation string of the instance. */ 214 private String indentation; 215 216 /** The line separator of the instance. */ 217 private String lineSeparator; 218 219 /** The listeners of the instance. */ 220 private List<Listener> listeners; 221 222 /** The log level of the instance. */ 223 private Level logLevel; 224 225 /** 226 * The locale of the instance. 227 * @since 1.2 228 */ 229 private Locale locale; 230 231 /** Cached indentation strings. */ 232 private volatile Reference<Map<String, String>> indentationCache; 233 234 /** 235 * Cached templates. 236 * @since 1.3 237 */ 238 private volatile Reference<Map<String, TemplateData>> templateCache; 239 240 /** 241 * Cached template profile context properties. 242 * @since 1.3 243 */ 244 private volatile Reference<Map<String, java.util.Properties>> templateProfileContextPropertiesCache; 245 246 /** 247 * Cached template profile properties. 248 * @since 1.3 249 */ 250 private volatile Reference<Map<String, java.util.Properties>> templateProfilePropertiesCache; 251 252 /** Cached Java keywords. */ 253 private volatile Reference<Set<String>> javaKeywordsCache; 254 255 /** Creates a new {@code JomcTool} instance. */ 256 public JomcTool() 257 { 258 super(); 259 } 260 261 /** 262 * Creates a new {@code JomcTool} instance taking a {@code JomcTool} instance to initialize the new instance with. 263 * 264 * @param tool The instance to initialize the new instance with. 265 * 266 * @throws NullPointerException if {@code tool} is {@code null}. 267 * @throws IOException if copying {@code tool} fails. 268 */ 269 public JomcTool( final JomcTool tool ) throws IOException 270 { 271 this(); 272 273 if ( tool == null ) 274 { 275 throw new NullPointerException( "tool" ); 276 } 277 278 this.indentation = tool.indentation; 279 this.inputEncoding = tool.inputEncoding; 280 this.lineSeparator = tool.lineSeparator; 281 this.listeners = tool.listeners != null ? new CopyOnWriteArrayList<Listener>( tool.listeners ) : null; 282 this.logLevel = tool.logLevel; 283 this.model = tool.model != null ? tool.model.clone() : null; 284 this.outputEncoding = tool.outputEncoding; 285 this.defaultTemplateEncoding = tool.defaultTemplateEncoding; 286 this.templateProfile = tool.templateProfile; 287 this.velocityEngine = tool.velocityEngine; 288 this.defaultVelocityEngine = tool.defaultVelocityEngine; 289 this.locale = tool.locale; 290 this.templateParameters = 291 tool.templateParameters != null 292 ? Collections.synchronizedMap( new HashMap<String, Object>( tool.templateParameters ) ) 293 : null; 294 295 this.templateLocation = 296 tool.templateLocation != null ? new URL( tool.templateLocation.toExternalForm() ) : null; 297 298 } 299 300 /** 301 * Gets the list of registered listeners. 302 * <p>This accessor method returns a reference to the live list, not a snapshot. Therefore any modification you make 303 * to the returned list will be present inside the object. This is why there is no {@code set} method for the 304 * listeners property.</p> 305 * 306 * @return The list of registered listeners. 307 * 308 * @see #log(java.util.logging.Level, java.lang.String, java.lang.Throwable) 309 */ 310 public List<Listener> getListeners() 311 { 312 if ( this.listeners == null ) 313 { 314 this.listeners = new CopyOnWriteArrayList<Listener>(); 315 } 316 317 return this.listeners; 318 } 319 320 /** 321 * Gets the default log level events are logged at. 322 * <p>The default log level is controlled by system property {@code org.jomc.tools.JomcTool.defaultLogLevel} holding 323 * the log level to log events at by default. If that property is not set, the {@code WARNING} default is 324 * returned.</p> 325 * 326 * @return The log level events are logged at by default. 327 * 328 * @see #getLogLevel() 329 * @see Level#parse(java.lang.String) 330 */ 331 public static Level getDefaultLogLevel() 332 { 333 if ( defaultLogLevel == null ) 334 { 335 defaultLogLevel = Level.parse( System.getProperty( "org.jomc.tools.JomcTool.defaultLogLevel", 336 DEFAULT_LOG_LEVEL.getName() ) ); 337 338 } 339 340 return defaultLogLevel; 341 } 342 343 /** 344 * Sets the default log level events are logged at. 345 * 346 * @param value The new default level events are logged at or {@code null}. 347 * 348 * @see #getDefaultLogLevel() 349 */ 350 public static void setDefaultLogLevel( final Level value ) 351 { 352 defaultLogLevel = value; 353 } 354 355 /** 356 * Gets the log level of the instance. 357 * 358 * @return The log level of the instance. 359 * 360 * @see #getDefaultLogLevel() 361 * @see #setLogLevel(java.util.logging.Level) 362 * @see #isLoggable(java.util.logging.Level) 363 */ 364 public final Level getLogLevel() 365 { 366 if ( this.logLevel == null ) 367 { 368 this.logLevel = getDefaultLogLevel(); 369 370 if ( this.isLoggable( Level.CONFIG ) ) 371 { 372 this.log( Level.CONFIG, getMessage( "defaultLogLevelInfo", this.logLevel.getLocalizedName() ), null ); 373 } 374 } 375 376 return this.logLevel; 377 } 378 379 /** 380 * Sets the log level of the instance. 381 * 382 * @param value The new log level of the instance or {@code null}. 383 * 384 * @see #getLogLevel() 385 * @see #isLoggable(java.util.logging.Level) 386 */ 387 public final void setLogLevel( final Level value ) 388 { 389 this.logLevel = value; 390 } 391 392 /** 393 * Checks if a message at a given level is provided to the listeners of the instance. 394 * 395 * @param level The level to test. 396 * 397 * @return {@code true}, if messages at {@code level} are provided to the listeners of the instance; 398 * {@code false}, if messages at {@code level} are not provided to the listeners of the instance. 399 * 400 * @throws NullPointerException if {@code level} is {@code null}. 401 * 402 * @see #getLogLevel() 403 * @see #setLogLevel(java.util.logging.Level) 404 * @see #log(java.util.logging.Level, java.lang.String, java.lang.Throwable) 405 */ 406 public boolean isLoggable( final Level level ) 407 { 408 if ( level == null ) 409 { 410 throw new NullPointerException( "level" ); 411 } 412 413 return level.intValue() >= this.getLogLevel().intValue(); 414 } 415 416 /** 417 * Gets the Java package name of a specification. 418 * 419 * @param specification The specification to get the Java package name of. 420 * 421 * @return The Java package name of {@code specification} or {@code null}, if the specification does not reference a 422 * type. 423 * 424 * @throws NullPointerException if {@code specification} is {@code null}. 425 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 426 * 427 * @see Specification#getJavaTypeName() 428 * @see JavaTypeName#getPackageName() 429 * 430 * @deprecated As of JOMC 1.4, please use method {@link Specification#getJavaTypeName()}. This method will be 431 * removed in JOMC 2.0. 432 */ 433 @Deprecated 434 public String getJavaPackageName( final Specification specification ) throws ModelObjectException 435 { 436 if ( specification == null ) 437 { 438 throw new NullPointerException( "specification" ); 439 } 440 441 final JavaTypeName javaTypeName = specification.getJavaTypeName(); 442 return javaTypeName != null ? javaTypeName.getPackageName() : null; 443 } 444 445 /** 446 * Gets the Java type name of a specification. 447 * 448 * @param specification The specification to get the Java type name of. 449 * @param qualified {@code true}, to return the fully qualified type name (with package name prepended); 450 * {@code false}, to return the short type name (without package name prepended). 451 * 452 * @return The Java type name of the type referenced by the specification or {@code null}, if the specification does 453 * not reference a type. 454 * 455 * @throws NullPointerException if {@code specification} is {@code null}. 456 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 457 * 458 * @see Specification#getJavaTypeName() 459 * @see JavaTypeName#getName(boolean) 460 * 461 * @deprecated As of JOMC 1.4, please use method {@link Specification#getJavaTypeName()}. This method will be 462 * removed in JOMC 2.0. 463 */ 464 @Deprecated 465 public String getJavaTypeName( final Specification specification, final boolean qualified ) 466 throws ModelObjectException 467 { 468 if ( specification == null ) 469 { 470 throw new NullPointerException( "specification" ); 471 } 472 473 final JavaTypeName javaTypeName = specification.getJavaTypeName(); 474 return javaTypeName != null ? javaTypeName.getName( qualified ) : null; 475 } 476 477 /** 478 * Gets the Java class path location of a specification. 479 * 480 * @param specification The specification to return the Java class path location of. 481 * 482 * @return The Java class path location of {@code specification} or {@code null}, if the specification does not 483 * reference a type. 484 * 485 * @throws NullPointerException if {@code specification} is {@code null}. 486 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 487 * 488 * @see Specification#getJavaTypeName() 489 * @see JavaTypeName#getQualifiedName() 490 * 491 * @deprecated As of JOMC 1.4, please use method {@link Specification#getJavaTypeName()}. This method will be 492 * removed in JOMC 2.0. 493 */ 494 @Deprecated 495 public String getJavaClasspathLocation( final Specification specification ) throws ModelObjectException 496 { 497 if ( specification == null ) 498 { 499 throw new NullPointerException( "specification" ); 500 } 501 502 final JavaTypeName javaTypeName = specification.getJavaTypeName(); 503 return javaTypeName != null ? javaTypeName.getQualifiedName().replace( '.', '/' ) : null; 504 } 505 506 /** 507 * Gets the Java package name of a specification reference. 508 * 509 * @param reference The specification reference to get the Java package name of. 510 * 511 * @return The Java package name of {@code reference} or {@code null}, if the referenced specification is not found 512 * or does not reference a type. 513 * 514 * @throws NullPointerException if {@code reference} is {@code null}. 515 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 516 * 517 * @see Modules#getSpecification(java.lang.String) 518 * @see Specification#getJavaTypeName() 519 * @see JavaTypeName#getPackageName() 520 * 521 * @deprecated As of JOMC 1.4, please use method {@link Specification#getJavaTypeName()}. This method will be 522 * removed in JOMC 2.0. 523 */ 524 @Deprecated 525 public String getJavaPackageName( final SpecificationReference reference ) throws ModelObjectException 526 { 527 if ( reference == null ) 528 { 529 throw new NullPointerException( "reference" ); 530 } 531 532 Specification s = null; 533 String javaPackageName = null; 534 535 if ( this.getModules() != null 536 && ( s = this.getModules().getSpecification( reference.getIdentifier() ) ) != null ) 537 { 538 final JavaTypeName javaTypeName = s.getJavaTypeName(); 539 javaPackageName = javaTypeName != null ? javaTypeName.getPackageName() : null; 540 } 541 else if ( this.isLoggable( Level.WARNING ) ) 542 { 543 this.log( Level.WARNING, getMessage( "specificationNotFound", reference.getIdentifier() ), null ); 544 } 545 546 return javaPackageName; 547 } 548 549 /** 550 * Gets the name of a Java type of a given specification reference. 551 * 552 * @param reference The specification reference to get a Java type name of. 553 * @param qualified {@code true}, to return the fully qualified type name (with package name prepended); 554 * {@code false}, to return the short type name (without package name prepended). 555 * 556 * @return The Java type name of {@code reference} or {@code null}, if the referenced specification is not found 557 * or does not reference a type. 558 * 559 * @throws NullPointerException if {@code reference} is {@code null}. 560 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 561 * 562 * @see Modules#getSpecification(java.lang.String) 563 * @see Specification#getJavaTypeName() 564 * @see JavaTypeName#getName(boolean) 565 * 566 * @deprecated As of JOMC 1.4, please use method {@link Specification#getJavaTypeName()}. This method will be 567 * removed in JOMC 2.0. 568 */ 569 @Deprecated 570 public String getJavaTypeName( final SpecificationReference reference, final boolean qualified ) 571 throws ModelObjectException 572 { 573 if ( reference == null ) 574 { 575 throw new NullPointerException( "reference" ); 576 } 577 578 Specification s = null; 579 String typeName = null; 580 581 if ( this.getModules() != null 582 && ( s = this.getModules().getSpecification( reference.getIdentifier() ) ) != null ) 583 { 584 final JavaTypeName javaTypeName = s.getJavaTypeName(); 585 typeName = javaTypeName != null ? javaTypeName.getName( qualified ) : null; 586 } 587 else if ( this.isLoggable( Level.WARNING ) ) 588 { 589 this.log( Level.WARNING, getMessage( "specificationNotFound", reference.getIdentifier() ), null ); 590 } 591 592 return typeName; 593 } 594 595 /** 596 * Gets the Java package name of an implementation. 597 * 598 * @param implementation The implementation to get the Java package name of. 599 * 600 * @return The Java package name of {@code implementation} or {@code null}, if the implementation does not reference 601 * a type. 602 * 603 * @throws NullPointerException if {@code implementation} is {@code null}. 604 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 605 * 606 * @see Implementation#getJavaTypeName() 607 * @see JavaTypeName#getPackageName() 608 * 609 * @deprecated As of JOMC 1.4, please use method {@link Implementation#getJavaTypeName()}. This method will be 610 * removed in JOMC 2.0. 611 */ 612 @Deprecated 613 public String getJavaPackageName( final Implementation implementation ) throws ModelObjectException 614 { 615 if ( implementation == null ) 616 { 617 throw new NullPointerException( "implementation" ); 618 } 619 620 final JavaTypeName javaTypeName = implementation.getJavaTypeName(); 621 return javaTypeName != null ? javaTypeName.getPackageName() : null; 622 } 623 624 /** 625 * Gets the Java type name of an implementation. 626 * 627 * @param implementation The implementation to get the Java type name of. 628 * @param qualified {@code true}, to return the fully qualified type name (with package name prepended); 629 * {@code false}, to return the short type name (without package name prepended). 630 * 631 * @return The Java type name of the type referenced by the implementation or {@code null}, if the implementation 632 * does not reference a type. 633 * 634 * @throws NullPointerException if {@code implementation} is {@code null}. 635 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 636 * 637 * @see Implementation#getJavaTypeName() 638 * @see JavaTypeName#getName(boolean) 639 * 640 * @deprecated As of JOMC 1.4, please use method {@link Implementation#getJavaTypeName()}. This method will be 641 * removed in JOMC 2.0. 642 */ 643 @Deprecated 644 public String getJavaTypeName( final Implementation implementation, final boolean qualified ) 645 throws ModelObjectException 646 { 647 if ( implementation == null ) 648 { 649 throw new NullPointerException( "implementation" ); 650 } 651 652 final JavaTypeName javaTypeName = implementation.getJavaTypeName(); 653 return javaTypeName != null ? javaTypeName.getName( qualified ) : null; 654 } 655 656 /** 657 * Gets the Java class path location of an implementation. 658 * 659 * @param implementation The implementation to return the Java class path location of. 660 * 661 * @return The Java class path location of {@code implementation} or {@code null}, if the implementation does not 662 * reference a type. 663 * 664 * @throws NullPointerException if {@code implementation} is {@code null}. 665 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 666 * 667 * @see Implementation#getJavaTypeName() 668 * @see JavaTypeName#getQualifiedName() 669 * 670 * @deprecated As of JOMC 1.4, please use method {@link Implementation#getJavaTypeName()}. This method will be 671 * removed in JOMC 2.0. 672 */ 673 @Deprecated 674 public String getJavaClasspathLocation( final Implementation implementation ) throws ModelObjectException 675 { 676 if ( implementation == null ) 677 { 678 throw new NullPointerException( "implementation" ); 679 } 680 681 final JavaTypeName javaTypeName = implementation.getJavaTypeName(); 682 return javaTypeName != null ? javaTypeName.getQualifiedName().replace( '.', '/' ) : null; 683 } 684 685 /** 686 * Gets a list of names of all Java types an implementation implements. 687 * 688 * @param implementation The implementation to get names of all implemented Java types of. 689 * @param qualified {@code true}, to return the fully qualified type names (with package name prepended); 690 * {@code false}, to return the short type names (without package name prepended). 691 * 692 * @return An unmodifiable list of names of all Java types implemented by {@code implementation}. 693 * 694 * @throws NullPointerException if {@code implementation} is {@code null}. 695 * @throws ModelObjectException if compiling the name of a referenced type to a {@code JavaTypeName} fails. 696 * 697 * @deprecated As of JOMC 1.2, replaced by method {@link #getImplementedJavaTypeNames(org.jomc.model.Implementation, boolean)}. 698 * This method will be removed in version 2.0. 699 */ 700 @Deprecated 701 public List<String> getJavaInterfaceNames( final Implementation implementation, final boolean qualified ) 702 throws ModelObjectException 703 { 704 if ( implementation == null ) 705 { 706 throw new NullPointerException( "implementation" ); 707 } 708 709 return this.getImplementedJavaTypeNames( implementation, qualified ); 710 } 711 712 /** 713 * Gets a list of names of all Java types an implementation implements. 714 * 715 * @param implementation The implementation to get names of all implemented Java types of. 716 * @param qualified {@code true}, to return the fully qualified type names (with package name prepended); 717 * {@code false}, to return the short type names (without package name prepended). 718 * 719 * @return An unmodifiable list of names of all Java types implemented by {@code implementation}. 720 * 721 * @throws NullPointerException if {@code implementation} is {@code null}. 722 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 723 * 724 * @since 1.2 725 * 726 * @see Implementation#getJavaTypeNames(org.jomc.model.Modules) 727 * 728 * @deprecated As of JOMC 1.4, please use method {@link Modules#getImplementedJavaTypeNames(java.lang.String)}. 729 * This method will be removed in JOMC 2.0. 730 */ 731 @Deprecated 732 public List<String> getImplementedJavaTypeNames( final Implementation implementation, final boolean qualified ) 733 throws ModelObjectException 734 { 735 if ( implementation == null ) 736 { 737 throw new NullPointerException( "implementation" ); 738 } 739 740 List<String> col = null; 741 742 if ( this.getModules() != null ) 743 { 744 final List<JavaTypeName> javaTypeNames = 745 this.getModules().getImplementedJavaTypeNames( implementation.getIdentifier() ); 746 747 if ( javaTypeNames != null ) 748 { 749 col = new ArrayList<String>( javaTypeNames.size() ); 750 751 for ( int i = 0, s0 = javaTypeNames.size(); i < s0; i++ ) 752 { 753 if ( !col.contains( javaTypeNames.get( i ).getName( qualified ) ) ) 754 { 755 col.add( javaTypeNames.get( i ).getName( qualified ) ); 756 } 757 } 758 } 759 } 760 else if ( this.isLoggable( Level.WARNING ) ) 761 { 762 this.log( Level.WARNING, getMessage( "modulesNotFound", this.getModel().getIdentifier() ), null ); 763 } 764 765 return Collections.unmodifiableList( col != null ? col : Collections.<String>emptyList() ); 766 } 767 768 /** 769 * Gets the Java type name of an argument. 770 * 771 * @param argument The argument to get the Java type name of. 772 * 773 * @return The Java type name of the type referenced by the argument or {@code null}, if the argument does not 774 * reference a type. 775 * 776 * @throws NullPointerException if {@code argument} is {@code null}. 777 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 778 * 779 * @see Argument#getJavaTypeName() 780 * @see JavaTypeName#getName(boolean) 781 * 782 * @deprecated As of JOMC 1.4, please use method {@link Argument#getJavaTypeName()}. This method will be removed in 783 * JOMC 2.0. 784 */ 785 @Deprecated 786 public String getJavaTypeName( final Argument argument ) throws ModelObjectException 787 { 788 if ( argument == null ) 789 { 790 throw new NullPointerException( "argument" ); 791 } 792 793 final JavaTypeName javaTypeName = argument.getJavaTypeName(); 794 return javaTypeName != null ? javaTypeName.getName( true ) : null; 795 } 796 797 /** 798 * Gets a Java method parameter name of an argument. 799 * 800 * @param argument The argument to get the Java method parameter name of. 801 * 802 * @return The Java method parameter name of {@code argument}. 803 * 804 * @throws NullPointerException if {@code argument} is {@code null}. 805 * @throws ModelObjectException if compiling the name of the argument to a {@code JavaIdentifier} fails. 806 * 807 * @see Argument#getJavaVariableName() 808 * 809 * @since 1.2 810 * 811 * @deprecated As of JOMC 1.4, please use method {@link Argument#getJavaVariableName()}. This method will be 812 * removed in JOMC 2.0. 813 */ 814 @Deprecated 815 public String getJavaMethodParameterName( final Argument argument ) throws ModelObjectException 816 { 817 if ( argument == null ) 818 { 819 throw new NullPointerException( "argument" ); 820 } 821 822 return this.getJavaMethodParameterName( argument.getName() ); 823 } 824 825 /** 826 * Gets the Java type name of a property. 827 * 828 * @param property The property to get the Java type name of. 829 * @param boxify {@code true}, to return the name of the Java wrapper class when the type is a Java primitive type; 830 * {@code false}, to return the exact binary name (unboxed name) of the Java type. 831 * 832 * @return The Java type name of the type referenced by the property or {@code null}, if the property does not 833 * reference a type. 834 * 835 * @throws NullPointerException if {@code property} is {@code null}. 836 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 837 * 838 * @see Property#getJavaTypeName() 839 * @see JavaTypeName#getBoxedName() 840 * @see JavaTypeName#getName(boolean) 841 * 842 * @deprecated As of JOMC 1.4, please use method {@link Property#getJavaTypeName()}. This method will be removed in 843 * JOMC 2.0. 844 */ 845 @Deprecated 846 public String getJavaTypeName( final Property property, final boolean boxify ) throws ModelObjectException 847 { 848 if ( property == null ) 849 { 850 throw new NullPointerException( "property" ); 851 } 852 853 JavaTypeName javaTypeName = property.getJavaTypeName(); 854 855 if ( javaTypeName != null ) 856 { 857 if ( boxify && javaTypeName.isPrimitive() ) 858 { 859 javaTypeName = javaTypeName.getBoxedName(); 860 } 861 862 return javaTypeName.getName( true ); 863 } 864 865 return null; 866 } 867 868 /** 869 * Gets a flag indicating the type of a given property is a Java primitive. 870 * 871 * @param property The property to query. 872 * 873 * @return {@code true}, if the Java type referenced by the property is primitive or {@code false}, if the property 874 * does not reference a type or if the Java type referenced by the property is not primitive. 875 * 876 * @throws NullPointerException if {@code property} is {@code null}. 877 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 878 * 879 * @see Property#getJavaTypeName() 880 * @see JavaTypeName#isPrimitive() 881 * 882 * @deprecated As of JOMC 1.4, please use method {@link Property#getJavaTypeName()}. This method will be removed in 883 * JOMC 2.0. 884 */ 885 @Deprecated 886 public boolean isJavaPrimitiveType( final Property property ) throws ModelObjectException 887 { 888 if ( property == null ) 889 { 890 throw new NullPointerException( "property" ); 891 } 892 893 final JavaTypeName javaTypeName = property.getJavaTypeName(); 894 return javaTypeName != null && javaTypeName.isPrimitive(); 895 } 896 897 /** 898 * Gets the name of a Java getter method of a given property. 899 * 900 * @param property The property to get a Java getter method name of. 901 * 902 * @return The Java getter method name of {@code property}. 903 * 904 * @throws NullPointerException if {@code property} is {@code null}. 905 * @throws ModelObjectException if compiling the name of the property to a {@code JavaIdentifier} fails. 906 * 907 * @see Property#getJavaGetterMethodName() 908 * 909 * @deprecated As of JOMC 1.4, please use method {@link Property#getJavaGetterMethodName()}. This method will be 910 * removed in JOMC 2.0. 911 */ 912 @Deprecated 913 public String getJavaGetterMethodName( final Property property ) throws ModelObjectException 914 { 915 if ( property == null ) 916 { 917 throw new NullPointerException( "property" ); 918 } 919 920 String prefix = "get"; 921 922 final String javaTypeName = this.getJavaTypeName( property, true ); 923 if ( Boolean.class.getName().equals( javaTypeName ) ) 924 { 925 prefix = "is"; 926 } 927 928 return prefix + this.getJavaIdentifier( property.getName(), true ); 929 } 930 931 /** 932 * Gets the name of a Java setter method of a given property. 933 * 934 * @param property The property to get a Java setter method name of. 935 * 936 * @return The Java setter method name of {@code property}. 937 * 938 * @throws NullPointerException if {@code property} is {@code null}. 939 * @throws ModelObjectException if compiling the name of the property to a {@code JavaIdentifier} fails. 940 * 941 * @see Property#getJavaSetterMethodName() 942 * 943 * @since 1.2 944 * 945 * @deprecated As of JOMC 1.4, please use method {@link Property#getJavaSetterMethodName()}. This method will be 946 * removed in JOMC 2.0. 947 */ 948 @Deprecated 949 public String getJavaSetterMethodName( final Property property ) throws ModelObjectException 950 { 951 if ( property == null ) 952 { 953 throw new NullPointerException( "property" ); 954 } 955 956 return "set" + this.getJavaIdentifier( property.getName(), true ); 957 } 958 959 /** 960 * Gets a Java method parameter name of a property. 961 * 962 * @param property The property to get the Java method parameter name of. 963 * 964 * @return The Java method parameter name of {@code property}. 965 * 966 * @throws NullPointerException if {@code property} is {@code null}. 967 * @throws ModelObjectException if copmiling the name of the property to a {@code JavaIdentifier} fails. 968 * 969 * @see Property#getJavaVariableName() 970 * 971 * @since 1.2 972 * 973 * @deprecated As of JOMC 1.4, please use method {@link Property#getJavaVariableName()}. This method will be 974 * removed in JOMC 2.0. 975 */ 976 @Deprecated 977 public String getJavaMethodParameterName( final Property property ) throws ModelObjectException 978 { 979 if ( property == null ) 980 { 981 throw new NullPointerException( "property" ); 982 } 983 984 return this.getJavaMethodParameterName( property.getName() ); 985 } 986 987 /** 988 * Gets a Java field name of a property. 989 * 990 * @param property The property to get the Java field name of. 991 * 992 * @return The Java field name of {@code property}. 993 * 994 * @throws NullPointerException if {@code property} is {@code null}. 995 * @throws ModelObjectException if compiling the name of the property to a {@code JavaIdentifier} fails. 996 * 997 * @see Property#getJavaVariableName() 998 * 999 * @since 1.3 1000 * 1001 * @deprecated As of JOMC 1.4, please use method {@link Property#getJavaVariableName()}. This method will be removed 1002 * in JOMC 2.0. 1003 */ 1004 @Deprecated 1005 public String getJavaFieldName( final Property property ) throws ModelObjectException 1006 { 1007 if ( property == null ) 1008 { 1009 throw new NullPointerException( "property" ); 1010 } 1011 1012 return this.getJavaFieldName( property.getName() ); 1013 } 1014 1015 /** 1016 * Gets the name of a Java type of a given dependency. 1017 * 1018 * @param dependency The dependency to get a dependency Java type name of. 1019 * 1020 * @return The Java type name of the dependency or {@code null}, if the referenced specification is not found or 1021 * does not reference a type. 1022 * 1023 * @throws NullPointerException if {@code dependency} is {@code null}. 1024 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 1025 * 1026 * @see Dependency#getJavaTypeName(org.jomc.model.Modules) 1027 * @see JavaTypeName#getName(boolean) 1028 * 1029 * @deprecated As of JOMC 1.4, please use method {@link Modules#getDependencyJavaTypeName(java.lang.String, java.lang.String)}. 1030 * This method will be removed in JOMC 2.0. 1031 */ 1032 @Deprecated 1033 public String getJavaTypeName( final Dependency dependency ) throws ModelObjectException 1034 { 1035 if ( dependency == null ) 1036 { 1037 throw new NullPointerException( "dependency" ); 1038 } 1039 1040 Specification s = null; 1041 StringBuilder typeName = null; 1042 String javaTypeName = null; 1043 1044 try 1045 { 1046 if ( this.getModules() != null 1047 && ( s = this.getModules().getSpecification( dependency.getIdentifier() ) ) != null ) 1048 { 1049 if ( s.getClazz() != null ) 1050 { 1051 typeName = new StringBuilder( s.getClazz().length() ); 1052 typeName.append( this.getJavaTypeName( s, true ) ); 1053 1054 if ( s.getMultiplicity() == Multiplicity.MANY && dependency.getImplementationName() == null ) 1055 { 1056 typeName.append( "[]" ); 1057 } 1058 1059 javaTypeName = JavaTypeName.parse( typeName.toString() ).getName( true ); 1060 } 1061 } 1062 else if ( this.isLoggable( Level.WARNING ) ) 1063 { 1064 this.log( Level.WARNING, getMessage( "specificationNotFound", dependency.getIdentifier() ), null ); 1065 } 1066 1067 return javaTypeName; 1068 } 1069 catch ( final ParseException e ) 1070 { 1071 throw new ModelObjectException( getMessage( "dependencyJavaTypeNameParseException", typeName, 1072 getMessage( e ) ), e ); 1073 1074 } 1075 } 1076 1077 /** 1078 * Gets the name of a Java getter method of a given dependency. 1079 * 1080 * @param dependency The dependency to get a Java getter method name of. 1081 * 1082 * @return The Java getter method name of {@code dependency}. 1083 * 1084 * @throws NullPointerException if {@code dependency} is {@code null}. 1085 * @throws ModelObjectException if compiling the name of the dependency to a {@code JavaIdentifier} fails. 1086 * 1087 * @see Dependency#getJavaGetterMethodName() 1088 * 1089 * @deprecated As of JOMC 1.4, please use method {@link Dependency#getJavaGetterMethodName()}. This method will be 1090 * removed in JOMC 2.0. 1091 */ 1092 @Deprecated 1093 public String getJavaGetterMethodName( final Dependency dependency ) throws ModelObjectException 1094 { 1095 if ( dependency == null ) 1096 { 1097 throw new NullPointerException( "dependency" ); 1098 } 1099 1100 return "get" + this.getJavaIdentifier( dependency.getName(), true ); 1101 } 1102 1103 /** 1104 * Gets the name of a Java setter method of a given dependency. 1105 * 1106 * @param dependency The dependency to get a Java setter method name of. 1107 * 1108 * @return The Java setter method name of {@code dependency}. 1109 * 1110 * @throws NullPointerException if {@code dependency} is {@code null}. 1111 * @throws ModelObjectException if compiling the name of the dependency to a {@code JavaIdentifier} fails. 1112 * 1113 * @see Dependency#getJavaSetterMethodName() 1114 * 1115 * @since 1.2 1116 * 1117 * @deprecated As of JOMC 1.4, please use method {@link Dependency#getJavaSetterMethodName()}. This method will be 1118 * removed in JOMC 2.0. 1119 */ 1120 @Deprecated 1121 public String getJavaSetterMethodName( final Dependency dependency ) throws ModelObjectException 1122 { 1123 if ( dependency == null ) 1124 { 1125 throw new NullPointerException( "dependency" ); 1126 } 1127 1128 return "set" + this.getJavaIdentifier( dependency.getName(), true ); 1129 } 1130 1131 /** 1132 * Gets a Java method parameter name of a dependency. 1133 * 1134 * @param dependency The dependency to get the Java method parameter name of. 1135 * 1136 * @return The Java method parameter name of {@code dependency}. 1137 * 1138 * @throws NullPointerException if {@code dependency} is {@code null}. 1139 * @throws ModelObjectException if compiling the name of the dependency to a {@code JavaIdentifier} fails. 1140 * 1141 * @see Dependency#getJavaVariableName() 1142 * 1143 * @since 1.2 1144 * 1145 * @deprecated As of JOMC 1.4, please use method {@link Dependency#getJavaVariableName()}. This method will be 1146 * removed in JOMC 2.0. 1147 */ 1148 @Deprecated 1149 public String getJavaMethodParameterName( final Dependency dependency ) throws ModelObjectException 1150 { 1151 if ( dependency == null ) 1152 { 1153 throw new NullPointerException( "dependency" ); 1154 } 1155 1156 return this.getJavaMethodParameterName( dependency.getName() ); 1157 } 1158 1159 /** 1160 * Gets a Java field name of a dependency. 1161 * 1162 * @param dependency The dependency to get the Java field name of. 1163 * 1164 * @return The Java field name of {@code dependency}. 1165 * 1166 * @throws NullPointerException if {@code dependency} is {@code null}. 1167 * @throws ModelObjectException if compiling the name of the dependency to a {@code JavaIdentifier} fails. 1168 * 1169 * @see Dependency#getJavaVariableName() 1170 * 1171 * @since 1.3 1172 * 1173 * @deprecated As of JOMC 1.4, please use method {@link Dependency#getJavaVariableName()}. This method will be 1174 * removed in JOMC 2.0. 1175 */ 1176 @Deprecated 1177 public String getJavaFieldName( final Dependency dependency ) throws ModelObjectException 1178 { 1179 if ( dependency == null ) 1180 { 1181 throw new NullPointerException( "dependency" ); 1182 } 1183 1184 return this.getJavaFieldName( dependency.getName() ); 1185 } 1186 1187 /** 1188 * Gets the name of a Java getter method of a given message. 1189 * 1190 * @param message The message to get a Java getter method name of. 1191 * 1192 * @return The Java getter method name of {@code message}. 1193 * 1194 * @throws NullPointerException if {@code message} is {@code null}. 1195 * @throws ModelObjectException if compiling the name of the message to a {@code JavaIdentifier} fails. 1196 * 1197 * @see Message#getJavaGetterMethodName() 1198 * 1199 * @deprecated As of JOMC 1.4, please use method {@link Message#getJavaGetterMethodName()}. This method will be 1200 * removed in JOMC 2.0. 1201 */ 1202 @Deprecated 1203 public String getJavaGetterMethodName( final Message message ) throws ModelObjectException 1204 { 1205 if ( message == null ) 1206 { 1207 throw new NullPointerException( "message" ); 1208 } 1209 1210 return "get" + this.getJavaIdentifier( message.getName(), true ); 1211 } 1212 1213 /** 1214 * Gets the name of a Java setter method of a given message. 1215 * 1216 * @param message The message to get a Java setter method name of. 1217 * 1218 * @return The Java setter method name of {@code message}. 1219 * 1220 * @throws NullPointerException if {@code message} is {@code null}. 1221 * @throws ModelObjectException if compiling the name of the message to a {@code JavaIdentifier} fails. 1222 * 1223 * @see Message#getJavaSetterMethodName() 1224 * 1225 * @since 1.2 1226 * 1227 * @deprecated As of JOMC 1.4, please use method {@link Message#getJavaSetterMethodName()}. This method will be 1228 * removed in JOMC 2.0. 1229 */ 1230 @Deprecated 1231 public String getJavaSetterMethodName( final Message message ) throws ModelObjectException 1232 { 1233 if ( message == null ) 1234 { 1235 throw new NullPointerException( "message" ); 1236 } 1237 1238 return "set" + this.getJavaIdentifier( message.getName(), true ); 1239 } 1240 1241 /** 1242 * Gets a Java method parameter name of a message. 1243 * 1244 * @param message The message to get the Java method parameter name of. 1245 * 1246 * @return The Java method parameter name of {@code message}. 1247 * 1248 * @throws NullPointerException if {@code message} is {@code null}. 1249 * @throws ModelObjectException if compiling the name of the message to a {@code JavaIdentifier} fails. 1250 * 1251 * @see Message#getJavaVariableName() 1252 * 1253 * @since 1.2 1254 * 1255 * @deprecated As of JOMC 1.4, please use method {@link Message#getJavaVariableName()}. This method will be removed 1256 * in JOMC 2.0. 1257 */ 1258 @Deprecated 1259 public String getJavaMethodParameterName( final Message message ) throws ModelObjectException 1260 { 1261 if ( message == null ) 1262 { 1263 throw new NullPointerException( "message" ); 1264 } 1265 1266 return this.getJavaMethodParameterName( message.getName() ); 1267 } 1268 1269 /** 1270 * Gets a Java field name of a message. 1271 * 1272 * @param message The message to get the Java field name of. 1273 * 1274 * @return The Java field name of {@code message}. 1275 * 1276 * @throws NullPointerException if {@code message} is {@code null}. 1277 * @throws ModelObjectException if compiling the name of the message to a {@code JavaIdentifier} fails. 1278 * 1279 * @see Message#getJavaVariableName() 1280 * 1281 * @since 1.3 1282 * 1283 * @deprecated As of JOMC 1.4, please use method {@link Message#getJavaVariableName()}. This method will be removed 1284 * in JOMC 2.0. 1285 */ 1286 @Deprecated 1287 public String getJavaFieldName( final Message message ) throws ModelObjectException 1288 { 1289 if ( message == null ) 1290 { 1291 throw new NullPointerException( "message" ); 1292 } 1293 1294 return this.getJavaFieldName( message.getName() ); 1295 } 1296 1297 /** 1298 * Gets the Java modifier name of a dependency of a given implementation. 1299 * 1300 * @param implementation The implementation declaring the dependency to get a Java modifier name of. 1301 * @param dependency The dependency to get a Java modifier name of. 1302 * 1303 * @return The Java modifier name of {@code dependency} of {@code implementation}. 1304 * 1305 * @throws NullPointerException if {@code implementation} or {@code dependency} is {@code null}. 1306 * 1307 * @deprecated As of JOMC 1.4, please use method {@link Modules#getDependencyJavaModifierName(java.lang.String, java.lang.String)}. 1308 * This method will be removed in JOMC 2.0. 1309 */ 1310 @Deprecated 1311 public String getJavaModifierName( final Implementation implementation, final Dependency dependency ) 1312 { 1313 if ( implementation == null ) 1314 { 1315 throw new NullPointerException( "implementation" ); 1316 } 1317 if ( dependency == null ) 1318 { 1319 throw new NullPointerException( "dependency" ); 1320 } 1321 1322 String modifierName = "private"; 1323 1324 if ( this.getModules() != null ) 1325 { 1326 modifierName = 1327 this.getModules().getDependencyJavaModifierName( implementation.getIdentifier(), dependency.getName() ); 1328 1329 if ( modifierName == null ) 1330 { 1331 modifierName = "private"; 1332 } 1333 } 1334 1335 return modifierName; 1336 } 1337 1338 /** 1339 * Gets the Java modifier name of a message of a given implementation. 1340 * 1341 * @param implementation The implementation declaring the message to get a Java modifier name of. 1342 * @param message The message to get a Java modifier name of. 1343 * 1344 * @return The Java modifier name of {@code message} of {@code implementation}. 1345 * 1346 * @throws NullPointerException if {@code implementation} or {@code message} is {@code null}. 1347 * 1348 * @deprecated As of JOMC 1.4, please use method {@link Modules#getMessageJavaModifierName(java.lang.String, java.lang.String)}. 1349 * This method will be removed in JOMC 2.0. 1350 */ 1351 @Deprecated 1352 public String getJavaModifierName( final Implementation implementation, final Message message ) 1353 { 1354 if ( implementation == null ) 1355 { 1356 throw new NullPointerException( "implementation" ); 1357 } 1358 if ( message == null ) 1359 { 1360 throw new NullPointerException( "message" ); 1361 } 1362 1363 String modifierName = "private"; 1364 1365 if ( this.getModules() != null ) 1366 { 1367 modifierName = 1368 this.getModules().getMessageJavaModifierName( implementation.getIdentifier(), message.getName() ); 1369 1370 if ( modifierName == null ) 1371 { 1372 modifierName = "private"; 1373 } 1374 } 1375 1376 return modifierName; 1377 } 1378 1379 /** 1380 * Gets the Java modifier name of a property of a given implementation. 1381 * 1382 * @param implementation The implementation declaring the property to get a Java modifier name of. 1383 * @param property The property to get a Java modifier name of. 1384 * 1385 * @return The Java modifier name of {@code property} of {@code implementation}. 1386 * 1387 * @throws NullPointerException if {@code implementation} or {@code property} is {@code null}. 1388 * 1389 * @deprecated As of JOMC 1.4, please use method {@link Modules#getPropertyJavaModifierName(java.lang.String, java.lang.String)}. 1390 * This method will be removed in JOMC 2.0. 1391 */ 1392 @Deprecated 1393 public String getJavaModifierName( final Implementation implementation, final Property property ) 1394 { 1395 if ( implementation == null ) 1396 { 1397 throw new NullPointerException( "implementation" ); 1398 } 1399 if ( property == null ) 1400 { 1401 throw new NullPointerException( "property" ); 1402 } 1403 1404 String modifierName = "private"; 1405 1406 if ( this.getModules() != null ) 1407 { 1408 modifierName = 1409 this.getModules().getPropertyJavaModifierName( implementation.getIdentifier(), property.getName() ); 1410 1411 if ( modifierName == null ) 1412 { 1413 modifierName = "private"; 1414 } 1415 } 1416 1417 return modifierName; 1418 } 1419 1420 /** 1421 * Formats a text to a Javadoc comment. 1422 * 1423 * @param text The text to format to a Javadoc comment. 1424 * @param indentationLevel The indentation level of the comment. 1425 * @param linePrefix The text to prepend lines with. 1426 * 1427 * @return {@code text} formatted to a Javadoc comment. 1428 * 1429 * @throws NullPointerException if {@code text} or {@code linePrefix} is {@code null}. 1430 * @throws IllegalArgumentException if {@code indentationLevel} is negative. 1431 * @throws ModelObjectException if compiling the type of the text to a {@code MimeType} fails. 1432 * 1433 * @deprecated As of JOMC 1.4, please use method {@link Text#getJavadocComment(java.lang.String, java.lang.String)}. 1434 * This method will be removed in JOMC 2.0. 1435 */ 1436 @Deprecated 1437 public String getJavadocComment( final Text text, final int indentationLevel, final String linePrefix ) 1438 throws ModelObjectException 1439 { 1440 if ( text == null ) 1441 { 1442 throw new NullPointerException( "text" ); 1443 } 1444 if ( linePrefix == null ) 1445 { 1446 throw new NullPointerException( "linePrefix" ); 1447 } 1448 if ( indentationLevel < 0 ) 1449 { 1450 throw new IllegalArgumentException( Integer.toString( indentationLevel ) ); 1451 } 1452 1453 BufferedReader reader = null; 1454 boolean suppressExceptionOnClose = true; 1455 1456 try 1457 { 1458 String javadoc = ""; 1459 1460 if ( text.getValue() != null ) 1461 { 1462 final String indent = this.getIndentation( indentationLevel ); 1463 reader = new BufferedReader( new StringReader( text.getValue() ) ); 1464 final StringBuilder builder = new StringBuilder( text.getValue().length() ); 1465 1466 String line; 1467 while ( ( line = reader.readLine() ) != null ) 1468 { 1469 builder.append( this.getLineSeparator() ).append( indent ).append( linePrefix ). 1470 append( line.replaceAll( "\\/\\*\\*", "/*" ).replaceAll( "\\*/", "/" ) ); 1471 1472 } 1473 1474 if ( builder.length() > 0 ) 1475 { 1476 javadoc = 1477 builder.substring( this.getLineSeparator().length() + indent.length() + linePrefix.length() ); 1478 1479 if ( !text.getMimeType().match( "text/html" ) ) 1480 { 1481 javadoc = StringEscapeUtils.escapeHtml( javadoc ); 1482 } 1483 } 1484 } 1485 1486 suppressExceptionOnClose = false; 1487 return javadoc; 1488 } 1489 catch ( final MimeTypeParseException e ) 1490 { 1491 throw new AssertionError( e ); 1492 } 1493 catch ( final IOException e ) 1494 { 1495 throw new AssertionError( e ); 1496 } 1497 finally 1498 { 1499 try 1500 { 1501 if ( reader != null ) 1502 { 1503 reader.close(); 1504 } 1505 } 1506 catch ( final IOException e ) 1507 { 1508 if ( suppressExceptionOnClose ) 1509 { 1510 this.log( Level.SEVERE, getMessage( e ), e ); 1511 } 1512 else 1513 { 1514 throw new AssertionError( e ); 1515 } 1516 } 1517 } 1518 } 1519 1520 /** 1521 * Formats a text from a list of texts to a Javadoc comment. 1522 * 1523 * @param texts The list of texts to format to a Javadoc comment. 1524 * @param indentationLevel The indentation level of the comment. 1525 * @param linePrefix The text to prepend lines with. 1526 * 1527 * @return The text corresponding to the locale of the instance from the list of texts formatted to a Javadoc 1528 * comment. 1529 * 1530 * @throws NullPointerException if {@code texts} or {@code linePrefix} is {@code null}. 1531 * @throws IllegalArgumentException if {@code indentationLevel} is negative. 1532 * @throws ModelObjectException if compiling a referenced type to a {@code MimeType} fails. 1533 * 1534 * @see #getLocale() 1535 * 1536 * @since 1.2 1537 * 1538 * @deprecated As of JOMC 1.4, please use method {@link Text#getJavadocComment(java.lang.String, java.lang.String)}. 1539 * This method will be removed in JOMC 2.0. 1540 */ 1541 @Deprecated 1542 public String getJavadocComment( final Texts texts, final int indentationLevel, final String linePrefix ) 1543 throws ModelObjectException 1544 { 1545 if ( texts == null ) 1546 { 1547 throw new NullPointerException( "texts" ); 1548 } 1549 if ( linePrefix == null ) 1550 { 1551 throw new NullPointerException( "linePrefix" ); 1552 } 1553 if ( indentationLevel < 0 ) 1554 { 1555 throw new IllegalArgumentException( Integer.toString( indentationLevel ) ); 1556 } 1557 1558 return this.getJavadocComment( texts.getText( this.getLocale().getLanguage() ), indentationLevel, linePrefix ); 1559 } 1560 1561 /** 1562 * Formats a string to a Java string with unicode escapes. 1563 * 1564 * @param str The string to format to a Java string or {@code null}. 1565 * 1566 * @return {@code str} formatted to a Java string or {@code null}. 1567 * 1568 * @see StringEscapeUtils#escapeJava(java.lang.String) 1569 */ 1570 public String getJavaString( final String str ) 1571 { 1572 return StringEscapeUtils.escapeJava( str ); 1573 } 1574 1575 /** 1576 * Formats a string to a Java class path location. 1577 * 1578 * @param str The string to format or {@code null}. 1579 * @param absolute {@code true} to return an absolute class path location; {@code false} to return a relative 1580 * class path location. 1581 * 1582 * @return {@code str} formatted to a Java class path location. 1583 * 1584 * @since 1.3 1585 * 1586 * @deprecated As of JOMC 1.4, please use {@link JavaTypeName#getQualifiedName()}. This method will be removed in 1587 * JOMC 2.0. 1588 */ 1589 @Deprecated 1590 public String getJavaClasspathLocation( final String str, final boolean absolute ) 1591 { 1592 String classpathLocation = null; 1593 1594 if ( str != null ) 1595 { 1596 classpathLocation = str.replace( '.', '/' ); 1597 1598 if ( absolute ) 1599 { 1600 classpathLocation = "/" + classpathLocation; 1601 } 1602 } 1603 1604 return classpathLocation; 1605 } 1606 1607 /** 1608 * Formats a string to a Java identifier. 1609 * 1610 * @param str The string to format or {@code null}. 1611 * @param capitalize {@code true}, to return an identifier with the first character upper cased; {@code false}, to 1612 * return an identifier with the first character lower cased. 1613 * 1614 * @return {@code str} formatted to a Java identifier or {@code null}. 1615 * 1616 * @since 1.2 1617 * 1618 * @deprecated As of JOMC 1.4, please use method {@link #toJavaVariableName(java.lang.String)}. This method will be 1619 * removed in JOMC 2.0. 1620 */ 1621 @Deprecated 1622 public String getJavaIdentifier( final String str, final boolean capitalize ) 1623 { 1624 String identifier = null; 1625 1626 if ( str != null ) 1627 { 1628 final int len = str.length(); 1629 final StringBuilder builder = new StringBuilder( len ); 1630 boolean uc = capitalize; 1631 1632 for ( int i = 0; i < len; i++ ) 1633 { 1634 final char c = str.charAt( i ); 1635 final String charString = Character.toString( c ); 1636 1637 if ( builder.length() > 0 ) 1638 { 1639 if ( Character.isJavaIdentifierPart( c ) ) 1640 { 1641 builder.append( uc ? charString.toUpperCase( this.getLocale() ) : charString ); 1642 uc = false; 1643 } 1644 else 1645 { 1646 uc = true; 1647 } 1648 } 1649 else 1650 { 1651 if ( Character.isJavaIdentifierStart( c ) ) 1652 { 1653 builder.append( uc ? charString.toUpperCase( this.getLocale() ) 1654 : charString.toLowerCase( this.getLocale() ) ); 1655 1656 uc = false; 1657 } 1658 else 1659 { 1660 uc = capitalize; 1661 } 1662 } 1663 } 1664 1665 identifier = builder.toString(); 1666 1667 if ( identifier.length() <= 0 && this.isLoggable( Level.WARNING ) ) 1668 { 1669 this.log( Level.WARNING, getMessage( "invalidJavaIdentifier", str ), null ); 1670 } 1671 } 1672 1673 return identifier; 1674 } 1675 1676 /** 1677 * Formats a string to a Java method parameter name. 1678 * 1679 * @param str The string to format or {@code null}. 1680 * 1681 * @return {@code str} formatted to a Java method parameter name or {@code null}. 1682 * 1683 * @since 1.3 1684 * 1685 * @deprecated As of JOMC 1.4, please use method {@link #toJavaVariableName(java.lang.String)}. This method will be 1686 * removed in JOMC 2.0. 1687 */ 1688 @Deprecated 1689 public String getJavaMethodParameterName( final String str ) 1690 { 1691 String methodParameterName = null; 1692 1693 if ( str != null ) 1694 { 1695 final int len = str.length(); 1696 final StringBuilder builder = new StringBuilder( len ); 1697 boolean uc = false; 1698 1699 for ( int i = 0; i < len; i++ ) 1700 { 1701 final char c = str.charAt( i ); 1702 final String charString = Character.toString( c ); 1703 1704 if ( builder.length() > 0 ) 1705 { 1706 if ( Character.isJavaIdentifierPart( c ) ) 1707 { 1708 builder.append( uc ? charString.toUpperCase( this.getLocale() ) : charString ); 1709 uc = false; 1710 } 1711 else 1712 { 1713 uc = true; 1714 } 1715 } 1716 else if ( Character.isJavaIdentifierStart( c ) ) 1717 { 1718 builder.append( charString.toLowerCase( this.getLocale() ) ); 1719 } 1720 } 1721 1722 methodParameterName = builder.toString(); 1723 1724 if ( methodParameterName.length() <= 0 && this.isLoggable( Level.WARNING ) ) 1725 { 1726 this.log( Level.WARNING, getMessage( "invalidJavaMethodParameterName", str ), null ); 1727 } 1728 1729 if ( this.getJavaKeywords().contains( methodParameterName ) ) 1730 { 1731 methodParameterName = "_" + methodParameterName; 1732 } 1733 } 1734 1735 return methodParameterName; 1736 } 1737 1738 /** 1739 * Formats a string to a Java field name. 1740 * 1741 * @param str The string to format or {@code null}. 1742 * 1743 * @return {@code str} formatted to a Java field name or {@code null}. 1744 * 1745 * @since 1.3 1746 * 1747 * @deprecated As of JOMC 1.4, please use method {@link #toJavaVariableName(java.lang.String)}. This method will be 1748 * removed in JOMC 2.0. 1749 */ 1750 @Deprecated 1751 public String getJavaFieldName( final String str ) 1752 { 1753 String fieldName = null; 1754 1755 if ( str != null ) 1756 { 1757 final int len = str.length(); 1758 final StringBuilder builder = new StringBuilder( len ); 1759 boolean uc = false; 1760 1761 for ( int i = 0; i < len; i++ ) 1762 { 1763 final char c = str.charAt( i ); 1764 final String charString = Character.toString( c ); 1765 1766 if ( builder.length() > 0 ) 1767 { 1768 if ( Character.isJavaIdentifierPart( c ) ) 1769 { 1770 builder.append( uc ? charString.toUpperCase( this.getLocale() ) : charString ); 1771 uc = false; 1772 } 1773 else 1774 { 1775 uc = true; 1776 } 1777 } 1778 else if ( Character.isJavaIdentifierStart( c ) ) 1779 { 1780 builder.append( charString.toLowerCase( this.getLocale() ) ); 1781 } 1782 } 1783 1784 fieldName = builder.toString(); 1785 1786 if ( fieldName.length() <= 0 && this.isLoggable( Level.WARNING ) ) 1787 { 1788 this.log( Level.WARNING, getMessage( "invalidJavaFieldName", str ), null ); 1789 } 1790 1791 if ( this.getJavaKeywords().contains( fieldName ) ) 1792 { 1793 fieldName = "_" + fieldName; 1794 } 1795 } 1796 1797 return fieldName; 1798 } 1799 1800 /** 1801 * Formats a string to a Java constant name. 1802 * 1803 * @param str The string to format or {@code null}. 1804 * 1805 * @return {@code str} formatted to a Java constant name or {@code null}. 1806 * 1807 * @since 1.3 1808 * 1809 * @deprecated As of JOMC 1.4, please use method {@link #toJavaConstantName(java.lang.String)}. This method will be 1810 * removed in JOMC 2.0. 1811 */ 1812 @Deprecated 1813 public String getJavaConstantName( final String str ) 1814 { 1815 String name = null; 1816 1817 if ( str != null ) 1818 { 1819 final int len = str.length(); 1820 final StringBuilder builder = new StringBuilder( len ); 1821 boolean separator = false; 1822 1823 for ( int i = 0; i < len; i++ ) 1824 { 1825 final char c = str.charAt( i ); 1826 1827 if ( builder.length() > 0 ? Character.isJavaIdentifierPart( c ) : Character.isJavaIdentifierStart( c ) ) 1828 { 1829 if ( builder.length() > 0 ) 1830 { 1831 if ( !separator ) 1832 { 1833 final char previous = builder.charAt( builder.length() - 1 ); 1834 separator = Character.isLowerCase( previous ) && Character.isUpperCase( c ); 1835 } 1836 1837 if ( separator ) 1838 { 1839 builder.append( '_' ); 1840 } 1841 } 1842 1843 builder.append( c ); 1844 separator = false; 1845 } 1846 else 1847 { 1848 separator = true; 1849 } 1850 } 1851 1852 name = builder.toString().toUpperCase( this.getLocale() ); 1853 1854 if ( name.length() <= 0 && this.isLoggable( Level.WARNING ) ) 1855 { 1856 this.log( Level.WARNING, getMessage( "invalidJavaConstantName", str ), null ); 1857 } 1858 } 1859 1860 return name; 1861 } 1862 1863 /** 1864 * Formats a string to a Java constant name. 1865 * 1866 * @param str The string to format or {@code null}. 1867 * 1868 * @return {@code str} formatted to a Java constant name or {@code null}. 1869 * 1870 * @throws ParseException if normalizing {@code str} to a {@code JavaIdentifier} fails. 1871 * 1872 * @since 1.3 1873 * 1874 * @see JavaIdentifier#normalize(java.lang.String, org.jomc.model.JavaIdentifier.NormalizationMode) 1875 * @see org.jomc.model.JavaIdentifier.NormalizationMode#CONSTANT_NAME_CONVENTION 1876 */ 1877 public JavaIdentifier toJavaConstantName( final String str ) throws ParseException 1878 { 1879 JavaIdentifier constantName = null; 1880 1881 if ( str != null ) 1882 { 1883 constantName = JavaIdentifier.normalize( str, JavaIdentifier.NormalizationMode.CONSTANT_NAME_CONVENTION ); 1884 } 1885 1886 return constantName; 1887 } 1888 1889 /** 1890 * Compiles a string to a Java method name. 1891 * 1892 * @param str The string to compile or {@code null}. 1893 * 1894 * @return {@code str} compiled to a {@code JavaIdentifier} or {@code null}, if {@code str} is {@code null}. 1895 * 1896 * @throws ParseException if compiling {@code str} to a {@code JavaIdentifier} fails. 1897 * 1898 * @since 1.4 1899 * 1900 * @see JavaIdentifier#normalize(java.lang.String, org.jomc.model.JavaIdentifier.NormalizationMode) 1901 * @see org.jomc.model.JavaIdentifier.NormalizationMode#METHOD_NAME_CONVENTION 1902 */ 1903 public JavaIdentifier toJavaMethodName( final String str ) throws ParseException 1904 { 1905 JavaIdentifier variableName = null; 1906 1907 if ( str != null ) 1908 { 1909 variableName = 1910 JavaIdentifier.normalize( str, JavaIdentifier.NormalizationMode.METHOD_NAME_CONVENTION ); 1911 1912 } 1913 1914 return variableName; 1915 } 1916 1917 /** 1918 * Compiles a string to a Java variable name. 1919 * 1920 * @param str The string to compile or {@code null}. 1921 * 1922 * @return {@code str} compiled to a {@code JavaIdentifier} or {@code null}, if {@code str} is {@code null}. 1923 * 1924 * @throws ParseException if compiling {@code str} to a {@code JavaIdentifier} fails. 1925 * 1926 * @since 1.4 1927 * 1928 * @see JavaIdentifier#normalize(java.lang.String, org.jomc.model.JavaIdentifier.NormalizationMode) 1929 * @see org.jomc.model.JavaIdentifier.NormalizationMode#VARIABLE_NAME_CONVENTION 1930 */ 1931 public JavaIdentifier toJavaVariableName( final String str ) throws ParseException 1932 { 1933 JavaIdentifier variableName = null; 1934 1935 if ( str != null ) 1936 { 1937 variableName = 1938 JavaIdentifier.normalize( str, JavaIdentifier.NormalizationMode.VARIABLE_NAME_CONVENTION ); 1939 1940 } 1941 1942 return variableName; 1943 } 1944 1945 /** 1946 * Gets a flag indicating the type referenced by a given specification is located in an unnamed Java package. 1947 * 1948 * @param specification The specification to query. 1949 * 1950 * @return {@code true}, if the type referenced by {@code specification} is located in an unnamed Java package; 1951 * {@code false}, if the specification does not reference a type or if the referenced type is not located in an 1952 * unnamed Java package. 1953 * 1954 * @throws NullPointerException if {@code specification} is {@code null}. 1955 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 1956 * 1957 * @see Specification#getJavaTypeName() 1958 * @see JavaTypeName#isUnnamedPackage() 1959 * 1960 * @deprecated As of JOMC 1.4, please use method {@link Specification#getJavaTypeName()}. This method will be 1961 * removed in JOMC 2.0. 1962 */ 1963 @Deprecated 1964 public boolean isJavaDefaultPackage( final Specification specification ) throws ModelObjectException 1965 { 1966 if ( specification == null ) 1967 { 1968 throw new NullPointerException( "specification" ); 1969 } 1970 1971 final JavaTypeName javaTypeName = specification.getJavaTypeName(); 1972 return javaTypeName != null && javaTypeName.isUnnamedPackage(); 1973 } 1974 1975 /** 1976 * Gets a flag indicating the type referenced by a given implementation is located in an unnamed Java package. 1977 * 1978 * @param implementation The implementation to query. 1979 * 1980 * @return {@code true}, if the type referenced by {@code implementation} is located in an unnamed Java package; 1981 * {@code false}, if the implementation does not reference a type or if the referenced type is not located in an 1982 * unnamed Java package. 1983 * 1984 * @throws NullPointerException if {@code implementation} is {@code null}. 1985 * @throws ModelObjectException if compiling the name of the referenced type to a {@code JavaTypeName} fails. 1986 * 1987 * @see Implementation#getJavaTypeName() 1988 * @see JavaTypeName#isUnnamedPackage() 1989 * 1990 * @deprecated As of JOMC 1.4, please use method {@link Implementation#getJavaTypeName()}. This method will be 1991 * removed in JOMC 2.0. 1992 */ 1993 @Deprecated 1994 public boolean isJavaDefaultPackage( final Implementation implementation ) throws ModelObjectException 1995 { 1996 if ( implementation == null ) 1997 { 1998 throw new NullPointerException( "implementation" ); 1999 } 2000 2001 final JavaTypeName javaTypeName = implementation.getJavaTypeName(); 2002 return javaTypeName != null && javaTypeName.isUnnamedPackage(); 2003 } 2004 2005 /** 2006 * Formats a string to a HTML string with HTML entities. 2007 * 2008 * @param str The string to format to a HTML string with HTML entities or {@code null}. 2009 * 2010 * @return {@code str} formatted to a HTML string with HTML entities or {@code null}. 2011 * 2012 * @since 1.2 2013 */ 2014 public String getHtmlString( final String str ) 2015 { 2016 return str != null ? str.replace( "&", "&" ).replace( "<", "<" ).replace( ">", ">" ). 2017 replace( "\"", """ ).replace( "*", "∗" ) : null; 2018 2019 } 2020 2021 /** 2022 * Formats a string to a XML string with XML entities. 2023 * 2024 * @param str The string to format to a XML string with XML entities or {@code null}. 2025 * 2026 * @return {@code str} formatted to a XML string with XML entities or {@code null}. 2027 * 2028 * @see StringEscapeUtils#escapeXml(java.lang.String) 2029 * 2030 * @since 1.2 2031 */ 2032 public String getXmlString( final String str ) 2033 { 2034 return StringEscapeUtils.escapeXml( str ); 2035 } 2036 2037 /** 2038 * Formats a string to a JavaScript string applying JavaScript string rules. 2039 * 2040 * @param str The string to format to a JavaScript string by applying JavaScript string rules or {@code null}. 2041 * 2042 * @return {@code str} formatted to a JavaScript string with JavaScript string rules applied or {@code null}. 2043 * 2044 * @see StringEscapeUtils#escapeJavaScript(java.lang.String) 2045 * 2046 * @since 1.2 2047 */ 2048 public String getJavaScriptString( final String str ) 2049 { 2050 return StringEscapeUtils.escapeJavaScript( str ); 2051 } 2052 2053 /** 2054 * Formats a string to a SQL string. 2055 * 2056 * @param str The string to format to a SQL string or {@code null}. 2057 * 2058 * @return {@code str} formatted to a SQL string or {@code null}. 2059 * 2060 * @see StringEscapeUtils#escapeSql(java.lang.String) 2061 * 2062 * @since 1.2 2063 */ 2064 public String getSqlString( final String str ) 2065 { 2066 return StringEscapeUtils.escapeSql( str ); 2067 } 2068 2069 /** 2070 * Formats a string to a CSV string. 2071 * 2072 * @param str The string to format to a CSV string or {@code null}. 2073 * 2074 * @return {@code str} formatted to a CSV string or {@code null}. 2075 * 2076 * @see StringEscapeUtils#escapeCsv(java.lang.String) 2077 * 2078 * @since 1.2 2079 */ 2080 public String getCsvString( final String str ) 2081 { 2082 return StringEscapeUtils.escapeCsv( str ); 2083 } 2084 2085 /** 2086 * Formats a {@code Boolean} to a string. 2087 * 2088 * @param b The {@code Boolean} to format to a string or {@code null}. 2089 * 2090 * @return {@code b} formatted to a string. 2091 * 2092 * @see #getLocale() 2093 * 2094 * @since 1.2 2095 */ 2096 public String getBooleanString( final Boolean b ) 2097 { 2098 final MessageFormat messageFormat = new MessageFormat( ResourceBundle.getBundle( 2099 JomcTool.class.getName().replace( '.', '/' ), this.getLocale() ). 2100 getString( b ? "booleanStringTrue" : "booleanStringFalse" ), this.getLocale() ); 2101 2102 return messageFormat.format( null ); 2103 } 2104 2105 /** 2106 * Gets the display language of a given language code. 2107 * 2108 * @param language The language code to get the display language of. 2109 * 2110 * @return The display language of {@code language}. 2111 * 2112 * @throws NullPointerException if {@code language} is {@code null}. 2113 */ 2114 public String getDisplayLanguage( final String language ) 2115 { 2116 if ( language == null ) 2117 { 2118 throw new NullPointerException( "language" ); 2119 } 2120 2121 final Locale l = new Locale( language ); 2122 return l.getDisplayLanguage( l ); 2123 } 2124 2125 /** 2126 * Formats a calendar instance to a string. 2127 * 2128 * @param calendar The calendar to format to a string. 2129 * 2130 * @return The date of {@code calendar} formatted using a short format style pattern. 2131 * 2132 * @throws NullPointerException if {@code calendar} is {@code null}. 2133 * 2134 * @see DateFormat#SHORT 2135 */ 2136 public String getShortDate( final Calendar calendar ) 2137 { 2138 if ( calendar == null ) 2139 { 2140 throw new NullPointerException( "calendar" ); 2141 } 2142 2143 return DateFormat.getDateInstance( DateFormat.SHORT, this.getLocale() ).format( calendar.getTime() ); 2144 } 2145 2146 /** 2147 * Formats a calendar instance to a string. 2148 * 2149 * @param calendar The calendar to format to a string. 2150 * 2151 * @return The date of {@code calendar} formatted using a medium format style pattern. 2152 * 2153 * @throws NullPointerException if {@code calendar} is {@code null}. 2154 * 2155 * @see DateFormat#MEDIUM 2156 * 2157 * @since 1.2 2158 */ 2159 public String getMediumDate( final Calendar calendar ) 2160 { 2161 if ( calendar == null ) 2162 { 2163 throw new NullPointerException( "calendar" ); 2164 } 2165 2166 return DateFormat.getDateInstance( DateFormat.MEDIUM, this.getLocale() ).format( calendar.getTime() ); 2167 } 2168 2169 /** 2170 * Formats a calendar instance to a string. 2171 * 2172 * @param calendar The calendar to format to a string. 2173 * 2174 * @return The date of {@code calendar} formatted using a long format style pattern. 2175 * 2176 * @throws NullPointerException if {@code calendar} is {@code null}. 2177 * 2178 * @see DateFormat#LONG 2179 */ 2180 public String getLongDate( final Calendar calendar ) 2181 { 2182 if ( calendar == null ) 2183 { 2184 throw new NullPointerException( "calendar" ); 2185 } 2186 2187 return DateFormat.getDateInstance( DateFormat.LONG, this.getLocale() ).format( calendar.getTime() ); 2188 } 2189 2190 /** 2191 * Formats a calendar instance to a string. 2192 * 2193 * @param calendar The calendar to format to a string. 2194 * 2195 * @return The date of {@code calendar} formatted using an ISO-8601 format style. 2196 * 2197 * @throws NullPointerException if {@code calendar} is {@code null}. 2198 * 2199 * @see SimpleDateFormat yyyy-DDD 2200 * 2201 * @since 1.2 2202 */ 2203 public String getIsoDate( final Calendar calendar ) 2204 { 2205 if ( calendar == null ) 2206 { 2207 throw new NullPointerException( "calendar" ); 2208 } 2209 2210 return new SimpleDateFormat( "yyyy-DDD", this.getLocale() ).format( calendar.getTime() ); 2211 } 2212 2213 /** 2214 * Formats a calendar instance to a string. 2215 * 2216 * @param calendar The calendar to format to a string. 2217 * 2218 * @return The time of {@code calendar} formatted using a short format style pattern. 2219 * 2220 * @throws NullPointerException if {@code calendar} is {@code null}. 2221 * 2222 * @see DateFormat#SHORT 2223 */ 2224 public String getShortTime( final Calendar calendar ) 2225 { 2226 if ( calendar == null ) 2227 { 2228 throw new NullPointerException( "calendar" ); 2229 } 2230 2231 return DateFormat.getTimeInstance( DateFormat.SHORT, this.getLocale() ).format( calendar.getTime() ); 2232 } 2233 2234 /** 2235 * Formats a calendar instance to a string. 2236 * 2237 * @param calendar The calendar to format to a string. 2238 * 2239 * @return The time of {@code calendar} formatted using a medium format style pattern. 2240 * 2241 * @throws NullPointerException if {@code calendar} is {@code null}. 2242 * 2243 * @see DateFormat#MEDIUM 2244 * 2245 * @since 1.2 2246 */ 2247 public String getMediumTime( final Calendar calendar ) 2248 { 2249 if ( calendar == null ) 2250 { 2251 throw new NullPointerException( "calendar" ); 2252 } 2253 2254 return DateFormat.getTimeInstance( DateFormat.MEDIUM, this.getLocale() ).format( calendar.getTime() ); 2255 } 2256 2257 /** 2258 * Formats a calendar instance to a string. 2259 * 2260 * @param calendar The calendar to format to a string. 2261 * 2262 * @return The time of {@code calendar} formatted using a long format style pattern. 2263 * 2264 * @throws NullPointerException if {@code calendar} is {@code null}. 2265 * 2266 * @see DateFormat#LONG 2267 */ 2268 public String getLongTime( final Calendar calendar ) 2269 { 2270 if ( calendar == null ) 2271 { 2272 throw new NullPointerException( "calendar" ); 2273 } 2274 2275 return DateFormat.getTimeInstance( DateFormat.LONG, this.getLocale() ).format( calendar.getTime() ); 2276 } 2277 2278 /** 2279 * Formats a calendar instance to a string. 2280 * 2281 * @param calendar The calendar to format to a string. 2282 * 2283 * @return The time of {@code calendar} formatted using an ISO-8601 format style. 2284 * 2285 * @throws NullPointerException if {@code calendar} is {@code null}. 2286 * 2287 * @see SimpleDateFormat HH:mm 2288 * 2289 * @since 1.2 2290 */ 2291 public String getIsoTime( final Calendar calendar ) 2292 { 2293 if ( calendar == null ) 2294 { 2295 throw new NullPointerException( "calendar" ); 2296 } 2297 2298 return new SimpleDateFormat( "HH:mm", this.getLocale() ).format( calendar.getTime() ); 2299 } 2300 2301 /** 2302 * Formats a calendar instance to a string. 2303 * 2304 * @param calendar The calendar to format to a string. 2305 * 2306 * @return The date and time of {@code calendar} formatted using a short format style pattern. 2307 * 2308 * @throws NullPointerException if {@code calendar} is {@code null}. 2309 * 2310 * @see DateFormat#SHORT 2311 */ 2312 public String getShortDateTime( final Calendar calendar ) 2313 { 2314 if ( calendar == null ) 2315 { 2316 throw new NullPointerException( "calendar" ); 2317 } 2318 2319 return DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.SHORT, this.getLocale() ). 2320 format( calendar.getTime() ); 2321 2322 } 2323 2324 /** 2325 * Formats a calendar instance to a string. 2326 * 2327 * @param calendar The calendar to format to a string. 2328 * 2329 * @return The date and time of {@code calendar} formatted using a medium format style pattern. 2330 * 2331 * @throws NullPointerException if {@code calendar} is {@code null}. 2332 * 2333 * @see DateFormat#MEDIUM 2334 * 2335 * @since 1.2 2336 */ 2337 public String getMediumDateTime( final Calendar calendar ) 2338 { 2339 if ( calendar == null ) 2340 { 2341 throw new NullPointerException( "calendar" ); 2342 } 2343 2344 return DateFormat.getDateTimeInstance( DateFormat.MEDIUM, DateFormat.MEDIUM, this.getLocale() ). 2345 format( calendar.getTime() ); 2346 2347 } 2348 2349 /** 2350 * Formats a calendar instance to a string. 2351 * 2352 * @param calendar The calendar to format to a string. 2353 * 2354 * @return The date and time of {@code calendar} formatted using a long format style pattern. 2355 * 2356 * @throws NullPointerException if {@code calendar} is {@code null}. 2357 * 2358 * @see DateFormat#LONG 2359 */ 2360 public String getLongDateTime( final Calendar calendar ) 2361 { 2362 if ( calendar == null ) 2363 { 2364 throw new NullPointerException( "calendar" ); 2365 } 2366 2367 return DateFormat.getDateTimeInstance( DateFormat.LONG, DateFormat.LONG, this.getLocale() ). 2368 format( calendar.getTime() ); 2369 2370 } 2371 2372 /** 2373 * Formats a calendar instance to a string. 2374 * 2375 * @param calendar The calendar to format to a string. 2376 * 2377 * @return The date and time of {@code calendar} formatted using a ISO-8601 format style. 2378 * 2379 * @throws NullPointerException if {@code calendar} is {@code null}. 2380 * 2381 * @see SimpleDateFormat yyyy-MM-dd'T'HH:mm:ssZ 2382 * 2383 * @since 1.2 2384 */ 2385 public String getIsoDateTime( final Calendar calendar ) 2386 { 2387 if ( calendar == null ) 2388 { 2389 throw new NullPointerException( "calendar" ); 2390 } 2391 2392 // JDK: As of JDK 7, "yyyy-MM-dd'T'HH:mm:ssXXX". 2393 return new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ssZ", this.getLocale() ).format( calendar.getTime() ); 2394 } 2395 2396 /** 2397 * Gets a string describing the range of years for given calendars. 2398 * 2399 * @param start The start of the range. 2400 * @param end The end of the range. 2401 * 2402 * @return Formatted range of the years of {@code start} and {@code end} (e.g. {@code "start - end"}). 2403 * 2404 * @throws NullPointerException if {@code start} or {@code end} is {@code null}. 2405 */ 2406 public String getYears( final Calendar start, final Calendar end ) 2407 { 2408 if ( start == null ) 2409 { 2410 throw new NullPointerException( "start" ); 2411 } 2412 if ( end == null ) 2413 { 2414 throw new NullPointerException( "end" ); 2415 } 2416 2417 final Format yearFormat = new SimpleDateFormat( "yyyy", this.getLocale() ); 2418 final int s = start.get( Calendar.YEAR ); 2419 final int e = end.get( Calendar.YEAR ); 2420 final StringBuilder years = new StringBuilder(); 2421 2422 if ( s != e ) 2423 { 2424 if ( s < e ) 2425 { 2426 years.append( yearFormat.format( start.getTime() ) ).append( " - " ). 2427 append( yearFormat.format( end.getTime() ) ); 2428 2429 } 2430 else 2431 { 2432 years.append( yearFormat.format( end.getTime() ) ).append( " - " ). 2433 append( yearFormat.format( start.getTime() ) ); 2434 2435 } 2436 } 2437 else 2438 { 2439 years.append( yearFormat.format( start.getTime() ) ); 2440 } 2441 2442 return years.toString(); 2443 } 2444 2445 /** 2446 * Gets the model of the instance. 2447 * 2448 * @return The model of the instance. 2449 * 2450 * @see #getModules() 2451 * @see #setModel(org.jomc.modlet.Model) 2452 */ 2453 public final Model getModel() 2454 { 2455 if ( this.model == null ) 2456 { 2457 this.model = new Model(); 2458 this.model.setIdentifier( ModelObject.MODEL_PUBLIC_ID ); 2459 } 2460 2461 return this.model; 2462 } 2463 2464 /** 2465 * Sets the model of the instance. 2466 * 2467 * @param value The new model of the instance or {@code null}. 2468 * 2469 * @see #getModel() 2470 */ 2471 public final void setModel( final Model value ) 2472 { 2473 this.model = value; 2474 } 2475 2476 /** 2477 * Gets the modules of the model of the instance. 2478 * 2479 * @return The modules of the model of the instance or {@code null}, if no modules are found. 2480 * 2481 * @see #getModel() 2482 * @see #setModel(org.jomc.modlet.Model) 2483 */ 2484 public final Modules getModules() 2485 { 2486 return ModelHelper.getModules( this.getModel() ); 2487 } 2488 2489 /** 2490 * Gets the {@code VelocityEngine} of the instance. 2491 * 2492 * @return The {@code VelocityEngine} of the instance. 2493 * 2494 * @throws IOException if initializing a new velocity engine fails. 2495 * 2496 * @see #setVelocityEngine(org.apache.velocity.app.VelocityEngine) 2497 */ 2498 public final VelocityEngine getVelocityEngine() throws IOException 2499 { 2500 if ( this.velocityEngine == null ) 2501 { 2502 /** {@code LogChute} logging to the listeners of the tool. */ 2503 class JomcLogChute implements LogChute 2504 { 2505 2506 JomcLogChute() 2507 { 2508 super(); 2509 } 2510 2511 public void init( final RuntimeServices runtimeServices ) throws Exception 2512 { 2513 } 2514 2515 public void log( final int level, final String message ) 2516 { 2517 this.log( level, message, null ); 2518 } 2519 2520 public void log( final int level, final String message, final Throwable throwable ) 2521 { 2522 JomcTool.this.log( Level.FINEST, message, throwable ); 2523 } 2524 2525 public boolean isLevelEnabled( final int level ) 2526 { 2527 return isLoggable( Level.FINEST ); 2528 } 2529 2530 } 2531 2532 final VelocityEngine engine = new VelocityEngine(); 2533 engine.setProperty( RuntimeConstants.RUNTIME_REFERENCES_STRICT, Boolean.TRUE.toString() ); 2534 engine.setProperty( RuntimeConstants.VM_ARGUMENTS_STRICT, Boolean.TRUE.toString() ); 2535 engine.setProperty( RuntimeConstants.STRICT_MATH, Boolean.TRUE.toString() ); 2536 engine.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, new JomcLogChute() ); 2537 2538 engine.setProperty( RuntimeConstants.RESOURCE_LOADER, "class" ); 2539 engine.setProperty( "class.resource.loader.class", ClasspathResourceLoader.class.getName() ); 2540 engine.setProperty( "class.resource.loader.cache", Boolean.TRUE.toString() ); 2541 2542 if ( this.getTemplateLocation() != null ) 2543 { 2544 engine.setProperty( RuntimeConstants.RESOURCE_LOADER, "class,url" ); 2545 engine.setProperty( "url.resource.loader.class", URLResourceLoader.class.getName() ); 2546 engine.setProperty( "url.resource.loader.cache", Boolean.TRUE.toString() ); 2547 engine.setProperty( "url.resource.loader.root", this.getTemplateLocation().toExternalForm() ); 2548 engine.setProperty( "url.resource.loader.timeout", Integer.toString( 60000 ) ); 2549 } 2550 2551 this.velocityEngine = engine; 2552 this.defaultVelocityEngine = true; 2553 } 2554 2555 return this.velocityEngine; 2556 } 2557 2558 /** 2559 * Sets the {@code VelocityEngine} of the instance. 2560 * 2561 * @param value The new {@code VelocityEngine} of the instance or {@code null}. 2562 * 2563 * @see #getVelocityEngine() 2564 */ 2565 public final void setVelocityEngine( final VelocityEngine value ) 2566 { 2567 this.velocityEngine = value; 2568 this.defaultVelocityEngine = false; 2569 } 2570 2571 /** 2572 * Gets a new velocity context used for merging templates. 2573 * 2574 * @return A new velocity context used for merging templates. 2575 * 2576 * @throws IOException if creating a new context instance fails. 2577 * 2578 * @see #getTemplateParameters() 2579 */ 2580 public VelocityContext getVelocityContext() throws IOException 2581 { 2582 final Calendar now = Calendar.getInstance(); 2583 final VelocityContext ctx = 2584 new VelocityContext( new HashMap<String, Object>( this.getTemplateParameters() ) ); 2585 2586 this.mergeTemplateProfileContextProperties( this.getTemplateProfile(), this.getLocale().getLanguage(), ctx ); 2587 this.mergeTemplateProfileContextProperties( this.getTemplateProfile(), null, ctx ); 2588 2589 final Model clonedModel = this.getModel().clone(); 2590 final Modules clonedModules = ModelHelper.getModules( clonedModel ); 2591 assert clonedModules != null : "Unexpected missing modules for model '" + clonedModel.getIdentifier() + "'."; 2592 2593 ctx.put( "model", clonedModel ); 2594 ctx.put( "modules", clonedModules ); 2595 ctx.put( "imodel", new InheritanceModel( clonedModules ) ); 2596 ctx.put( "tool", this ); 2597 ctx.put( "toolName", this.getClass().getName() ); 2598 ctx.put( "toolVersion", getMessage( "projectVersion" ) ); 2599 ctx.put( "toolUrl", getMessage( "projectUrl" ) ); 2600 ctx.put( "calendar", now.getTime() ); 2601 2602 // JDK: As of JDK 7, "yyyy-MM-dd'T'HH:mm:ss.SSSXXX". 2603 ctx.put( "now", 2604 new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss.SSSZ", this.getLocale() ).format( now.getTime() ) ); 2605 2606 ctx.put( "year", new SimpleDateFormat( "yyyy", this.getLocale() ).format( now.getTime() ) ); 2607 ctx.put( "month", new SimpleDateFormat( "MM", this.getLocale() ).format( now.getTime() ) ); 2608 ctx.put( "day", new SimpleDateFormat( "dd", this.getLocale() ).format( now.getTime() ) ); 2609 ctx.put( "hour", new SimpleDateFormat( "HH", this.getLocale() ).format( now.getTime() ) ); 2610 ctx.put( "minute", new SimpleDateFormat( "mm", this.getLocale() ).format( now.getTime() ) ); 2611 ctx.put( "second", new SimpleDateFormat( "ss", this.getLocale() ).format( now.getTime() ) ); 2612 ctx.put( "timezone", new SimpleDateFormat( "Z", this.getLocale() ).format( now.getTime() ) ); 2613 ctx.put( "shortDate", this.getShortDate( now ) ); 2614 ctx.put( "mediumDate", this.getMediumDate( now ) ); 2615 ctx.put( "longDate", this.getLongDate( now ) ); 2616 ctx.put( "isoDate", this.getIsoDate( now ) ); 2617 ctx.put( "shortTime", this.getShortTime( now ) ); 2618 ctx.put( "mediumTime", this.getMediumTime( now ) ); 2619 ctx.put( "longTime", this.getLongTime( now ) ); 2620 ctx.put( "isoTime", this.getIsoTime( now ) ); 2621 ctx.put( "shortDateTime", this.getShortDateTime( now ) ); 2622 ctx.put( "mediumDateTime", this.getMediumDateTime( now ) ); 2623 ctx.put( "longDateTime", this.getLongDateTime( now ) ); 2624 ctx.put( "isoDateTime", this.getIsoDateTime( now ) ); 2625 2626 return ctx; 2627 } 2628 2629 /** 2630 * Gets the template parameters of the instance. 2631 * <p>This accessor method returns a reference to the live map, not a snapshot. Therefore any modification you make 2632 * to the returned map will be present inside the object. This is why there is no {@code set} method for the 2633 * template parameters property.</p> 2634 * 2635 * @return The template parameters of the instance. 2636 * 2637 * @see #getVelocityContext() 2638 * 2639 * @since 1.2 2640 */ 2641 public final Map<String, Object> getTemplateParameters() 2642 { 2643 if ( this.templateParameters == null ) 2644 { 2645 this.templateParameters = Collections.synchronizedMap( new HashMap<String, Object>() ); 2646 } 2647 2648 return this.templateParameters; 2649 } 2650 2651 /** 2652 * Gets the location to search for templates in addition to searching the class path. 2653 * 2654 * @return The location to search for templates in addition to searching the class path or {@code null}. 2655 * 2656 * @see #setTemplateLocation(java.net.URL) 2657 * 2658 * @since 1.2 2659 */ 2660 public final URL getTemplateLocation() 2661 { 2662 return this.templateLocation; 2663 } 2664 2665 /** 2666 * Sets the location to search for templates in addition to searching the class path. 2667 * 2668 * @param value The new location to search for templates in addition to searching the class path or {@code null}. 2669 * 2670 * @see #getTemplateLocation() 2671 * 2672 * @since 1.2 2673 */ 2674 public final void setTemplateLocation( final URL value ) 2675 { 2676 this.templateLocation = value; 2677 this.templateProfileContextPropertiesCache = null; 2678 this.templateProfilePropertiesCache = null; 2679 2680 if ( this.defaultVelocityEngine ) 2681 { 2682 this.setVelocityEngine( null ); 2683 } 2684 } 2685 2686 /** 2687 * Gets the encoding to use for reading templates. 2688 * 2689 * @return The encoding to use for reading templates. 2690 * 2691 * @see #setTemplateEncoding(java.lang.String) 2692 * 2693 * @deprecated As of JOMC 1.3, replaced by method {@link #getDefaultTemplateEncoding()}. This method will be removed 2694 * in JOMC 2.0. 2695 */ 2696 @Deprecated 2697 public final String getTemplateEncoding() 2698 { 2699 return this.getDefaultTemplateEncoding(); 2700 } 2701 2702 /** 2703 * Sets the encoding to use for reading templates. 2704 * 2705 * @param value The new encoding to use for reading templates or {@code null}. 2706 * 2707 * @see #getTemplateEncoding() 2708 * 2709 * @deprecated As of JOMC 1.3, replaced by method {@link #setDefaultTemplateEncoding(java.lang.String)}. This method 2710 * will be removed in JOMC 2.0. 2711 */ 2712 @Deprecated 2713 public final void setTemplateEncoding( final String value ) 2714 { 2715 this.setDefaultTemplateEncoding( value ); 2716 } 2717 2718 /** 2719 * Gets the default encoding used for reading templates. 2720 * 2721 * @return The default encoding used for reading templates. 2722 * 2723 * @see #setDefaultTemplateEncoding(java.lang.String) 2724 * 2725 * @since 1.3 2726 */ 2727 public final String getDefaultTemplateEncoding() 2728 { 2729 if ( this.defaultTemplateEncoding == null ) 2730 { 2731 this.defaultTemplateEncoding = getMessage( "buildSourceEncoding" ); 2732 2733 if ( this.isLoggable( Level.CONFIG ) ) 2734 { 2735 this.log( Level.CONFIG, getMessage( "defaultTemplateEncoding", this.defaultTemplateEncoding ), null ); 2736 } 2737 } 2738 2739 return this.defaultTemplateEncoding; 2740 } 2741 2742 /** 2743 * Sets the default encoding to use for reading templates. 2744 * 2745 * @param value The new default encoding to use for reading templates or {@code null}. 2746 * 2747 * @see #getDefaultTemplateEncoding() 2748 * 2749 * @since 1.3 2750 */ 2751 public final void setDefaultTemplateEncoding( final String value ) 2752 { 2753 this.defaultTemplateEncoding = value; 2754 this.templateCache = null; 2755 } 2756 2757 /** 2758 * Gets the template encoding of a given template profile. 2759 * 2760 * @param tp The template profile to get the template encoding of. 2761 * 2762 * @return The template encoding of the template profile identified by {@code tp} or the default template encoding 2763 * if no such encoding is defined. 2764 * 2765 * @throws NullPointerException if {@code tp} is {@code null}. 2766 * 2767 * @see #getDefaultTemplateEncoding() 2768 * 2769 * @since 1.3 2770 */ 2771 public final String getTemplateEncoding( final String tp ) 2772 { 2773 if ( tp == null ) 2774 { 2775 throw new NullPointerException( "tp" ); 2776 } 2777 2778 String te = null; 2779 2780 try 2781 { 2782 te = this.getTemplateProfileProperties( tp ).getProperty( TEMPLATE_ENCODING_PROFILE_PROPERTY_NAME ); 2783 } 2784 catch ( final IOException e ) 2785 { 2786 if ( this.isLoggable( Level.SEVERE ) ) 2787 { 2788 this.log( Level.SEVERE, getMessage( e ), e ); 2789 } 2790 } 2791 2792 return te != null ? te : this.getDefaultTemplateEncoding(); 2793 } 2794 2795 /** 2796 * Gets the encoding to use for reading files. 2797 * 2798 * @return The encoding to use for reading files. 2799 * 2800 * @see #setInputEncoding(java.lang.String) 2801 */ 2802 public final String getInputEncoding() 2803 { 2804 if ( this.inputEncoding == null ) 2805 { 2806 this.inputEncoding = new InputStreamReader( new ByteArrayInputStream( NO_BYTES ) ).getEncoding(); 2807 2808 if ( this.isLoggable( Level.CONFIG ) ) 2809 { 2810 this.log( Level.CONFIG, getMessage( "defaultInputEncoding", this.inputEncoding ), null ); 2811 } 2812 } 2813 2814 return this.inputEncoding; 2815 } 2816 2817 /** 2818 * Sets the encoding to use for reading files. 2819 * 2820 * @param value The new encoding to use for reading files or {@code null}. 2821 * 2822 * @see #getInputEncoding() 2823 */ 2824 public final void setInputEncoding( final String value ) 2825 { 2826 this.inputEncoding = value; 2827 } 2828 2829 /** 2830 * Gets the encoding to use for writing files. 2831 * 2832 * @return The encoding to use for writing files. 2833 * 2834 * @see #setOutputEncoding(java.lang.String) 2835 */ 2836 public final String getOutputEncoding() 2837 { 2838 if ( this.outputEncoding == null ) 2839 { 2840 this.outputEncoding = new OutputStreamWriter( new ByteArrayOutputStream() ).getEncoding(); 2841 2842 if ( this.isLoggable( Level.CONFIG ) ) 2843 { 2844 this.log( Level.CONFIG, getMessage( "defaultOutputEncoding", this.outputEncoding ), null ); 2845 } 2846 } 2847 2848 return this.outputEncoding; 2849 } 2850 2851 /** 2852 * Sets the encoding to use for writing files. 2853 * 2854 * @param value The encoding to use for writing files or {@code null}. 2855 * 2856 * @see #getOutputEncoding() 2857 */ 2858 public final void setOutputEncoding( final String value ) 2859 { 2860 this.outputEncoding = value; 2861 } 2862 2863 /** 2864 * Gets the default template profile. 2865 * <p>The default template profile is the implicit parent profile of any template profile not specifying a parent 2866 * template profile.</p> 2867 * 2868 * @return The default template profile. 2869 * 2870 * @see #setDefaultTemplateProfile(java.lang.String) 2871 * 2872 * @deprecated The {@code static} modifier of this method and support to setup the default template profile using 2873 * a system property will be removed in version 2.0. 2874 */ 2875 @Deprecated 2876 public static String getDefaultTemplateProfile() 2877 { 2878 if ( defaultTemplateProfile == null ) 2879 { 2880 defaultTemplateProfile = System.getProperty( "org.jomc.tools.JomcTool.defaultTemplateProfile", 2881 DEFAULT_TEMPLATE_PROFILE ); 2882 2883 } 2884 2885 return defaultTemplateProfile; 2886 } 2887 2888 /** 2889 * Sets the default template profile. 2890 * 2891 * @param value The new default template profile or {@code null}. 2892 * 2893 * @see #getDefaultTemplateProfile() 2894 * 2895 * @deprecated The {@code static} modifier of this method will be removed in version 2.0. 2896 */ 2897 @Deprecated 2898 public static void setDefaultTemplateProfile( final String value ) 2899 { 2900 defaultTemplateProfile = value; 2901 } 2902 2903 /** 2904 * Gets the template profile of the instance. 2905 * 2906 * @return The template profile of the instance. 2907 * 2908 * @see #getDefaultTemplateProfile() 2909 * @see #setTemplateProfile(java.lang.String) 2910 */ 2911 public final String getTemplateProfile() 2912 { 2913 if ( this.templateProfile == null ) 2914 { 2915 this.templateProfile = getDefaultTemplateProfile(); 2916 2917 if ( this.isLoggable( Level.CONFIG ) ) 2918 { 2919 this.log( Level.CONFIG, getMessage( "defaultTemplateProfile", this.templateProfile ), null ); 2920 } 2921 } 2922 2923 return this.templateProfile; 2924 } 2925 2926 /** 2927 * Sets the template profile of the instance. 2928 * 2929 * @param value The new template profile of the instance or {@code null}. 2930 * 2931 * @see #getTemplateProfile() 2932 */ 2933 public final void setTemplateProfile( final String value ) 2934 { 2935 this.templateProfile = value; 2936 } 2937 2938 /** 2939 * Gets the parent template profile of a given template profile. 2940 * 2941 * @param tp The template profile to get the parent template profile of. 2942 * 2943 * @return The parent template profile of the template profile identified by {@code tp}; the default template 2944 * profile, if no such parent template profile is defined; {@code null}, if {@code tp} denotes the default template 2945 * profile. 2946 * 2947 * @throws NullPointerException if {@code tp} is {@code null}. 2948 * 2949 * @see #getDefaultTemplateProfile() 2950 * 2951 * @since 1.3 2952 */ 2953 public final String getParentTemplateProfile( final String tp ) 2954 { 2955 if ( tp == null ) 2956 { 2957 throw new NullPointerException( "tp" ); 2958 } 2959 2960 String parentTemplateProfile = null; 2961 2962 try 2963 { 2964 parentTemplateProfile = 2965 this.getTemplateProfileProperties( tp ).getProperty( PARENT_TEMPLATE_PROFILE_PROPERTY_NAME ); 2966 2967 } 2968 catch ( final IOException e ) 2969 { 2970 if ( this.isLoggable( Level.SEVERE ) ) 2971 { 2972 this.log( Level.SEVERE, getMessage( e ), e ); 2973 } 2974 } 2975 2976 return parentTemplateProfile != null ? parentTemplateProfile 2977 : tp.equals( this.getDefaultTemplateProfile() ) ? null : this.getDefaultTemplateProfile(); 2978 2979 } 2980 2981 /** 2982 * Gets the indentation string of the instance. 2983 * 2984 * @return The indentation string of the instance. 2985 * 2986 * @see #setIndentation(java.lang.String) 2987 */ 2988 public final String getIndentation() 2989 { 2990 if ( this.indentation == null ) 2991 { 2992 this.indentation = " "; 2993 2994 if ( this.isLoggable( Level.CONFIG ) ) 2995 { 2996 this.log( Level.CONFIG, getMessage( "defaultIndentation", 2997 StringEscapeUtils.escapeJava( this.indentation ) ), null ); 2998 2999 } 3000 } 3001 3002 return this.indentation; 3003 } 3004 3005 /** 3006 * Gets an indentation string for a given indentation level. 3007 * 3008 * @param level The indentation level to get an indentation string for. 3009 * 3010 * @return The indentation string for {@code level}. 3011 * 3012 * @throws IllegalArgumentException if {@code level} is negative. 3013 * 3014 * @see #getIndentation() 3015 */ 3016 public final String getIndentation( final int level ) 3017 { 3018 if ( level < 0 ) 3019 { 3020 throw new IllegalArgumentException( Integer.toString( level ) ); 3021 } 3022 3023 Map<String, String> map = this.indentationCache == null ? null : this.indentationCache.get(); 3024 3025 if ( map == null ) 3026 { 3027 map = new ConcurrentHashMap<String, String>( 8 ); 3028 this.indentationCache = new SoftReference<Map<String, String>>( map ); 3029 } 3030 3031 final String key = this.getIndentation() + "|" + level; 3032 String idt = map.get( key ); 3033 3034 if ( idt == null ) 3035 { 3036 final StringBuilder b = new StringBuilder( this.getIndentation().length() * level ); 3037 3038 for ( int i = level; i > 0; i-- ) 3039 { 3040 b.append( this.getIndentation() ); 3041 } 3042 3043 idt = b.toString(); 3044 map.put( key, idt ); 3045 } 3046 3047 return idt; 3048 } 3049 3050 /** 3051 * Sets the indentation string of the instance. 3052 * 3053 * @param value The new indentation string of the instance or {@code null}. 3054 * 3055 * @see #getIndentation() 3056 */ 3057 public final void setIndentation( final String value ) 3058 { 3059 this.indentation = value; 3060 } 3061 3062 /** 3063 * Gets the line separator of the instance. 3064 * 3065 * @return The line separator of the instance. 3066 * 3067 * @see #setLineSeparator(java.lang.String) 3068 */ 3069 public final String getLineSeparator() 3070 { 3071 if ( this.lineSeparator == null ) 3072 { 3073 this.lineSeparator = System.getProperty( "line.separator", "\n" ); 3074 3075 if ( this.isLoggable( Level.CONFIG ) ) 3076 { 3077 this.log( Level.CONFIG, getMessage( "defaultLineSeparator", 3078 StringEscapeUtils.escapeJava( this.lineSeparator ) ), null ); 3079 3080 } 3081 } 3082 3083 return this.lineSeparator; 3084 } 3085 3086 /** 3087 * Sets the line separator of the instance. 3088 * 3089 * @param value The new line separator of the instance or {@code null}. 3090 * 3091 * @see #getLineSeparator() 3092 */ 3093 public final void setLineSeparator( final String value ) 3094 { 3095 this.lineSeparator = value; 3096 } 3097 3098 /** 3099 * Gets the locale of the instance. 3100 * 3101 * @return The locale of the instance. 3102 * 3103 * @see #setLocale(java.util.Locale) 3104 * 3105 * @since 1.2 3106 */ 3107 public final Locale getLocale() 3108 { 3109 if ( this.locale == null ) 3110 { 3111 this.locale = Locale.ENGLISH; 3112 3113 if ( this.isLoggable( Level.CONFIG ) ) 3114 { 3115 this.log( Level.CONFIG, getMessage( "defaultLocale", this.locale ), null ); 3116 } 3117 } 3118 3119 return this.locale; 3120 } 3121 3122 /** 3123 * Sets the locale of the instance. 3124 * 3125 * @param value The new locale of the instance or {@code null}. 3126 * 3127 * @see #getLocale() 3128 * 3129 * @since 1.2 3130 */ 3131 public final void setLocale( final Locale value ) 3132 { 3133 this.locale = value; 3134 } 3135 3136 /** 3137 * Gets a velocity template for a given name. 3138 * <p>This method searches templates at the following locations recursively in the shown order stopping whenever 3139 * a matching template is found. 3140 * <ol> 3141 * <li><code>org/jomc/tools/templates/{@link #getTemplateProfile() profile}/{@link #getLocale() language}/<i>templateName</i></code></li> 3142 * <li><code>org/jomc/tools/templates/{@link #getParentTemplateProfile(java.lang.String) parent profile}/{@link #getLocale() language}/<i>templateName</i></code></li> 3143 * <li><code>org/jomc/tools/templates/{@link #getTemplateProfile() profile}/<i>templateName</i></code></li> 3144 * <li><code>org/jomc/tools/templates/{@link #getParentTemplateProfile(java.lang.String) parent profile}/{@link #getLocale() language}/<i>templateName</i></code></li> 3145 * </ol></p> 3146 * 3147 * @param templateName The name of the template to get. 3148 * 3149 * @return The template matching {@code templateName}. 3150 * 3151 * @throws NullPointerException if {@code templateName} is {@code null}. 3152 * @throws FileNotFoundException if no such template is found. 3153 * @throws IOException if getting the template fails. 3154 * 3155 * @see #getTemplateProfile() 3156 * @see #getParentTemplateProfile(java.lang.String) 3157 * @see #getLocale() 3158 * @see #getTemplateEncoding(java.lang.String) 3159 * @see #getVelocityEngine() 3160 */ 3161 public Template getVelocityTemplate( final String templateName ) throws FileNotFoundException, IOException 3162 { 3163 if ( templateName == null ) 3164 { 3165 throw new NullPointerException( "templateName" ); 3166 } 3167 3168 return this.getVelocityTemplate( this.getTemplateProfile(), templateName ); 3169 } 3170 3171 /** 3172 * Notifies registered listeners. 3173 * 3174 * @param level The level of the event. 3175 * @param message The message of the event or {@code null}. 3176 * @param throwable The throwable of the event or {@code null}. 3177 * 3178 * @throws NullPointerException if {@code level} is {@code null}. 3179 * 3180 * @see #getListeners() 3181 * @see #isLoggable(java.util.logging.Level) 3182 */ 3183 public void log( final Level level, final String message, final Throwable throwable ) 3184 { 3185 if ( level == null ) 3186 { 3187 throw new NullPointerException( "level" ); 3188 } 3189 3190 if ( this.isLoggable( level ) ) 3191 { 3192 for ( int i = this.getListeners().size() - 1; i >= 0; i-- ) 3193 { 3194 this.getListeners().get( i ).onLog( level, message, throwable ); 3195 } 3196 } 3197 } 3198 3199 private Template findVelocityTemplate( final String location, final String encoding ) throws IOException 3200 { 3201 try 3202 { 3203 return this.getVelocityEngine().getTemplate( location, encoding ); 3204 } 3205 catch ( final ResourceNotFoundException e ) 3206 { 3207 if ( this.isLoggable( Level.FINER ) ) 3208 { 3209 this.log( Level.FINER, getMessage( "templateNotFound", location ), null ); 3210 } 3211 3212 return null; 3213 } 3214 catch ( final ParseErrorException e ) 3215 { 3216 String m = getMessage( e ); 3217 m = m == null ? "" : " " + m; 3218 3219 // JDK: As of JDK 6, "new IOException( message, cause )". 3220 throw (IOException) new IOException( getMessage( "invalidTemplate", location, m ) ).initCause( e ); 3221 } 3222 catch ( final VelocityException e ) 3223 { 3224 String m = getMessage( e ); 3225 m = m == null ? "" : " " + m; 3226 3227 // JDK: As of JDK 6, "new IOException( message, cause )". 3228 throw (IOException) new IOException( getMessage( "velocityException", location, m ) ).initCause( e ); 3229 } 3230 } 3231 3232 private java.util.Properties getTemplateProfileContextProperties( final String profileName, final String language ) 3233 throws IOException 3234 { 3235 Map<String, java.util.Properties> map = this.templateProfileContextPropertiesCache == null 3236 ? null : this.templateProfileContextPropertiesCache.get(); 3237 3238 if ( map == null ) 3239 { 3240 map = new ConcurrentHashMap<String, java.util.Properties>(); 3241 this.templateProfileContextPropertiesCache = new SoftReference<Map<String, java.util.Properties>>( map ); 3242 } 3243 3244 final String key = profileName + "|" + language; 3245 java.util.Properties profileProperties = map.get( key ); 3246 boolean suppressExceptionOnClose = true; 3247 3248 if ( profileProperties == null ) 3249 { 3250 InputStream in = null; 3251 URL url = null; 3252 profileProperties = new java.util.Properties(); 3253 3254 final String resourceName = TEMPLATE_PREFIX + profileName + ( language == null ? "" : "/" + language ) 3255 + "/context.properties"; 3256 3257 try 3258 { 3259 url = this.getClass().getResource( "/" + resourceName ); 3260 3261 if ( url != null ) 3262 { 3263 in = url.openStream(); 3264 3265 if ( this.isLoggable( Level.CONFIG ) ) 3266 { 3267 this.log( Level.CONFIG, getMessage( "contextPropertiesFound", url.toExternalForm() ), null ); 3268 } 3269 3270 profileProperties.load( in ); 3271 } 3272 else if ( this.getTemplateLocation() != null ) 3273 { 3274 if ( this.isLoggable( Level.CONFIG ) ) 3275 { 3276 this.log( Level.CONFIG, getMessage( "contextPropertiesNotFound", resourceName ), null ); 3277 } 3278 3279 url = new URL( this.getTemplateLocation(), resourceName ); 3280 in = url.openStream(); 3281 3282 if ( this.isLoggable( Level.CONFIG ) ) 3283 { 3284 this.log( Level.CONFIG, getMessage( "contextPropertiesFound", url.toExternalForm() ), null ); 3285 } 3286 3287 profileProperties.load( in ); 3288 } 3289 else if ( this.isLoggable( Level.CONFIG ) ) 3290 { 3291 this.log( Level.CONFIG, getMessage( "contextPropertiesNotFound", resourceName ), null ); 3292 } 3293 3294 suppressExceptionOnClose = false; 3295 } 3296 catch ( final FileNotFoundException e ) 3297 { 3298 if ( this.isLoggable( Level.CONFIG ) ) 3299 { 3300 this.log( Level.CONFIG, getMessage( "contextPropertiesNotFound", url.toExternalForm() ), null ); 3301 } 3302 } 3303 finally 3304 { 3305 map.put( key, profileProperties ); 3306 3307 try 3308 { 3309 if ( in != null ) 3310 { 3311 in.close(); 3312 } 3313 } 3314 catch ( final IOException e ) 3315 { 3316 if ( suppressExceptionOnClose ) 3317 { 3318 this.log( Level.SEVERE, getMessage( e ), e ); 3319 } 3320 else 3321 { 3322 throw e; 3323 } 3324 } 3325 } 3326 } 3327 3328 return profileProperties; 3329 } 3330 3331 private void mergeTemplateProfileContextProperties( final String profileName, final String language, 3332 final VelocityContext velocityContext ) throws IOException 3333 { 3334 if ( profileName != null ) 3335 { 3336 final java.util.Properties templateProfileProperties = 3337 this.getTemplateProfileContextProperties( profileName, language ); 3338 3339 for ( final Enumeration<?> e = templateProfileProperties.propertyNames(); e.hasMoreElements(); ) 3340 { 3341 final String name = e.nextElement().toString(); 3342 final String value = templateProfileProperties.getProperty( name ); 3343 final String[] values = value.split( "\\|" ); 3344 3345 if ( !velocityContext.containsKey( name ) ) 3346 { 3347 final String className = values[0]; 3348 3349 try 3350 { 3351 if ( values.length > 1 ) 3352 { 3353 final Class<?> valueClass = Class.forName( className ); 3354 velocityContext.put( name, 3355 valueClass.getConstructor( String.class ).newInstance( values[1] ) ); 3356 } 3357 else if ( value.contains( "|" ) ) 3358 { 3359 velocityContext.put( name, Class.forName( values[0] ).newInstance() ); 3360 } 3361 else 3362 { 3363 velocityContext.put( name, value ); 3364 } 3365 } 3366 catch ( final InstantiationException ex ) 3367 { 3368 // JDK: As of JDK 6, "new IOException( message, cause )". 3369 throw (IOException) new IOException( getMessage( 3370 "contextPropertiesException", profileName + ( language != null ? ", " + language : "" ) ) ). 3371 initCause( ex ); 3372 3373 } 3374 catch ( final IllegalAccessException ex ) 3375 { 3376 // JDK: As of JDK 6, "new IOException( message, cause )". 3377 throw (IOException) new IOException( getMessage( 3378 "contextPropertiesException", profileName + ( language != null ? ", " + language : "" ) ) ). 3379 initCause( ex ); 3380 3381 } 3382 catch ( final InvocationTargetException ex ) 3383 { 3384 // JDK: As of JDK 6, "new IOException( message, cause )". 3385 throw (IOException) new IOException( getMessage( 3386 "contextPropertiesException", profileName + ( language != null ? ", " + language : "" ) ) ). 3387 initCause( ex ); 3388 3389 } 3390 catch ( final NoSuchMethodException ex ) 3391 { 3392 // JDK: As of JDK 6, "new IOException( message, cause )". 3393 throw (IOException) new IOException( getMessage( 3394 "contextPropertiesException", profileName + ( language != null ? ", " + language : "" ) ) ). 3395 initCause( ex ); 3396 3397 } 3398 catch ( final ClassNotFoundException ex ) 3399 { 3400 // JDK: As of JDK 6, "new IOException( message, cause )". 3401 throw (IOException) new IOException( getMessage( 3402 "contextPropertiesException", profileName + ( language != null ? ", " + language : "" ) ) ). 3403 initCause( ex ); 3404 3405 } 3406 } 3407 } 3408 3409 this.mergeTemplateProfileContextProperties( this.getParentTemplateProfile( profileName ), language, 3410 velocityContext ); 3411 3412 } 3413 } 3414 3415 private java.util.Properties getTemplateProfileProperties( final String profileName ) throws IOException 3416 { 3417 Map<String, java.util.Properties> map = this.templateProfilePropertiesCache == null 3418 ? null : this.templateProfilePropertiesCache.get(); 3419 3420 if ( map == null ) 3421 { 3422 map = new ConcurrentHashMap<String, java.util.Properties>(); 3423 this.templateProfilePropertiesCache = new SoftReference<Map<String, java.util.Properties>>( map ); 3424 } 3425 3426 java.util.Properties profileProperties = map.get( profileName ); 3427 boolean suppressExceptionOnClose = true; 3428 3429 if ( profileProperties == null ) 3430 { 3431 InputStream in = null; 3432 profileProperties = new java.util.Properties(); 3433 3434 final String resourceName = TEMPLATE_PREFIX + profileName + "/profile.properties"; 3435 URL url = null; 3436 3437 try 3438 { 3439 url = this.getClass().getResource( "/" + resourceName ); 3440 3441 if ( url != null ) 3442 { 3443 in = url.openStream(); 3444 3445 if ( this.isLoggable( Level.CONFIG ) ) 3446 { 3447 this.log( Level.CONFIG, getMessage( "templateProfilePropertiesFound", url.toExternalForm() ), 3448 null ); 3449 3450 } 3451 3452 profileProperties.load( in ); 3453 } 3454 else if ( this.getTemplateLocation() != null ) 3455 { 3456 if ( this.isLoggable( Level.CONFIG ) ) 3457 { 3458 this.log( Level.CONFIG, getMessage( "templateProfilePropertiesNotFound", resourceName ), null ); 3459 } 3460 3461 url = new URL( this.getTemplateLocation(), resourceName ); 3462 in = url.openStream(); 3463 3464 if ( this.isLoggable( Level.CONFIG ) ) 3465 { 3466 this.log( Level.CONFIG, getMessage( "templateProfilePropertiesFound", url.toExternalForm() ), 3467 null ); 3468 3469 } 3470 3471 profileProperties.load( in ); 3472 } 3473 else if ( this.isLoggable( Level.CONFIG ) ) 3474 { 3475 this.log( Level.CONFIG, getMessage( "templateProfilePropertiesNotFound", resourceName ), null ); 3476 } 3477 3478 suppressExceptionOnClose = false; 3479 } 3480 catch ( final FileNotFoundException e ) 3481 { 3482 if ( this.isLoggable( Level.CONFIG ) ) 3483 { 3484 this.log( Level.CONFIG, getMessage( "templateProfilePropertiesNotFound", url.toExternalForm() ), 3485 null ); 3486 3487 } 3488 } 3489 finally 3490 { 3491 map.put( profileName, profileProperties ); 3492 3493 try 3494 { 3495 if ( in != null ) 3496 { 3497 in.close(); 3498 } 3499 } 3500 catch ( final IOException e ) 3501 { 3502 if ( suppressExceptionOnClose ) 3503 { 3504 this.log( Level.SEVERE, getMessage( e ), e ); 3505 } 3506 else 3507 { 3508 throw e; 3509 } 3510 } 3511 } 3512 } 3513 3514 return profileProperties; 3515 } 3516 3517 private Set<String> getJavaKeywords() 3518 { 3519 Reader in = null; 3520 Set<String> set = this.javaKeywordsCache == null ? null : this.javaKeywordsCache.get(); 3521 3522 try 3523 { 3524 if ( set == null ) 3525 { 3526 in = new InputStreamReader( this.getClass().getResourceAsStream( 3527 "/" + this.getClass().getPackage().getName().replace( ".", "/" ) + "/JavaKeywords.txt" ), "UTF-8" ); 3528 3529 set = new CopyOnWriteArraySet<String>( IOUtils.readLines( in ) ); 3530 3531 this.javaKeywordsCache = new SoftReference<Set<String>>( set ); 3532 } 3533 } 3534 catch ( final IOException e ) 3535 { 3536 throw new IllegalStateException( getMessage( e ), e ); 3537 } 3538 finally 3539 { 3540 try 3541 { 3542 if ( in != null ) 3543 { 3544 in.close(); 3545 } 3546 } 3547 catch ( final IOException e ) 3548 { 3549 throw new IllegalStateException( getMessage( e ), e ); 3550 } 3551 } 3552 3553 return set; 3554 } 3555 3556 private Template getVelocityTemplate( final String tp, final String tn ) throws IOException 3557 { 3558 Template template = null; 3559 3560 if ( tp != null ) 3561 { 3562 final String key = this.getLocale() + "|" + this.getTemplateProfile() + "|" 3563 + this.getDefaultTemplateProfile() + "|" + tn; 3564 3565 Map<String, TemplateData> map = this.templateCache == null 3566 ? null : this.templateCache.get(); 3567 3568 if ( map == null ) 3569 { 3570 map = new ConcurrentHashMap<String, TemplateData>( 32 ); 3571 this.templateCache = new SoftReference<Map<String, TemplateData>>( map ); 3572 } 3573 3574 TemplateData templateData = map.get( key ); 3575 3576 if ( templateData == null ) 3577 { 3578 templateData = new TemplateData(); 3579 3580 if ( !StringUtils.EMPTY.equals( this.getLocale().getLanguage() ) ) 3581 { 3582 templateData.location = TEMPLATE_PREFIX + tp + "/" + this.getLocale().getLanguage() + "/" + tn; 3583 templateData.template = 3584 this.findVelocityTemplate( templateData.location, this.getTemplateEncoding( tp ) ); 3585 3586 } 3587 3588 if ( templateData.template == null ) 3589 { 3590 templateData.location = TEMPLATE_PREFIX + tp + "/" + tn; 3591 templateData.template = 3592 this.findVelocityTemplate( templateData.location, this.getTemplateEncoding( tp ) ); 3593 3594 } 3595 3596 if ( templateData.template == null ) 3597 { 3598 template = this.getVelocityTemplate( this.getParentTemplateProfile( tp ), tn ); 3599 3600 if ( template == null ) 3601 { 3602 map.put( key, new TemplateData() ); 3603 throw new FileNotFoundException( getMessage( "noSuchTemplate", tn ) ); 3604 } 3605 } 3606 else 3607 { 3608 if ( this.isLoggable( Level.FINER ) ) 3609 { 3610 this.log( Level.FINER, getMessage( "templateInfo", tn, templateData.location ), null ); 3611 } 3612 3613 template = templateData.template; 3614 map.put( key, templateData ); 3615 } 3616 } 3617 else if ( templateData.template == null ) 3618 { 3619 throw new FileNotFoundException( getMessage( "noSuchTemplate", tn ) ); 3620 } 3621 else 3622 { 3623 if ( this.isLoggable( Level.FINER ) ) 3624 { 3625 this.log( Level.FINER, getMessage( "templateInfo", tn, templateData.location ), null ); 3626 } 3627 3628 template = templateData.template; 3629 } 3630 } 3631 3632 return template; 3633 } 3634 3635 private static String getMessage( final String key, final Object... arguments ) 3636 { 3637 return MessageFormat.format( ResourceBundle.getBundle( 3638 JomcTool.class.getName().replace( '.', '/' ) ).getString( key ), arguments ); 3639 3640 } 3641 3642 private static String getMessage( final Throwable t ) 3643 { 3644 return t != null ? t.getMessage() != null ? t.getMessage() : getMessage( t.getCause() ) : null; 3645 } 3646 3647 /** @since 1.3 */ 3648 private static class TemplateData 3649 { 3650 3651 private String location; 3652 3653 private Template template; 3654 3655 } 3656 3657}