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