@Override public void bindData(final V data) { this.currentData = data; for (final DataBinder<V> binder : binders) { binder.bindData(data); } }
// scan up the component hierarchy until the real owner is found and collect all cloned // components. private static List<Component> scanClones(DataBinder binder, Component comp) { if (DataBinder.isTemplate(comp)) { final List<Component> owners = scanClones(binder, binder.getCollectionOwner(comp)); // recursive final List<Component> kidowners = new LinkedList<Component>(); for (Component owner : owners) { final CollectionItem decor = binder.getCollectionItemByOwner(owner); // backward compatible, CollectionItemEx.getItems() is faster if (decor instanceof CollectionItemExt) { final CollectionItemExt decorex = (CollectionItemExt) decor; for (final Iterator iti = decorex.getItems(owner).iterator(); iti.hasNext(); ) { final Component item = (Component) iti.next(); kidowners.add(DataBinder.lookupClone(item, comp)); } } else { try { for (int j = 0; true; ++j) { // iterate until out of bound final Component item = decor.getComponentAtIndexByOwner(owner, j); kidowners.add(DataBinder.lookupClone(item, comp)); } } catch (IndexOutOfBoundsException ex) { // ignore, iterate until out of bound } } } return kidowners; } else { final List<Component> owners = new ArrayList<Component>(); owners.add(comp); return owners; } }
/** * Add a binding in the BindingNode of the specified path. * * @param path the path of the specified BindingNode in the tree. * @param binding the binding to be added to the specified BindingNode. * @param varnameSet set with all _var names */ public void addBinding(String path, Binding binding, Set varnameSet) { final List nodeids = DataBinder.parseExpression(path, "."); if (nodeids.size() <= 0) { throw new UiException("Incorrect bean expression: " + path); } boolean var = varnameSet.contains(nodeids.get(0)); BindingNode currentNode = this; for (final Iterator it = nodeids.iterator(); it.hasNext(); ) { final String nodeid = (String) it.next(); if (nodeid == null) { throw new UiException("Incorrect bean expression: " + path); } BindingNode kidNode = currentNode.getKidNode(nodeid); if (kidNode == null) { // if not found, then add one if ("/".equals(currentNode._path)) { kidNode = new BindingNode(nodeid, var, nodeid, true); } else { kidNode = new BindingNode(currentNode._path + "." + nodeid, var, nodeid, false); } currentNode.addKidNode(nodeid, kidNode); } else { var = var || kidNode._var; } currentNode = kidNode; } if (currentNode == this) { throw new UiException("Incorrect bean expression: " + path); } currentNode.addBinding(binding); if ("_var".equals(binding.getAttr())) { currentNode._innerCollectionNode = DataBinder.hasTemplateOwner(binding.getComponent()); } }
@Override public int getItemCount() { int itemCount = 0; for (DataBinder binder : mBinderMap.values()) { itemCount += binder.getItemCount(); } return itemCount; }
/** * load bean value into the attribute of the specified component. * * @param comp the component. */ public void loadAttribute(Component comp) { if (!isLoadable() || _attr.startsWith("_") || DataBinder.isTemplate(comp) || comp == null // bug #1941947 Cannot find associated CollectionItem || comp.getPage() == null) { return; // cannot load, a control attribute, or a detached component, skip! } Object bean = _binder.getBeanAndRegisterBeanSameNodes(comp, _expression); myLoadAttribute(comp, bean); }
/** Get converted value and original value of this Binding. */ private Object[] getAttributeValues(Component comp) { if (!isSavable() || _attr.startsWith("_") || DataBinder.isTemplate(comp) || comp.getPage() == null) { return null; // cannot save, a control attribute, or a detached component, skip! } Object rawval = null; try { rawval = Fields.get(comp, _attr); } catch (NoSuchMethodException ex) { // Bug #1813278, Annotations do not work with xhtml tags if (comp instanceof DynamicPropertied) { final DynamicPropertied dpcomp = (DynamicPropertied) comp; if (dpcomp.hasDynamicProperty(_attr)) { rawval = dpcomp.getDynamicProperty(_attr); } else { throw UiException.Aide.wrap(ex); } } else if (comp.getAttributes() .containsKey( _attr)) { // Feature #2855116. Get value from component custom-attribute(also a // variable in ZK5). rawval = comp.getAttribute(_attr); } else { throw UiException.Aide.wrap(ex); } } try { final Object val = (_converter == null) ? rawval : _converter.coerceToBean(rawval, comp); return val == TypeConverter.IGNORE ? null : new Object[] {val, rawval}; } catch (ClassCastException ex) { throw UiException.Aide.wrap(ex); } }
protected void handleEvent(Event event) { for (BindingInfo bi : _dataTargets) { final Component dt = bi.getComponent(); final Binding binding = bi.getBinding(); final DataBinder binder = binding.getBinder(); final Component dataTarget = DataBinder.isTemplate(dt) ? DataBinder.lookupClone(event.getTarget(), dt) : dt; if (dataTarget != null) { binding.loadAttribute(dataTarget); } else { // #bug 2897202 final List<Component> clones = scanClones(binder, dt); for (final Component dataTarget1 : clones) { binding.loadAttribute(dataTarget1); } } } }
/** * load bean value into the attribute of the specified component. * * @param comp the component. * @param bean the bean value. */ public void loadAttribute(Component comp, Object bean) { if (!isLoadable() || _attr.startsWith("_") || DataBinder.isTemplate(comp) || comp.getPage() == null) { return; // cannot load, a control attribute, or a detached component, skip! } myLoadAttribute(comp, bean); }
/** * Returns the associated bean of this binding; e.g., for a binding to the bean "a.b.c", this will * return the bean associated to "a.b" (and c is the property name). * * <p>Note if the expression is associated to a single variable; e.g. "a" only, this method * returns null. * * @param comp * @return the associated bean of this binding. * @since 5.0.7 */ public Object getBean(Component comp) { if (_expression != null) { int j = _expression.lastIndexOf('.'); if (j >= 0) { return _binder.getBeanWithExpression(comp, _expression.substring(0, j)); } } return null; }
@SuppressWarnings("unchecked") public void render(Comboitem item, Object bean, int index) throws Exception { final List<Component> kids = cast((List) item.getAttribute(KIDS)); ((List<Component>) item.getChildren()).addAll(kids); // item.removeAttribute(KIDS); // remove template mark of cloned component and its descendants _binder.setupTemplateComponent(item, null); // setup clone id BindingRendererUtil.setupCloneIds(item); // bind bean to the associated listitem and its descendants final String varname = (String) _template.getAttribute(DataBinder.VARNAME); final Map<Object, Object> templatemap = cast((Map) item.getAttribute(DataBinder.TEMPLATEMAP)); templatemap.put(varname, bean); // apply the data binding _binder.loadComponent(item); // feature# 3026221: Databinder shall fire onCreate when cloning each items DataBinder.postOnCreateEvents(item); // since 5.0.4 }
/** * Locate the BindingNode of the specified path. * * @param path the path of the specified BindingNode in the tree. */ public BindingNode locate(String path) { BindingNode currentNode = this; final List nodeids = DataBinder.parseExpression(path, "."); for (final Iterator it = nodeids.iterator(); it.hasNext(); ) { final String nodeid = (String) it.next(); if (nodeid == null) { throw new UiException("Incorrect format of bean expression: " + path); } currentNode = currentNode.getKidNode(nodeid); if (currentNode == null) { return null; } } return currentNode == this ? null : currentNode; }
private void saveAttributeValue( Component comp, Object[] vals, List<Object> loadOnSaveInfos, String triggerEventName) { if (vals == null) return; final Object val = vals[0]; final Object rawval = vals[1]; _binder.setBeanAndRegisterBeanSameNodes( comp, val, this, _expression, _converter == null, rawval, loadOnSaveInfos, triggerEventName); }
public <D extends IModel> void notifyModelChanged(D data) { if (binder != null) binder.viewBindModel(viewDelegate, data); }
@Override public void commitHandler() { for (final DataBinder<V> binder : binders) { binder.commitHandler(); } }
public void appendBinder(final DataBinder<V> newBinder) { binders.add(newBinder); if (currentData != null) newBinder.bindData(currentData); }
protected void handleEvent(Event event) { final Component target = event.getTarget(); final String triggerEventName = event.getName(); final List<BindingInfo> tmplist = new ArrayList<BindingInfo>(_dataTargets.size()); final List<Object> values = new LinkedList<Object>(); final List<Component> refs = new LinkedList<Component>(); final List<Binding> bindings = new LinkedList<Binding>(); // fire onSave for each binding for (BindingInfo bi : _dataTargets) { final Component dt = bi.getComponent(); final Binding binding = bi.getBinding(); final DataBinder binder = binding.getBinder(); final Component dataTarget = DataBinder.isTemplate(dt) ? DataBinder.lookupClone(target, dt) : dt; // bug# 1904389: NullPointerException if save-when in collection binding // event.getTarget() might not inside the collection item (i.e. row, listitem, etc.) // then binder.lookupClone() will return null dataTarget. if (dataTarget != null) { final Object[] vals = binding.getAttributeValues(dataTarget); if (vals != null) { tmplist.add(new BindingInfo(binding, dataTarget, vals)); values.add(vals[0]); refs.add(dataTarget); bindings.add(binding); Events.sendEvent( new BindingSaveEvent("onBindingSave", dataTarget, target, binding, vals[0])); } } else { // bi.getComponent a template and a null dataTarget, meaning all collection items has to // be handled. Search the owner to iterate all cloned items. final List<Component> clones = scanClones(binder, dt); for (Component dataTarget1 : clones) { final Object[] vals = binding.getAttributeValues(dataTarget1); if (vals != null) { tmplist.add(new BindingInfo(binding, dataTarget1, vals)); values.add(vals[0]); refs.add(dataTarget1); bindings.add(binding); Events.sendEvent( new BindingSaveEvent("onBindingSave", dataTarget1, target, binding, vals[0])); } } } } // fire onValidate for target component Events.sendEvent( new BindingValidateEvent("onBindingValidate", target, refs, bindings, values)); // saveAttribute for each binding Component loadOnSaveProxy = null; Component dataTarget = null; DataBinder binder = null; final List<Object> loadOnSaveInfos = new ArrayList<Object>(tmplist.size()); for (BindingInfo bi : tmplist) { dataTarget = bi.getComponent(); final Binding binding = bi.getBinding(); if (binder == null) { binder = binding.getBinder(); } final Object[] vals = bi.getAttributeValues(); binding.saveAttributeValue(dataTarget, vals, loadOnSaveInfos, triggerEventName); if (loadOnSaveProxy == null && dataTarget.isListenerAvailable("onLoadOnSave", true)) { loadOnSaveProxy = dataTarget; } } // bug #1895856 : data binding LoadOnSave works only on the last save-when component // do loadOnSave // if (dataTarget != null) { // Events.postEvent(new Event("onLoadOnSave", dataTarget, loadOnSaveInfos)); // } // (use first working dataTarget as proxy) // feature#2990932, allow disable load-on-save mechanism if (loadOnSaveProxy != null && binder.isLoadOnSave()) { Events.postEvent(new Event("onLoadOnSave", loadOnSaveProxy, loadOnSaveInfos)); } }