📄 databinder.java
字号:
/* DataBinder.java{{IS_NOTE Purpose: Description: History: Thu Feb 1 18:27:18 2007, Created by Henri}}IS_NOTECopyright (C) 2006 Potix Corporation. All Rights Reserved.{{IS_RIGHT}}IS_RIGHT*/package org.zkoss.zkplus.databind;import org.zkoss.zk.ui.Page;import org.zkoss.zk.ui.Path;import org.zkoss.zk.ui.Component;import org.zkoss.zk.ui.UiException;import org.zkoss.zk.ui.sys.ComponentCtrl;import org.zkoss.zk.ui.metainfo.Annotation; import org.zkoss.zk.ui.event.Event;import org.zkoss.zk.ui.event.Events;import org.zkoss.zk.ui.event.EventListener;import org.zkoss.zk.scripting.Namespace;import org.zkoss.zk.scripting.Interpreter;import org.zkoss.zk.scripting.HierachicalAware;import org.zkoss.zul.Row;import org.zkoss.zul.Listitem;import org.zkoss.zul.ListModel;import org.zkoss.util.ModificationException;import org.zkoss.lang.Objects;import org.zkoss.lang.Primitives;import org.zkoss.lang.reflect.Fields;import java.util.Map;import java.util.Set;import java.util.Date;import java.util.Map.Entry;import java.util.List;import java.util.HashSet;import java.util.Iterator;import java.util.ArrayList;import java.util.ListIterator;import java.util.HashMap;import java.util.HashSet;import java.util.Collection;import java.util.LinkedHashMap;import java.util.LinkedHashSet;/** * The DataBinder used for binding ZK UI component and the backend data bean. * * @author Henri Chen */public class DataBinder { public static final String NULLIFY = "none"; //used to nullify default configuration public static final String VARNAME = "zkplus.databind.VARNAME"; //_var name public static final String TEMPLATEMAP = "zkplus.databind.TEMPLATEMAP"; // template -> clone public static final String TEMPLATE = "zkplus.databind.TEMPLATE"; //clone -> template private static final String OWNER = "zkplus.databind.OWNER"; //the collection owner of the template component private static final String HASTEMPLATEOWNER = "zkplus.databind.HASTEMPLATEOWNER"; //whether has template owner (collection in collection) private static final Object NA = new Object(); private Map _compBindingMap = new LinkedHashMap(29); //(comp, Map(attr, Binding)) private Map _beans = new HashMap(29); //bean local to this DataBinder private Map _beanSameNodes = new HashMap(29); //(bean, Set(BindingNode)) bean same nodes, diff expression but actually hold the same bean private BindingNode _pathTree = new BindingNode("/", false, "/", false); //path dependency tree. private boolean _defaultConfig = true; //whether load default configuration from lang-addon.xml private boolean _init; //whether this databinder is initialized. private EventListener _listener = new LoadOnSaveEventListener(); //Databinder is init automatically when saveXXX or loadXxx is called protected Map _collectionItemMap = new HashMap(3); /** Binding bean to UI component. This is the same as * addBinding(Component comp, String attr, String expr, (List)null, (List)null, (String)null, (String)null). * @param comp The component to be associated. * @param attr The attribute of the component to be associated. * @param expr The expression to associate the data bean. */ public void addBinding(Component comp, String attr, String expr) { addBinding(comp, attr, expr, (List)null, (List)null, null, null); } /** Binding bean to UI component. * @param comp The component to be associated. * @param attr The attribute of the component to be associated. * @param expr The expression to associate the data bean. * @param loadWhenEvents The event list when to load data. * @param saveWhenEvent The event when to save data. * @param access In the view of UI component: "load" load only, * "both" load/save, "save" save only when doing * data binding. null means using the default access natural of the component. * e.g. Label.value is "load", but Textbox.value is "both". * @param converter The converter class used to convert classes between component * and the associated bean. null means using the default class conversion method. */ public void addBinding(Component comp, String attr, String expr, String[] loadWhenEvents, String saveWhenEvent, String access, String converter) { List loadEvents = null; if (loadWhenEvents != null && loadWhenEvents.length > 0) { loadEvents = new ArrayList(loadWhenEvents.length); for (int j = 0; j < loadWhenEvents.length; ++j) { loadEvents.add(loadWhenEvents[j]); } } addBinding(comp, attr, expr, loadEvents, saveWhenEvent, access, converter); } /** Binding bean to UI component. * @param comp The component to be associated. * @param attr The attribute of the component to be associated. * @param expr The expression to associate the data bean. * @param loadWhenEvents The event list when to load data. * @param saveWhenEvents The event when to save data. * @param access In the view of UI component: "load" load only, * "both" load/save, "save" save only when doing * data binding. null means using the default access natural of the component. * e.g. Label.value is "load", but Textbox.value is "both". * @param converter The converter class used to convert classes between component * and the associated bean. null means using the default class conversion method. * @since 3.0.0 */ public void addBinding(Component comp, String attr, String expr, String[] loadWhenEvents, String[] saveWhenEvents, String access, String converter) { List loadEvents = null; if (loadWhenEvents != null && loadWhenEvents.length > 0) { loadEvents = new ArrayList(loadWhenEvents.length); for (int j = 0; j < loadWhenEvents.length; ++j) { loadEvents.add(loadWhenEvents[j]); } } List saveEvents = null; if (saveWhenEvents != null && saveWhenEvents.length > 0) { saveEvents = new ArrayList(saveWhenEvents.length); for (int j = 0; j < saveWhenEvents.length; ++j) { saveEvents.add(saveWhenEvents[j]); } } addBinding(comp, attr, expr, loadEvents, saveEvents, access, converter); } /** Binding bean to UI component. * @param comp The component to be associated. * @param attr The attribute of the component to be associated. * @param expr The expression to associate the data bean. * @param loadWhenEvents The event list when to load data. * @param saveWhenEvent The event when to save data. * @param access In the view of UI component: "load" load only, * "both" load/save, "save" save only when doing * data binding. null means using the default access natural of the component. * e.g. Label.value is "load", but Textbox.value is "both". * @param converter The converter class used to convert classes between component * and the associated bean. null means using the default class conversion method. */ public void addBinding(Component comp, String attr, String expr, List loadWhenEvents, String saveWhenEvent, String access, String converter) { List saveEvents = new ArrayList(1); saveEvents.add(saveWhenEvent); addBinding(comp, attr, expr, loadWhenEvents, saveEvents, access, converter); } /** Binding bean to UI component. * @param comp The component to be associated. * @param attr The attribute of the component to be associated. * @param expr The expression to associate the data bean. * @param loadWhenEvents The event list when to load data. * @param saveWhenEvents The event list when to save data. * @param access In the view of UI component: "load" load only, * "both" load/save, "save" save only when doing * data binding. null means using the default access natural of the component. * e.g. Label.value is "load", but Textbox.value is "both". * @param converter The converter class used to convert classes between component * and the associated bean. null means using the default class conversion method. * @since 3.0.0 */ public void addBinding(Component comp, String attr, String expr, List loadWhenEvents, List saveWhenEvents, String access, String converter) { //Since 2.5, 20070726, Henri Chen: we accept "each" to replace "_var" in collection data binding //Before 2.4.1 //<a:bind _var="person"> //<listitem...> //After 2.5 //<listitem self="@{bind(each='person')}"...> //or <listitem self="@{each='person'}"...> if ("each".equals(attr)) { attr = "_var"; } if (isDefaultConfig()) { //use default binding configuration //handle default-bind defined in lang-addon.xml Object[] objs = loadPropertyAnnotation(comp, attr, "default-bind"); /* logically impossible to hold "expr" in default binding if (expr == null && objs[0] != null) { expr = (String) objs[0]; } */ if (loadWhenEvents == null && objs[1] != null) { loadWhenEvents = (List) objs[1]; } if (saveWhenEvents == null && objs[2] != null) { saveWhenEvents = (List) objs[2]; } if (access == null && objs[3] != null) { access = (String) objs[3]; } if (converter == null && objs[4] != null) { converter = (String) objs[4]; } } //nullify check boolean nullify = false; LinkedHashSet loadEvents = null; if (loadWhenEvents != null && loadWhenEvents.size() > 0) { loadEvents = new LinkedHashSet(loadWhenEvents.size()); for(final Iterator it = loadWhenEvents.iterator(); it.hasNext();) { final String event = (String) it.next(); if (NULLIFY.equals(event)) { loadEvents.clear(); nullify = true; } else { nullify = false; loadEvents.add(event); } } if (loadEvents.isEmpty()) { loadEvents = null; } } nullify = false; Set saveEvents = null; if (saveWhenEvents != null && saveWhenEvents.size() > 0) { saveEvents = new HashSet(saveWhenEvents.size()); for(final Iterator it = saveWhenEvents.iterator(); it.hasNext();) { final String event = (String) it.next(); if (NULLIFY.equals(event)) { saveEvents.clear(); nullify = true; } else { nullify = false; saveEvents.add(event); } } if (saveEvents.isEmpty()) { saveEvents = null; } } if (NULLIFY.equals(access)) { access = null; } if (NULLIFY.equals(converter)) { converter = null; } Map attrMap = (Map) _compBindingMap.get(comp); if (attrMap == null) { attrMap = new LinkedHashMap(3); _compBindingMap.put(comp, attrMap); } if (attrMap.containsKey(attr)) { //override final Binding binding = (Binding) attrMap.get(attr); binding.setExpression(expr); binding.setLoadWhenEvents(loadEvents); binding.setSaveWhenEvents(saveEvents); binding.setAccess(access); binding.setConverter(converter); } else { attrMap.put(attr, new Binding(this, comp, attr, expr, loadEvents, saveEvents, access, converter)); } } /** Remove the binding associated with the attribute of the component. * @param comp The component to be removed the data binding association. * @param attr The attribute of the component to be removed the data binding association. */ public void removeBinding(Component comp, String attr) { Map attrMap = (Map) _compBindingMap.get(comp); if (attrMap != null) { attrMap.remove(attr); } } /** Given component and attr, return the associated {@link Binding}. * @param comp the concerned component * @param attr the concerned attribute */ public Binding getBinding(Component comp, String attr) { if (isClone(comp)) { comp = (Component) comp.getAttribute(TEMPLATE); } Map attrMap = (Map) _compBindingMap.get(comp); return attrMap != null ? (Binding) attrMap.get(attr) : null; } /** Given component, return the associated list of {@link Binding}s. * @param comp the concerned component */ public Collection getBindings(Component comp) { if (isClone(comp)) { comp = (Component) comp.getAttribute(TEMPLATE); } Map attrMap = (Map)_compBindingMap.get(comp); return attrMap != null ? (Collection) attrMap.values() : null; } /** Whether this component associated with any bindings. */ public boolean existsBindings(Component comp) { if (isClone(comp)) { comp = (Component) comp.getAttribute(TEMPLATE); } return _compBindingMap.containsKey(comp); } /** Whether this component and attribute associated with a binding. */ public boolean existBinding(Component comp, String attr) { if (isClone(comp)) { comp = (Component) comp.getAttribute(TEMPLATE); } if (_compBindingMap.containsKey(comp)) { Map attrMap = (Map) _compBindingMap.get(comp); return attrMap.containsKey(attr); } return false; } /** Whether use the default binding configuration. */ public boolean isDefaultConfig(){ return _defaultConfig; } /** Whether use the default binding configuration. */ public void setDefaultConfig(boolean b) { _defaultConfig = b; } /** Bind a real bean object to the specified beanid. You might not need to call this method because this * DataBinder would look up the variable via the {@link org.zkoss.zk.ui.Component#getVariable} method * if it cannot find the specified bean via the given beanid. * * @param beanid The bean id used in data binding. * @param bean The real bean object to be associated with the bean id. */ public void bindBean(String beanid, Object bean) { _beans.put(beanid, bean); } /** Load value from the data bean property to a specified attribute of the UI component. * @param comp the UI component to be loaded value. * @param attr the UI component attribute to be loaded value. */ public void loadAttribute(Component comp, String attr) { if (isTemplate(comp) || comp.getPage() == null) { return; //skip detached component } init(); Binding binding = getBinding(comp, attr); if (binding != null) { binding.loadAttribute(comp); } } /** Save value from a specified attribute of the UI component to a data bean property. * @param comp the UI component used to save value into backend data bean. * @param attr the UI component attribute used to save value into backend data bean. */ public void saveAttribute(Component comp, String attr) { if (isTemplate(comp) || comp.getPage() == null) { return; //skip detached component } init(); Binding binding = getBinding(comp, attr); if (binding != null) { binding.saveAttribute(comp); } } /** Load values from the data bean properties to all attributes of a specified UI component. * @param comp the UI component to be loaded value. */ public void loadComponent(Component comp) { if (isTemplate(comp) || comp.getPage() == null) { return; //skip detached component } init(); Collection bindings = getBindings(comp); if (bindings != null) { loadAttrs(comp, bindings); } //load kids of this component for(final Iterator it = comp.getChildren().iterator(); it.hasNext();) { loadComponent((Component) it.next()); //recursive } } /** Save values from all attributes of a specified UI component to data bean properties. * @param comp the UI component used to save value into backend data bean. */ public void saveComponent(Component comp) { if (isTemplate(comp) || comp.getPage() == null) { return; //skip detached component } init(); Collection bindings = getBindings(comp); if (bindings != null) { saveAttrs(comp, bindings);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -