1 package org.kuali.common.util.validate.hibernate.factory;
2
3 import java.lang.annotation.Annotation;
4 import java.lang.reflect.Field;
5 import java.util.List;
6 import java.util.Map;
7
8 import org.hibernate.validator.cfg.ConstraintDef;
9 import org.kuali.common.util.ReflectionUtils;
10
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.ImmutableMap;
13 import com.google.common.collect.Lists;
14 import com.google.common.collect.Maps;
15
16 public final class DefaultConstraintDefService implements ConstraintDefService {
17
18 private final Map<Class<? extends Annotation>, ConstraintDefFactory<? extends ConstraintDef<?, ?>, ?>> factories;
19
20 private DefaultConstraintDefService(Builder builder) {
21 this.factories = builder.factories;
22 }
23
24 @Override
25 public boolean supports(Class<? extends Annotation> annotationType) {
26 Preconditions.checkNotNull(annotationType, "'annotationType' cannot be null");
27 return factories.containsKey(annotationType);
28 }
29
30 @Override
31 public ConstraintDef<?, ?> getConstraintDef(Field annotatedField, Class<? extends Annotation> annotationType) {
32 Preconditions.checkNotNull(annotatedField, "'annotatedField' cannot be null");
33 Preconditions.checkNotNull(annotationType, "'annotationType' cannot be null");
34 Preconditions.checkState(supports(annotationType), "[" + annotationType.getCanonicalName() + "] is not supported");
35 ConstraintDefFactory<?, ?> factory = factories.get(annotationType);
36 return factory.getConstraintDef(annotatedField);
37 }
38
39 @Override
40 public ConstraintDef<?, ?> getConstraintDef(Class<?> annotatedClass, Class<? extends Annotation> annotationType) {
41 Preconditions.checkNotNull(annotatedClass, "'annotatedClass' cannot be null");
42 Preconditions.checkNotNull(annotationType, "'annotationType' cannot be null");
43 Preconditions.checkState(supports(annotationType), "[" + annotationType.getCanonicalName() + "] is not supported");
44 ConstraintDefFactory<?, ?> factory = factories.get(annotationType);
45 return factory.getConstraintDef(annotatedClass);
46 }
47
48 public static Builder builder() {
49 return new Builder();
50 }
51
52 public static class Builder implements org.kuali.common.util.builder.Builder<DefaultConstraintDefService> {
53
54 private Map<Class<? extends Annotation>, ConstraintDefFactory<? extends ConstraintDef<?, ?>, ?>> factories = getDefaultMappings();
55
56 private static Map<Class<? extends Annotation>, ConstraintDefFactory<? extends ConstraintDef<?, ?>, ?>> getDefaultMappings() {
57 List<ConstraintDefFactory<? extends ConstraintDef<?, ?>, ?>> list = Lists.newArrayList();
58 list.add(new AssertFalseDefFactory());
59 list.add(new AssertTrueDefFactory());
60 list.add(new CreditCardNumberDefFactory());
61 list.add(new BulletProofPojoDefFactory());
62 list.add(new BulletProofBuilderDefFactory());
63 list.add(new ValidPortDefFactory());
64 list.add(new DecimalMaxDefFactory());
65 list.add(new DecimalMinDefFactory());
66 list.add(new SizeDefFactory());
67 list.add(new MinDefFactory());
68 Map<Class<? extends Annotation>, ConstraintDefFactory<? extends ConstraintDef<?, ?>, ?>> factories = Maps.newHashMap();
69 for (ConstraintDefFactory<? extends ConstraintDef<?, ?>, ?> element : list) {
70 factories.put(element.getAnnotationType(), element);
71 }
72 return factories;
73 }
74
75 public Builder factories(Map<Class<? extends Annotation>, ConstraintDefFactory<? extends ConstraintDef<?, ?>, ?>> factories) {
76 this.factories = factories;
77 return this;
78 }
79
80 public Builder register(ConstraintDefFactory<? extends ConstraintDef<?, ?>, ?> factory) {
81 factories.put(factory.getAnnotationType(), factory);
82 return this;
83 }
84
85 @Override
86 public DefaultConstraintDefService build() {
87 this.factories = ImmutableMap.copyOf(factories);
88 DefaultConstraintDefService instance = new DefaultConstraintDefService(this);
89 validate(instance);
90 return instance;
91 }
92
93 private void validate(DefaultConstraintDefService instance) {
94 Preconditions.checkNotNull(instance.getFactories(), "'factories' cannot be null");
95 Class<?> mapClass = instance.getFactories().getClass();
96 boolean immutable = ReflectionUtils.isImmutableGuavaMap(mapClass);
97 Preconditions.checkArgument(immutable, "[%s] is not an immutable Guava map", mapClass.getCanonicalName());
98 }
99 }
100
101 public Map<Class<? extends Annotation>, ConstraintDefFactory<? extends ConstraintDef<?, ?>, ?>> getFactories() {
102 return factories;
103 }
104
105 }