class ChainReferenceValidator implements ConstraintValidator<ValidChainReference, ProcessorReferenceChainDescription> {

	@Override
	public boolean isValid(ProcessorReferenceChainDescription chainReference, ConstraintValidatorContext context) {
		if (chainReference == null) return true;

		List<ProcessorReference> references = chainReference.getProcessors();
		if (references == null || references.isEmpty())
			return setAndReturnErrorMessage(context, "processor chain cannot be empty");
		if (!specificationManager.getByName(references.get(0).getName()).getType().equals(ProcessorType.SOURCE_ADAPTER))
			return setAndReturnErrorMessage(context, "processor chain must start with " + ProcessorType.SOURCE_ADAPTER);

		ProcessorReference lastReference =  null;
		for (ProcessorReference reference : references) {
			if (lastReference != null) {
				ProcessorType lastType = specificationManager.getByName(lastReference.getName()).getType();
				ProcessorType nextType = specificationManager.getByName(reference.getName()).getType();
				if (!lastType.isValidNextFilter(nextType)) return setAndReturnErrorMessage(context, lastType + " cannot be followed by " + nextType);
			}
			if (!isValid(reference, context)) return false;
			lastReference = reference;
		}
		return true;
	}

	@Inject  ChainReferenceValidator(SpecificationManager specificationManager);

}