View Javadoc

1   package org.lsst.ccs.config;
2   
3   import groovy.util.Eval;
4   import org.apache.commons.beanutils.MethodUtils;
5   import org.lsst.gruth.types.IncompatibleTypeException;
6   import org.lsst.gruth.jutils.SStructParm;
7   import org.lsst.gruth.types.GArray;
8   import org.lsst.gruth.types.GStruct;
9   
10  import java.lang.reflect.InvocationTargetException;
11  import java.util.List;
12  import java.util.Map;
13  
14  /**
15   * A set of static methods to check constraints.
16   * @author bamade
17   */
18  // Date: 31/05/12
19  
20  public class Constraints {
21      /**
22       * A specific code to control a value.
23       * instance of this class are supposed to have a no-arg constructor.
24       */
25      public static interface Controler {
26          /**
27           * should transform the String argument as a valid value and check it.
28           * @param value
29           * @returna the correct object or throws an exception
30           */
31          public Object control(String value);
32      }
33  
34      public static Object check (String type, String value , String constraints) {
35          Object realValue = null ;
36          type = type.trim() ;
37          //TODO: whatif value == null or "".equals(value) ?
38          value = value.trim() ;
39          if(constraints != null) {
40              constraints = constraints.trim() ;
41              if(! "".equals(constraints)) {
42                  return checkConstraints(type, value, constraints) ;
43              }
44          }
45          Class thatClass = null;
46          try {
47              thatClass = Class.forName(type);
48              if(thatClass.isArray()) {
49                 realValue = GArray.valueOf(value, thatClass.getName()) ;
50              } else if (null!= SStructParm.structClassUsesList(thatClass)) {
51                  realValue = GStruct.valueOf(thatClass, value) ;
52              } else {
53                  realValue = MethodUtils.invokeStaticMethod(thatClass, "valueOf", value);
54              }
55          } catch (ClassNotFoundException e) {
56              throw new IllegalArgumentException(e);
57          } catch (NoSuchMethodException e) {
58              if( Map.class.isAssignableFrom(thatClass)||
59                      List.class.isAssignableFrom(thatClass)){
60                  try {
61                      realValue = Eval.me(value) ;
62                  } catch (Exception exc) {
63                      throw new IllegalArgumentException(exc);
64                  }
65                  Class realClass = realValue.getClass();
66                  if(! thatClass.isAssignableFrom(realClass)) {
67                      throw new IncompatibleTypeException(thatClass, realClass);
68                  }
69              } else {
70                  throw new IllegalArgumentException(e);
71              }
72          } catch (IllegalAccessException e) {
73              throw new IllegalArgumentException(e);
74          } catch (InvocationTargetException e) {
75              throw new IllegalArgumentException(e);
76          } catch (Exception exc) {
77              return null ;
78          }
79          return realValue ;
80  
81      }
82  
83      public static Object checkConstraints(String type, String value, String constraints) {
84          //type = type.trim();
85          //value = value.trim() ;
86          // constraints = constraints.trim() ;
87          //is a range
88          String[] split = constraints.split("\\.\\.");
89          if (split.length == 2) {
90              return checkRange(type, value, split[0], split[1]);
91          }
92          // is a controler
93          try {
94  
95              Controler controler = (Controler) Class.forName(constraints).newInstance();
96              return checkWithControler(value, controler);
97          } catch (Exception exc) {
98              throw new IllegalArgumentException("constraint :" + constraints + " " + exc);
99          }
100     }
101 
102     /**
103      * checks if the value of type  is between lower and upper (included).
104      * @param type a Class Name. the class <B>should</B> have a static factory method <TT>valueOf(String val)</TT>
105      *             (but <TT>java.lang.Character</TT> is still ok)
106      * @param value
107      * @param lower
108      * @param upper
109      * @return
110      */
111     public static Object checkRange(String type, String value, String lower, String upper) {
112         // should have a valueOf method and should yiled a Comparable Object
113         Class thatClass = null;
114         try {
115             //TODO: does not work for Character!
116             if("java.lang.Character".equals(type)) {
117                 type = "java.lang.String" ;
118             }
119             thatClass = Class.forName(type);
120         } catch (Exception exc) {
121             throw new IllegalArgumentException(exc);
122         }
123          return checkRange(thatClass, value, lower, upper) ;
124 
125     }
126 
127     public static Object checkRange(Class thatClass, String value, String lower, String upper) {
128         Object realValue = null ;
129         try {
130              realValue = MethodUtils.invokeStaticMethod(thatClass, "valueOf", value);
131             Object realUpper = MethodUtils.invokeStaticMethod(thatClass, "valueOf", upper);
132             Object realLower = MethodUtils.invokeStaticMethod(thatClass, "valueOf", lower);
133             Comparable compValue = (Comparable) realValue ;
134             if((compValue.compareTo(realLower) >= 0) && (compValue.compareTo(realUpper) <= 0)) {
135                 return realValue ;
136             } else {
137                throw new IllegalArgumentException(realValue + "not in range [" +realLower + ".." + realUpper+"]") ;
138             }
139         } catch (Exception exc) {
140             throw new IllegalArgumentException("range " + lower + ".." + upper +
141                     " and value :" + value + " raises :" + exc);
142         }
143 
144     }
145 
146     public static Object checkWithControler(String value, Controler controler) {
147         return controler.control(value);
148     }
149 }