001: /* ComponentDefinition.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Tue May 31 17:54:45 2005, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2005 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.Collection;
022: import java.util.Map;
023: import java.net.URL;
024:
025: import org.zkoss.zk.ui.Page;
026: import org.zkoss.zk.ui.Component;
027: import org.zkoss.zk.ui.metainfo.impl.ComponentDefinitionImpl;
028: import org.zkoss.zk.ui.render.ComponentRenderer;
029:
030: /**
031: * A component definition.
032: * Like class in Java, a {@link ComponentDefinition} defines the behavior
033: * of a component.
034: *
035: * <p>The implementation need NOT to be thread safe, since the caller
036: * has to {@link #clone} first if accessed concurrently.
037: *
038: * @author tomyeh
039: */
040: public interface ComponentDefinition extends Cloneable {
041: /** A special definition to represent the zk component. */
042: public final static ComponentDefinition ZK = new ComponentDefinitionImpl(
043: null, null, "zk", Component.class);;
044:
045: /** Returns the language definition, or null if it is a temporty definition
046: * belonging to a page.
047: */
048: public LanguageDefinition getLanguageDefinition();
049:
050: /** Returns name of this component definition (never null).
051: * It is unique in the same language, {@link LanguageDefinition},
052: * if it belongs to a language, i.e.,
053: * {@link #getLanguageDefinition} is not null.
054: */
055: public String getName();
056:
057: /** Returns the property name to which the text enclosed within
058: * the element (associated with this component definition) is assigned to.
059: *
060: * <p>Default: null (means to create a Label component as the child)
061: *
062: * <p>For example, if {@link #getTextAs} returns null, then
063: * a Label component is created as a child of <code>comp</code>
064: * with the "Hi Text" value in the following example:
065: *
066: *<pre><code><comp>
067: * Hi Text
068: *</comp></code></pre>
069: *
070: * <p>In other words, it is equivalent to
071: *
072: *<pre><code><comp>
073: * <label value="Hi Text"/>
074: *</comp></code></pre>
075: *
076: * <p>On the other hand, if {@link #getTextAs} returns a non-empty string,
077: * say, "content", then
078: * "Hi Text" is assigned to the content property of <code>comp</comp>.
079: * In other words, it is equivalent to
080: *
081: *<pre><code><comp content="Hi Text"/>
082: *</comp></code></pre>
083: *
084: * <p>It is also the same as
085: *
086: *<pre><code><comp>
087: * <attribute name="content"/>
088: * Hi Text
089: * </attribute>
090: *</comp></code></pre>
091: *
092: * <p>To enable it, you can declare <code>text-as</code> in
093: * the component definition in lang.xml or lang-addon.xml:
094: *
095: * <pre><code><component>
096: * <component-name>html</component-name>
097: * <text-as>content</text-as>
098: *...</code></pre>
099: *
100: * @since 3.0.0
101: */
102: public String getTextAs();
103:
104: /** Returns whether this is a macro component.
105: * @see #getMacroURI
106: */
107: public boolean isMacro();
108:
109: /** Returns the macro URI, or null if not a macro.
110: */
111: public String getMacroURI();
112:
113: /** Returns whether this is an inline macro.
114: * If false, you have to examine {@link #isMacro} to see whether it
115: * is a regular macro.
116: */
117: public boolean isInlineMacro();
118:
119: /** Returns whether this is used for the native namespace.
120: *
121: * @since 3.0.0
122: * @see LanguageDefinition#getNativeDefinition
123: */
124: public boolean isNative();
125:
126: /** Returns the class (Class) or the class name (String) that
127: * implements the component.
128: *
129: * <p>If a string is returned, the real class may depend on
130: * which page a component will be created to.
131: * Reason: the zscript interpreter is associated with a page and
132: * it may define classes upon evaluating a page.
133: */
134: public Object getImplementationClass();
135:
136: /** Sets the class to implements the component.
137: *
138: * <p>Note: currently, classes specified in lang.xml or lang-addon.xml
139: * must be resolved when loading the files.
140: * However, classes specified in a page (by use of class or use attributes)
141: * might be resolved later because it might be defined by zscript.
142: */
143: public void setImplementationClass(Class cls);
144:
145: /** Sets the class name to implements the component.
146: * Unlike {@link #setImplementationClass(Class)}, the class won't
147: * be resolved until {@link ComponentInfo#newInstance} or {@link #getImplementationClass}
148: * is used. In other words, the class can be provided later
149: * (thru, usually, zscript).
150: */
151: public void setImplementationClass(String clsnm);
152:
153: /** Resolves and returns the class that implements the component.
154: *
155: * <p>Unlike {@link #getImplementationClass},
156: * this method will resolve a class name (String) to a class (Class),
157: * if necessary.
158: * In addition, if the clsnm argument is specified,
159: * it is used instead of {@link #getImplementationClass}.
160: * In other words, it overrides the default class.
161: *
162: * @param clsnm [optional] If specified, clsnm is used instead of
163: * {@link #getImplementationClass}.
164: * In other words, it overrides the default class.
165: * @param page the page to check whether the class is defined
166: * in its interpreters. Ignored if null.
167: * This method will search the class loader of the current thread.
168: * If not found, it will search the interpreters of the specifed
169: * page ({@link Page#getLoadedInterpreters}).
170: * Note: this method won't attach the component to the specified page.
171: * @exception ClassNotFoundException if the class not found
172: */
173: public Class resolveImplementationClass(Page page, String clsnm)
174: throws ClassNotFoundException;
175:
176: /** Returns whether a component belongs to this definition.
177: *
178: * <p>If {@link #resolveImplementationClass} failed to resolve,
179: * true is returned!
180: */
181: public boolean isInstance(Component comp);
182:
183: /** Creates an component of this definition.
184: *
185: * <p>Note: this method doesn't invoke {@link #applyProperties}.
186: * It is caller's job to apply these properties if necessary.
187: * Since the value of a property might depend on the component tree,
188: * it is better to assign the component with a proper parent
189: * before calling {@link #applyProperties}.
190: *
191: * <p>Similarly, this method doesn't attach the component to the
192: * specified page. Developers may or may not add it to a page or
193: * a parent.
194: *
195: * <p>An application developer can invoke
196: * {@link org.zkoss.zk.ui.sys.UiFactory#newComponent}
197: * instead of {@link #newInstance}, since a deployer might
198: * customize the way to create components by providing
199: * an implementation of {@link org.zkoss.zk.ui.sys.UiFactory}.
200: * In additions, it also invokes {@link #applyProperties}
201: * assigning page/parent.
202: *
203: * <p>On the other hand, this method is 'low-level'. It simply resolves
204: * the implementation class by use of {@link #resolveImplementationClass},
205: * and then uses it to create an instance.
206: *
207: * @param clsnm [optional] If specified, clsnm is used instead of
208: * {@link #getImplementationClass}.
209: * In other words, it overrides the default class.
210: * @param page the page that is used to resolve the implementation
211: * class. It is used only this definition is associated
212: * with a class name by {@link #setImplementationClass(String)},
213: * or clsnm is not null.
214: * Note: this method won't attach the component to the specified page.
215: * It can be null if {@link #getImplementationClass} returns a Class
216: * instance, and clsnm is null.
217: * @return the new component (never null)
218: */
219: public Component newInstance(Page page, String clsnm);
220:
221: /** Creates an component of this definition.
222: * Refer to {@link #newInstance(Page, String)}. They are the same
223: * except this method accepts the class directly,
224: * while {@link #newInstance(Page, String)} invokes
225: * {@link #resolveImplementationClass} to resolve the class first.
226: *
227: * @return the new component (never null)
228: * @since 3.0.2
229: */
230: public Component newInstance(Class cls);
231:
232: /** Adds a mold based on an URI.
233: *
234: * @param moldURI an URI of the mold; never null nor empty.
235: * If it starts with "class:", the following substring is assumed to be
236: * the class name of {@link ComponentRenderer}, and then it invokes
237: * {@link #addMold(String, ComponentRenderer)}.
238: * If not staring with "class:", it is pure an URI, and it may
239: * contain XEL expressions.
240: */
241: public void addMold(String name, String moldURI);
242:
243: /** Adds a mold based on {@link ComponentRenderer}.
244: *
245: * @param renderer a component renderer. It is shared
246: * by all component instances belonging to this definition.
247: * @since 3.0.0
248: */
249: public void addMold(String name, ComponentRenderer renderer);
250:
251: /** Returns the URI (String) or an instance of {@link ComponentRenderer}
252: * of the mold, or null if no such mold available.
253: * In other words, if a String instance is returned, it is the URI
254: * of the mold. If a {@link ComponentRenderer}
255: * instance is returned, it is the object responsible to handle
256: * the generation of the component's output.
257: *
258: * <p>If the mold URI contains an expression, it will be evaluated first
259: * before returning.
260: *
261: * @param name the mold
262: * @return an URI in String, or a {@link ComponentRenderer},
263: * as of release 3.0.0
264: * @see org.zkoss.zk.ui.AbstractComponent#redraw
265: */
266: public Object getMoldURI(Component comp, String name);
267:
268: /** Returns whether the specified mold exists.
269: */
270: public boolean hasMold(String name);
271:
272: /** Returns a readonly collection of mold names supported by
273: * this definition.
274: */
275: public Collection getMoldNames();
276:
277: /** Adds a property initializer.
278: * It will initialize a component when created with is definition.
279: *
280: * @param name the member name. The component must have a valid setter
281: * for it.
282: * @param value the value. It might contain expressions (${}).
283: */
284: public void addProperty(String name, String value);
285:
286: /** Applies the properties and custom attributes defined in
287: * this definition to the specified component.
288: *
289: * <p>Note: annotations are applied to the component when a component
290: * is created. So, this method doesn't and need not to copy them.
291: */
292: public void applyProperties(Component comp);
293:
294: /** Evaluates and retrieves properties to the specified map.
295: *
296: * @param propmap the map to store the retrieved properties.
297: * If null, a HashMap instance is created.
298: * (String name, Object value).
299: * @param owner the owner page; used if parent is null
300: * @param parent the parent
301: */
302: public Map evalProperties(Map propmap, Page owner, Component parent);
303:
304: /** Returns the annotation map defined in this definition, or null
305: * if no annotation is ever defined.
306: */
307: public AnnotationMap getAnnotationMap();
308:
309: /** Returns the URL where this component definition is declared, or
310: * null if not available.
311: * @since 3.0.3
312: */
313: public URL getDeclarationURL();
314:
315: /** Clones this definition and assins with the specified language
316: * definition and name.
317: */
318: public ComponentDefinition clone(LanguageDefinition langdef,
319: String name);
320:
321: /** Clones this component definition.
322: * You rarely invoke this method directly. Rather, use
323: * {@link #clone(LanguageDefinition, String)}.
324: *
325: * <p>Note: the caller usually has to change the component name,
326: * and then assign to a language definition ({@link LanguageDefinition})
327: * or a page definition ({@link PageDefinition}).
328: *
329: * @return the new component definition by cloning from this definition.
330: */
331: public Object clone();
332: }
|