Coverage Report - de.smartics.properties.api.core.domain.PropertiesContext
 
Classes in this File Line Coverage Branch Coverage Complexity
PropertiesContext
0%
0/60
0%
0/22
1.652
PropertiesContext$1
N/A
N/A
N/A
N/A
1.652
PropertiesContext$Builder
0%
0/13
N/A
N/A
1.652
 
 1  
 /*
 2  
  * Copyright 2012-2013 smartics, Kronseder & Reiner GmbH
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package de.smartics.properties.api.core.domain;
 17  
 
 18  
 import java.io.Serializable;
 19  
 import java.net.URL;
 20  
 import java.util.ArrayList;
 21  
 import java.util.List;
 22  
 import java.util.Locale;
 23  
 import java.util.regex.Pattern;
 24  
 
 25  
 import javax.annotation.CheckForNull;
 26  
 import javax.annotation.concurrent.ThreadSafe;
 27  
 
 28  
 import org.apache.commons.lang.LocaleUtils;
 29  
 import org.apache.commons.lang.StringUtils;
 30  
 import org.apache.commons.lang.builder.ToStringBuilder;
 31  
 
 32  
 import de.smartics.properties.api.core.context.alias.AliasTraverser;
 33  
 import de.smartics.properties.api.core.context.alias.DuplicateAliasException;
 34  
 import de.smartics.properties.api.core.context.alias.PropertyAliasMapping;
 35  
 import de.smartics.properties.api.core.context.alias.UnknownAliasException;
 36  
 import de.smartics.util.lang.Arg;
 37  
 import de.smartics.util.lang.BlankArgumentException;
 38  
 
 39  
 /**
 40  
  * Defines the configuration for smartics properties configuration.
 41  
  * <p>
 42  
  * A context provides information for all its properties. Not all properties of
 43  
  * an application may refer to the same context.
 44  
  * </p>
 45  
  *
 46  
  * @impl For testing purposes please refer to
 47  
  *       <code>help.de.smartics.properties.core.PropertiesContextBuilder</code>.
 48  
  */
 49  
 @ThreadSafe
 50  0
 public final class PropertiesContext implements Serializable
 51  
 { // NOPMD
 52  
   // ********************************* Fields *********************************
 53  
 
 54  
   // --- constants ------------------------------------------------------------
 55  
 
 56  
   /**
 57  
    * The class version identifier.
 58  
    */
 59  
   private static final long serialVersionUID = 1L;
 60  
 
 61  
   /**
 62  
    * The path to the folder within <code>META-INF</code> where properties
 63  
    * resources are located.
 64  
    * <p>
 65  
    * The value of this constant is {@value}.
 66  
    * </p>
 67  
    */
 68  
   public static final String META_INF_HOME = "META-INF/smartics-properties";
 69  
 
 70  
   /**
 71  
    * Pattern to detect boot properties files.
 72  
    *
 73  
    * @impl Note that the pattern here is only the file name pattern without a
 74  
    *       path.
 75  
    */
 76  0
   public static final Pattern BOOT_PROPERTIES_PATTERN = Pattern
 77  
       .compile("boot\\.properties");
 78  
 
 79  
   /**
 80  
    * The the path to the <code>boot.properties</code> file to access boot
 81  
    * configuration properties to create the configuration infrastructure.
 82  
    * <p>
 83  
    * This file is only found by the boot definition search process, but hidden
 84  
    * from the main definition search process.
 85  
    * </p>
 86  
    * <p>
 87  
    * The value of this constant is {@value}.
 88  
    * </p>
 89  
    */
 90  
   public static final String BOOT_PROPERTIES = META_INF_HOME
 91  
                                                + "/boot.properties";
 92  
 
 93  
   /**
 94  
    * The path to the folder within <code>{@value #META_INF_HOME}</code> where
 95  
    * boot properties resources are located.
 96  
    * <p>
 97  
    * This folder contains definition files that are hidden from the main
 98  
    * definition search process (no properties file in META-INFO is taken into
 99  
    * account). Third party implementations may place properties for their
 100  
    * implementations here, if these implementations are part of the
 101  
    * configuration infrastructure.
 102  
    * <p>
 103  
    * The value of this constant is {@value}.
 104  
    * </p>
 105  
    */
 106  
   public static final String BOOT_PROPERTIES_HOME = META_INF_HOME + "/boot";
 107  
 
 108  
   /**
 109  
    * The name of the properties configuration file that provides information for
 110  
    * declarations. This file provides information in archives that provide
 111  
    * property meta data (descriptors).
 112  
    * <p>
 113  
    * The value of this constant is {@value}.
 114  
    * </p>
 115  
    */
 116  
   public static final String DECLARATION_FILE_NAME = "declaration.xml";
 117  
 
 118  
   /**
 119  
    * The name of the properties configuration file that provides information for
 120  
    * definitions. This file provides information in archives that provide
 121  
    * property values.
 122  
    * <p>
 123  
    * The value of this constant is {@value}.
 124  
    * </p>
 125  
    */
 126  
   public static final String DEFINITION_FILE_NAME = "definition.xml";
 127  
 
 128  
   /**
 129  
    * The default location of the properties declaration configuration file.
 130  
    * <p>
 131  
    * The value of this constant is {@value}.
 132  
    * </p>
 133  
    */
 134  
   public static final String DECLARATION_FILE = META_INF_HOME + '/'
 135  
                                                 + DECLARATION_FILE_NAME;
 136  
 
 137  
   /**
 138  
    * The default location of the properties definition configuration file.
 139  
    * <p>
 140  
    * The value of this constant is {@value}.
 141  
    * </p>
 142  
    */
 143  
   public static final String DEFINITION_FILE = META_INF_HOME + '/'
 144  
                                                + DEFINITION_FILE_NAME;
 145  
 
 146  
   /**
 147  
    * The location of the property reports within the <code>META-INF</code>
 148  
    * folder.
 149  
    * <p>
 150  
    * The value of this constant is {@value}.
 151  
    * </p>
 152  
    */
 153  
   private static final String META_INF_PROPERTY_REPORT = META_INF_HOME
 154  
                                                          + "/property-report/";
 155  
 
 156  
   /**
 157  
    * The location of the property set reports within the <code>META-INF</code>
 158  
    * folder.
 159  
    * <p>
 160  
    * The value of this constant is {@value}.
 161  
    * </p>
 162  
    */
 163  
   public static final String META_INF_PROPERTY_SET_REPORT =
 164  
       META_INF_HOME + "/property-set-report/";
 165  
 
 166  
   /**
 167  
    * Specifies the default report location on the home page.
 168  
    * <p>
 169  
    * The value of this constant is {@value}.
 170  
    * </p>
 171  
    */
 172  
   private static final String DEFAULT_REPORT_LOCATION = "/property";
 173  
 
 174  
   // --- members --------------------------------------------------------------
 175  
 
 176  
   /**
 177  
    * The list of supported locales. The list contains locales the context
 178  
    * provides localized information for.
 179  
    *
 180  
    * @serial
 181  
    */
 182  
   private final List<Locale> locales;
 183  
 
 184  
   /**
 185  
    * The URL to the home page of the project. May be <code>null</code>.
 186  
    *
 187  
    * @serial
 188  
    */
 189  
   private final String homePageUrl;
 190  
 
 191  
   /**
 192  
    * The URL to the root directory of smartics properties reports. May be
 193  
    * <code>null</code>.
 194  
    *
 195  
    * @serial
 196  
    */
 197  
   private final String propertiesReportUrl;
 198  
 
 199  
   /**
 200  
    * The mapping of alias names of property reports to their physical names.
 201  
    *
 202  
    * @impl Although {@link PropertyAliasMapping} is not thread-safe, this
 203  
    *       instance provides no write-access to it.
 204  
    * @serial
 205  
    */
 206  
   private final PropertyAliasMapping aliasMapping;
 207  
 
 208  
   // ****************************** Initializer *******************************
 209  
 
 210  
   // ****************************** Constructors ******************************
 211  
 
 212  
   /**
 213  
    * Default constructor.
 214  
    */
 215  
   private PropertiesContext(final Builder builder)
 216  0
   {
 217  0
     this.locales = builder.locales;
 218  0
     this.homePageUrl = builder.homePageUrl;
 219  0
     this.propertiesReportUrl = builder.propertiesReportUrl;
 220  0
     this.aliasMapping = builder.aliasMapping;
 221  0
   }
 222  
 
 223  
   // ****************************** Inner Classes *****************************
 224  
 
 225  
   /**
 226  
    * The builder of {@link PropertiesContext}.
 227  
    */
 228  0
   public static final class Builder
 229  
   {
 230  
     // ******************************** Fields ********************************
 231  
 
 232  
     // --- constants ----------------------------------------------------------
 233  
 
 234  
     // --- members ------------------------------------------------------------
 235  
 
 236  
     /**
 237  
      * The list of supported locales. The list contains locales the context
 238  
      * provides localized information for.
 239  
      */
 240  0
     private List<Locale> locales = new ArrayList<Locale>();
 241  
 
 242  
     /**
 243  
      * The URL to the home page of the project.
 244  
      */
 245  
     private String homePageUrl;
 246  
 
 247  
     /**
 248  
      * The URL to the root directory of smartics properties reports.
 249  
      */
 250  
     private String propertiesReportUrl;
 251  
 
 252  
     /**
 253  
      * The mapping of alias names of property reports to their physical names.
 254  
      */
 255  0
     private final PropertyAliasMapping aliasMapping =
 256  
         new PropertyAliasMapping();
 257  
 
 258  
     // ***************************** Initializer ******************************
 259  
 
 260  
     // ***************************** Constructors *****************************
 261  
 
 262  
     // ***************************** Inner Classes ****************************
 263  
 
 264  
     // ******************************** Methods *******************************
 265  
 
 266  
     // --- init ---------------------------------------------------------------
 267  
 
 268  
     // --- get&set ------------------------------------------------------------
 269  
 
 270  
     /**
 271  
      * Sets the list of supported locales. The list contains locales the context
 272  
      * provides localized information for.
 273  
      *
 274  
      * @param locales the list of supported locales.
 275  
      * @return a reference to the builder.
 276  
      * @throws NullPointerException if {@code locales} is <code>null</code>.
 277  
      */
 278  
     public Builder withLocales(final List<Locale> locales)
 279  
       throws NullPointerException
 280  
     {
 281  0
       this.locales = Arg.checkNotNull("locales", locales);
 282  0
       return this;
 283  
     }
 284  
 
 285  
     /**
 286  
      * Sets the URL to the home page of the project.
 287  
      *
 288  
      * @param homePageUrl the URL to the home page of the project.
 289  
      * @return a reference to the builder.
 290  
      * @throws NullPointerException if {@code homePageUrl} is <code>null</code>.
 291  
      * @throws IllegalArgumentException if {@code homePageUrl} is blank.
 292  
      */
 293  
     public Builder withHomePageUrl(final String homePageUrl)
 294  
       throws NullPointerException, IllegalArgumentException
 295  
     {
 296  0
       this.homePageUrl =
 297  
           normalizeUrl(Arg.checkNotBlank("homePageUrl", homePageUrl));
 298  0
       return this;
 299  
     }
 300  
 
 301  
     /**
 302  
      * Sets the URL to the root directory of smartics properties reports.
 303  
      *
 304  
      * @param propertiesReportUrl the URL to the root directory of smartics
 305  
      *          properties reports.
 306  
      * @return a reference to the builder.
 307  
      * @throws NullPointerException if {@code propertiesReportUrl} is
 308  
      *           <code>null</code>.
 309  
      * @throws IllegalArgumentException if {@code propertiesReportUrl} is blank.
 310  
      */
 311  
     public Builder withPropertiesReportUrl(final String propertiesReportUrl)
 312  
       throws NullPointerException, IllegalArgumentException
 313  
     {
 314  0
       Arg.checkNotBlank("propertiesReportUrl", propertiesReportUrl);
 315  0
       this.propertiesReportUrl = normalizeUrl(propertiesReportUrl);
 316  0
       return this;
 317  
     }
 318  
 
 319  
     /**
 320  
      * Adds a new alias to the given physical resource.
 321  
      *
 322  
      * @param alias the new alias.
 323  
      * @param physical the resource the alias refers to.
 324  
      * @return a reference to the builder.
 325  
      * @throws BlankArgumentException if either {@code alias} or
 326  
      *           {@code physical} is blank.
 327  
      * @throws DuplicateAliasException if there is already an alias registered
 328  
      *           that points to a different physical resource.
 329  
      */
 330  
     public Builder withAlias(final String alias, final String physical)
 331  
       throws BlankArgumentException, DuplicateAliasException
 332  
     {
 333  0
       aliasMapping.add(alias, physical);
 334  0
       return this;
 335  
     }
 336  
 
 337  
     // --- business -----------------------------------------------------------
 338  
 
 339  
     /**
 340  
      * Creates the instance.
 341  
      *
 342  
      * @return the new instance.
 343  
      */
 344  
     public PropertiesContext build()
 345  
     {
 346  0
       return new PropertiesContext(this);
 347  
     }
 348  
 
 349  
     // --- object basics ------------------------------------------------------
 350  
   }
 351  
 
 352  
   // ********************************* Methods ********************************
 353  
 
 354  
   // --- init -----------------------------------------------------------------
 355  
 
 356  
   // --- factory --------------------------------------------------------------
 357  
 
 358  
   /**
 359  
    * Creates an empty context.
 360  
    *
 361  
    * @return an empty context.
 362  
    */
 363  
   public static PropertiesContext createEmptyContext()
 364  
   {
 365  0
     return new Builder().build();
 366  
   }
 367  
 
 368  
   // --- get&set --------------------------------------------------------------
 369  
 
 370  
   /**
 371  
    * Returns the URL to the home page of the project.
 372  
    *
 373  
    * @return the URL to the home page of the project. May be <code>null</code>.
 374  
    */
 375  
   @CheckForNull
 376  
   public String getHomePageUrl()
 377  
   {
 378  0
     return homePageUrl;
 379  
   }
 380  
 
 381  
   /**
 382  
    * Returns the URL to the root directory of smartics properties reports.
 383  
    *
 384  
    * @return the URL to the root directory of smartics properties reports. May
 385  
    *         be <code>null</code>.
 386  
    */
 387  
   @CheckForNull
 388  
   public String getPropertiesReportUrl()
 389  
   {
 390  0
     if (propertiesReportUrl == null && homePageUrl != null)
 391  
     {
 392  0
       return homePageUrl + DEFAULT_REPORT_LOCATION;
 393  
     }
 394  0
     return propertiesReportUrl;
 395  
   }
 396  
 
 397  
   /**
 398  
    * Returns the URL to the index document of smartics properties reports.
 399  
    *
 400  
    * @return the URL to the index document of smartics properties reports. May
 401  
    *         be <code>null</code>.
 402  
    */
 403  
   @CheckForNull
 404  
   public String getPropertiesReportIndexUrl()
 405  
   {
 406  0
     return createReportUrl("smartics-properties-report");
 407  
   }
 408  
 
 409  
   /**
 410  
    * Returns the list of supported locales. The list contains locales the
 411  
    * context provides localized information for.
 412  
    *
 413  
    * @return the list of supported locales.
 414  
    */
 415  
   public List<Locale> getLocales()
 416  
   {
 417  0
     return locales;
 418  
   }
 419  
 
 420  
   // --- business -------------------------------------------------------------
 421  
 
 422  
   private static String normalizeUrl(final String url)
 423  
   {
 424  0
     return StringUtils.chomp(url, "/");
 425  
   }
 426  
 
 427  
   /**
 428  
    * Returns the URL to the relative target.
 429  
    *
 430  
    * @param target the relative URL.
 431  
    * @return the absolute URL to the report or <code>null</code> if no root URL
 432  
    *         is provided by the context.
 433  
    * @throws IllegalArgumentException of {@code target} is blank.
 434  
    */
 435  
   public String createReportUrl(final String target)
 436  
     throws IllegalArgumentException
 437  
   {
 438  0
     Arg.checkNotBlank("target", target);
 439  
 
 440  0
     if (StringUtils.isEmpty(propertiesReportUrl))
 441  
     {
 442  0
       return null;
 443  
     }
 444  
 
 445  0
     final String htmlFile = target + ".html";
 446  0
     if (target.charAt(0) == '/')
 447  
     {
 448  0
       return propertiesReportUrl + htmlFile;
 449  
     }
 450  
     else
 451  
     {
 452  0
       return propertiesReportUrl + '/' + htmlFile;
 453  
     }
 454  
   }
 455  
 
 456  
   /**
 457  
    * Returns the URL to the report documentation for the given descriptor.
 458  
    *
 459  
    * @param descriptor the properties descriptor whose report documentation URL
 460  
    *          is requested.
 461  
    * @return the absolute URL to the report.
 462  
    */
 463  
   public String createReportUrl(final PropertyDescriptor descriptor)
 464  
   {
 465  0
     final String target = resolve(descriptor);
 466  0
     final String url = createReportUrl(target);
 467  0
     return url;
 468  
   }
 469  
 
 470  
   private static String resolve(final PropertyDescriptor descriptor)
 471  
   {
 472  0
     final DocumentName name = descriptor.getDocumentName();
 473  0
     final String target = name.getName();
 474  
     // final String target = descriptor.getKey().toString();
 475  0
     return target;
 476  
   }
 477  
 
 478  
   /**
 479  
    * Returns the URL to the XML report in the META-INF directory of the given
 480  
    * descriptor.
 481  
    *
 482  
    * @param descriptor the properties descriptor whose XML report URL is
 483  
    *          requested.
 484  
    * @return the class loader root rooted path.
 485  
    */
 486  
   public String createMetaInfPath(final PropertyDescriptor descriptor)
 487  
   {
 488  0
     return createMetaInfPath(descriptor, null);
 489  
   }
 490  
 
 491  
   /**
 492  
    * Returns the URL to the XML report in the META-INF directory of the given
 493  
    * descriptor.
 494  
    *
 495  
    * @param descriptor the properties descriptor whose XML report URL is
 496  
    *          requested.
 497  
    * @param locale the locale to determine the comments.
 498  
    * @return the class loader root rooted path.
 499  
    */
 500  
   @SuppressWarnings("unchecked")
 501  
   public String createMetaInfPath(final PropertyDescriptor descriptor,
 502  
       final Locale locale)
 503  
   {
 504  0
     final String target = resolve(descriptor);
 505  
 
 506  0
     if (locale != null)
 507  
     {
 508  0
       final List<Locale> locales = LocaleUtils.localeLookupList(locale);
 509  0
       for (final Locale currentLocale : locales)
 510  
       {
 511  0
         final String path =
 512  
             META_INF_PROPERTY_REPORT + target + '_' + currentLocale + ".xml";
 513  0
         final ClassLoader loader = descriptor.getClass().getClassLoader(); // NOPMD
 514  0
         final URL resource = loader.getResource(path);
 515  0
         if (resource != null)
 516  
         {
 517  0
           return path;
 518  
         }
 519  0
       }
 520  
     }
 521  
 
 522  0
     final String path = META_INF_PROPERTY_REPORT + target + ".xml";
 523  0
     return path;
 524  
   }
 525  
 
 526  
   /**
 527  
    * Returns the URL to the property set XML report in the META-INF directory of
 528  
    * the given descriptor.
 529  
    *
 530  
    * @param descriptor the properties descriptor whose property set XML report
 531  
    *          URL is requested.
 532  
    * @return the class loader root rooted path.
 533  
    */
 534  
   public String createMetaInfPathPropertySet(final PropertyDescriptor descriptor)
 535  
   {
 536  0
     return createMetaInfPathPropertySet(descriptor, null);
 537  
   }
 538  
 
 539  
   /**
 540  
    * Returns the URL to the property set XML report in the META-INF directory of
 541  
    * the given descriptor.
 542  
    *
 543  
    * @param descriptor the properties descriptor whose property set XML report
 544  
    *          URL is requested.
 545  
    * @param locale the locale to determine the comments.
 546  
    * @return the class loader root rooted path.
 547  
    */
 548  
   @SuppressWarnings("unchecked")
 549  
   public String createMetaInfPathPropertySet(
 550  
       final PropertyDescriptor descriptor, final Locale locale)
 551  
   {
 552  0
     final String target = descriptor.getKey().getPropertySet();
 553  
 
 554  0
     if (locale != null)
 555  
     {
 556  0
       final List<Locale> locales = LocaleUtils.localeLookupList(locale);
 557  0
       for (final Locale currentLocale : locales)
 558  
       {
 559  0
         final String path =
 560  
             META_INF_PROPERTY_SET_REPORT + target + '_' + currentLocale
 561  
                 + ".xml";
 562  0
         final ClassLoader loader = descriptor.getClass().getClassLoader(); // NOPMD
 563  0
         final URL resource = loader.getResource(path);
 564  0
         if (resource != null)
 565  
         {
 566  0
           return path;
 567  
         }
 568  0
       }
 569  
     }
 570  
 
 571  0
     final String path = META_INF_PROPERTY_SET_REPORT + target + ".xml";
 572  0
     return path;
 573  
   }
 574  
 
 575  
   /**
 576  
    * Resolves the alias to the target it points to.
 577  
    *
 578  
    * @param alias the alias whose physical resource is requested.
 579  
    * @return the target the alias points to.
 580  
    * @throws BlankArgumentException if {@code alias} is blank.
 581  
    * @throws UnknownAliasException if the alias is not known.
 582  
    */
 583  
   public String resolve(final String alias) throws BlankArgumentException,
 584  
     UnknownAliasException
 585  
   {
 586  0
     return aliasMapping.get(alias);
 587  
   }
 588  
 
 589  
   /**
 590  
    * Traverses the registered aliases.
 591  
    *
 592  
    * @param traverser the traverser to use.
 593  
    * @throws NullPointerException if {@code traverser} is <code>null</code>.
 594  
    */
 595  
   public void traverseAliases(final AliasTraverser traverser)
 596  
     throws NullPointerException
 597  
   {
 598  0
     aliasMapping.traverse(traverser);
 599  0
   }
 600  
 
 601  
   /**
 602  
    * Checks whether any aliases are registered.
 603  
    *
 604  
    * @return <code>true</code> if at least one alias is registered,
 605  
    *         <code>false</code> otherwise.
 606  
    */
 607  
   public boolean hasAliases()
 608  
   {
 609  0
     return !aliasMapping.isEmpty();
 610  
   }
 611  
 
 612  
   // --- object basics --------------------------------------------------------
 613  
 
 614  
   /**
 615  
    * Returns the string representation of the object.
 616  
    *
 617  
    * @return the string representation of the object.
 618  
    */
 619  
   @Override
 620  
   public String toString()
 621  
   {
 622  0
     return ToStringBuilder.reflectionToString(this);
 623  
   }
 624  
 }