Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.zkoss.bind.impl.SavePropertyBindingImpl Maven / Gradle / Ivy
/* SavePropertyBindingImpl.java
Purpose:
Description:
History:
Aug 1, 2011 2:45:43 PM, Created by henrichen
Copyright (C) 2011 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.bind.impl;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Map;
import org.zkoss.bind.BindContext;
import org.zkoss.bind.Binder;
import org.zkoss.bind.Converter;
import org.zkoss.bind.Property;
import org.zkoss.bind.ValidationContext;
import org.zkoss.bind.Validator;
import org.zkoss.bind.proxy.FormProxyObject;
import org.zkoss.bind.sys.BindEvaluatorX;
import org.zkoss.bind.sys.BinderCtrl;
import org.zkoss.bind.sys.ConditionType;
import org.zkoss.bind.sys.SavePropertyBinding;
import org.zkoss.bind.sys.debugger.BindingExecutionInfoCollector;
import org.zkoss.bind.sys.debugger.impl.info.SaveInfo;
import org.zkoss.bind.sys.debugger.impl.info.ValidationInfo;
import org.zkoss.xel.ExpressionX;
import org.zkoss.xel.ValueReference;
import org.zkoss.zel.PropertyNotFoundException;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.UiException;
import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.WrongValuesException;
/**
* Implementation of {@link SavePropertyBinding}.
* @author henrichen
* @since 6.0.0
*/
public class SavePropertyBindingImpl extends PropertyBindingImpl implements SavePropertyBinding {
private static final long serialVersionUID = 1463169907348730644L;
private final ExpressionX _validator;
private final Map _validatorArgs;
private FormFieldInfo _formFieldInfo;
public SavePropertyBindingImpl(Binder binder, Component comp, String attr, String saveAttr, String saveExpr,
ConditionType conditionType, String command, Map bindingArgs, String converterExpr,
Map converterArgs, String validatorExpr, Map validatorArgs) {
super(binder, comp, attr, "self." + saveAttr, saveExpr, conditionType, command, bindingArgs, converterExpr,
converterArgs);
final BindEvaluatorX eval = binder.getEvaluatorX();
_validator = validatorExpr == null ? null : parseValidator(eval, validatorExpr);
_validatorArgs = validatorArgs;
//ZK-3185: Enable form validation with reference and collection binding
final BindContext ctx = BindContextUtil.newBindContext(getBinder(), this, true, null, getComponent(), null);
ctx.setAttribute(BinderImpl.IGNORE_REF_VALUE, Boolean.FALSE);
ctx.setAttribute(BinderImpl.IGNORE_TRACKER, Boolean.TRUE);
ValueReference valref = null;
try {
valref = eval.getValueReference(ctx, getComponent(), _accessInfo.getProperty());
} catch (PropertyNotFoundException e) {
//ignore null
}
if (valref != null) {
Object base = valref.getBase();
if (base instanceof FormProxyObject)
((FormProxyObject) base).cacheSavePropertyBinding((String) valref.getProperty(), this);
}
}
public Map getValidatorArgs() {
return _validatorArgs;
}
protected boolean ignoreTracker() {
return true;
}
private ExpressionX parseValidator(BindEvaluatorX eval, String validatorExpr) {
// final BindContext ctx = BindContextUtil.newBindContext(getBinder(), this, false, null, getComponent(), null);
// ctx.setAttribute(BinderImpl.IGNORE_TRACKER, Boolean.TRUE);//ignore tracker when doing el, we don't need to trace validator
//expression will/should not be tracked, (although, from the impl, tracker don't care savebinding)
return eval.parseExpressionX(/*ctx*/null, validatorExpr, Object.class);
}
public Validator getValidator() {
if (_validator == null)
return null;
// final BindContext ctx = BindContextUtil.newBindContext(getBinder(), this, false, null, getComponent(), null);
// ctx.setAttribute(BinderImpl.IGNORE_TRACKER, Boolean.TRUE);//ignore tracker when doing el, we don't need to trace validator
final BindEvaluatorX eval = getBinder().getEvaluatorX();
Object obj = eval.getValue(null, getComponent(), _validator);
if (obj instanceof Validator) {
return (Validator) obj;
} else if (obj instanceof String) {
return getBinder().getValidator((String) obj); //binder will throw exception if not found
} else {
throw new ClassCastException(
"result of expression '" + _validator.getExpressionString() + "' is not a Validator, is " + obj);
}
}
private static final String COMPVALUE = "$COMPVALUE$";
private static final String COMPVALUENOCONVERT = "$COMPVALUENOCONVERT$";
private static final String VALUEREF = "$VALUEREF$";
private Object getComponentValue(BindContext ctx) {
if (!containsAttribute(ctx, COMPVALUE)) {
final Component comp = getComponent(); //ctx.getComponent();
final BindEvaluatorX eval = getBinder().getEvaluatorX();
//get data from component attribute
Object value = eval.getValue(null, comp, _fieldExpr);
setAttribute(ctx, COMPVALUENOCONVERT, value);
//use converter to convert type if any
@SuppressWarnings("unchecked")
final Converter conv = getConverter();
if (conv != null) {
value = conv.coerceToBean(value, comp, ctx);
// ValueReference ref = getValueReference(ctx);
// //collect Property for @NotifyChange, kept in BindContext
// //see BinderImpl$CommandEventListener#onEvent()
// BindELContext.addNotifys(getConverterMethod(conv.getClass()), ref.getBase(), null, value, ctx);
}
setAttribute(ctx, COMPVALUE, value);
}
return getAttribute(ctx, COMPVALUE);
}
public String getValidatorExpressionString() {
return _validator == null ? null : BindEvaluatorXUtil.getExpressionString(_validator);
}
public void save(BindContext ctx) {
final BindingExecutionInfoCollector collector = ((BinderCtrl) getBinder()).getBindingExecutionInfoCollector();
final Component comp = getComponent();
//get data from component attribute
Object value = getComponentValue(ctx);
if (value == Converter.IGNORED_VALUE) {
if (collector != null) {
Object old = getAttribute(ctx, COMPVALUENOCONVERT);
collector.addInfo(new SaveInfo(SaveInfo.PROP_SAVE, comp, getConditionString(ctx), getFieldName(),
getPropertyString(), old, getArgs(), "*Converter.IGNORED_VALUE"));
}
return;
}
if (collector != null) {
collector.addInfo(new SaveInfo(SaveInfo.PROP_SAVE, comp, getConditionString(ctx), getFieldName(),
getPropertyString(), value, getArgs(), null));
}
//set data into bean property
final BindEvaluatorX eval = getBinder().getEvaluatorX();
eval.setValue(ctx, comp, _accessInfo.getProperty(), value);
}
private String getConditionString(BindContext ctx) {
StringBuilder condition = new StringBuilder();
if (getConditionType() == ConditionType.BEFORE_COMMAND) {
condition.append("before = '").append(getCommandName()).append("'");
} else if (getConditionType() == ConditionType.AFTER_COMMAND) {
condition.append("after = '").append(getCommandName()).append("'");
} else {
condition.append(ctx.getTriggerEvent() == null ? "" : "event = " + ctx.getTriggerEvent().getName());
}
return condition.toString();
}
//get and cache value reference of this binding
private ValueReference getValueReference(BindContext ctx) {
ValueReference valref = (ValueReference) getAttribute(ctx, VALUEREF);
if (valref == null) {
//ZK-1017: Property of a form is not correct when validation
if (_formFieldInfo != null && _formFieldInfo._fieldName.indexOf("[$INDEX$]") == -1) { // skip collection field name
final Object form = getComponent().getAttribute(_formFieldInfo._id, true);
final String fieldName = _formFieldInfo._fieldName;
valref = new org.zkoss.xel.zel.ELXelExpression.ValueReferenceImpl(form, fieldName);
} else {
final Component comp = getComponent(); //ctx.getComponent();
final BindEvaluatorX eval = getBinder().getEvaluatorX();
valref = eval.getValueReference(ctx, comp, _accessInfo.getProperty());
if (valref == null) {
throw new UiException("value reference not found by expression ["
+ _accessInfo.getProperty().getExpressionString()
+ "], check if you are trying to save to a variable only expression");
}
}
setAttribute(ctx, VALUEREF, valref);
}
return valref;
}
//ZK-1017: Property of a form is not correct when validation
//@see BinderImpl#addFormAssociatedSaveBinding
/*package*/ void setFormFieldInfo(Component formComp, String formId, String fieldName) {
if (_formFieldInfo == null) {
_formFieldInfo = new FormFieldInfo();
}
_formFieldInfo._component = formComp;
_formFieldInfo._id = formId;
_formFieldInfo._fieldName = fieldName;
}
//--SaveBinding--//
public Property getValidate(BindContext ctx) {
//we should not check this binding need to validate or not,
//maybe other validator want to know the value of this binding, so just provide it
final ValueReference ref = getValueReference(ctx);
try {
final Object value = getComponentValue(ctx);
return new PropertyImpl(ref.getBase(), String.valueOf(ref.getProperty()),
value == Converter.IGNORED_VALUE ? null : value);
} catch (Exception e) {
// ZK-878 Exception if binding a form with errorMessage
// a wrong value exception might be thrown when a component has constraint
Throwable t = e;
while (t != null) {
if (t instanceof WrongValueException || t instanceof WrongValuesException) {
return new WrongValuePropertyImpl(ref.getBase(), (String) ref.getProperty(), t);
} else {
t = t.getCause();
}
}
throw UiException.Aide.wrap(e);
}
}
public boolean hasValidator() {
return _validator != null;
}
public void validate(ValidationContext vctx) {
Validator validator = getValidator();
if (validator == null) {
throw new NullPointerException("cannot find validator for " + this);
}
//ZK-1005 ZK 6.0.1 validation fails on nested bean
if (_formFieldInfo != null) {
vctx.getBindContext().setAttribute(BinderImpl.LOAD_FORM_COMPONENT, _formFieldInfo._component);
}
validator.validate(vctx);
BindingExecutionInfoCollector collector = ((BinderCtrl) getBinder()).getBindingExecutionInfoCollector();
if (collector != null) {
collector.addInfo(new ValidationInfo(ValidationInfo.PROP, getComponent(), getValidatorExpressionString(),
validator.toString(), Boolean.valueOf(vctx.isValid()),
((BindContextImpl) vctx.getBindContext()).getValidatorArgs(), null));
}
// //collect notify change
// collectNotifyChange(validator,vctx);
}
// private void collectNotifyChange(Validator validator, ValidationContext vctx) {
// ValueReference ref = getValueReference(vctx.getBindContext());
// BindELContext.addNotifys(getValidatorMethod(validator.getClass()), ref.getBase(), null, null, vctx.getBindContext());
// }
private Method getConverterMethod(Class extends Converter> cls) {
try {
return cls.getMethod("coerceToBean", new Class[] { Object.class, Component.class, BindContext.class });
} catch (NoSuchMethodException e) {
//ignore
}
return null; //shall never come here
}
private Method getValidatorMethod(Class extends Validator> cls) {
try {
return cls.getMethod("validate", new Class[] { ValidationContext.class });
} catch (NoSuchMethodException e) {
//ignore
}
return null; //shall never come here
}
//ZK-1005 ZK 6.0.1 validation fails on nested bean
private static class FormFieldInfo implements Serializable {
private static final long serialVersionUID = 1L;
private Component _component;
private String _fieldName;
private String _id;
}
/**
* Internal use only, only for collections
*/
public Property getBasePropertyIfFromCollection() {
Property p = null;
int index = -1;
String fieldName = "";
if (_formFieldInfo != null && (fieldName = _formFieldInfo._fieldName) != null && (index = fieldName.indexOf("[$INDEX$]")) != -1) {
final BindContext ctx = BindContextUtil.newBindContext(getBinder(), this, false, null, getComponent(), null);
final ValueReference valref = getValueReference(ctx);
if (valref != null) {
Object base = valref.getBase();
if (base instanceof FormProxyObject)
base = ((FormProxyObject) base).getOriginObject();
if (base != null) {
final BindEvaluatorX eval = getBinder().getEvaluatorX();
Object value = eval.getValue(ctx, getComponent(), _accessInfo.getProperty());
String replacedFieldString = fieldName.substring(0, index) + ".$each";
if (fieldName.length() > (index + 9))
replacedFieldString += fieldName.substring(index + 9);
p = new PropertyImpl(base, replacedFieldString, value);
}
}
}
return p;
}
}