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