View Javadoc

1   /*
2    * StandartConstraintsFactory.java
3    * Created on 26 Июнь 2006 г., 13:16
4    */
5   
6   package org.weda.property.impl;
7   
8   import java.lang.reflect.Method;
9   import java.util.ArrayList;
10  import java.util.HashSet;
11  import java.util.LinkedList;
12  import java.util.List;
13  import java.util.Set;
14  import org.weda.property.Constraint;
15  import org.weda.property.ConstraintCheck;
16  import org.weda.property.ConstraintException;
17  import org.weda.property.ConstraintIdentificatorHolder;
18  import org.weda.property.ConstraintsFactory;
19  import org.weda.property.ConstraintsFactoryException;
20  
21  /**
22   *
23   * @author Mikhail Titov
24   */
25  public class ConstraintsFactoryImpl implements ConstraintsFactory {
26      private List<Constraint> constraints = new LinkedList<Constraint>();
27      //list of ConstraintInfo or Constraint
28      private List constraintsConfig;
29      
30      public void init() throws ConstraintsFactoryException {
31          try {            
32              for (Object config: constraintsConfig){
33                  Constraint constraint = null;
34                  if (config instanceof ConstraintInfo){
35                      ConstraintInfo info = (ConstraintInfo)config;
36                      constraint = lookupForAnnotatedConstraint(info);
37                      if (constraint==null){
38                          if (AbstractConstraint.class.isAssignableFrom(
39                                  info.getConstraintClass()))
40                          {
41                              constraint = 
42                                      (Constraint)info
43                                          .getConstraintClass().newInstance();
44                              ((AbstractConstraint)constraint)
45                                      .setId(info.getId());
46                          }else
47                              throw new ConstraintException(
48                                      String.format(
49                                          "Can't create constraint (%s) of " +
50                                          "class (%s). All constraints must be " +
51                                          "subclasses of %s"
52                                          , info.getId()
53                                          , info.getConstraintClass().getName()
54                                          , AbstractConstraint.class.getName()));
55                      }
56                  }else if (config instanceof Constraint)
57                      constraint = (Constraint)config;
58                  if (constraint instanceof AbstractConstraint)
59                      ((AbstractConstraint)constraint).init();
60                  constraints.add((Constraint)constraint);
61              }
62          }catch (Exception ex){
63              throw new ConstraintsFactoryException(
64                      "Can't initialize standart constraints factory", ex);            
65          }
66      }
67      
68      private Constraint lookupForAnnotatedConstraint(ConstraintInfo info)
69          throws Exception
70      {
71          Method[] methods = info.getConstraintClass().getMethods();
72          Set<Class> valueTypes = new HashSet<Class>();
73          List<ConstraintCheckMethod> checkMethods = 
74                  new ArrayList<ConstraintCheckMethod>();
75          ConstraintCheckMethod defaultCheckMethod = null;
76          for (Method method: methods){
77              if (method.isAnnotationPresent(ConstraintCheck.class)){
78                  Class[] methodParameters = method.getParameterTypes();
79                  if (methodParameters.length==0)
80                      throw new ConstraintsFactoryException(
81                              String.format(
82                                  "Bad constraint check method declaration " +
83                                  "(class: %s; method: %s). Check method must " +
84                                  "take at least one parameter"
85                                  , info.getConstraintClass().getName()
86                                  , method.getName()));                
87                  Class valueType = method.getParameterTypes()[0];
88                  if (valueTypes.contains(valueType))
89                      throw new ConstraintsFactoryException(
90                              String.format(
91                                  "Constraint (%s) already has check method " +
92                                  "for value type (%s)"
93                                  , info.getConstraintClass().getName()
94                                  , valueType.getName()));
95                  ConstraintCheckMethod checkMethod 
96                          = new ConstraintCheckMethod(method);
97                  checkMethods.add(checkMethod);
98                  ConstraintCheck checkAnn = 
99                          method.getAnnotation(ConstraintCheck.class);
100                 if (checkAnn.defaultMethod()){
101                     if (defaultCheckMethod!=null)
102                         throw new ConstraintsFactoryException(
103                                 String.format(
104                                     "Constraint (%s) already has default " +
105                                     "check method"
106                                     , info.getConstraintClass().getName()));
107                     else
108                         defaultCheckMethod = checkMethod;
109                 }
110             }
111         }
112         if (checkMethods.size()>0){
113             Object constraint = info.getConstraintClass().newInstance();
114             if (constraint instanceof ConstraintIdentificatorHolder)
115                 ((ConstraintIdentificatorHolder)constraint)
116                     .setId(info.getId());
117             ConstraintContainer container = 
118                     new ConstraintContainer(
119                         info.getId(), constraint
120                         , checkMethods.toArray(
121                             new ConstraintCheckMethod[checkMethods.size()])
122                         , defaultCheckMethod);
123             return container;
124         }
125         return null;
126     }
127     
128     public List<Constraint> getConstraints() {
129         return constraints;
130     }    
131 
132     public void setConstraintsConfig(List config) {
133         this.constraintsConfig = config;
134     }
135     
136 }