org.zkoss.zk.ui.metainfo.ComponentDefinition Maven / Gradle / Ivy
/* ComponentDefinition.java
Purpose:
Description:
History:
Tue May 31 17:54:45 2005, Created by tomyeh
Copyright (C) 2005 Potix Corporation. All Rights Reserved.
{{IS_RIGHT
This program is distributed under LGPL Version 2.1 in the hope that
it will be useful, but WITHOUT ANY WARRANTY.
}}IS_RIGHT
*/
package org.zkoss.zk.ui.metainfo;
import java.net.URL;
import java.util.Collection;
import java.util.Map;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.util.Composer;
import org.zkoss.zk.xel.ExValue;
/**
* A component definition.
* Like class in Java, a {@link ComponentDefinition} defines the behavior
* of a component.
*
* The implementation need NOT to be thread safe, since the caller
* has to {@link #clone} first if accessed concurrently.
*
* @author tomyeh
*/
public interface ComponentDefinition extends Cloneable {
/** Returns the language definition, or null if it is a temporary definition
* belonging to a page.
*/
public LanguageDefinition getLanguageDefinition();
/** Returns name of this component definition (never null).
* It is unique in the same language, {@link LanguageDefinition},
* if it belongs to a language, i.e.,
* {@link #getLanguageDefinition} is not null.
*/
public String getName();
/** Returns the property name to which the text enclosed within
* the element (associated with this component definition) is assigned to.
*
*
Default: null (means to create a Label component as the child)
*
*
For example, if {@link #getTextAs} returns null, then
* a Label component is created as a child of comp
* with the "Hi Text" value in the following example:
*
*
<comp>
* Hi Text
*</comp>
*
* In other words, it is equivalent to
*
*
<comp>
* <label value="Hi Text"/>
*</comp>
*
* On the other hand, if {@link #getTextAs} returns a non-empty string,
* say, "content", then
* "Hi Text" is assigned to the content property of comp.
* In other words, it is equivalent to
*
*<comp content="Hi Text"/>
*</comp>
*
* It is also the same as
*
*
<comp>
* <attribute name="content"/>
* Hi Text
* </attribute>
*</comp>
*
* To enable it, you can declare text-as
in
* the component definition in lang.xml or lang-addon.xml:
*
*
<component>
* <component-name>html</component-name>
* <text-as>content</text-as>
*...
*
* Notice that it is valid to have XML fragment, including XML elements,
* within the element. For example,
<html>
<ul>
<li forEach="apple, orange">${each}</li>
</ul>
</html>
*
* If the component allows child components, it is better not to try
* XML fragment as the plain text. And then, it shall return true
* in {@link #isChildAllowedInTextAs}. Example, {@link org.zkoss.zul.A}.
*
* @see #isChildAllowedInTextAs
* @since 3.0.0
*/
public String getTextAs();
/** Returns if a child is allowed in the text-as area.
* It is meaningful only if {@link #getTextAs} is not null.
* If true, the text enclosed within the element is considered as
* text only if there is no other XML element.
*
For example, <div> in the following example won't
* be considered as text. Rather, a div component will be created.
*
<a>
* <div>...</div>
*</a>
*
* Default: false.
* @see #getTextAs
* @since 6.0.0
*/
public boolean isChildAllowedInTextAs();
/** Returns whether to preserve the blank text.
* If false, the blank text (a non-empty string consisting of whitespaces)
* are ignored.
* If true, they are converted to a label child.
*
Default: false.
* @since 3.5.0
*/
public boolean isBlankPreserved();
/** Returns whether this is a macro component.
* @see #getMacroURI
*/
public boolean isMacro();
/** Returns the macro URI, or null if not a macro.
*/
public String getMacroURI();
/** Returns whether this is an inline macro.
* If false, you have to examine {@link #isMacro} to see whether it
* is a regular macro.
*/
public boolean isInlineMacro();
/** Returns whether this is used for the native namespace.
*
* @since 3.0.0
* @see LanguageDefinition#getNativeDefinition
*/
public boolean isNative();
/** Returns whether this is a shadow element.
*
* @since 8.0.0
* @see LanguageDefinition#getShadowDefinition
*/
public boolean isShadowElement();
/** Returns the class (Class) or the class name (String) that
* implements the component.
*
*
If a string is returned, the real class may depend on
* which page a component will be created to.
* Reason: the zscript interpreter is associated with a page and
* it may define classes upon evaluating a page.
*/
public Object getImplementationClass();
/** Sets the class to implements the component.
*
*
Note: currently, classes specified in lang.xml or lang-addon.xml
* must be resolved when loading the files.
* However, classes specified in a page (by use of class or use attributes)
* might be resolved later because it might be defined by zscript.
*/
public void setImplementationClass(Class extends Component> cls);
/** Sets the class name to implements the component.
* Unlike {@link #setImplementationClass(Class)}, the class won't
* be resolved until {@link ComponentInfo#newInstance} or {@link #getImplementationClass}
* is used. In other words, the class can be provided later
* (thru, usually, zscript).
*/
public void setImplementationClass(String clsnm);
/** Resolves and returns the class that implements the component.
*
*
Unlike {@link #getImplementationClass},
* this method will resolve a class name (String) to a class (Class),
* if necessary.
* In addition, if the clsnm argument is specified,
* it is used instead of {@link #getImplementationClass}.
* In other words, it overrides the default class.
*
* @param clsnm [optional] If specified, clsnm is used instead of
* {@link #getImplementationClass}.
* In other words, it overrides the default class.
* @param page the page to check whether the class is defined
* in its interpreters. Ignored if null.
* This method will search the class loader of the current thread.
* If not found, it will search the interpreters of the specified
* page ({@link Page#getLoadedInterpreters}).
* Note: this method won't attach the component to the specified page.
* @exception ClassNotFoundException if the class not found
*/
public Class> resolveImplementationClass(Page page, String clsnm) throws ClassNotFoundException;
/** Returns whether a component belongs to this definition.
*
*
If {@link #resolveImplementationClass} failed to resolve,
* true is returned!
*/
public boolean isInstance(Component comp);
/** Creates an component of this definition.
*
*
Note: this method doesn't invoke {@link #applyProperties}.
* It is caller's job to apply these properties if necessary.
* Since the value of a property might depend on the component tree,
* it is better to assign the component with a proper parent
* before calling {@link #applyProperties}.
*
*
Similarly, this method doesn't attach the component to the
* specified page. Developers may or may not add it to a page or
* a parent.
*
*
An application developer can invoke
* {@link org.zkoss.zk.ui.sys.UiFactory#newComponent}
* instead of {@link #newInstance}, since a deployer might
* customize the way to create components by providing
* an implementation of {@link org.zkoss.zk.ui.sys.UiFactory}.
* In additions, it also invokes {@link #applyProperties}
* assigning page/parent.
*
*
On the other hand, this method is 'low-level'. It simply resolves
* the implementation class by use of {@link #resolveImplementationClass},
* and then uses it to create an instance.
*
* @param clsnm [optional] If specified, clsnm is used instead of
* {@link #getImplementationClass}.
* In other words, it overrides the default class.
* @param page the page that is used to resolve the implementation
* class. It is used only this definition is associated
* with a class name by {@link #setImplementationClass(String)},
* or clsnm is not null.
* Note: this method won't attach the component to the specified page.
* It can be null if {@link #getImplementationClass} returns a Class
* instance, and clsnm is null.
* @return the new component (never null)
*/
public Component newInstance(Page page, String clsnm);
/** Creates an component of this definition.
* Refer to {@link #newInstance(Page, String)}. They are the same
* except this method accepts the class directly,
* while {@link #newInstance(Page, String)} invokes
* {@link #resolveImplementationClass} to resolve the class first.
*
* @return the new component (never null)
* @since 3.0.2
*/
public Component newInstance(Class extends Component> cls);
/** Adds a mold.
*
* @param name the mold name.
* @param widgetClass the widget class (a.k.a., name).
* Ignored if null.
* @since 5.0.0 (the 2nd argument is the class name of the peer widget)
*/
public void addMold(String name, String widgetClass);
/** Returns the widget class associated with specified mold,
* or the default widget class ({@link #getWidgetClass}) if not available.
* The returned widget class includes the package name (JavaScript class).
* @param comp the component used to evaluate EL expression, if any,
* when retrieving the widget class. Ignored if null.
* @param moldName the mold name
* @since 5.0.4
*/
public String getWidgetClass(Component comp, String moldName);
/** Returns the default widget class, or null if not available.
* @param comp the component used to evaluate EL expression, if any,
* when retrieving the widget class. Ignored if null.
* @since 5.0.4
*/
public String getDefaultWidgetClass(Component comp);
/** Sets the default widget class.
* @param widgetClass the name of the widget class (JavaScript class),
* including the package name.
* @since 5.0.0
*/
public void setDefaultWidgetClass(String widgetClass);
/** Returns whether the specified mold exists.
*/
public boolean hasMold(String name);
/** Returns a readonly collection of the names of the mold.
*/
public Collection getMoldNames();
/** Adds a property initializer.
* It will initialize a component when created with is definition.
*
* @param name the member name. The component must have a valid setter
* for it.
* @param value the value. It might contain expressions (${}).
*/
public void addProperty(String name, String value);
/** Applies the properties defined in
* this definition to the specified component.
*
* Note: annotations are applied to the component when a component
* is created. So, this method doesn't and need not to copy them.
*
Also notice that, since 5.0.7, custom-attributes are applied automatically
* in the constructor of {@link org.zkoss.zk.ui.AbstractComponent#AbstractComponent}
* (by invoking {@link #applyAttributes},
* so they are always available no matter this method is called or not.
*/
public void applyProperties(Component comp);
/** Applies the custom attributes defined in this definition
* to the specified component.
*
It is called automatically in
* {@link org.zkoss.zk.ui.AbstractComponent#AbstractComponent}, so
* you rarely need to invoke this method.
* @since 5.0.7
*/
public void applyAttributes(Component comp);
/** Evaluates and retrieves properties to the specified map.
*
* @param propmap the map to store the retrieved properties.
* If null, a HashMap instance is created.
* (String name, Object value).
* @param owner the owner page; used if parent is null
* @param parent the parent
*/
public Map evalProperties(Map propmap, Page owner, Component parent);
/** Returns the annotation map defined in this definition, or null
* if no annotation is ever defined.
*/
public AnnotationMap getAnnotationMap();
/** Returns the apply attribute that is a list of
*{@link Composer} class
* names or EL expressions returning classes, class names or composer
* instances, or null if no apply attribute.
*
* @see #getParsedApply
* @since 3.6.0
*/
public String getApply();
/** Return the parsed expressions of the apply attribute.
* @see #getApply
* @since 3.6.0
*/
public ExValue[] getParsedApply();
/** Sets the apply attribute that is is a list of {@link Composer} class
* or EL expressions returning classes, class names or composer instances.
*
* @param apply the attribute this is a list of {@link Composer} class
* or EL expressions
* El expressions are allowed, but self means the parent, if available;
* or page, if no parent at all. (Note: the component is not created yet
* when the apply attribute is evaluated).
* @since 3.6.0
*/
public void setApply(String apply);
/** Returns the URL where this component definition is declared, or
* null if not available.
* @since 3.0.3
*/
public URL getDeclarationURL();
/** Clones this definition and assigns with the specified language
* definition and name.
*/
public ComponentDefinition clone(LanguageDefinition langdef, String name);
/** Clones this component definition.
* You rarely invoke this method directly. Rather, use
* {@link #clone(LanguageDefinition, String)}.
*
* Note: the caller usually has to change the component name,
* and then assign to a language definition ({@link LanguageDefinition})
* or a page definition ({@link PageDefinition}).
*
* @return the new component definition by cloning from this definition.
*/
public Object clone();
}