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

com.strategicgains.syntaxe.ValidationEngine Maven / Gradle / Ivy

There is a newer version: 1.0
Show newest version
/*
    Copyright 2010, Strategic Gains, Inc.

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

		http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
 */
package com.strategicgains.syntaxe;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import com.strategicgains.syntaxe.annotation.FieldValidation;
import com.strategicgains.syntaxe.annotation.ObjectValidation;
import com.strategicgains.syntaxe.annotation.ValidationProvider;
import com.strategicgains.syntaxe.util.ClassUtils;
import com.strategicgains.syntaxe.validator.AnnotatedFieldValidator;
import com.strategicgains.syntaxe.validator.Validator;

/**
 * @author toddf
 * @since Oct 7, 2010
 */
public class ValidationEngine
{
	private static final ConcurrentHashMap, List> cachedFieldsByClass = new ConcurrentHashMap, List>();
	private static final ConcurrentHashMap> cachedValidatorsByHashcode = new ConcurrentHashMap>();
	private static final ConcurrentHashMap, Validator> cachedObjectValidatorsByClass = new ConcurrentHashMap, Validator>();

	private ValidationEngine()
	{
		// Prevents instantiation.
	}

	/**
	 * Validates the object, returning a list of error messages
	 * if validation fails.  If the list is empty, no errors
	 * occurred.
	 * 
	 * @param object
	 * @return a List of error message strings. Never null.
	 */
	public static List validate(Object object)
	{
		List errors = new ArrayList();

		try
		{
			validateFields(object, errors);
			validateObject(object, errors);
//			validateIfValidatable(object);
		}
		catch (Exception e)
		{
			errors.add("Exception while validating: " + e.getMessage());
		}

		return errors;
	}

	/**
	 * Validates the object, throwing a ValidationException
	 * if there were errors.
	 * 
	 * @param object
	 * @throws ValidationException containing the error messages if a validation error occurs.
	 */
	public static void validateAndThrow(Object object)
	{
		List errors = validate(object);
		
		if (!errors.isEmpty())
		{
			throw new ValidationException(errors);
		}
	}

	private static void validateFields(Object object, List errors)
	throws Exception
	{
		Collection fields = getAllDeclaredFields(object.getClass());

		for (Field field : fields)
		{
			List validators = getValidators(field, object);

			if (!validators.isEmpty())
			{
				try
				{
					for (Validator validator : validators)
					{
						validator.perform(object, errors);
					}
				}
				catch (ValidationException e)
				{
					e.printStackTrace();
				}
			}
		}
	}

	private static List getValidators(Field field, Object object)
	throws InstantiationException, IllegalAccessException, SecurityException,
		NoSuchMethodException, IllegalArgumentException, InvocationTargetException
	{
		List validators = cachedValidatorsByHashcode.get(field.hashCode());
		
		if (validators != null)
		{
			return validators;
		}
		
		validators  = new ArrayList();

		for (Annotation a : field.getAnnotations())
		{
			if (a.annotationType().isAnnotationPresent(ValidationProvider.class))
			{
				ValidationProvider providerAnnotation = a.annotationType().getAnnotation(ValidationProvider.class);
				Constructor constructor = providerAnnotation.value().getConstructor(Field.class, a.annotationType());
				AnnotatedFieldValidator provider = (AnnotatedFieldValidator) constructor.newInstance(field, a);
				validators.add(provider);
			}
			else if (a.annotationType().isAssignableFrom(FieldValidation.class))
			{
				Class vc = ((FieldValidation) a).value();
				validators.add(vc.newInstance());
			}
		}

		cachedValidatorsByHashcode.put(field.hashCode(), validators);
		return validators;
	}
	
	private static Collection getAllDeclaredFields(Class aClass)
	{
		List fields = cachedFieldsByClass.get(aClass);
		
		if (fields == null)
		{
			fields = ClassUtils.getAllDeclaredFields(aClass);
			cachedFieldsByClass.put(aClass, fields);
		}
		
		return fields;
	}

	private static void validateObject(Object object, List errors)
	throws InstantiationException, IllegalAccessException
	{
		ObjectValidation annotation = object.getClass().getAnnotation(ObjectValidation.class);
		
		if (annotation == null) return;
		
		Validator validator = cachedObjectValidatorsByClass.get(object.getClass());
		
		if (validator == null)
		{
			validator = annotation.value().newInstance();
			cachedObjectValidatorsByClass.put(object.getClass(), validator);
		}
		
		validator.perform(object, errors);
	}

//	private static void validateIfValidatable(Object object)
//	{
//		if (Validatable.class.isAssignableFrom(object.getClass()))
//		{
//			((Validatable) object).validate();
//		}
//	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy