org.zkoss.bind.xel.zel.BindELResolver Maven / Gradle / Ivy
The newest version!
/* BindELResolver.java
Purpose:
Description:
History:
Aug 10, 2011 4:31:51 PM, Created by henrichen
Copyright (C) 2011 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.bind.xel.zel;
import java.lang.reflect.Method;
import java.util.Set;
import org.zkoss.bind.BindContext;
import org.zkoss.bind.Binder;
import org.zkoss.bind.Form;
import org.zkoss.bind.FormLegacyExt;
import org.zkoss.bind.impl.BinderImpl;
import org.zkoss.bind.impl.LoadFormBindingImpl;
import org.zkoss.bind.impl.Path;
import org.zkoss.bind.impl.SimpleBindXelContext;
import org.zkoss.bind.proxy.FormProxyObject;
import org.zkoss.bind.sys.BinderCtrl;
import org.zkoss.bind.sys.Binding;
import org.zkoss.bind.sys.LoadBinding;
import org.zkoss.bind.sys.ReferenceBinding;
import org.zkoss.bind.sys.SaveBinding;
import org.zkoss.bind.tracker.impl.TrackerImpl;
import org.zkoss.lang.Objects;
import org.zkoss.xel.XelContext;
import org.zkoss.xel.zel.XelELResolver;
import org.zkoss.zel.CompositeELResolver;
import org.zkoss.zel.ELContext;
import org.zkoss.zel.ELException;
import org.zkoss.zel.ELResolver;
import org.zkoss.zel.MethodInfo;
import org.zkoss.zel.MethodNotFoundException;
import org.zkoss.zel.PropertyNotFoundException;
import org.zkoss.zel.PropertyNotWritableException;
import org.zkoss.zel.impl.lang.EvaluationContext;
import org.zkoss.zel.impl.parser.AstMethodParameters;
import org.zkoss.zk.ui.Component;
/**
* ELResolver for Binding; handle Form bean.
* @author henrichen
* @since 6.0.0
*/
public class BindELResolver extends XelELResolver {
protected CompositeELResolver _resolver;
protected PathELResolver _pathResolver;
private ImplicitObjectELResolver _implicitResolver;
public BindELResolver(XelContext ctx) {
super(ctx);
init();
}
protected void init() {
_resolver = new CompositeELResolver();
if (_pathResolver == null)
_resolver.add(_pathResolver = new PathELResolver()); //must be the first
else
_resolver.add(_pathResolver);
_resolver.add(new FormELResolver());
_resolver.add(new ListModelELResolver());
_resolver.add(new TreeModelELResolver());
_resolver.add(new ValidationMessagesELResolver());
_resolver.add(getImplicitResolver()); //ZK-1032 Able to wire Event to command method
_resolver.add(new DynamicPropertiedELResolver()); //ZK-1472 Bind Include Arg
_resolver.add(getSuperELResolver());
}
protected ELResolver getSuperELResolver() {
return super.getELResolver();
}
protected ELResolver getELResolver() {
return _resolver;
}
protected ImplicitObjectELResolver getImplicitResolver() {
if (_implicitResolver == null)
_implicitResolver = new ImplicitObjectELResolver();
return _implicitResolver;
}
//ELResolver//
public Object getValue(ELContext ctx, Object base, Object property) throws PropertyNotFoundException, ELException {
Object value = null;
if (base == null) {
if (_pathResolver == null) {
_pathResolver = new PathELResolver(); // init
}
_pathResolver.getValue(ctx, base, property);
if (value == null && _ctx instanceof SimpleBindXelContext) {
SimpleBindXelContext bctxt = (SimpleBindXelContext) _ctx;
if ("self".equals(property)) {
value = bctxt.getSelf();
}
if (Objects.equals(bctxt.getViewModelName(), property))
value = bctxt.getViewModel();
}
// resolver first.
if (value == null) {
value = resolve(ctx, base, property);
}
if (value == null)
value = getImplicitResolver().getValue(ctx, base, property);
// it may be BeanName resolver
if (value == null) {
value = super.getELResolver().getValue(ctx, base, property);
}
if (value != null)
ctx.setPropertyResolved(true);
} else {
value = super.getValue(ctx, base, property);
}
// in order to support more complex case, ex: .stream().filter(x -> x.contains(vm.value))
final BindELContext bctx;
ELContext ec = ((EvaluationContext) ctx).getELContext();
if (ec instanceof BindELContext)
bctx = (BindELContext) ec;
else {
bctx = (BindELContext) ((EvaluationContext) ec).getELContext();
}
Object ignoreRefVal = bctx.getAttribute(BinderImpl.IGNORE_REF_VALUE);
//ZK-950: The expression reference doesn't update while change the instant of the reference
final ReferenceBinding rbinding = value instanceof ReferenceBinding ? (ReferenceBinding) value : null;
if (rbinding != null) {
//ZK-3320 cause stack overflow
if (property.equals(rbinding.getPropertyString())) {
throw new RuntimeException("Property \"" + property + "\" is not allowed to be same as the reference expression in reference binding");
}
//ZK-1299 Use @ref and save after will cause null point exception
if (Boolean.TRUE.equals(ignoreRefVal)) {
return rbinding;
}
// value = rbinding.getValue((BindELContext) ((EvaluationContext)ctx).getELContext());
value = rbinding.getValue(bctx);
final Object invalidateRef = bctx.getAttribute(BinderCtrl.INVALIDATE_REF_VALUE);
if ("true".equalsIgnoreCase(String.valueOf(invalidateRef)))
rbinding.invalidateCache();
}
//If value evaluated to a ReferenceBinding, always tie the ReferenceBinding itself as the
//evaluated bean, @see TrackerImpl#getLoadBindings0() and TrackerImpl#getAllTrackerNodesByBeanNodes()
tieValue(ctx, base, property, rbinding != null ? rbinding : value, false);
return value;
}
@Override
public Object invoke(ELContext ctx, Object base, Object method, Class[] paramTypes, Object[] params)
throws MethodNotFoundException {
Object value = super.invoke(ctx, base, method, paramTypes, params);
// in order to support more complex case, ex: .stream().filter(x -> x.contains(vm.value))
final BindELContext bctx;
ELContext ec = ((EvaluationContext) ctx).getELContext();
if (ec instanceof BindELContext)
bctx = (BindELContext) ec;
else {
bctx = (BindELContext) ((EvaluationContext) ec).getELContext();
}
Object ignoreRefVal = bctx.getAttribute(BinderImpl.IGNORE_REF_VALUE);
//ZK-950: The expression reference doesn't update while change the instant of the reference
final ReferenceBinding rbinding = value instanceof ReferenceBinding ? (ReferenceBinding) value : null;
if (rbinding != null) {
//ZK-1299 Use @ref and save after will cause null point exception
if (Boolean.TRUE.equals(ignoreRefVal)) {
return rbinding;
}
// value = rbinding.getValue((BindELContext) ((EvaluationContext)ctx).getELContext());
value = rbinding.getValue(bctx);
final Object invalidateRef = bctx.getAttribute(BinderCtrl.INVALIDATE_REF_VALUE);
if ("true".equalsIgnoreCase(String.valueOf(invalidateRef)))
rbinding.invalidateCache();
}
AstMethodParameters mps = (AstMethodParameters) bctx.getContext(AstMethodParameters.class);
if (mps != null) {
String result = BindELContext.toNodeString(mps, new StringBuilder());
Path newPath = new Path();
newPath.add(String.valueOf(method) + result, String.valueOf(method) + result);
bctx.putContext(Path.class, newPath);
}
//If value evaluated to a ReferenceBinding, always tie the ReferenceBinding itself as the
//evaluated bean, @see TrackerImpl#getLoadBindings0() and TrackerImpl#getAllTrackerNodesByBeanNodes()
tieValue(ctx, base, method, rbinding != null ? rbinding : value, false);
return value;
}
public void setValue(ELContext ctx, Object base, Object property, Object value)
throws PropertyNotFoundException, PropertyNotWritableException, ELException {
if (base == null) {
//ZK-1085 PropertyNotWritableException when using reference binding
//for setting value to a reference-binding and simple-node (base = null), we let reference-binding handle it
Object val = super.getValue(ctx, base, property); //property resolved sets true when getValue
if (val instanceof ReferenceBinding) {
((ReferenceBinding) val).setValue((BindELContext) ((EvaluationContext) ctx).getELContext(), value);
return;
}
} else if (base instanceof ReferenceBinding) {
base = ((ReferenceBinding) base).getValue((BindELContext) ((EvaluationContext) ctx).getELContext());
}
super.setValue(ctx, base, property, value);
tieValue(ctx, base, property, value, true);
}
private static Path getPathList(BindELContext ctx) {
return (Path) ctx.getContext(Path.class); //get path, see #PathResolver
}
//save value into equal beans
private void saveEqualBeans(ELContext elCtx, Object base, String prop, Object value) {
final BindELContext ctx = (BindELContext) ((EvaluationContext) elCtx).getELContext();
final BindContext bctx = (BindContext) ctx.getAttribute(BinderImpl.BINDCTX);
if (bctx.getAttribute(BinderImpl.SAVE_BASE) != null) { //recursive back, return
return;
}
ctx.setAttribute(BinderImpl.SAVE_BASE, Boolean.TRUE);
try {
final Binder binder = bctx.getBinder();
final TrackerImpl tracker = (TrackerImpl) ((BinderCtrl) binder).getTracker();
final Set
© 2015 - 2025 Weber Informatics LLC | Privacy Policy