All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zkoss.bind.impl.ValidationHelper Maven / Gradle / Ivy

There is a newer version: 10.0.0-jakarta
Show newest version
/* ValidationHelper.java

	Purpose:
		
	Description:
		
	History:
		2011/10/1 Created by Dennis Chen

Copyright (C) 2011 Potix Corporation. All Rights Reserved.
*/
package org.zkoss.bind.impl;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.zkoss.bind.BindContext;
import org.zkoss.bind.Binder;
import org.zkoss.bind.Form;
import org.zkoss.bind.Property;
import org.zkoss.bind.proxy.FormProxyObject;
import org.zkoss.bind.sys.BinderCtrl;
import org.zkoss.bind.sys.Binding;
import org.zkoss.bind.sys.SaveBinding;
import org.zkoss.bind.sys.SaveFormBinding;
import org.zkoss.bind.sys.SavePropertyBinding;
import org.zkoss.bind.sys.ValidationMessages;
import org.zkoss.util.Pair;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;

/**
 * a internal stateless helper to helps BindImpl to the validation.
 * 
 * @author dennis
 * @since 6.0.0
 */
/*public*/ class ValidationHelper {

	private final Binder _binder;
	private final InfoProvider _infoProvider;

	//	private Map> _collectedPropertyCache;
	private Map _mainPropertyCache;

	public ValidationHelper(Binder binder, InfoProvider infoProvider) {
		this._binder = binder;
		this._infoProvider = infoProvider;
		this._mainPropertyCache = new HashMap(2);
		//		this._collectedPropertyCache = new HashMap>(2);
	}

	// a binder validation information provider, it is related to implementation of BindImpl 
	interface InfoProvider {
		Map> getSaveBeforeBindings();

		Map> getSaveAfterBindings();

		Map> getSaveFormBeforeBindings();

		Map> getSaveFormAfterBindings();

		BindingKey getBindingKey(Component comp, String attr);
	}

	//doCommand -> doValidate ->
	public void collectSaveBefore(Component comp, String command, Event evt, Set validates) {
		collectSavePropertyBefore(comp, command, evt, validates);
		collectSaveFormBefore(comp, command, evt, validates);
	}

	//doCommand -> doValidate -> collectSaveBefore ->
	private void collectSavePropertyBefore(Component comp, String command, Event evt, Set validates) {
		final List bindings = _infoProvider.getSaveBeforeBindings().get(command); //_saveBeforeBindings.get(command);
		if (bindings != null) {
			for (SavePropertyBinding binding : bindings) {
				collectSavePropertyBinding(comp, binding, command, evt, validates);
			}
		}
	}

	//doCommand -> doValidate -> collectSaveBefore ->
	private void collectSaveFormBefore(Component comp, String command, Event evt, Set validates) {
		final List bindings = _infoProvider.getSaveFormBeforeBindings().get(command); //_saveFormBeforeBindings.get(command);
		if (bindings != null) {
			for (SaveFormBinding binding : bindings) {
				collectSaveFormBinding(comp, binding, command, evt, validates);
			}
		}
	}

	//doValidate -> 
	public void collectSaveAfter(Component comp, String command, Event evt, Set validates) {
		collectSavePropertyAfter(comp, command, evt, validates);
		collectSaveFormAfter(comp, command, evt, validates);
	}

	//doValidate -> collectSaveAfter ->
	private void collectSavePropertyAfter(Component comp, String command, Event evt, Set validates) {
		final List bindings = _infoProvider.getSaveAfterBindings().get(command); //_saveAfterBindings.get(command);
		if (bindings != null) {
			for (SavePropertyBinding binding : bindings) {
				collectSavePropertyBinding(comp, binding, command, evt, validates);
			}
		}
	}

	//doValidate -> collectSaveAfter ->
	private void collectSaveFormAfter(Component comp, String command, Event evt, Set validates) {
		final List bindings = _infoProvider.getSaveFormAfterBindings().get(command); //_saveFormAfterBindings.get(command);
		if (bindings != null) {
			for (SaveFormBinding binding : bindings) {
				collectSaveFormBinding(comp, binding, command, evt, validates);
			}
		}
	}

	//validations

	public boolean validateSaveBefore(Component comp, String command, Map validates, boolean valid,
			Set notifys) {
		boolean r = valid;
		r &= validateSavePropertyBefore(comp, command, validates, r, notifys);
		r &= validateSaveFormBefore(comp, command, validates, r, notifys);
		return r;
	}

	//doCommand -> doValidate -> validateSaveBefore ->
	private boolean validateSavePropertyBefore(Component comp, String command, Map validates,
			boolean valid, Set notifys) {
		final List bindings = _infoProvider.getSaveBeforeBindings().get(command); //_saveBeforeBindings.get(command);
		boolean r = valid;
		if (bindings != null) {
			for (SavePropertyBinding binding : bindings) {
				r &= validateSavePropertyBinding(comp, binding, command, validates, r, notifys);
			}
		}
		return r;
	}

	//doCommand -> doValidate -> validateSaveBefore ->
	private boolean validateSaveFormBefore(Component comp, String command, Map validates,
			boolean valid, Set notifys) {
		final List bindings = _infoProvider.getSaveFormBeforeBindings().get(command); //_saveFormBeforeBindings.get(command);
		boolean r = valid;
		if (bindings != null) {
			for (SaveFormBinding binding : bindings) {
				r &= validateSaveFormBinding(comp, binding, command, validates, r, notifys);
			}
		}
		return r;
	}

	public boolean validateSaveAfter(Component comp, String command, Map validates, boolean valid,
			Set notifys) {
		boolean r = valid;
		r &= validateSavePropertyAfter(comp, command, validates, r, notifys);
		r &= validateSaveFormAfter(comp, command, validates, r, notifys);
		return r;
	}

	//doCommand -> doValidate -> validateSaveBefore ->
	private boolean validateSavePropertyAfter(Component comp, String command, Map validates,
			boolean valid, Set notifys) {
		final List bindings = _infoProvider.getSaveAfterBindings().get(command); //_saveBeforeBindings.get(command);
		boolean r = true;
		if (bindings != null) {
			for (SavePropertyBinding binding : bindings) {
				r &= validateSavePropertyBinding(comp, binding, command, validates, valid, notifys);
			}
		}
		return r;
	}

	//doCommand -> doValidate -> validateSaveBefore ->
	private boolean validateSaveFormAfter(Component comp, String command, Map validates,
			boolean valid, Set notifys) {
		final List bindings = _infoProvider.getSaveFormAfterBindings().get(command); //_saveFormBeforeBindings.get(command);
		boolean r = valid;
		if (bindings != null) {
			for (SaveFormBinding binding : bindings) {
				r &= validateSaveFormBinding(comp, binding, command, validates, r, notifys);
			}
		}
		return r;
	}

	//collect properties from a save-binding
	private void collectSavePropertyBinding(Component comp, SavePropertyBinding binding, String command, Event evt,
			Set validates, boolean checkFormFieldFromCollection) {
		final BindContext ctx = BindContextUtil.newBindContext(_binder, binding, true, command, binding.getComponent(),
				evt);
		BindContextUtil.setConverterArgs(_binder, binding.getComponent(), ctx, binding);
		Set cp = new HashSet();
		Property p = binding.getValidate(ctx);
		_mainPropertyCache.put(binding, p);
		cp.add(p); //main property
		if (checkFormFieldFromCollection) { //ZK-3185: Enable form validation with reference and collection binding
			Property pc = ((SavePropertyBindingImpl) binding).getBasePropertyIfFromCollection(); //Check if field from collection
			if (pc != null) cp.add(pc);
		}
		validates.addAll(cp); //collect properties to be validated
	}

	//collect properties from a save-binding
	private void collectSavePropertyBinding(Component comp, SavePropertyBinding binding, String command, Event evt,
											Set validates) {
		collectSavePropertyBinding(comp, binding, command, evt, validates, false);
	}

	//collect properties form a save-form-binding
	private void collectSaveFormBinding(Component comp, SaveFormBinding binding, String command, Event evt,
			Set validates) {
		//ZK-3185: Enable form validation with reference and collection binding
		String formId = binding.getFormId();
		Component formComp = binding.getComponent();
		Binder binder = binding.getBinder();
		Form form = ((BinderCtrl) binding.getBinder()).getForm(formComp, formId);
		if (form instanceof FormProxyObject) {
			Set> cachedSavePropertyBindings = ((FormProxyObject) form).collectCachedSavePropertyBinding();
			for (Pair p : cachedSavePropertyBindings) {
				SavePropertyBinding spbinding = p.getY();
				String fieldName = p.getX();
				Component cachedComp = spbinding.getComponent();
				if (cachedComp.getDesktop() != null) {
					((BinderCtrl) binder).addFormAssociatedSaveBinding(spbinding.getComponent(), formId, spbinding, fieldName);
					((BinderCtrl) binder).addSaveFormFieldName(form, fieldName);
				}
			}
		}

		Set savebindings = ((BinderCtrl) binder).getFormAssociatedSaveBindings(formComp);
		for (SaveBinding sbinding : savebindings) {
			if (sbinding instanceof SavePropertyBinding) {
				collectSavePropertyBinding(comp, ((SavePropertyBinding) sbinding), command, evt, validates, true);
			} else {
				// any other possible to go here?
			}
		}

		final BindContext ctx = BindContextUtil.newBindContext(_binder, binding, true, command, binding.getComponent(),
				evt);

		Set cp = new HashSet();
		Property p = binding.getValidate(ctx);
		_mainPropertyCache.put(binding, p);

		cp.add(p); // the main property
		cp.addAll(binding.getValidates(ctx)); // the field properties in form
		validates.addAll(cp); //collect properties to be validated
	}

	//validate a save-binding
	private boolean validateSavePropertyBinding(Component comp, SavePropertyBinding binding, String command,
			Map validates, boolean valid, Set notifys) {
		if (!binding.hasValidator())
			return true;

		//clear previous message before validation
		if (((BinderImpl) binding.getBinder()).hasValidator(binding.getComponent(), binding.getFieldName())) {
			clearValidationMessage(binding.getBinder(), binding.getComponent(), binding.getFieldName());
		}

		final BindContext ctx = BindContextUtil.newBindContext(_binder, binding, true, command, binding.getComponent(),
				null);
		BindContextUtil.setValidatorArgs(binding.getBinder(), binding.getComponent(), ctx, binding);

		Property p = _mainPropertyCache.get(binding);
		ValidationContextImpl vContext = new ValidationContextImpl(command, p, validates, ctx, valid);
		binding.validate(vContext);
		final Set xnotifys = getNotifys(ctx);
		if (xnotifys != null) {
			notifys.addAll(xnotifys);
		}
		return vContext.isValid();
	}

	private void clearValidationMessage(Binder binder, Component component, String attr) {
		ValidationMessages vmsgs = ((BinderCtrl) binder).getValidationMessages();
		if (vmsgs != null) {
			vmsgs.clearMessages(component, attr);
		}
	}

	//validate a save-form-binding
	private boolean validateSaveFormBinding(Component comp, SaveFormBinding binding, String command,
			Map validates, boolean valid, Set notifys) {
		//validate tracked savebinding
		Set savebindings = ((BinderCtrl) binding.getBinder())
				.getFormAssociatedSaveBindings(binding.getComponent());
		boolean svalid = true;
		for (SaveBinding sbinding : savebindings) {
			if (sbinding instanceof SavePropertyBinding) {
				svalid &= validateSavePropertyBinding(comp, ((SavePropertyBinding) sbinding), command, validates,
						svalid & valid, notifys);
			} else {
				// any other possible to go here?
			}
		}
		if (!binding.hasValidator())
			return svalid;

		//clear previous message before validation
		if (((BinderImpl) binding.getBinder()).hasValidator(binding.getComponent(), binding.getFormId())) {
			clearValidationMessage(binding.getBinder(), binding.getComponent(), binding.getFormId());
		}

		final BindContext ctx = BindContextUtil.newBindContext(_binder, binding, true, command, binding.getComponent(),
				null);
		BindContextUtil.setValidatorArgs(binding.getBinder(), binding.getComponent(), ctx, binding);

		Property p = _mainPropertyCache.get(binding);
		ValidationContextImpl vContext = new ValidationContextImpl(command, p, validates, ctx, svalid & valid);
		binding.validate(vContext);
		final Set xnotifys = getNotifys(ctx);
		if (xnotifys != null) {
			notifys.addAll(xnotifys);
		}
		return svalid && vContext.isValid();

	}

	@SuppressWarnings("unchecked")
	private static Set getNotifys(BindContext ctx) {
		return (Set) ctx.getAttribute(BinderImpl.NOTIFYS);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy