/* ReferenceImpl.java Purpose: Description: History: Jan 12, 2012 9:11:03 AM, Created by henrichen Copyright (C) 2012 Potix Corporation. All Rights Reserved. */ package org.zkoss.bind.impl; import java.util.Set; import org.zkoss.bind.BindContext; import org.zkoss.bind.Binder; import org.zkoss.bind.Property; import org.zkoss.bind.sys.BinderCtrl; import org.zkoss.bind.sys.ReferenceBinding; import org.zkoss.bind.sys.debugger.BindingExecutionInfoCollector; import org.zkoss.bind.sys.debugger.impl.info.LoadInfo; import org.zkoss.bind.sys.debugger.impl.info.SaveInfo; import org.zkoss.bind.xel.zel.BindELContext; import org.zkoss.xel.ExpressionX; import org.zkoss.xel.ValueReference; import org.zkoss.zk.ui.Component; /** * Implementation of {@link ReferenceBinding}. * @author henrichen * @since 6.0.0 */ public class ReferenceBindingImpl extends BindingImpl implements ReferenceBinding { private static final long serialVersionUID = 20120204122151L; private static final Object NULL_VALUE = new Object(); // make lazy init private ExpressionX _exprX; private final String _expression; private transient Object _cacheValue; //null means invalid private final String _attr; public ReferenceBindingImpl(Binder binder, Component comp, String attr, String expression) { super(binder, comp, null); _expression = expression; _attr = attr; } // make lazy init private ExpressionX initExpressionX() { if (_exprX == null) { final BindContext ctx = newBindContext(); _exprX = getBinder().getEvaluatorX().parseExpressionX(ctx, _expression, Object.class); } return _exprX; } public Object getValue(BindELContext ctx) { load(null); return _cacheValue == NULL_VALUE ? null : _cacheValue; } public void setValue(BindELContext ctx, Object val) { invalidateCache(); final BindContext bctx = newBindContext(); getBinder().getEvaluatorX().setValue(bctx, getComponent(), initExpressionX(), val); final BindingExecutionInfoCollector collector = ((BinderCtrl) getBinder()).getBindingExecutionInfoCollector(); if (collector != null) { collector.addInfo(new SaveInfo(SaveInfo.REFERENCE, getComponent(), null, _attr, getPropertyString(), val, null, null)); } //copy notifies back final Set<Property> notifies = BindELContext.getNotifys(bctx); if (notifies != null) { BindELContext.addNotifys(notifies, ctx.getBindContext()); } } private BindContext newBindContext() { return BindContextUtil.newBindContext(getBinder(), this, false, null, getComponent(), null); } public void load(BindContext ctx) { if (_cacheValue == null) { final BindContext bctx = newBindContext(); final Object val = getBinder().getEvaluatorX().getValue(bctx, getComponent(), initExpressionX()); _cacheValue = val == null ? NULL_VALUE : val; final BindingExecutionInfoCollector collector = ((BinderCtrl) getBinder()) .getBindingExecutionInfoCollector(); if (collector != null) { collector.addInfo(new LoadInfo(LoadInfo.REFERENCE, getComponent(), null, getPropertyString(), _attr, _cacheValue, null, null)); } } } public String getPropertyString() { return BindEvaluatorXUtil.getExpressionString(initExpressionX()); } public void invalidateCache() { _cacheValue = null; } public String toString() { return new StringBuilder().append(getClass().getSimpleName()).append("@") .append(Integer.toHexString(hashCode())).append(",component:").append(getComponent()).toString(); } /*package*/ ValueReference getValueReference() { final BindContext bctx = newBindContext(); return getBinder().getEvaluatorX().getValueReference(bctx, getComponent(), initExpressionX()); } }