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

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

/* PropertyBindingHelper.java

	Purpose:
		
	Description:
		
	History:
		2011/11/14 Created by Dennis Chen

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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zkoss.bind.BindContext;
import org.zkoss.bind.Phase;
import org.zkoss.bind.Property;
import org.zkoss.bind.ValidationContext;
import org.zkoss.bind.sys.Binding;
import org.zkoss.bind.sys.InitPropertyBinding;
import org.zkoss.bind.sys.LoadPropertyBinding;
import org.zkoss.bind.sys.SavePropertyBinding;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.UiException;
import org.zkoss.zk.ui.event.Event;

/**
 * to help property-binding implementation of  BinderImpl 
 * @author dennis
 * @since 6.0.0
 */
/*package*/ class PropertyBindingHandler extends AbstractBindingHandler{
	private static final long serialVersionUID = 1L;

	private static final Logger _log = LoggerFactory.getLogger(PropertyBindingHandler.class);
	
	private final Map> _initBindings; //comp+_fieldExpr -> bindings (load when init)
	private final Map> _loadPromptBindings; //comp+_fieldExpr -> bindings (load _prompt | load on property change)
	private final Map> _loadEventBindings; //comp+evtnm -> bindings (load on event)
	private final Map> _saveEventBindings; //comp+evtnm -> bindings (save on event)
	private final Map> _loadAfterBindings; //command -> bindings (load after command)
	private final Map> _saveAfterBindings; //command -> bindings (save after command)
	private final Map> _loadBeforeBindings; //command -> bindings (load before command)
	private final Map> _saveBeforeBindings; //command -> bindings (save before command)
	
	
	PropertyBindingHandler() {
		_initBindings = new HashMap>();
		_loadPromptBindings = new HashMap>();
		_loadEventBindings = new HashMap>();
		_saveEventBindings = new HashMap>();
		_loadAfterBindings = new HashMap>();
		_saveAfterBindings = new HashMap>();
		_loadBeforeBindings = new HashMap>();
		_saveBeforeBindings = new HashMap>();
	}
	
	void addLoadEventBinding(Component comp, BindingKey bkey, LoadPropertyBinding binding) {
		List bindings = _loadEventBindings.get(bkey); 
		if (bindings == null) {
			bindings = new ArrayList();
			_loadEventBindings.put(bkey, bindings);
		}
		bindings.add(binding);
	}
	void addLoadPromptBinding(Component comp, BindingKey bkey, LoadPropertyBinding binding) {
		List bindings = _loadPromptBindings.get(bkey); 
		if (bindings == null) {
			bindings = new ArrayList();
			_loadPromptBindings.put(bkey, bindings);
		}
		bindings.add(binding);
	}
	void addInitBinding(BindingKey bkey, InitPropertyBinding binding) {
		List bindings = _initBindings.get(bkey); 
		if (bindings == null) {
			bindings = new ArrayList();
			_initBindings.put(bkey, bindings);
		}
		bindings.add(binding);
	}
	
	void addLoadBeforeBinding(String command, LoadPropertyBinding binding) {
		List bindings = _loadBeforeBindings.get(command);
		if (bindings == null) {
			bindings = new ArrayList();
			_loadBeforeBindings.put(command, bindings);
		}
		bindings.add(binding);
	}
	
	void addLoadAfterBinding(String command, LoadPropertyBinding binding) {
		List bindings = _loadAfterBindings.get(command);
		if (bindings == null) {
			bindings = new ArrayList();
			_loadAfterBindings.put(command, bindings);
		}
		bindings.add(binding);
	}

	void addSavePromptBinding(Component comp, BindingKey bkey, SavePropertyBinding binding) {
		List bindings = _saveEventBindings.get(bkey); 
		if (bindings == null) {
			bindings = new ArrayList();
			_saveEventBindings.put(bkey, bindings);
		}
		bindings.add(binding);
	}
	
	void addSaveBeforeBinding(String command, SavePropertyBinding binding) {
		List bindings = _saveBeforeBindings.get(command);
		if (bindings == null) {
			bindings = new ArrayList();
			_saveBeforeBindings.put(command, bindings);
		}
		bindings.add(binding);
	}
	
	void addSaveAfterBinding(String command, SavePropertyBinding binding) {
		List bindings = _saveAfterBindings.get(command);
		if (bindings == null) {
			bindings = new ArrayList();
			_saveAfterBindings.put(command, bindings);
		}
		bindings.add(binding);
	}
	
	//generic operation to save a property binding
	private void doSaveBinding(Component comp, SavePropertyBinding binding, String command, Event evt, Set notifys) {
		final BindContext ctx = BindContextUtil.newBindContext(_binder, binding, true, command, binding.getComponent(), evt);
		BindContextUtil.setConverterArgs(_binder, binding.getComponent(), ctx, binding);
		BindContextUtil.setValidatorArgs(_binder, binding.getComponent(), ctx, binding);
		try {
			if(_log.isDebugEnabled()){
				_log.debug("doSavePropertyBinding:binding.save() comp=[%s],binding=[%s],command=[%s],evt=[%s],notifys=[%s]",comp,binding,command,evt,notifys);
			}
			doPrePhase(Phase.SAVE_BINDING, ctx);
			binding.save(ctx);
		} finally {
			doPostPhase(Phase.SAVE_BINDING, ctx);
		}
		
		final Set xnotifys = getNotifys(ctx);
		if (xnotifys != null) {
			notifys.addAll(xnotifys);
		}
	}
	
	//generic operation to load a property binding
	private void doLoadBinding(Component comp, LoadPropertyBinding binding, String command, Event evt) {
		final BindContext ctx = BindContextUtil.newBindContext(_binder, binding, false, command, binding.getComponent(), evt);
		BindContextUtil.setConverterArgs(_binder, binding.getComponent(), ctx, binding);
		if(binding instanceof InitPropertyBindingImpl){
			ctx.setAttribute(BinderImpl.IGNORE_TRACKER, Boolean.TRUE);//ignore tracker when doing el , we don't need to track the init
		}
		try { 
			if(_log.isDebugEnabled()){
				_log.debug("doLoadPropertyBinding:binding.load(),component=[%s],binding=[%s],context=[%s],command=[%s]",comp,binding,ctx,command);
			}
			doPrePhase(Phase.LOAD_BINDING, ctx);
			binding.load(ctx);
			
			//if there is a validator, clear the validation message after load
			if(((BinderImpl)binding.getBinder()).hasValidator(binding.getComponent(), binding.getFieldName())){
				clearValidationMessages(binding.getBinder(),binding.getComponent(),binding.getFieldName());
			}
		} finally {
			doPostPhase(Phase.LOAD_BINDING, ctx);
		}
	}
	
	//for event -> prompt only, no command
	void doLoadEvent(BindingKey bkey,Component comp, Event evt) {
		final List bindings = _loadEventBindings.get(bkey);
		if (bindings != null) {
			for (LoadPropertyBinding binding : bindings) {
				doLoadBinding(comp, binding, null,evt);
			}
		}
	}
	
	boolean doSaveEvent(BindingKey bkey,Component comp, Event evt, Set notifys) {
		final List bindings = _saveEventBindings.get(bkey);
		if (bindings != null) {
			boolean valid = true;
			for (SavePropertyBinding binding : bindings) {
				valid &= doValidateSaveEvent(comp, binding, evt,notifys);
			}
			if(!valid){
				return false;
			}
			for (SavePropertyBinding binding : bindings) {
				doSaveBinding(comp, binding, null, evt, notifys);
			}
		}
		return true;
	}	
	
	//validate a prompt save property binding
	private boolean doValidateSaveEvent(Component comp, SavePropertyBinding binding, Event evt, Set notifys) {
		//for a single binding, if it doesn't need to do validation, then we don't need to anything.
		if (binding.hasValidator()) {
			final BindContext ctx = BindContextUtil.newBindContext(_binder, binding, true, null, binding.getComponent(), evt);
			BindContextUtil.setConverterArgs(_binder, binding.getComponent(), ctx, binding);
			BindContextUtil.setValidatorArgs(_binder, binding.getComponent(), ctx, binding);
			
			try {
				doPrePhase(Phase.VALIDATE, ctx);
				final Property p = binding.getValidate(ctx); 
				if(_log.isDebugEnabled()){
					_log.debug("doValidateSaveEvent comp=[%s],binding=[%s],evt=[%s],validate=[%s]",comp,binding,evt,p);
				}
				if(p==null){
					throw new UiException("no main property for save-binding "+binding);
				}
				
				//clear previous message before validation
				if(((BinderImpl)binding.getBinder()).hasValidator(binding.getComponent(), binding.getFieldName())){
					clearValidationMessages(binding.getBinder(),binding.getComponent(),binding.getFieldName());
				}
				
				ValidationContext vctx = new ValidationContextImpl(null, p, toCollectedProperties(p), ctx, true);
				binding.validate(vctx);
				boolean valid = vctx.isValid();
				if(_log.isDebugEnabled()){
					_log.debug("doValidateSaveEvent result=[%s]",valid);
				}
				
				
				final Set xnotifys = getNotifys(ctx);
				if (xnotifys != null) {
					notifys.addAll(xnotifys);
				}
				
				return valid;
			} catch (Exception e) {
				throw UiException.Aide.wrap(e);
			} finally {
				doPostPhase(Phase.VALIDATE, ctx);
			}
		}
		return true;
	}
	
	

	Map toCollectedProperties(Property validate) {
		Set cp = new HashSet();
		cp.add(validate);
		return toCollectedProperties(cp);
	}
	
	Map toCollectedProperties(Set validates) {
		if(validates==null || validates.size()==0) return Collections.emptyMap();
		Map> temp = new HashMap>(validates.size());
		
		for(Property p:validates){
			List l = temp.get(p.getProperty());
			if(l==null){
				l = new ArrayList();
				temp.put(p.getProperty(), l);
			}
			l.add(p);
		}
		
		Map collected = new HashMap(temp.size());
		for(Entry> e : temp.entrySet()){
			collected.put(e.getKey(), e.getValue().toArray(new Property[e.getValue().size()]));
		}
		return collected;
	}
	
	List getLoadPromptBindings(BindingKey bkey) {
		return _loadPromptBindings.get(bkey);
	}

	Map> getSaveAfterBindings() {
		return _saveAfterBindings;
	}

	Map> getSaveBeforeBindings() {
		return _saveBeforeBindings;
	}

	Map> getSaveEventBindings() {
		return _saveEventBindings;
	}
	
	//doCommand -> doSaveBefore -> doSavePropertyBefore
	void doSaveBefore(Component comp, String command, Event evt, Set notifys) {
		final List bindings = _saveBeforeBindings.get(command);
		if (bindings != null) {
			for (SavePropertyBinding binding : bindings) {
				doSaveBinding(comp, binding, command, evt, notifys);
			}
		}
	}
	
	void doSaveAfter(Component comp, String command, Event evt, Set notifys) {
//		final BindEvaluatorX eval = getEvaluatorX(); 
		final List bindings = _saveAfterBindings.get(command);
		if (bindings != null) {
			for (SavePropertyBinding binding : bindings) {
				doSaveBinding(comp, binding, command, evt, notifys);
			}
		}
	}
	
	void doLoadBefore(Component comp, String command) {
		final List bindings = _loadBeforeBindings.get(command);
		if (bindings != null) {
			for (LoadPropertyBinding binding : bindings) {
				doLoadBinding(comp, binding, command, null);
			}
		}
	}
	
	void doLoadAfter(Component comp, String command) {
		final List bindings = _loadAfterBindings.get(command);
		if (bindings != null) {
			for (LoadPropertyBinding binding : bindings) {
				doLoadBinding(comp, binding, command, null);
			}
		}
	}
	
	void removeBindings(BindingKey bkey, Set removed) {
		List bindingx;
		if((bindingx = _initBindings.remove(bkey)) !=null){
			removed.addAll(bindingx); //comp+_fieldExpr -> bindings (load _prompt)
		}
		if((bindingx = _loadPromptBindings.remove(bkey)) !=null){
			removed.addAll(bindingx); //comp+_fieldExpr -> bindings (load _prompt)
		}
		if((bindingx = _loadEventBindings.remove(bkey)) !=null){
			removed.addAll(bindingx); //comp+evtnm -> bindings (load on event)
		}
		if((bindingx = _saveEventBindings.remove(bkey)) !=null){
			removed.addAll(bindingx); //comp+evtnm -> bindings (save on event)
		}
	}

	void removeBindings(Collection removes) {
		for(List bindings:_loadAfterBindings.values()){
			bindings.removeAll(removes); //command -> bindings (load after command)
		}
		for(List bindings:_saveAfterBindings.values()){
			bindings.removeAll(removes); //command -> bindings (save after command)
		}
		for(List bindings:_loadBeforeBindings.values()){
			bindings.removeAll(removes); //command -> bindings (load before command)
		}
		for(List bindings:_saveBeforeBindings.values()){
			bindings.removeAll(removes); //command -> bindings save before command)
		}
	}

	void doLoad(Component comp, BindingKey bkey) {
		final List propBindings = _loadPromptBindings.get(bkey);
		if (propBindings != null) {
			for (LoadPropertyBinding binding : propBindings) {
				doLoadBinding(comp,binding,null,null);
			}
		}
	}
	
	void doInit(Component comp,BindingKey bkey) {
		final List initBindings = _initBindings.get(bkey);
		if (initBindings != null) {
			for (InitPropertyBinding binding : initBindings) {
				doLoadBinding(comp, binding,null,null);
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy