KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tapestry > spec > LibrarySpecification


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 JavaDoc;
18 import java.util.Collections JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
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 JavaDoc _pages;
45
46     /**
47      * Map of component alias to component specification path.
48      */

49     private Map JavaDoc _components;
50
51     /**
52      * Map of library id to library specification path.
53      */

54
55     private Map JavaDoc _libraries;
56
57     private String JavaDoc _description;
58
59     /**
60      * Map of extension name to {@link IExtensionSpecification}.
61      */

62
63     private Map JavaDoc _extensions;
64
65     /**
66      * Map of extension name to Object for instantiated extensions.
67      */

68
69     private Map JavaDoc _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 JavaDoc _publicId;
78
79     /**
80      * The location of the specification.
81      */

82
83     private Resource _specificationLocation;
84
85     public String JavaDoc getLibrarySpecificationPath(String JavaDoc id)
86     {
87         return (String JavaDoc) 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     public void setLibrarySpecificationPath(String JavaDoc id, String JavaDoc path)
98     {
99         if (_libraries == null)
100             _libraries = new HashMap JavaDoc();
101
102         if (_libraries.containsKey(id))
103             throw new IllegalArgumentException JavaDoc(Tapestry.format(
104                     "LibrarySpecification.duplicate-child-namespace-id",
105                     id));
106
107         _libraries.put(id, path);
108     }
109
110     public List JavaDoc getLibraryIds()
111     {
112         return sortedKeys(_libraries);
113     }
114
115     public String JavaDoc getPageSpecificationPath(String JavaDoc name)
116     {
117         return (String JavaDoc) get(_pages, name);
118     }
119
120     public void setPageSpecificationPath(String JavaDoc name, String JavaDoc path)
121     {
122         if (_pages == null)
123             _pages = new HashMap JavaDoc();
124
125         if (_pages.containsKey(name))
126             throw new IllegalArgumentException JavaDoc(Tapestry.format(
127                     "LibrarySpecification.duplicate-page-name",
128                     name));
129
130         _pages.put(name, path);
131     }
132
133     public List JavaDoc getPageNames()
134     {
135         return sortedKeys(_pages);
136     }
137
138     public void setComponentSpecificationPath(String JavaDoc alias, String JavaDoc path)
139     {
140         if (_components == null)
141             _components = new HashMap JavaDoc();
142
143         if (_components.containsKey(alias))
144             throw new IllegalArgumentException JavaDoc(Tapestry.format(
145                     "LibrarySpecification.duplicate-component-alias",
146                     alias));
147
148         _components.put(alias, path);
149     }
150
151     public String JavaDoc getComponentSpecificationPath(String JavaDoc alias)
152     {
153         return (String JavaDoc) get(_components, alias);
154     }
155
156     /**
157      * @since 3.0
158      */

159
160     public List JavaDoc getComponentTypes()
161     {
162         return sortedKeys(_components);
163     }
164
165     public String JavaDoc getServiceClassName(String JavaDoc name)
166     {
167         throw new UnsupportedOperationException JavaDoc();
168     }
169
170     public List JavaDoc getServiceNames()
171     {
172         return Collections.EMPTY_LIST;
173     }
174
175     public void setServiceClassName(String JavaDoc name, String JavaDoc className)
176     {
177         throw new UnsupportedOperationException JavaDoc();
178     }
179
180     private List JavaDoc sortedKeys(Map JavaDoc map)
181     {
182         if (map == null)
183             return Collections.EMPTY_LIST;
184
185         List JavaDoc result = new ArrayList JavaDoc(map.keySet());
186
187         Collections.sort(result);
188
189         return result;
190     }
191
192     private Object JavaDoc get(Map JavaDoc map, Object JavaDoc key)
193     {
194         if (map == null)
195             return null;
196
197         return map.get(key);
198     }
199
200     /**
201      * Returns the documentation for this library..
202      */

203
204     public String JavaDoc getDescription()
205     {
206         return _description;
207     }
208
209     /**
210      * Sets the documentation for this library.
211      */

212
213     public void setDescription(String JavaDoc description)
214     {
215         _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     public Map JavaDoc getExtensionSpecifications()
225     {
226         if (_extensions == null)
227             return null;
228
229         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     public void addExtensionSpecification(String JavaDoc name, IExtensionSpecification extension)
240     {
241         if (_extensions == null)
242             _extensions = new HashMap JavaDoc();
243
244         if (_extensions.containsKey(name))
245             throw new IllegalArgumentException JavaDoc(Tapestry.format(
246                     "LibrarySpecification.duplicate-extension-name",
247                     this,
248                     name));
249
250         _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     public synchronized List JavaDoc getExtensionNames()
259     {
260         return sortedKeys(_instantiatedExtensions);
261     }
262
263     /**
264      * Returns the named IExtensionSpecification, or null if it doesn't exist.
265      */

266
267     public IExtensionSpecification getExtensionSpecification(String JavaDoc name)
268     {
269         if (_extensions == null)
270             return null;
271
272         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     public boolean checkExtension(String JavaDoc name)
280     {
281         if (_extensions == null)
282             return false;
283
284         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     public synchronized Object JavaDoc getExtension(String JavaDoc name)
295     {
296         return getExtension(name, null);
297     }
298
299     /** @since 3.0 * */
300
301     public synchronized Object JavaDoc getExtension(String JavaDoc name, Class JavaDoc typeConstraint)
302     {
303         if (_instantiatedExtensions == null)
304             _instantiatedExtensions = new HashMap JavaDoc();
305
306         Object JavaDoc result = _instantiatedExtensions.get(name);
307         IExtensionSpecification spec = getExtensionSpecification(name);
308
309         if (spec == null)
310             throw new IllegalArgumentException JavaDoc(Tapestry.format(
311                     "LibrarySpecification.no-such-extension",
312                     name));
313
314         if (result == null)
315         {
316
317             result = spec.instantiateExtension();
318
319             _instantiatedExtensions.put(name, result);
320         }
321
322         if (typeConstraint != null)
323             applyTypeConstraint(name, result, typeConstraint, spec.getLocation());
324
325         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     protected void applyTypeConstraint(String JavaDoc name, Object JavaDoc extension, Class JavaDoc typeConstraint,
337             Location location)
338     {
339         Class JavaDoc extensionClass = extension.getClass();
340
341         // Can you assign an instance of the extension to a variable
342
// of type typeContraint legally?
343

344         if (typeConstraint.isAssignableFrom(extensionClass))
345             return;
346
347         String JavaDoc key = typeConstraint.isInterface() ? "LibrarySpecification.extension-does-not-implement-interface"
348                 : "LibrarySpecification.extension-not-a-subclass";
349
350         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     public synchronized void instantiateImmediateExtensions()
363     {
364         if (_extensions == null)
365             return;
366
367         Iterator JavaDoc i = _extensions.entrySet().iterator();
368
369         while (i.hasNext())
370         {
371             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
372
373             IExtensionSpecification spec = (IExtensionSpecification) entry.getValue();
374
375             if (!spec.isImmediate())
376                 continue;
377
378             String JavaDoc name = (String JavaDoc) entry.getKey();
379
380             getExtension(name);
381         }
382
383     }
384
385     /**
386      * Returns the extensions map.
387      *
388      * @return Map of objects.
389      */

390
391     protected Map JavaDoc getExtensions()
392     {
393         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     protected void setExtensions(Map JavaDoc extension)
406     {
407         _extensions = extension;
408     }
409
410     /**
411      * Returns the libraries map.
412      *
413      * @return Map of {@link LibrarySpecification}.
414      */

415
416     protected Map JavaDoc getLibraries()
417     {
418         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     protected void setLibraries(Map JavaDoc libraries)
431     {
432         _libraries = libraries;
433     }
434
435     /**
436      * Returns the pages map.
437      *
438      * @return Map of {@link IComponentSpecification}.
439      */

440
441     protected Map JavaDoc getPages()
442     {
443         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     protected void setPages(Map JavaDoc pages)
456     {
457         _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     protected Map JavaDoc getServices()
468     {
469         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     protected void setServices(Map JavaDoc services)
484     {
485     }
486
487     /**
488      * Returns the components map.
489      *
490      * @return Map of {@link IContainedComponent}.
491      */

492
493     protected Map JavaDoc getComponents()
494     {
495         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     protected void setComponents(Map JavaDoc components)
507     {
508         _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     public String JavaDoc getPublicId()
519     {
520         return _publicId;
521     }
522
523     public void setPublicId(String JavaDoc publicId)
524     {
525         _publicId = publicId;
526     }
527
528     /** @since 3.0 * */
529
530     public Resource getSpecificationLocation()
531     {
532         return _specificationLocation;
533     }
534
535     /** @since 3.0 * */
536
537     public void setSpecificationLocation(Resource specificationLocation)
538     {
539         _specificationLocation = specificationLocation;
540     }
541
542     /** @since 3.0 * */
543
544     public synchronized String JavaDoc toString()
545     {
546         ToStringBuilder builder = new ToStringBuilder(this);
547
548         builder.append("components", _components);
549         builder.append("description", _description);
550         builder.append("instantiatedExtensions", _instantiatedExtensions);
551         builder.append("libraries", _libraries);
552         builder.append("pages", _pages);
553         builder.append("publicId", _publicId);
554         builder.append("specificationLocation", _specificationLocation);
555
556         extendDescription(builder);
557
558         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     protected void extendDescription(ToStringBuilder builder)
569     {
570     }
571
572 }
Popular Tags