org.zkoss.zk.ui.metainfo.InitiatorInfo Maven / Gradle / Ivy
/* InitiatorInfo.java
Purpose:
Description:
History:
Fri Mar 31 14:24:37 2006, Created by tomyeh
Copyright (C) 2006 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.Map;
import org.zkoss.lang.Classes;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.UiException;
import org.zkoss.zk.ui.util.Initiator;
import org.zkoss.zk.xel.ExValue;
import org.zkoss.zk.xel.Evaluator;
/**
* The init directive in the ZUML page.
*
* Note: we resolve the class by using Classes.forNameByThread.
* In other words, it doesn't support the class defined in zscript.
* Why not? Since there is no way to run zscript before the init directive
* (and better performance).
*
* Note: it is not serializable.
*
* @author tomyeh
*/
public class InitiatorInfo extends ArgumentInfo { //directive
// private static final Logger log = LoggerFactory.getLogger(InitiatorInfo.class);
/** A class, an ExValue or an Initiator. */
private Object _init;
/** Constructs with a class, and {@link #newInitiator} will
* instantiate a new instance.
* @param args the map of arguments. Ignored if null.
* Notice that, once assigned, the map belongs to this object, and the caller
* shall not access it again
* @since 3.6.2
*/
public InitiatorInfo(Class extends Initiator> cls, Map args) {
super(args);
checkClass(cls);
_init = cls;
}
/** Constructs with a class name and {@link #newInitiator} will
* instantiate a new instance.
*
* @param clsnm the class name; it could be an EL expression.
* @since 3.6.2
*/
public InitiatorInfo(String clsnm, Map args)
throws ClassNotFoundException {
super(args);
if (clsnm == null || clsnm.length() == 0)
throw new IllegalArgumentException();
if (clsnm.indexOf("${") < 0) {
if (clsnm.indexOf('.') >= 0) { //resolve it now
try {
final Class cls = Classes.forNameByThread(clsnm);
checkClass(cls);
_init = cls;
} catch (ClassNotFoundException ex) {
throw new ClassNotFoundException("Class not found: "+clsnm, ex);
}
} else { //it might depend on
_init = clsnm;
}
} else {
_init = new ExValue(clsnm, String.class);
}
}
/** Constructs with an initiator that will be reuse each time
* {@link #newInitiator} is called.
* @since 3.6.2
*/
public InitiatorInfo(Initiator init, Map args) {
super(args);
if (init == null)
throw new IllegalArgumentException("null");
_init = init;
}
private static void checkClass(Class> cls) {
if (!Initiator.class.isAssignableFrom(cls))
throw new UiException(Initiator.class+" must be implemented: "+cls);
}
/** Creates and returns the initiator, or null if no initiator is resolved.
* Notice that {@link Initiator#doInit} was called before returned.
*/
public Initiator newInitiator(PageDefinition pgdef, Page page)
throws Exception {
return newInitiator(pgdef.getEvaluator(), page);
}
/** Creates and returns the initiator, or null if no initiator is resolved.
* Notice that {@link Initiator#doInit} was called before returned.
* @since 3.6.2
*/
public Initiator newInitiator(Evaluator eval, Page page)
throws Exception {
if (_init instanceof Initiator)
return doInit((Initiator)_init, eval, page);
String clsnm = null;
if (_init instanceof ExValue) {
clsnm = (String)((ExValue)_init).getValue(eval, page);
if (clsnm == null || clsnm.length() == 0) {
// if (log.isDebugEnabled()) log.debug("Ignore "+_init+" due to empty");
return null; //ignore it!!
}
} else if (_init instanceof String) {
clsnm = (String)_init;
}
final Class> cls;
if (clsnm != null) {
try {
cls = page != null ?
page.resolveClass(clsnm): Classes.forNameByThread(clsnm);
checkClass(cls);
} catch (ClassNotFoundException ex) {
throw new ClassNotFoundException("Class not found: "+clsnm+" ("+_init+")", ex);
}
if (clsnm.equals(_init))
_init = cls; //cache it for better performance
} else {
cls = (Class>)_init;
}
return doInit((Initiator)cls.newInstance(), eval, page);
}
private Initiator doInit(Initiator init, Evaluator eval, Page page)
throws Exception {
final Map args = resolveArguments(eval, page);
init.doInit(page, args);
return init;
}
}