# ParameterBinderProvider.java

    package org.codefilarete.stalactite.sql.statement.binder;

    import java.util.Map;

    import org.codefilarete.stalactite.sql.statement.SQLStatement.BindingException;

    /**
     * Simple contract for giving a {@link ParameterBinder} thanks to a certain kind of key.
     *
     * @author Guillaume Mary
     */
    public interface ParameterBinderProvider<K> extends PreparedStatementWriterProvider<K>, ResultSetReaderProvider<K> {

    	/**
    	 * Gives a {@link ParameterBinder} from a key.
    	 * Will throw an exception in case of missing {@link ParameterBinder}
    	 *
    	 * @param key an object for which a {@link ParameterBinder} is expected
    	 * @return the {@link ParameterBinder} associated with the key
    	 */
    	default ParameterBinder getBinder(K key) {
    		ParameterBinder binder = doGetBinder(key);
    		if (binder == null) {
    			throw new BindingException("Binder for " + key + " is not registered");
    		}
    		return binder;
    	}

    	ParameterBinder doGetBinder(K key);

    	@Override
    	default PreparedStatementWriter doGetWriter(K key) {
    		return doGetBinder(key);
    	}

    	@Override
    	default ResultSetReader doGetReader(K key) {
    		return doGetBinder(key);
    	}

    	/**
    	 * A simple {@link ParameterBinderProvider} that takes its values from a {@link Map}
    	 *
    	 * @author Guillaume Mary
    	 */
    	class ParameterBinderProviderFromMap<ParamType, BINDER extends ParameterBinder> implements ParameterBinderProvider<ParamType> {

    		private final Map<ParamType, BINDER> parameterBinders;

    		public ParameterBinderProviderFromMap(Map<ParamType, BINDER> parameterBinders) {
    			this.parameterBinders = parameterBinders;
    		}

    		public Map<ParamType, BINDER> getParameterBinders() {
    			return parameterBinders;
    		}

    		@Override
    		public BINDER doGetBinder(ParamType key) {
    			return parameterBinders.get(key);
    		}

    	}
    }