1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.grouplens.grapht;
21
22 import com.google.common.collect.ArrayListMultimap;
23 import com.google.common.collect.Multimap;
24 import org.grouplens.grapht.context.ContextMatcher;
25 import org.grouplens.grapht.solver.BindRule;
26 import org.grouplens.grapht.solver.BindingFunction;
27 import org.grouplens.grapht.solver.RuleBasedBindingFunction;
28
29 import java.io.Externalizable;
30 import java.io.Serializable;
31 import java.util.Collections;
32 import java.util.HashSet;
33 import java.util.Set;
34
35
36
37
38
39
40
41
42 public class BindingFunctionBuilder implements Cloneable {
43
44
45
46
47 public static enum RuleSet {
48
49
50
51 EXPLICIT,
52
53
54
55
56
57 INTERMEDIATE_TYPES,
58
59
60
61
62 SUPER_TYPES
63 }
64
65 private final Context root;
66
67 private final Set<Class<?>> defaultExcludes;
68 private final boolean generateRules;
69
70 private final Multimap<ContextMatcher,BindRule> manualRules;
71 private final Multimap<ContextMatcher,BindRule> intermediateRules;
72 private final Multimap<ContextMatcher,BindRule> superRules;
73
74
75
76
77
78 public BindingFunctionBuilder() {
79 this(true);
80 }
81
82
83
84
85
86
87
88
89 public BindingFunctionBuilder(boolean generateRules) {
90 this.generateRules = generateRules;
91
92 defaultExcludes = new HashSet<Class<?>>();
93 defaultExcludes.add(Object.class);
94 defaultExcludes.add(Comparable.class);
95 defaultExcludes.add(Serializable.class);
96 defaultExcludes.add(Externalizable.class);
97 defaultExcludes.add(Cloneable.class);
98
99 manualRules = ArrayListMultimap.create();
100 intermediateRules = ArrayListMultimap.create();
101 superRules = ArrayListMultimap.create();
102
103 root = ContextImpl.root(this);
104 }
105
106 private BindingFunctionBuilder(BindingFunctionBuilder clone) {
107 generateRules = clone.generateRules;
108 defaultExcludes = new HashSet<Class<?>>(clone.defaultExcludes);
109 manualRules = ArrayListMultimap.create(clone.manualRules);
110 intermediateRules = ArrayListMultimap.create(clone.intermediateRules);
111 superRules = ArrayListMultimap.create(clone.superRules);
112 root = ContextImpl.root(this);
113 }
114
115 @Override
116 public BindingFunctionBuilder clone() {
117 return new BindingFunctionBuilder(this);
118 }
119
120
121
122
123
124 public boolean getGenerateRules() {
125 return generateRules;
126 }
127
128
129
130
131 public Context getRootContext() {
132 return root;
133 }
134
135
136
137
138
139
140
141 public void applyModule(Module module) {
142 module.configure(getRootContext());
143 }
144
145
146
147
148
149
150
151
152 public void addDefaultExclusion(Class<?> type) {
153 if (type == null) {
154 throw new NullPointerException("Exclusion type cannot be null");
155 }
156 defaultExcludes.add(type);
157 }
158
159
160
161
162
163
164
165
166 public void removeDefaultExclusion(Class<?> type) {
167 if (type == null) {
168 throw new NullPointerException("Exclusion type cannot be null");
169 }
170 defaultExcludes.remove(type);
171 }
172
173
174
175
176
177
178
179 public BindingFunction build(RuleSet set) {
180 return new RuleBasedBindingFunction(getMap(set));
181 }
182
183 void addBindRule(RuleSet set, ContextMatcher context, BindRule rule) {
184 Multimap<ContextMatcher, BindRule> map = getMap(set);
185 map.put(context, rule);
186 }
187
188 Set<Class<?>> getDefaultExclusions() {
189 return Collections.unmodifiableSet(defaultExcludes);
190 }
191
192 private Multimap<ContextMatcher, BindRule> getMap(RuleSet set) {
193 switch(set) {
194 case EXPLICIT:
195 return manualRules;
196 case INTERMEDIATE_TYPES:
197 return intermediateRules;
198 case SUPER_TYPES:
199 return superRules;
200 default:
201 throw new RuntimeException("Should not happen");
202 }
203 }
204 }