View Javadoc

1   package org.xmlfield.validation;
2   
3   import java.lang.annotation.Annotation;
4   import java.lang.reflect.InvocationTargetException;
5   import java.lang.reflect.Method;
6   import java.lang.reflect.Type;
7   import java.util.HashSet;
8   import java.util.Iterator;
9   import java.util.Set;
10  
11  import org.xmlfield.annotations.FieldXPath;
12  import org.xmlfield.validation.handlers.ConstraintViolation;
13  import org.xmlfield.validation.handlers.IHandler;
14  import org.xmlfield.validation.handlers.NotEmptyHandler;
15  import org.xmlfield.validation.handlers.RangeHandler;
16  import org.xmlfield.validation.handlers.SizeHandler;
17  import org.xmlfield.validation.handlers.ValuesHandler;
18  
19  public class XmlFieldValidator {
20  
21      static IHandler[] handlers = new IHandler[] { new NotEmptyHandler(), new SizeHandler(), new ValuesHandler(),
22              new RangeHandler() };
23  
24      public XmlFieldValidator() {
25  
26      }
27  
28      public void ensureValidation(Object xmlFieldObject, Class<?> group) throws XmlFieldValidationException,
29              IllegalArgumentException, IllegalAccessException, InvocationTargetException {
30          Set<ConstraintViolation<Object>> result = validate(xmlFieldObject, true, group);
31  
32          Iterator<ConstraintViolation<Object>> i = result.iterator();
33          while (i.hasNext()) {
34              ConstraintViolation<Object> c = i.next();
35              throw new XmlFieldValidationException(c.getMethodName(), c.getExpected(), c.getActual());
36          }
37  
38      }
39  
40      public void ensureValidation(Object xmlFieldObject) throws XmlFieldValidationException, IllegalArgumentException,
41              IllegalAccessException, InvocationTargetException {
42          ensureValidation(xmlFieldObject, null);
43      }
44  
45      public Set<ConstraintViolation<Object>> validate(Object xmlFieldObject) throws IllegalArgumentException,
46              IllegalAccessException, InvocationTargetException {
47          return validate(xmlFieldObject, null);
48      }
49  
50      public Set<ConstraintViolation<Object>> validate(Object xmlFieldObject, Class<?> group)
51              throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
52          return validate(xmlFieldObject, false, group);
53      }
54  
55      private Set<ConstraintViolation<Object>> validate(Object xmlFieldObject, boolean returnOnFirstViolation,
56              Class<?> group) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
57  
58          // Prepare result
59          Set<ConstraintViolation<Object>> result = new HashSet<ConstraintViolation<Object>>();
60  
61          // Get object interfaces.
62          Type[] types = xmlFieldObject.getClass().getGenericInterfaces();
63  
64          for (Type type : types) {
65              Class<?> interfaceClass = (Class<?>) type;
66              Method[] methods = interfaceClass.getMethods();
67  
68              if (methods != null) {
69                  for (Method m : methods) {
70  
71                      String methodName = m.getName();
72  
73                      // We only process annotations on 'get' or 'is' method. All
74                      // other methods are ignored.
75                      if (!methodName.startsWith("get") && !methodName.startsWith("is"))
76                          continue;
77  
78                      Annotation[] anos = m.getAnnotations();
79                      for (Annotation a : anos) {
80  
81                          // Do validation
82                          for (IHandler h : handlers) {
83                              if (h.handles(a)) {
84                                  Set<ConstraintViolation<Object>> resultHandler = h.validate(a, m, xmlFieldObject, group);
85                                  if (resultHandler != null && resultHandler.size() > 0) {
86                                      result.addAll(resultHandler);
87  
88                                      if (returnOnFirstViolation)
89                                          return result;
90                                  }
91                              }
92                          }
93  
94                          // If the method returns another XmlField object, do
95                          // recursive validation.
96                          if (a instanceof FieldXPath) {
97                              // Single object
98                              if (m.getReturnType() != null && m.getReturnType().isInterface()) {
99                                  Object o = m.invoke(xmlFieldObject);
100                                 if (o != null) {
101                                     result.addAll(validate(m.invoke(xmlFieldObject)));
102                                     if (result.size() > 0 && returnOnFirstViolation)
103                                         return result;
104                                 }
105                             }
106 
107                             // Array
108                             if (m.getReturnType() != null && m.getReturnType().isArray()
109                                     && m.getReturnType().getComponentType().isInterface()) {
110                                 Object[] arrayResult = (Object[]) m.invoke(xmlFieldObject);
111                                 // Validate every object
112                                 if (arrayResult != null) {
113                                     for (Object o : arrayResult) {
114                                         if (o != null) {
115                                             result.addAll(validate(o));
116                                             if (result.size() > 0 && returnOnFirstViolation)
117                                                 return result;
118                                         }
119                                     }
120                                 }
121                             }
122                         }
123                     }
124                 }
125             }
126         }
127         return result;
128     }
129 }