1
2
3
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
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 }