org.zkoss.zk.ui.metainfo.PageDefinition Maven / Gradle / Ivy
/* PageDefinition.java
Purpose:
Description:
History:
Tue May 31 11:27:07 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.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.zkoss.html.HTMLs;
import org.zkoss.lang.ClassResolver;
import org.zkoss.lang.ImportedClassResolver;
import org.zkoss.util.resource.Locator;
import org.zkoss.xel.ExpressionFactory;
import org.zkoss.xel.Expressions;
import org.zkoss.xel.Function;
import org.zkoss.xel.FunctionMapper;
import org.zkoss.xel.VariableResolver;
import org.zkoss.xel.taglib.FunctionDefinition;
import org.zkoss.xel.taglib.Taglib;
import org.zkoss.xel.taglib.Taglibs;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.UiException;
import org.zkoss.zk.ui.sys.PageConfig;
import org.zkoss.zk.ui.sys.PageCtrl;
import org.zkoss.zk.ui.util.Initiator;
import org.zkoss.zk.xel.Evaluator;
import org.zkoss.zk.xel.EvaluatorRef;
import org.zkoss.zk.xel.ExValue;
import org.zkoss.zk.xel.impl.SimpleEvaluator;
/**
* A page definition.
* It represents a ZUL page.
*
* Note: it is not thread-safe.
*
*
Note: it is not serializable.
*
* @author tomyeh
* @see ComponentDefinition
*/
public class PageDefinition implements NodeInfo {
/** A list of a children ({@link NodeInfo}). */
private final List _children = new LinkedList();
private final LanguageDefinition _langdef;
private final Locator _locator;
private String _id, _title, _style, _viewport;
/** The request path. */
private String _path = "";
/** The zscript language. */
private String _zslang = "Java";
private List _taglibs;
/** A map of imported classes for expression, Map. */
private Map> _expimps;
/** A list of XEL methods, List. */
private List _xelfuncs;
/** The evaluator. */
private Evaluator _eval;
/** The evaluator reference. */
private EvaluatorRef _evalr;
/** The function mapper. */
private FunctionMapper _mapper;
/* List(InitiatorInfo). */
private List _initdefs;
/** List(VariableResolverInfo). */
private List _resolvdefs;
/** List(FunctionMapperInfo mapper). */
private List _mapperdefs;
/** List(HeaderInfo). They are generated before ZK default headers, such as meta. */
private List _hdBfrDefs;
/** List(HeaderInfo). They are generated after ZK default headers. */
private List _hdAftDefs;
/** List(ResponseHeaderInfo). */
private List _hdResDefs;
/** List(ForwardInfo). */
private List _forwdefs;
/** Map(String name, ExValue value). */
private Map _rootAttrs;
private ExValue _contentType, _docType, _firstLine, _wgtcls;
/** The class of the expression factory (ExpressionFactory).*/
private Class extends ExpressionFactory> _expfcls;
/** The class resolver. */
private final ImportedClassResolver _clsresolver = new ImportedClassResolver();
private final ComponentDefinitionMap _compdefs;
private Boolean _cacheable;
private Boolean _autoTimeout;
private boolean _complete;
//ZK-2623: page scope template
private Map _templatesInfo;
/** Constructor.
* @param langdef the default language which is used if no namespace
* is specified. Note: a page might have components from different
* languages.
*/
public PageDefinition(LanguageDefinition langdef, Locator locator) {
if (langdef == null)
throw new IllegalArgumentException("null langdef");
if (locator == null)
throw new IllegalArgumentException("null locator");
_langdef = langdef;
_locator = locator;
_compdefs = new ComponentDefinitionMap(_langdef.getComponentDefinitionMap().isCaseInsensitive());
}
/** Constructor.
* @param langdef the default language which is used if no namespace
* is specified. Note: a page might have components from different
* languages.
* @param id the identifier. See {@link #setId}.
* @param title the title. See {@link #setTitle}.
* @param style the CSS style. See {@link #setStyle}.
*/
public PageDefinition(LanguageDefinition langdef, String id, String title, String style, Locator locator) {
this(langdef, locator);
setId(id);
setTitle(title);
setStyle(style);
}
/** Returns the language definition that this page is default to be.
*/
public LanguageDefinition getLanguageDefinition() {
return _langdef;
}
/** Returns the locator associated with this page definition.
*/
public Locator getLocator() {
return _locator;
}
/** Returns the default scripting language which is assumed when
* a zscript element doesn't specify any language.
*
* Default: Java.
*/
public String getZScriptLanguage() {
return _zslang;
}
/** Sets the default scripting language which is assumed when
* a zscript element doesn't specify any language.
*
* @param zslang the default scripting language.
*/
public void setZScriptLanguage(String zslang) {
if (zslang == null || zslang.length() == 0)
throw new IllegalArgumentException("null or empty");
_zslang = zslang;
}
/** Returns the identifier that will be assigned to pages created from
* this definition, or null if the identifier shall be generated automatically.
*
Note: the returned value might contain EL expressions.
*/
public String getId() {
return _id;
}
/** Sets the identifier that will be assigned to pages created from this
* definition.
* @param id the identifier. It might contain EL expressions.
* If null or empty (null is assumed), page's ID is generated automatically.
* If not empty, ID (after evaluated) must be unique in the same request.
*/
public void setId(String id) {
_id = id != null && id.length() > 0 ? id : null;
}
/** Returns the title that will be assigned to pages created from
* this definition, or null if no title is assigned at the beginning.
*
Note: the returned value might contain EL expressions.
*/
public String getTitle() {
return _title;
}
/** Sets the title that will be assigned to pages created from
* this definition, or null if no title is assigned at the beginning.
* @param title the title. If empty, null is assumed.
*/
public void setTitle(String title) {
_title = title != null && title.length() > 0 ? title : null;
}
/** Returns the CSS style that will be assigned to pages created from
* this definition, or null if no style is assigned at the beginning.
*
Note: the returned value might contain EL expressions.
*/
public String getStyle() {
return _style;
}
/** Sets the CSS style that will be assigned to pages created from
* this definition, or null if no style is assigned at the beginning.
* @param style the CSS style. If empty, null is assumed.
*/
public void setStyle(String style) {
_style = style != null && style.length() > 0 ? style : null;
}
/** Returns the viewport that will be assigned to pages created from
* this definition, or "auto" if no viewport is assigned at the beginning.
*
Note: the returned value might contain EL expressions.
* @since 6.5.0
*/
public String getViewport() {
return _viewport;
}
/** Sets the viewport that will be assigned to pages created from
* this definition, or "auto" if no viewport is assigned at the beginning.
* @param viewport the viewport setting. If empty, "auto" is assumed.
* @since 6.5.0
*/
public void setViewport(String viewport) {
_viewport = viewport != null && viewport.length() > 0 ? viewport : "auto";
}
/** Returns the widget class of the given page, or null if the default is used.
* @since 5.0.5
*/
public String getWidgetClass(Page page) {
return _wgtcls != null ? (String) _wgtcls.getValue(_evalr, page) : null;
}
/** Sets the widget class of the page.
* @param wgtcls the widget class. It may contain EL expressions.
* If null or empty, the default widget class is assumed.
* @since 5.0.5
*/
public void setWidgetClass(String wgtcls) {
_wgtcls = wgtcls != null && wgtcls.length() > 0 ? new ExValue(wgtcls, String.class) : null;
}
/** Returns the request path of this page definition, or ""
* if not available.
*
It is the same as the servlet path
* (javax.servlet.http.HttpServletRequest's getServletPath), if ZK is running
* at a servlet container.
*/
public String getRequestPath() {
return _path;
}
/** Sets the request path of this page definition.
*/
public void setRequestPath(String path) {
_path = path != null ? path : "";
}
/** Imports the specified directives from the specified page definition.
*
* @param pgdef the page definition to import from.
* @param directives an array of the directive names to import.
* If null, {"init", "component"} is assumed, i.e., only the init
* directives and component definitions are imported.
* Importable directives include "component", "init", "meta",
* "taglib", "variable-resolver", and "xel-method".
* If "*", all of them are imported.
* Note: "meta" implies "link".
* @since 3.0.2
*/
public void imports(PageDefinition pgdef, String[] directives) {
if (directives == null || contains(directives, "import"))
_clsresolver.addAll(pgdef._clsresolver);
if (pgdef._initdefs != null && (directives == null || contains(directives, "init")))
for (InitiatorInfo ii : pgdef._initdefs)
addInitiatorInfo(ii);
if (directives == null || contains(directives, "component")) {
for (Iterator it = pgdef._compdefs.getNames().iterator(); it.hasNext();)
addComponentDefinition(pgdef._compdefs.get((String) it.next()));
}
if (pgdef._taglibs != null && directives != null && contains(directives, "taglib"))
for (Taglib tl : pgdef._taglibs)
addTaglib(tl);
if (pgdef._resolvdefs != null && directives != null && contains(directives, "variable-resolver")) {
for (VariableResolverInfo vri : pgdef._resolvdefs)
addVariableResolverInfo(vri);
}
if (pgdef._mapperdefs != null && directives != null && contains(directives, "function-mapper")) {
for (FunctionMapperInfo fmi : pgdef._mapperdefs)
addFunctionMapperInfo(fmi);
}
if (pgdef._xelfuncs != null && directives != null && contains(directives, "xel-method"))
for (FunctionDefinition xfi : pgdef._xelfuncs)
addXelMethod(xfi.prefix, xfi.name, xfi.function);
if (pgdef._hdBfrDefs != null && directives != null && contains(directives, "meta")) {
for (HeaderInfo hi : pgdef._hdBfrDefs)
addHeaderInfo(hi, true);
}
if (pgdef._hdAftDefs != null && directives != null && contains(directives, "meta")) {
for (HeaderInfo hi : pgdef._hdAftDefs)
addHeaderInfo(hi, false);
}
if (pgdef._hdResDefs != null && directives != null && contains(directives, "header")) {
for (ResponseHeaderInfo rhi : pgdef._hdResDefs)
addResponseHeaderInfo(rhi);
}
}
/** Imports the init directives and component definitions from
* the specified page definition.
*
*
It is the same as imports(pgdef, null).
*
* @since #imports(PageDefinition, String[])
*/
public void imports(PageDefinition pgdef) {
imports(pgdef, null);
}
private static boolean contains(String[] dirs, String dir) {
for (int j = dirs.length; --j >= 0;)
if ("*".equals(dirs[j]) || dir.equalsIgnoreCase(dirs[j]))
return true;
return false;
}
/** Adds an imported class
* Like Java, it is used to import a class or a package of classes, so
* that it simplifies the use of the apply attribute, the init directive
* and others.
*
* @param clsptn the class's fully-qualified name, e.g., com.foo.FooComposer
,
* a wildcard representing all classes of the give package, e.g., com.foo.*
.
* @since 6.0.0
*/
public void addImportedClass(String clsptn) throws ClassNotFoundException {
_clsresolver.addImportedClass(clsptn);
}
/** Returns a readonly list of the imported class names.
* @since 6.0.0
*/
public List getImportedClasses() {
return _clsresolver.getImportedClasses();
}
/** Returns the class resolver represented by {@link #getImportedClasses}.
* @since 6.0.0
*/
public ClassResolver getImportedClassResolver() {
return _clsresolver;
}
/** Adds a definition of {@link Initiator}. */
public void addInitiatorInfo(InitiatorInfo init) {
if (init == null)
throw new IllegalArgumentException("null");
if (_initdefs == null)
_initdefs = new LinkedList();
_initdefs.add(init);
}
/** Returns a list of all {@link Initiator} and invokes
* its {@link Initiator#doInit} before returning.
* It never returns null.
*/
public List doInit(Page page) {
if (_initdefs == null)
return Collections.emptyList();
final List inits = new LinkedList();
try {
for (InitiatorInfo ii : _initdefs) {
final Initiator init = ii.newInitiator(getEvaluator(), page);
if (init != null)
inits.add(init);
}
} catch (Throwable ex) {
throw UiException.Aide.wrap(ex);
}
return inits;
}
/** Adds a definition of {@link VariableResolver}.
*/
public void addVariableResolverInfo(VariableResolverInfo resolver) {
if (resolver == null)
throw new IllegalArgumentException("null");
if (_resolvdefs == null)
_resolvdefs = new LinkedList();
_resolvdefs.add(resolver);
}
/** Adds a definition of {@link FunctionMapper}.
* @since 3.5.0
*/
public void addFunctionMapperInfo(FunctionMapperInfo mapper) {
if (mapper == null)
throw new IllegalArgumentException("null");
if (_mapperdefs == null)
_mapperdefs = new LinkedList();
_mapperdefs.add(mapper);
}
/** Adds a XEL method.
*
* @param prefix the prefix of the method name
* @param name the method name. The final name is "prefix:name"
* @param func the function.
* @since 3.0.0
*/
public void addXelMethod(String prefix, String name, Function func) {
checkXelModifiable();
if (name == null || prefix == null || func == null)
throw new IllegalArgumentException();
if (_xelfuncs == null)
_xelfuncs = new LinkedList();
_xelfuncs.add(new FunctionDefinition(prefix, name, func));
}
/** Adds a response header.
* @since 5.0.2
*/
public void addResponseHeaderInfo(ResponseHeaderInfo header) {
if (header == null)
throw new IllegalArgumentException();
if (_hdResDefs == null)
_hdResDefs = new LinkedList();
_hdResDefs.add(header);
}
/** Returns a map of response headers (never null).
* The value of each entry is a two-element object array. The
* first element of the array is the value which is an instance of {@link java.util.Date}
* or {@link String} (and never null).
* The second element indicates whether to add (rather than set)
* header. It is an instance of Boolean (and never null).
*/
public Collection