Clover coverage report - Code Coverage for tapestry release 4.0-alpha-3
Coverage timestamp: Mon May 16 2005 09:05:49 EDT
file stats: LOC: 572   Methods: 41
NCLOC: 266   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
LibrarySpecification.java 72.7% 65% 53.7% 64.3%
coverage coverage
 1   
 // Copyright 2004, 2005 The Apache Software Foundation
 2   
 //
 3   
 // Licensed under the Apache License, Version 2.0 (the "License");
 4   
 // you may not use this file except in compliance with the License.
 5   
 // You may obtain a copy of the License at
 6   
 //
 7   
 //     http://www.apache.org/licenses/LICENSE-2.0
 8   
 //
 9   
 // Unless required by applicable law or agreed to in writing, software
 10   
 // distributed under the License is distributed on an "AS IS" BASIS,
 11   
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12   
 // See the License for the specific language governing permissions and
 13   
 // limitations under the License.
 14   
 
 15   
 package org.apache.tapestry.spec;
 16   
 
 17   
 import java.util.ArrayList;
 18   
 import java.util.Collections;
 19   
 import java.util.HashMap;
 20   
 import java.util.Iterator;
 21   
 import java.util.List;
 22   
 import java.util.Map;
 23   
 
 24   
 import org.apache.commons.lang.builder.ToStringBuilder;
 25   
 import org.apache.hivemind.ApplicationRuntimeException;
 26   
 import org.apache.hivemind.Location;
 27   
 import org.apache.hivemind.Resource;
 28   
 import org.apache.tapestry.Tapestry;
 29   
 
 30   
 /**
 31   
  * Specification for a library. {@link org.apache.tapestry.spec.ApplicationSpecification}is a
 32   
  * specialized kind of library.
 33   
  * 
 34   
  * @author Howard Lewis Ship
 35   
  * @since 2.2bv
 36   
  */
 37   
 
 38   
 public class LibrarySpecification extends LocatablePropertyHolder implements ILibrarySpecification
 39   
 {
 40   
     /**
 41   
      * Map of page name to page specification path.
 42   
      */
 43   
 
 44   
     private Map _pages;
 45   
 
 46   
     /**
 47   
      * Map of component alias to component specification path.
 48   
      */
 49   
     private Map _components;
 50   
 
 51   
     /**
 52   
      * Map of library id to library specification path.
 53   
      */
 54   
 
 55   
     private Map _libraries;
 56   
 
 57   
     private String _description;
 58   
 
 59   
     /**
 60   
      * Map of extension name to {@link IExtensionSpecification}.
 61   
      */
 62   
 
 63   
     private Map _extensions;
 64   
 
 65   
     /**
 66   
      * Map of extension name to Object for instantiated extensions.
 67   
      */
 68   
 
 69   
     private Map _instantiatedExtensions;
 70   
 
 71   
     /**
 72   
      * The XML Public Id used when the library specification was read (if applicable).
 73   
      * 
 74   
      * @since 2.2
 75   
      */
 76   
 
 77   
     private String _publicId;
 78   
 
 79   
     /**
 80   
      * The location of the specification.
 81   
      */
 82   
 
 83   
     private Resource _specificationLocation;
 84   
 
 85  18
     public String getLibrarySpecificationPath(String id)
 86   
     {
 87  18
         return (String) get(_libraries, id);
 88   
     }
 89   
 
 90   
     /**
 91   
      * Sets the specification path for an embedded library.
 92   
      * 
 93   
      * @throws IllegalArgumentException
 94   
      *             if a library with the given id already exists
 95   
      */
 96   
 
 97  23
     public void setLibrarySpecificationPath(String id, String path)
 98   
     {
 99  23
         if (_libraries == null)
 100  22
             _libraries = new HashMap();
 101   
 
 102  23
         if (_libraries.containsKey(id))
 103  0
             throw new IllegalArgumentException(Tapestry.format(
 104   
                     "LibrarySpecification.duplicate-child-namespace-id",
 105   
                     id));
 106   
 
 107  23
         _libraries.put(id, path);
 108   
     }
 109   
 
 110  1
     public List getLibraryIds()
 111   
     {
 112  1
         return sortedKeys(_libraries);
 113   
     }
 114   
 
 115  198
     public String getPageSpecificationPath(String name)
 116   
     {
 117  198
         return (String) get(_pages, name);
 118   
     }
 119   
 
 120  566
     public void setPageSpecificationPath(String name, String path)
 121   
     {
 122  566
         if (_pages == null)
 123  78
             _pages = new HashMap();
 124   
 
 125  566
         if (_pages.containsKey(name))
 126  0
             throw new IllegalArgumentException(Tapestry.format(
 127   
                     "LibrarySpecification.duplicate-page-name",
 128   
                     name));
 129   
 
 130  566
         _pages.put(name, path);
 131   
     }
 132   
 
 133  1
     public List getPageNames()
 134   
     {
 135  1
         return sortedKeys(_pages);
 136   
     }
 137   
 
 138  2049
     public void setComponentSpecificationPath(String alias, String path)
 139   
     {
 140  2049
         if (_components == null)
 141  71
             _components = new HashMap();
 142   
 
 143  2049
         if (_components.containsKey(alias))
 144  0
             throw new IllegalArgumentException(Tapestry.format(
 145   
                     "LibrarySpecification.duplicate-component-alias",
 146   
                     alias));
 147   
 
 148  2049
         _components.put(alias, path);
 149   
     }
 150   
 
 151  864
     public String getComponentSpecificationPath(String alias)
 152   
     {
 153  864
         return (String) get(_components, alias);
 154   
     }
 155   
 
 156   
     /**
 157   
      * @since 3.0
 158   
      */
 159   
 
 160  1
     public List getComponentTypes()
 161   
     {
 162  1
         return sortedKeys(_components);
 163   
     }
 164   
 
 165  0
     public String getServiceClassName(String name)
 166   
     {
 167  0
         throw new UnsupportedOperationException();
 168   
     }
 169   
 
 170  0
     public List getServiceNames()
 171   
     {
 172  0
         return Collections.EMPTY_LIST;
 173   
     }
 174   
 
 175  0
     public void setServiceClassName(String name, String className)
 176   
     {
 177  0
         throw new UnsupportedOperationException();
 178   
     }
 179   
 
 180  3
     private List sortedKeys(Map map)
 181   
     {
 182  3
         if (map == null)
 183  0
             return Collections.EMPTY_LIST;
 184   
 
 185  3
         List result = new ArrayList(map.keySet());
 186   
 
 187  3
         Collections.sort(result);
 188   
 
 189  3
         return result;
 190   
     }
 191   
 
 192  1080
     private Object get(Map map, Object key)
 193   
     {
 194  1080
         if (map == null)
 195  233
             return null;
 196   
 
 197  847
         return map.get(key);
 198   
     }
 199   
 
 200   
     /**
 201   
      * Returns the documentation for this library..
 202   
      */
 203   
 
 204  1
     public String getDescription()
 205   
     {
 206  1
         return _description;
 207   
     }
 208   
 
 209   
     /**
 210   
      * Sets the documentation for this library.
 211   
      */
 212   
 
 213  1
     public void setDescription(String description)
 214   
     {
 215  1
         _description = description;
 216   
     }
 217   
 
 218   
     /**
 219   
      * Returns a Map of extensions; key is extension name, value is
 220   
      * {@link org.apache.tapestry.spec.IExtensionSpecification}. May return null. The returned Map
 221   
      * is immutable.
 222   
      */
 223   
 
 224  0
     public Map getExtensionSpecifications()
 225   
     {
 226  0
         if (_extensions == null)
 227  0
             return null;
 228   
 
 229  0
         return Collections.unmodifiableMap(_extensions);
 230   
     }
 231   
 
 232   
     /**
 233   
      * Adds another extension specification.
 234   
      * 
 235   
      * @throws IllegalArgumentException
 236   
      *             if an extension with the given name already exists.
 237   
      */
 238   
 
 239  10
     public void addExtensionSpecification(String name, IExtensionSpecification extension)
 240   
     {
 241  10
         if (_extensions == null)
 242  10
             _extensions = new HashMap();
 243   
 
 244  10
         if (_extensions.containsKey(name))
 245  0
             throw new IllegalArgumentException(Tapestry.format(
 246   
                     "LibrarySpecification.duplicate-extension-name",
 247   
                     this,
 248   
                     name));
 249   
 
 250  10
         _extensions.put(name, extension);
 251   
     }
 252   
 
 253   
     /**
 254   
      * Returns a sorted List of the names of all extensions. May return the empty list, but won't
 255   
      * return null.
 256   
      */
 257   
 
 258  0
     public synchronized List getExtensionNames()
 259   
     {
 260  0
         return sortedKeys(_instantiatedExtensions);
 261   
     }
 262   
 
 263   
     /**
 264   
      * Returns the named IExtensionSpecification, or null if it doesn't exist.
 265   
      */
 266   
 
 267  10
     public IExtensionSpecification getExtensionSpecification(String name)
 268   
     {
 269  10
         if (_extensions == null)
 270  0
             return null;
 271   
 
 272  10
         return (IExtensionSpecification) _extensions.get(name);
 273   
     }
 274   
 
 275   
     /**
 276   
      * Returns true if this library specification has a specification for the named extension.
 277   
      */
 278   
 
 279  180
     public boolean checkExtension(String name)
 280   
     {
 281  180
         if (_extensions == null)
 282  176
             return false;
 283   
 
 284  4
         return _extensions.containsKey(name);
 285   
     }
 286   
 
 287   
     /**
 288   
      * Returns an instantiated extension. Extensions are created as needed and cached for later use.
 289   
      * 
 290   
      * @throws IllegalArgumentException
 291   
      *             if no extension specification exists for the given name.
 292   
      */
 293   
 
 294  2
     public synchronized Object getExtension(String name)
 295   
     {
 296  2
         return getExtension(name, null);
 297   
     }
 298   
 
 299   
     /** @since 3.0 * */
 300   
 
 301  6
     public synchronized Object getExtension(String name, Class typeConstraint)
 302   
     {
 303  6
         if (_instantiatedExtensions == null)
 304  6
             _instantiatedExtensions = new HashMap();
 305   
 
 306  6
         Object result = _instantiatedExtensions.get(name);
 307  6
         IExtensionSpecification spec = getExtensionSpecification(name);
 308   
 
 309  6
         if (spec == null)
 310  0
             throw new IllegalArgumentException(Tapestry.format(
 311   
                     "LibrarySpecification.no-such-extension",
 312   
                     name));
 313   
 
 314  6
         if (result == null)
 315   
         {
 316   
 
 317  6
             result = spec.instantiateExtension();
 318   
 
 319  6
             _instantiatedExtensions.put(name, result);
 320   
         }
 321   
 
 322  6
         if (typeConstraint != null)
 323  4
             applyTypeConstraint(name, result, typeConstraint, spec.getLocation());
 324   
 
 325  4
         return result;
 326   
     }
 327   
 
 328   
     /**
 329   
      * Checks that an extension conforms to the supplied type constraint.
 330   
      * 
 331   
      * @throws IllegalArgumentException
 332   
      *             if the extension fails the check.
 333   
      * @since 3.0
 334   
      */
 335   
 
 336  4
     protected void applyTypeConstraint(String name, Object extension, Class typeConstraint,
 337   
             Location location)
 338   
     {
 339  4
         Class extensionClass = extension.getClass();
 340   
 
 341   
         // Can you assign an instance of the extension to a variable
 342   
         // of type typeContraint legally?
 343   
 
 344  4
         if (typeConstraint.isAssignableFrom(extensionClass))
 345  2
             return;
 346   
 
 347  2
         String key = typeConstraint.isInterface() ? "LibrarySpecification.extension-does-not-implement-interface"
 348   
                 : "LibrarySpecification.extension-not-a-subclass";
 349   
 
 350  2
         throw new ApplicationRuntimeException(Tapestry.format(
 351   
                 key,
 352   
                 name,
 353   
                 extensionClass.getName(),
 354   
                 typeConstraint.getName()), location, null);
 355   
     }
 356   
 
 357   
     /**
 358   
      * Invoked after the entire specification has been constructed to instantiate any extensions
 359   
      * marked immediate.
 360   
      */
 361   
 
 362  108
     public synchronized void instantiateImmediateExtensions()
 363   
     {
 364  108
         if (_extensions == null)
 365  98
             return;
 366   
 
 367  10
         Iterator i = _extensions.entrySet().iterator();
 368   
 
 369  10
         while (i.hasNext())
 370   
         {
 371  10
             Map.Entry entry = (Map.Entry) i.next();
 372   
 
 373  10
             IExtensionSpecification spec = (IExtensionSpecification) entry.getValue();
 374   
 
 375  10
             if (!spec.isImmediate())
 376  9
                 continue;
 377   
 
 378  1
             String name = (String) entry.getKey();
 379   
 
 380  1
             getExtension(name);
 381   
         }
 382   
 
 383   
     }
 384   
 
 385   
     /**
 386   
      * Returns the extensions map.
 387   
      * 
 388   
      * @return Map of objects.
 389   
      */
 390   
 
 391  0
     protected Map getExtensions()
 392   
     {
 393  0
         return _extensions;
 394   
     }
 395   
 
 396   
     /**
 397   
      * Updates the extension map.
 398   
      * 
 399   
      * @param extension
 400   
      *            A Map of extension specification paths keyed on extension id.
 401   
      *            <p>
 402   
      *            The map is retained, not copied.
 403   
      */
 404   
 
 405  0
     protected void setExtensions(Map extension)
 406   
     {
 407  0
         _extensions = extension;
 408   
     }
 409   
 
 410   
     /**
 411   
      * Returns the libraries map.
 412   
      * 
 413   
      * @return Map of {@link LibrarySpecification}.
 414   
      */
 415   
 
 416  0
     protected Map getLibraries()
 417   
     {
 418  0
         return _libraries;
 419   
     }
 420   
 
 421   
     /**
 422   
      * Updates the library map.
 423   
      * 
 424   
      * @param libraries
 425   
      *            A Map of library specification paths keyed on library id.
 426   
      *            <p>
 427   
      *            The map is retained, not copied.
 428   
      */
 429   
 
 430  0
     protected void setLibraries(Map libraries)
 431   
     {
 432  0
         _libraries = libraries;
 433   
     }
 434   
 
 435   
     /**
 436   
      * Returns the pages map.
 437   
      * 
 438   
      * @return Map of {@link IComponentSpecification}.
 439   
      */
 440   
 
 441  0
     protected Map getPages()
 442   
     {
 443  0
         return _pages;
 444   
     }
 445   
 
 446   
     /**
 447   
      * Updates the page map.
 448   
      * 
 449   
      * @param pages
 450   
      *            A Map of page specification paths keyed on page id.
 451   
      *            <p>
 452   
      *            The map is retained, not copied.
 453   
      */
 454   
 
 455  0
     protected void setPages(Map pages)
 456   
     {
 457  0
         _pages = pages;
 458   
     }
 459   
 
 460   
     /**
 461   
      * Returns the services.
 462   
      * 
 463   
      * @return Map of service class names.
 464   
      * @deprecated To be removed in release 4.1.
 465   
      */
 466   
 
 467  0
     protected Map getServices()
 468   
     {
 469  0
         return Collections.EMPTY_MAP;
 470   
     }
 471   
 
 472   
     /**
 473   
      * Updates the services map.
 474   
      * 
 475   
      * @param services
 476   
      *            A Map of the fully qualified names of classes which implement
 477   
      *            {@link org.apache.tapestry.engine.IEngineService}keyed on service id.
 478   
      *            <p>
 479   
      *            The map is retained, not copied.
 480   
      * @deprecated To be removed in release 4.1.
 481   
      */
 482   
 
 483  0
     protected void setServices(Map services)
 484   
     {
 485   
     }
 486   
 
 487   
     /**
 488   
      * Returns the components map.
 489   
      * 
 490   
      * @return Map of {@link IContainedComponent}.
 491   
      */
 492   
 
 493  0
     protected Map getComponents()
 494   
     {
 495  0
         return _components;
 496   
     }
 497   
 
 498   
     /**
 499   
      * Updates the components map.
 500   
      * 
 501   
      * @param components
 502   
      *            A Map of {@link IContainedComponent}keyed on component id. The map is retained,
 503   
      *            not copied.
 504   
      */
 505   
 
 506  0
     protected void setComponents(Map components)
 507   
     {
 508  0
         _components = components;
 509   
     }
 510   
 
 511   
     /**
 512   
      * Returns the XML Public Id for the library file, or null if not applicable.
 513   
      * <p>
 514   
      * This method exists as a convienience for the Spindle plugin. A previous method used an
 515   
      * arbitrary version string, the public id is more useful and less ambiguous.
 516   
      */
 517   
 
 518  0
     public String getPublicId()
 519   
     {
 520  0
         return _publicId;
 521   
     }
 522   
 
 523  0
     public void setPublicId(String publicId)
 524   
     {
 525  0
         _publicId = publicId;
 526   
     }
 527   
 
 528   
     /** @since 3.0 * */
 529   
 
 530  990
     public Resource getSpecificationLocation()
 531   
     {
 532  990
         return _specificationLocation;
 533   
     }
 534   
 
 535   
     /** @since 3.0 * */
 536   
 
 537  141
     public void setSpecificationLocation(Resource specificationLocation)
 538   
     {
 539  141
         _specificationLocation = specificationLocation;
 540   
     }
 541   
 
 542   
     /** @since 3.0 * */
 543   
 
 544  0
     public synchronized String toString()
 545   
     {
 546  0
         ToStringBuilder builder = new ToStringBuilder(this);
 547   
 
 548  0
         builder.append("components", _components);
 549  0
         builder.append("description", _description);
 550  0
         builder.append("instantiatedExtensions", _instantiatedExtensions);
 551  0
         builder.append("libraries", _libraries);
 552  0
         builder.append("pages", _pages);
 553  0
         builder.append("publicId", _publicId);        
 554  0
         builder.append("specificationLocation", _specificationLocation);
 555   
 
 556  0
         extendDescription(builder);
 557   
 
 558  0
         return builder.toString();
 559   
     }
 560   
 
 561   
     /**
 562   
      * Does nothing, subclasses may override to add additional description.
 563   
      * 
 564   
      * @see #toString()
 565   
      * @since 3.0
 566   
      */
 567   
 
 568  0
     protected void extendDescription(ToStringBuilder builder)
 569   
     {
 570   
     }
 571   
 
 572   
 }