📄 databinder.java
字号:
/* DataBinder.java{{IS_NOTE Purpose: Description: History: Wed Nov 15 14:24:25 2006, Created by Henri Chen.}}IS_NOTECopyright (C) 2006 Potix Corporation. All Rights Reserved.{{IS_RIGHT}}IS_RIGHT*/package org.zkoss.zkplus.databind;import org.zkoss.zk.ui.Path;import org.zkoss.zk.ui.Component;import org.zkoss.zk.ui.UiException;import org.zkoss.zk.ui.WrongValueException;import org.zkoss.zk.ui.event.Event;import org.zkoss.zk.ui.event.Express;import org.zkoss.zk.ui.event.EventListener;import org.zkoss.zk.ui.sys.ComponentCtrl;import org.zkoss.zk.ui.metainfo.Annotation; import org.zkoss.zul.impl.InputElement;import org.zkoss.zul.Listbox;import org.zkoss.zul.Listitem;import org.zkoss.zul.ListModel;import org.zkoss.zul.Checkbox;import org.zkoss.zul.Slider;import org.zkoss.zul.Calendar;import org.zkoss.zul.ListitemRenderer;import org.zkoss.util.ModificationException;import org.zkoss.lang.Classes;import org.zkoss.lang.Objects;import org.zkoss.lang.reflect.Fields;import java.util.Map;import java.util.Set;import java.util.List;import java.util.HashSet;import java.util.HashMap;import java.util.Iterator;import java.util.ArrayList;import java.util.Collection;import java.util.LinkedHashSet;import java.util.LinkedHashMap;import java.lang.reflect.Method;/** * The DataBinder used for binding ZK UI component and the backend data bean. * * @author Henri Chen */public class DataBinder { private Map _compBindingMap = new LinkedHashMap(29); //(comp, Map(attr, Binding)) private Map _beanBindingMap = new HashMap(29); //(beanid, Set(Binding)) private Map _sameBeanidMap = new HashMap(5); //(bean, Set(beanid)) and (beanid, Set(beanid)); private Map _cloneMap = new HashMap(255); //(cloned item target, Map(template, clone)) private Map _beans = new HashMap(5); //(beanid, bean)// private Node _dependency = new Node(); //(beanid+prop) dependency tree. private boolean _init; //whether this databinder is initialized. //Databinder is init automatically when saveXXX or loadXxx is called private static Map _converterMap = new HashMap(5); //(converterClassName, converter) private static final String VAR = "org.koss.zkplus.databind.VAR"; //the template variable name private static final String INDEXITEM = "org.koss.zkplus.databind.INDEXITEM"; //the listitem with index private static final String TEMPLATE = "org.koss.zkplus.databind.TEMPLATE"; //the template private static final String ISTEMPLATE = "org.koss.zkplus.databind.ISTEMPLATE"; //whether a template private static final Object NA = new Object(); /** Binding bean to UI component. This is the same as addBinding(comp, attr, value, null, null). * @param comp The component to be associated. * @param attr The attribute of the component to be associated. * @param value The expression to associate the data bean. */ public void addBinding(Component comp, String attr, String value) { addBinding(comp, attr, value, null, 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 value 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 value, String[] loadWhenEvents, String saveWhenEvent, String access, String converter) { //handle default-bind defined in lang-addon.xml Object[] objs = loadPropertyAnnotation(comp, attr, "default-bind"); /* logically impossible to hold "value" in default binding if (value == null) { value = (String) objs[0]; } if (loadWhenEvents == null) { loadWhenEvents = (String[]) objs[1]; } */ if (saveWhenEvent == null) { saveWhenEvent = (String) objs[2]; } if (access == null) { access = (String) objs[3]; } if (converter == null) { converter = (String) objs[4]; } Map attrMap = (Map) _compBindingMap.get(comp); if (attrMap == null) { attrMap = new LinkedHashMap(3); _compBindingMap.put(comp, attrMap); } if (attrMap.containsKey(attr)) { //override and merge final Binding binding = (Binding) attrMap.get(attr); binding.setValue(value); binding.addLoadWhenEvents(loadWhenEvents); binding.setSaveWhenEvent(saveWhenEvent); binding.setAccess(access); binding.setConverter(converter); } else { if (objs[1] != null) { //default-bind loadWhenEvents = mergeStringArray((String[])objs[1], loadWhenEvents); } attrMap.put(attr, new Binding(comp, attr, value, loadWhenEvents, saveWhenEvent, 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); } } //[0] value, [1] loadWhenEvents, [2] saveWhenEvent, [3] access, [4] converter protected Object[] loadPropertyAnnotation(Component comp, String propName, String bindName) { ComponentCtrl compCtrl = (ComponentCtrl) comp; Annotation ann = compCtrl.getAnnotation(propName, bindName); if (ann != null) { final Map attrs = ann.getAttributes(); //(tag, tagExpr) String[] loadWhenEvents = null; String saveWhenEvent = null; String access = null; String converter = null; String expr = null; for (final Iterator it = attrs.entrySet().iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry) it.next(); String tag = (String) entry.getKey(); String tagExpr = (String) entry.getValue(); if ("save-when".equals(tag)) { saveWhenEvent = tagExpr; } else if ("access".equals(tag)) { access = tagExpr; } else if ("converter".equals(tag)) { converter = tagExpr; } else if ("load-when".equals(tag)) { loadWhenEvents = parseExpression(tagExpr, ","); } else if ("value".equals(tag)) { expr = tagExpr; } } return new Object[] {expr, loadWhenEvents, saveWhenEvent, access, converter}; } return new Object[5]; } /** 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) { //skip detached component if (comp.getPage() != null) { init(); final Component template = getTemplateComponent(comp); Map attrMap = (Map) (template != null ? _compBindingMap.get(template) : _compBindingMap.get(comp)); if (attrMap != null) { Binding binding = (Binding) attrMap.get(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) { //skip detached component if (comp.getPage() != null) { init(); final Component template = getTemplateComponent(comp); Map attrMap = (Map) (template != null ? _compBindingMap.get(template) : _compBindingMap.get(comp)); if (attrMap != null) { Binding binding = (Binding) attrMap.get(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) { //skip detached component if (comp.getPage() != null) { init(); final Component template = getTemplateComponent(comp); Map attrMap = (Map) (template != null ? _compBindingMap.get(template) : _compBindingMap.get(comp)); if (attrMap != null) { loadAttrs(comp, attrMap.values()); } //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) { //skip detached component if (comp.getPage() != null) { init(); final Component template = getTemplateComponent(comp); Map attrMap = (Map) (template != null ? _compBindingMap.get(template) : _compBindingMap.get(comp)); if (attrMap != null) { saveAttrs(comp, attrMap.values()); } //save kids of this component for(final Iterator it = comp.getChildren().iterator(); it.hasNext();) { saveComponent((Component) it.next()); //recursive } } } /** Load all value from data beans to UI components. */ public void loadAll() { init(); for (final Iterator it = _compBindingMap.keySet().iterator(); it.hasNext(); ) { final Component comp = (Component) it.next(); if (isTemplate(comp)) { //do via model and renderer, so skip continue; } loadComponent(comp); } } /** Save all values from UI components to beans. */ public void saveAll() { init(); for (final Iterator it = _compBindingMap.keySet().iterator(); it.hasNext(); ) { final Component comp = (Component) it.next(); if (isTemplate(comp)) { //do via model and renderer, so skip continue; } saveComponent(comp); } } private void loadAttrs(Component comp, Collection attrs) { for(final Iterator it = attrs.iterator(); it.hasNext();) { Binding binding = (Binding) it.next(); binding.loadAttribute(comp); } } private void saveAttrs(Component comp, Collection attrs) { for(final Iterator it = attrs.iterator(); it.hasNext();) { Binding binding = (Binding) it.next(); binding.saveAttribute(comp); } } //late init protected void init() { if (!_init) { _init = true; //process template data binding List detachs = new ArrayList(_compBindingMap.size()); for(final Iterator it = _compBindingMap.keySet().iterator(); it.hasNext();) { final Component comp = (Component) it.next(); final Map attrMap = (Map) _compBindingMap.get(comp); //_var special case; meaning a template component if (attrMap.containsKey("_var")) { comp.setAttribute(VAR, ((Binding)attrMap.get("_var")).getBeanid()); setupTemplate(comp, Boolean.TRUE); setupRenderer(comp); detachs.add(comp); } //register event handler registerEvents(comp, attrMap.values()); //register beanid -> Binding(s) map registerBeanidBinding(comp, attrMap.values()); } for(final Iterator it = detachs.iterator(); it.hasNext(); ) { final Component comp = (Component) it.next(); comp.detach(); } } } private void registerEvents(Component comp, Collection attrs) { for(final Iterator it = attrs.iterator(); it.hasNext();) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -