001 /******************************************************************************* 002 * Portions created by Sebastian Thomschke are copyright (c) 2005-2013 Sebastian 003 * Thomschke. 004 * 005 * All Rights Reserved. This program and the accompanying materials 006 * are made available under the terms of the Eclipse Public License v1.0 007 * which accompanies this distribution, and is available at 008 * http://www.eclipse.org/legal/epl-v10.html 009 * 010 * Contributors: 011 * Sebastian Thomschke - initial implementation. 012 *******************************************************************************/ 013 package net.sf.oval.constraint; 014 015 import static net.sf.oval.Validator.getCollectionFactory; 016 017 import java.lang.reflect.Method; 018 import java.util.Map; 019 020 import net.sf.oval.ConstraintTarget; 021 import net.sf.oval.Validator; 022 import net.sf.oval.configuration.annotation.AbstractAnnotationCheck; 023 import net.sf.oval.context.OValContext; 024 import net.sf.oval.exception.InvalidConfigurationException; 025 import net.sf.oval.exception.ReflectionException; 026 import net.sf.oval.internal.util.ReflectionUtils; 027 028 /** 029 * @author Sebastian Thomschke 030 */ 031 public class ValidateWithMethodCheck extends AbstractAnnotationCheck<ValidateWithMethod> 032 { 033 private static final long serialVersionUID = 1L; 034 035 private boolean ignoreIfNull; 036 private String methodName; 037 private Class< ? > parameterType; 038 039 /** 040 * {@inheritDoc} 041 */ 042 @Override 043 public void configure(final ValidateWithMethod constraintAnnotation) 044 { 045 super.configure(constraintAnnotation); 046 setMethodName(constraintAnnotation.methodName()); 047 setParameterType(constraintAnnotation.parameterType()); 048 setIgnoreIfNull(constraintAnnotation.ignoreIfNull()); 049 } 050 051 /** 052 * {@inheritDoc} 053 */ 054 @Override 055 protected Map<String, String> createMessageVariables() 056 { 057 final Map<String, String> messageVariables = getCollectionFactory().createMap(4); 058 messageVariables.put("ignoreIfNull", Boolean.toString(ignoreIfNull)); 059 messageVariables.put("methodName", methodName); 060 messageVariables.put("parameterType", parameterType.getName()); 061 return messageVariables; 062 } 063 064 /** 065 * {@inheritDoc} 066 */ 067 @Override 068 protected ConstraintTarget[] getAppliesToDefault() 069 { 070 return new ConstraintTarget[]{ConstraintTarget.VALUES}; 071 } 072 073 /** 074 * @return the methodName 075 */ 076 public String getMethodName() 077 { 078 return methodName; 079 } 080 081 /** 082 * @return the parameterType 083 */ 084 public Class< ? > getParameterType() 085 { 086 return parameterType; 087 } 088 089 /** 090 * @return the ignoreIfNull 091 */ 092 public boolean isIgnoreIfNull() 093 { 094 return ignoreIfNull; 095 } 096 097 /** 098 * {@inheritDoc} 099 */ 100 public boolean isSatisfied(final Object validatedObject, final Object valueToValidate, final OValContext context, 101 final Validator validator) throws ReflectionException 102 { 103 if (valueToValidate == null && ignoreIfNull) return true; 104 105 final Method method = ReflectionUtils.getMethodRecursive(validatedObject.getClass(), methodName, parameterType); 106 if (method == null) 107 throw new InvalidConfigurationException("Method " + validatedObject.getClass().getName() + "." + methodName + "(" 108 + parameterType + ") not found. Is [" + parameterType + "] the correct value for [parameterType]?"); 109 //explicit cast to avoid: type parameters of <T>T cannot be determined; no unique maximal instance exists for type variable T with upper bounds boolean,java.lang.Object 110 return (Boolean) ReflectionUtils.invokeMethod(method, validatedObject, valueToValidate); 111 } 112 113 /** 114 * @param ignoreIfNull the ignoreIfNull to set 115 */ 116 public void setIgnoreIfNull(final boolean ignoreIfNull) 117 { 118 this.ignoreIfNull = ignoreIfNull; 119 requireMessageVariablesRecreation(); 120 } 121 122 /** 123 * @param methodName the methodName to set 124 */ 125 public void setMethodName(final String methodName) 126 { 127 this.methodName = methodName; 128 requireMessageVariablesRecreation(); 129 } 130 131 /** 132 * @param parameterType the parameterType to set 133 */ 134 public void setParameterType(final Class< ? > parameterType) 135 { 136 this.parameterType = parameterType; 137 requireMessageVariablesRecreation(); 138 } 139 }