001 /******************************************************************************* 002 * Portions created by Sebastian Thomschke are copyright (c) 2005-2011 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.Field; 018 import java.lang.reflect.Method; 019 import java.util.Map; 020 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.FieldNotFoundException; 025 import net.sf.oval.exception.InvokingMethodFailedException; 026 import net.sf.oval.exception.MethodNotFoundException; 027 import net.sf.oval.internal.ContextCache; 028 import net.sf.oval.internal.util.ReflectionUtils; 029 030 /** 031 * @author Sebastian Thomschke 032 */ 033 public class NotEqualToFieldCheck extends AbstractAnnotationCheck<NotEqualToField> 034 { 035 private static final long serialVersionUID = 1L; 036 037 private boolean useGetter; 038 039 private String fieldName; 040 041 private Class< ? > declaringClass; 042 043 /** 044 * {@inheritDoc} 045 */ 046 @Override 047 public void configure(final NotEqualToField constraintAnnotation) 048 { 049 super.configure(constraintAnnotation); 050 setFieldName(constraintAnnotation.value()); 051 setDeclaringClass(constraintAnnotation.declaringClass()); 052 setUseGetter(constraintAnnotation.useGetter()); 053 } 054 055 /** 056 * {@inheritDoc} 057 */ 058 @Override 059 protected Map<String, String> createMessageVariables() 060 { 061 final Map<String, String> messageVariables = getCollectionFactory().createMap(2); 062 messageVariables.put("fieldName", fieldName); 063 messageVariables.put("declaringClass", declaringClass == null || declaringClass == Void.class ? null 064 : declaringClass.getName()); 065 messageVariables.put("useGetter", Boolean.toString(useGetter)); 066 return messageVariables; 067 } 068 069 /** 070 * @return the declaringClass 071 */ 072 public Class< ? > getDeclaringClass() 073 { 074 return declaringClass; 075 } 076 077 /** 078 * @return the fieldName 079 */ 080 public String getFieldName() 081 { 082 return fieldName; 083 } 084 085 /** 086 * {@inheritDoc} 087 */ 088 public boolean isSatisfied(final Object validatedObject, final Object valueToValidate, final OValContext context, 089 final Validator validator) 090 { 091 if (valueToValidate == null) return true; 092 093 final Class< ? > clazz = validatedObject.getClass(); 094 095 final Object valueToCompare; 096 if (useGetter) 097 { 098 final Method getter = ReflectionUtils.getGetterRecursive(clazz, fieldName); 099 if (getter == null) 100 throw new MethodNotFoundException("Getter for field <" + fieldName + "> not found in class <" + clazz 101 + "> or it's super classes."); 102 103 try 104 { 105 valueToCompare = getter.invoke(validatedObject); 106 } 107 catch (final Exception ex) 108 { 109 throw new InvokingMethodFailedException(getter.getName(), validatedObject, 110 ContextCache.getMethodReturnValueContext(getter), ex); 111 } 112 } 113 else 114 { 115 final Field field = ReflectionUtils.getFieldRecursive(clazz, fieldName); 116 117 if (field == null) 118 throw new FieldNotFoundException("Field <" + fieldName + "> not found in class <" + clazz 119 + "> or it's super classes."); 120 121 valueToCompare = ReflectionUtils.getFieldValue(field, validatedObject); 122 } 123 124 if (valueToCompare == null) return true; 125 126 return !valueToValidate.equals(valueToCompare); 127 } 128 129 /** 130 * @return the useGetter 131 */ 132 public boolean isUseGetter() 133 { 134 return useGetter; 135 } 136 137 /** 138 * @param declaringClass the declaringClass to set 139 */ 140 public void setDeclaringClass(final Class< ? > declaringClass) 141 { 142 this.declaringClass = declaringClass == Void.class ? null : declaringClass; 143 requireMessageVariablesRecreation(); 144 } 145 146 /** 147 * @param fieldName the fieldName to set 148 */ 149 public void setFieldName(final String fieldName) 150 { 151 this.fieldName = fieldName; 152 requireMessageVariablesRecreation(); 153 } 154 155 /** 156 * @param useGetter the useGetter to set 157 */ 158 public void setUseGetter(final boolean useGetter) 159 { 160 this.useGetter = useGetter; 161 requireMessageVariablesRecreation(); 162 } 163 }