001: /* ComponentDefinitionMap.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Mon Sep 4 20:20:36 2006, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2006 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zk.ui.metainfo;
020:
021: import java.util.Map;
022: import java.util.HashMap;
023: import java.util.Collection;
024: import java.util.Collections;
025: import java.util.Iterator;
026:
027: /**
028: * A map of component definitions.
029: * Used with {@link PageDefinition#getComponentDefinitionMap}
030: * and {@link LanguageDefinition}.
031: *
032: * <p>It is thread-safe (since it is used in {@link LanguageDefinition}).
033: *
034: * @author tomyeh
035: */
036: public class ComponentDefinitionMap implements Cloneable,
037: java.io.Serializable {
038: /** A map of component definition defined in this page. */
039: private transient Map _compdefs;
040: /** Map(String clsnm, ComponentDefinition compdef). */
041: private transient Map _compdefsByClass;
042: /** Whether the element name is case-insensitive. */
043: private final boolean _ignoreCase;
044:
045: /** Constructor.
046: */
047: public ComponentDefinitionMap(boolean ignoreCase) {
048: _ignoreCase = ignoreCase;
049: }
050:
051: /** Returns whether the component names are case-insensitive.
052: */
053: public boolean isCaseInsensitive() {
054: return _ignoreCase;
055: }
056:
057: /** Returns a collection of component definitions, {@link ComponentDefinition},
058: * defined in this map.
059: */
060: public Collection getNames() {
061: return _compdefs != null ? _compdefs.keySet()
062: : (Collection) Collections.EMPTY_LIST;
063: }
064:
065: /** Adds a component definition to this map.
066: *
067: * <p>Thread safe.
068: */
069: public void add(ComponentDefinition compdef) {
070: if (compdef == null)
071: throw new IllegalArgumentException("null");
072:
073: String name = compdef.getName();
074: if (isCaseInsensitive())
075: name = name.toLowerCase();
076:
077: Object implcls = compdef.getImplementationClass();
078: if (implcls instanceof Class)
079: implcls = ((Class) implcls).getName();
080:
081: synchronized (this ) {
082: if (_compdefs == null) {
083: _compdefsByClass = Collections
084: .synchronizedMap(new HashMap(3));
085: _compdefs = Collections.synchronizedMap(new HashMap(3));
086: }
087:
088: _compdefs.put(name, compdef);
089: _compdefsByClass.put(implcls, compdef);
090: }
091: }
092:
093: /** Returns whether the specified component exists.
094: */
095: public boolean contains(String name) {
096: return _compdefs != null
097: && _compdefs.containsKey(isCaseInsensitive() ? name
098: .toLowerCase() : name);
099: }
100:
101: /** Returns the component definition of the specified name, or null if not
102: * not found.
103: *
104: * <p>Note: unlike {@link LanguageDefinition#getComponentDefinition},
105: * this method doesn't throw ComponentNotFoundException if not found.
106: * It just returns null.
107: */
108: public ComponentDefinition get(String name) {
109: return _compdefs != null ? (ComponentDefinition) _compdefs
110: .get(isCaseInsensitive() ? name.toLowerCase() : name)
111: : null;
112: }
113:
114: /** Returns the component definition of the specified class, or null if not
115: * found.
116: *
117: * <p>Note: unlike {@link LanguageDefinition#getComponentDefinition},
118: * this method doesn't throw ComponentNotFoundException if not found.
119: * It just returns null.
120: */
121: public ComponentDefinition get(Class cls) {
122: if (_compdefsByClass != null) {
123: for (; cls != null; cls = cls.getSuperclass()) {
124: final ComponentDefinition compdef = (ComponentDefinition) _compdefsByClass
125: .get(cls.getName());
126: if (compdef != null)
127: return compdef;
128: }
129: }
130: return null;
131: }
132:
133: //Serializable//
134: //NOTE: they must be declared as private
135: private synchronized void writeObject(java.io.ObjectOutputStream s)
136: throws java.io.IOException {
137: s.defaultWriteObject();
138:
139: if (_compdefs != null) {
140: synchronized (_compdefs) {
141: s.writeInt(_compdefs.size());
142: for (Iterator it = _compdefs.values().iterator(); it
143: .hasNext();)
144: s.writeObject(it.next());
145: }
146: } else {
147: s.writeInt(0);
148: }
149: }
150:
151: private synchronized void readObject(java.io.ObjectInputStream s)
152: throws java.io.IOException, ClassNotFoundException {
153: s.defaultReadObject();
154:
155: int cnt = s.readInt();
156: while (--cnt >= 0)
157: add((ComponentDefinition) s.readObject());
158: }
159:
160: //Cloneable//
161: public Object clone() {
162: final ComponentDefinitionMap clone;
163: try {
164: clone = (ComponentDefinitionMap) super .clone();
165: clone._compdefs = Collections.synchronizedMap(new HashMap(
166: _compdefs));
167: clone._compdefsByClass = Collections
168: .synchronizedMap(new HashMap(_compdefsByClass));
169: } catch (CloneNotSupportedException ex) {
170: throw new InternalError();
171: }
172: return clone;
173: }
174: }
|