📄 databinder.java
字号:
} } if (val != null) { if (refChanged && !binding.isLoadable() && binding.isSavable()) { //the sameNodes should change accordingly. registerBeanNode(val, currentNode); } //20070309, Henri Chen: Tricky. //When loading page, listbox.selectedItem == null. The _var Listitem will not be able to //associate with the selectedItem (no way to associate via null bean). When end user then //select one Listitem, we have to force such association. if (rawval instanceof Component) { Binding varbinding = getBinding((Component) rawval, "_var"); if (varbinding != null) { registerBeanNode(val, currentNode); getBeanAndRegisterBeanSameNodes((Component) rawval, varbinding.getExpression()); } } } //TODO:Henri Chen: Is it possible to make the loadOnSave event to be called once only for a //setXxx. So avoid load a node several times? //register "onLoadSave" listener to this component if have not done so. if (!comp.isListenerAvailable("onLoadOnSave", true)) { comp.addEventListener("onLoadOnSave", _listener); } Object[] loadOnSaveInfo = new Object[] {this, currentNode, binding, (refChanged ? val : bean), Boolean.valueOf(refChanged), nodes, comp}; if (loadOnSaveInfos != null) { loadOnSaveInfos.add(loadOnSaveInfo); } else { //do loadOnSave immediately Events.postEvent(new Event("onLoadOnSave", comp, loadOnSaveInfo)); } } private void registerBeanNode(Object bean, BindingNode node) { if (isPrimitive(bean)) { return; } final Set nodeSameNodes = node.getSameNodes(); final Set binderSameNodes = getBeanSameNodes(bean); //variable node(with _var) is special. Assume selectedItem then _var. //e.g. a Listitem but no selectedItem yet if (node.isVar() && binderSameNodes == null) { return; } if (!nodeSameNodes.contains(bean)) { //remove the old bean for(final Iterator it = nodeSameNodes.iterator(); it.hasNext();) { final Object elm = it.next(); if (!(elm instanceof BindingNode)) { it.remove(); removeBeanSameNodes(elm); //remove the binderSameNodes of the original bean break; } } //add the new bean if not null if (bean != null) { nodeSameNodes.add(bean); } } if (binderSameNodes == null) { if (bean != null) { setBeanSameNodes(bean, nodeSameNodes); } } else { node.mergeAndSetSameNodes(binderSameNodes); } } private boolean isPrimitive(Object bean) { //String is deemed as primitive and null is not primitive return (bean instanceof String) || (bean != null && Primitives.toPrimitive(bean.getClass()) != null) || (bean instanceof Date) || (bean instanceof Number); } /** Sets the variable to all loaded interpreters, if it was defined in * the interpreter. * * @return whether it is set to the interpreter */ private boolean setZScriptVariable(Component comp, String beanid, Object val) { //for all loaded interperter, assign val to beanid boolean found = false; final Namespace ns = comp.getNamespace(); for(final Iterator it = comp.getPage().getLoadedInterpreters().iterator(); it.hasNext();) { final Interpreter ip = (Interpreter) it.next(); if (ip instanceof HierachicalAware) { final HierachicalAware ha = (HierachicalAware)ip; if (ha.containsVariable(ns, beanid)) { ha.setVariable(ns, beanid, val); found = true; } } else if (ip.containsVariable(beanid)) { ip.setVariable(beanid, val); found = true; } } return found; } /*package*/ Object lookupBean(Component comp, String beanid) { //fetch the bean object Object bean = null; if (isClone(comp)) { bean = myLookupBean1(comp, beanid); if (bean != NA) { return bean; } } if (existsBean(beanid)) { bean = getBean(beanid); } else if (beanid.startsWith("/")) { //a absolute component Path: // or / bean = Path.getComponent(beanid); } else if (beanid.startsWith(".")) { //a relative component Path: ./ or ../ bean = Path.getComponent(comp.getSpaceOwner(), beanid); } else { final Page page = comp.getPage(); if (page != null) bean = page.getZScriptVariable(comp.getNamespace(), beanid); if (bean == null) bean = comp.getVariable(beanid, false); } return bean; } //given a beanid and a template, return the associated bean //return NA if cannot find it private Object myLookupBean1(Component comp, String beanid) { Map templatemap = (Map) comp.getAttribute(TEMPLATEMAP); return myLookupBean2(beanid, templatemap); } private Object myLookupBean2(String beanid, Map templatemap) { if (templatemap != null) { if (templatemap.containsKey(beanid)) { //got it return templatemap.get(beanid); } else { //search up the parent templatemap templatemap = (Map) templatemap.get(TEMPLATEMAP); return myLookupBean2(beanid, templatemap); //recursive } } return NA; //not available } //given a clone and a template, return the associated clone of that template. /*package*/ static Component lookupClone(Component srcClone, Component srcTemplate) { if (isTemplate(srcTemplate)) { Map templatemap = (Map) srcClone.getAttribute(TEMPLATEMAP); return myLookupClone(srcTemplate, templatemap); } return null; } private static Component myLookupClone(Component srcTemplate, Map templatemap) { if (templatemap != null) { if (templatemap.containsKey(srcTemplate)) { //got it return (Component) templatemap.get(srcTemplate); } else { //search up the parent templatemap templatemap = (Map) templatemap.get(TEMPLATEMAP); return myLookupClone(srcTemplate, templatemap); //recursive } } return null; } // Given parentNode, path, and level, return associate same kid nodes of parent // a1.b.c -> a2.b.c, a3.b.c, ... private Set getAssociateSameNodes(BindingNode parentNode, String path, int level) { final List nodeids = DataBinder.parseExpression(path, "."); final int sz = nodeids.size(); final List subids = nodeids.subList(sz - level, sz); Object bean = null; for (final Iterator it = parentNode.getSameNodes().iterator(); it.hasNext();) { Object obj = it.next(); if (!(obj instanceof BindingNode)) { bean = obj; break; } } //for each same node, find the associated kid node final Set assocateSameNodes = new HashSet(); for (final Iterator it = parentNode.getSameNodes().iterator(); it.hasNext();) { //locate the associate kid node BindingNode currentNode = null; final Object obj = it.next(); if (!(obj instanceof BindingNode) || currentNode == parentNode) { continue; } currentNode = (BindingNode) obj; for(final Iterator itx = subids.iterator(); itx.hasNext();) { final String nodeid = (String) itx.next(); currentNode = (BindingNode) currentNode.getKidNode(nodeid); if (currentNode == null) { break; } } if (currentNode != null) { if (!currentNode.isVar()) { assocateSameNodes.add(currentNode); } else { //a var node, specialcase, find the var root Component varRootComp = getVarRootComponent(currentNode); assocateSameNodes.add(new Object[] {currentNode, varRootComp}); } } } return assocateSameNodes; } private Component getVarRootComponent(BindingNode node) { final BindingNode varRootNode = node.getRootNode(_pathTree); Object bean = null; for (final Iterator it = varRootNode.getSameNodes().iterator(); it.hasNext();) { Object obj = it.next(); if (!(obj instanceof BindingNode)) { bean = obj; break; } } Component comp = null; for(final Iterator itx = varRootNode.getBindings().iterator(); itx.hasNext();) { Binding binding = (Binding) itx.next(); if ("_var".equals(binding.getAttr())) { comp = binding.getComponent(); break; } } return getCollectionItem(comp, bean); } private class LoadOnSaveEventListener implements EventListener { public LoadOnSaveEventListener() { } //-- EventListener --// public void onEvent(Event event) { final Set walkedNodes = new HashSet(32); final Set loadedBindings = new HashSet(32*2); Object obj = event.getData(); if (obj instanceof List) { for(final Iterator it = ((List)obj).iterator(); it.hasNext();) { final Object[] data = (Object[]) it.next(); doLoad(data, walkedNodes, loadedBindings); } } else { doLoad((Object[]) obj, walkedNodes, loadedBindings); } } private void doLoad(Object[] data, Set walkedNodes, Set loadedBindings) { if (!data[0].equals(DataBinder.this)) { return; //not for this DataBinder, skip } final BindingNode node = (BindingNode) data[1]; //to be loaded nodes final Binding savebinding = (Binding) data[2]; //to be excluded binding final Object bean = data[3]; //saved bean final boolean refChanged = ((Boolean) data[4]).booleanValue(); //whether bean itself changed final List nodes = (List) data[5]; //the complete nodes along the path to the node final Component savecomp = (Component) data[6]; //saved comp that trigger this load-on-save event if (savecomp != null) { loadAllNodes(bean, node, savecomp, savebinding, refChanged, nodes, walkedNodes, loadedBindings); } } /** Load all associated BindingNodes below the given nodes (depth first traverse). */ private void loadAllNodes(Object bean, BindingNode node, Component collectionComp, Binding savebinding, boolean refChanged, List nodes, Set walkedNodes, Set loadedBindings) { myLoadAllNodes(bean, node, collectionComp, walkedNodes, savebinding, loadedBindings, refChanged); //for each ancestor, find associated same nodes if (!nodes.isEmpty()) { final String path = node.getPath(); int level = 1; for(final ListIterator it = nodes.listIterator(nodes.size()-1); it.hasPrevious(); ++level) { final BindingNode parentNode = (BindingNode) it.previous(); final Set associateSameNodes = getAssociateSameNodes(parentNode, path, level); for(final Iterator itx = associateSameNodes.iterator(); itx.hasNext();) { Object obj = itx.next(); if (obj instanceof BindingNode) { BindingNode samenode = (BindingNode) obj; myLoadAllNodes(bean, samenode, collectionComp, walkedNodes, savebinding, loadedBindings, refChanged); } else { BindingNode samenode = (BindingNode)((Object[])obj)[0]; Component varRootComp = (Component) ((Object[])obj)[1]; myLoadAllNodes(bean, samenode, varRootComp, walkedNodes, savebinding, loadedBindings, refChanged); } } } } } private void myLoadAllNodes(Object bean, BindingNode node, Component collectionComp, Set walkedNodes, Binding savebinding, Set loadedBindings, boolean refChanged) { if (walkedNodes.contains(node)) { return; //already walked, skip } //mark as walked already walkedNodes.add(node); //the component might have been removed if (collectionComp == null) { return; } //loading collectionComp = loadBindings(bean, node, collectionComp, savebinding, loadedBindings, refChanged); for(final Iterator it = node.getKidNodes().iterator(); it.hasNext();) { final BindingNode kidnode = (BindingNode) it.next(); final Object kidbean = fetchValue(bean, kidnode, kidnode.getNodeId()); myLoadAllNodes(kidbean, kidnode, collectionComp, walkedNodes, savebinding, loadedBindings, true); //recursive } for(final Iterator it = new ArrayList(node.getSameNodes()).iterator(); it.hasNext();) { final Object obj = it.next(); if (obj instanceof BindingNode) { final BindingNode samenode = (BindingNode) obj; if (node == samenode) { continue; } if (samenode.isVar()) { // -> var node //var node must traverse from the root //even a root, must make sure the samebean (could be diff) //even the same bean, if a inner var root(collection in collection), not a real root if (!samenode.isRoot() || !isSameBean(samenode, bean) || samenode.isInnerCollectionNode()) { continue; } } else if (node.isVar() && !isSameBean(samenode, bean)) { //var -> !var, must same bean continue; } myLoadAllNodes(bean, samenode, collectionComp, walkedNodes, savebinding, loadedBindings, refChanged); //recursive } } } private Object fetchValue(Object bean, BindingNode node, String nodeid) { if (bean != null) { try { bean = Fields.get(bean, nodeid); } catch (NoSuchMethodException ex) { throw UiException.Aide.wrap(ex); } } registerBeanNode(bean, node); return bean; } //return nearest collection item Component (i.e. Listitem) private Component loadBindings(Object bean, BindingNode node, Component collectionComp, Binding savebinding, Set loadedBindings, boolean refChanged) { final Collection bindings = node.getBindings(); for(final Iterator it = bindings.iterator(); it.hasNext();) { final Binding binding = (Binding) it.next(); if (loadedBindings.contains(binding)) { continue; } loadedBindings.add(binding); // bug 1775051: a multiple selection Listbox. When onSelect and loadOnSave cause // setSelectedItem (loading) to be called and cause deselection of other multiple // selected items. Must skip such case. // save binding that cause this loadOnSave, no need to load again. if (binding == savebinding) { continue; } Component comp = binding.getComponent(); if (isTemplate(comp)) { //a template component, locate the listitem Component clonecomp = null; if (isClone(collectionComp)) { //A listbox in listbox clonecomp = lookupClone(collectionComp, comp); } else { clonecomp = getCollectionItem(comp, bean); } if ("_var".equals(binding.getAttr())) { if (clonecomp == null) { //the comp is in another Listbox clonecomp = getCollectionItem(comp, bean); } collectionComp = clonecomp; } comp = clonecomp; } if (refChanged) { binding.loadAttribute(comp); } } return collectionComp; } private boolean isSameBean(BindingNode node, Object bean) { final Collection bindings = node.getBindings(); if (bindings.isEmpty()) { return true; } final Component comp = ((Binding)bindings.iterator().next()).getComponent(); if (isTemplate(comp)) { return true; } final Object nodebean = getBeanWithExpression(comp, node.getPath()); return Objects.equals(nodebean, bean); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -