package info.bukova.isspst.security;

import java.util.Map;

import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;

/**
 * Kontainer vyhodnocovačů práv. Nastavuje se přes Spring kontext:
 * <pre>
 * {@code
 * <bean id="evalHolder" class="info.bukova.isspst.security.EvaluatorsHolder">
 *		<property name="globalEvaluators">
 *			<map>
 *				<entry key="#{T(info.bukova.isspst.services.Service)}" value-ref="serviceEval"/>
 *				<entry key="#{T(info.bukova.isspst.data.Requirement)}" value-ref="reqEditEval"/>
 *				<entry key="#{T(info.bukova.isspst.data.TripRequirement)}" value-ref="tripReqEditEval"/>
 *				<entry key="#{T(info.bukova.isspst.data.User)}" value-ref="userEvaluator"/>
 *			</map>
 *		</property>
 *		.......
 * }
 * </pre>
 * Vyhodnocovače jsou registrovány pro třídy jejichž některé metody podléhají kontrole práv - mají
 * anotace {@link PreAuthorize} nebo {@link PostFilter}
 *  
 * @author pepa
 *
 */
public class EvaluatorsHolder {

	private Map<Class<?>, Evaluator> globalEvaluators;
	private Map<Class<?>, Evaluator> specialEvaluators;

	public void setGlobalEvaluators(Map<Class<?>, Evaluator> globalEvaluators) {
		this.globalEvaluators = globalEvaluators;
	}

	public void setSpecialEvaluators(Map<Class<?>, Evaluator> specialEvaluators) {
		this.specialEvaluators = specialEvaluators;
	}
	
	/**
	 * Podle třídy/rozhraní předaného objektu vrátí instanci vyhodnocovače.
	 * 
	 * @param object	objekt, ve kterém se provádí kontrola práv
	 * @param special	true, pokud se má kontrolovat speciální oprávnění vstažené ke středisku/komisi
	 * @return			instanci vyhodnocovače {@link Evaluator}. Pokud třída objektu nemá zaregistrovaný vyhodnocovač, vrací null.
	 */
	public Evaluator getForObject(Object object, boolean special) {
		Map<Class<?>, Evaluator> evals;
		
		if (special) {
			evals = specialEvaluators;
		} else {
			evals = globalEvaluators;
		}
		
		for (Class<?> key : evals.keySet()) {
			if (key.equals(object.getClass())) {
				return evals.get(key);
			}
		}
		
		for (Class<?> key : evals.keySet()) {
			if (key.isAssignableFrom(object.getClass())) {
				return evals.get(key);
			}
		}
		
		return null;
	}
}
