package info.joseluismartin.gui.bind;

import info.joseluismartin.gui.Binder;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;

/**
 * Composite Binder methods to a collection of
 * PropertyBinders that bind on the same model 
 * 
 * @author Jose Luis Martin - (jlm@joseluismartin.info)
 * @param <T> model 
 */
public class CompositeBinder<T> implements Binder<T> {
	
	private BinderFactory binderFactory;
	private Map<String, Binder<?>> binders = new HashMap<String, Binder<?>>();
	/** Default model to bind on for property binders */
	private T model;

	
	public CompositeBinder() {
		
	}
	
	/**
	 * @param T model
	 */
	public CompositeBinder(T model) {
		this.model = model;
	}

	public void bind(Object component, String propertyName) {
		bind(component, propertyName, false);
	}
	

	public void bind(Object component, String propertyName, boolean readOnly) {
		bind(component, propertyName, this, readOnly);
	}


	
	public void bind(Object component, String propertyName, Object object, boolean readOnly) {
		PropertyBinder binder = binderFactory.getBinder(component.getClass());
		if (binder != null) {
			binder.bind(component, propertyName, object, readOnly);
			binders.put(propertyName, binder);
		}
	}

	public void refresh() {
		for (Binder<?> b : binders.values())
			b.refresh();
	}

	public void addBinder(Binder<?> binder, String name) {
		binders.put(name, binder);
	}
	

	
	public void update() {
		for (Binder<?> b : binders.values())
			b.update();
		
	}
	
	public Binder<?> getBinder(String propertyName) {
		return binders.get(propertyName);
	}
	
	public Set<String> getPropertyNames() {
		return binders.keySet();
	}
	
	public Collection<Binder<?>> getPropertyBinders() {
		return binders.values();
	}

	/**
	 * @return the binderFactory
	 */
	public BinderFactory getBinderFactory() {
		return binderFactory;
	}

	/**
	 * @param binderFactory the binderFactory to set
	 */
	public void setBinderFactory(BinderFactory binderFactory) {
		this.binderFactory = binderFactory;
	}

	public T getModel() {
		return model;
	}
	
	public void setModel(T model) {
		this.model = model;
	}

	/**
	 * {@inheritDoc}
	 */
	public BindingResult getBindingResult() {
		BindingResult br = new BeanPropertyBindingResult(model, "model");
		for (Binder<?> b : binders.values())
			br.addAllErrors(b.getBindingResult());
		
		return br;
	}

}

@@ -475,16 +475,47 @@
 el %0A */%0A
+@SuppressWarnings(%22unchecked%22)%0A
 public c
@@ -629,17 +629,17 @@
  Binder%3C
-?
+T
 %3E%3E binde
@@ -670,17 +670,17 @@
  Binder%3C
-?
+T
 %3E%3E();%0A%09/
@@ -1092,20 +1092,26 @@
 tyName, 
-this
+getModel()
 , readOn
@@ -1120,18 +1120,16 @@
 );%0A%09%7D%0A%0A%0A
-%09%0A
 %09public 
@@ -1181,21 +1181,15 @@
 me, 
-Object object
+T model
 , bo
@@ -1231,16 +1231,17 @@
 binder =
+ 
  binderF
@@ -1348,14 +1348,13 @@
 me, 
-object
+model
 , re
@@ -1386,24 +1386,36 @@
 ropertyName,
+ (Binder%3CT%3E)
  binder);%0A%09%09
@@ -1579,16 +1579,28 @@
 ut(name,
+ (Binder%3CT%3E)
  binder)
@@ -1886,17 +1886,17 @@
 %3CBinder%3C
-?
+T
 %3E%3E getPr
@@ -2313,24 +2313,91 @@
 el = model;%0A
+%09%09for (Binder%3CT%3E b : binders.values()) %7B%0A%09%09%09b.setModel(model);%0A%09%09%7D%0A
 %09%7D%0A%0A%09/**%0A%09 *
@@ -2459,16 +2459,61 @@
 ult() %7B%0A
+%09%09if (getModel() == null)%0A%09%09%09return null;%0A%09%09%0A
 %09%09Bindin
@@ -2559,22 +2559,63 @@
 ult(
-model, %22model%22
+getModel(), getModel().getClass().getSimpleName(), true
 );%0A%09
@@ -2647,25 +2647,65 @@
 rs.values())
+ %7B
 %0A
+%09%09%09if (b.getBindingResult() != null)%0A%09
 %09%09%09br.addAll
@@ -2734,16 +2734,20 @@
 ult());%0A
+%09%09%7D%0A
 %09%09%0A%09%09ret

Add binding result to composite binder