Clover coverage report - Code Coverage for tapestry release 4.0-beta-2
Coverage timestamp: Sat Jul 9 2005 22:02:17 EDT
file stats: LOC: 572   Methods: 41
NCLOC: 266   Classes: 1
30 day Evaluation License registered to hlship@comcast.net Your 30 day evaluation period has expired. Please visit http://www.cenqua.com 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.hivemind.ApplicationRuntimeException;
 25    import org.apache.hivemind.Location;
 26    import org.apache.hivemind.Resource;
 27    import org.apache.hivemind.util.ToStringBuilder;
 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  17 public String getLibrarySpecificationPath(String id)
 86    {
 87  17 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  21 public void setLibrarySpecificationPath(String id, String path)
 98    {
 99  21 if (_libraries == null)
 100  20 _libraries = new HashMap();
 101   
 102  21 if (_libraries.containsKey(id))
 103  0 throw new IllegalArgumentException(Tapestry.format(
 104    "LibrarySpecification.duplicate-child-namespace-id",
 105    id));
 106   
 107  21 _libraries.put(id, path);
 108    }
 109   
 110  1 public List getLibraryIds()
 111    {
 112  1 return sortedKeys(_libraries);
 113    }
 114   
 115  184 public String getPageSpecificationPath(String name)
 116    {
 117  184 return (String) get(_pages, name);
 118    }
 119   
 120  500 public void setPageSpecificationPath(String name, String path)
 121    {
 122  500 if (_pages == null)
 123  71 _pages = new HashMap();
 124   
 125  500 if (_pages.containsKey(name))
 126  0 throw new IllegalArgumentException(Tapestry.format(
 127    "LibrarySpecification.duplicate-page-name",
 128    name));
 129   
 130  500 _pages.put(name, path);
 131    }
 132   
 133  1 public List getPageNames()
 134    {
 135  1 return sortedKeys(_pages);
 136    }
 137   
 138  2039 public void setComponentSpecificationPath(String alias, String path)
 139    {
 140  2039 if (_components == null)
 141  66 _components = new HashMap();
 142   
 143  2039 if (_components.containsKey(alias))
 144  0 throw new IllegalArgumentException(Tapestry.format(
 145    "LibrarySpecification.duplicate-component-alias",
 146    alias));
 147   
 148  2039 _components.put(alias, path);
 149    }
 150   
 151  768 public String getComponentSpecificationPath(String alias)
 152    {
 153  768 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  969 private Object get(Map map, Object key)
 193    {
 194  969 if (map == null)
 195  207 return null;
 196   
 197  762 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  164 public boolean checkExtension(String name)
 280    {
 281  164 if (_extensions == null)
 282  160 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  101 public synchronized void instantiateImmediateExtensions()
 363    {
 364  101 if (_extensions == null)
 365  91 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  904 public Resource getSpecificationLocation()
 531    {
 532  904 return _specificationLocation;
 533    }
 534   
 535    /** @since 3.0 * */
 536   
 537  132 public void setSpecificationLocation(Resource specificationLocation)
 538    {
 539  132 _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    }