1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.qualitytest.blueprint.configuration;
17
18 import java.lang.reflect.Field;
19 import java.lang.reflect.Method;
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import javax.annotation.Nonnull;
24 import javax.annotation.Nullable;
25
26 import net.sf.qualitycheck.Check;
27 import net.sf.qualitycheck.Throws;
28 import net.sf.qualitycheck.exception.IllegalEmptyArgumentException;
29 import net.sf.qualitycheck.exception.IllegalNullArgumentException;
30 import net.sf.qualitytest.blueprint.Blueprint;
31 import net.sf.qualitytest.blueprint.BlueprintConfiguration;
32 import net.sf.qualitytest.blueprint.BlueprintSession;
33 import net.sf.qualitytest.blueprint.CreationStrategy;
34 import net.sf.qualitytest.blueprint.CycleHandlingStrategy;
35 import net.sf.qualitytest.blueprint.MatchingStrategy;
36 import net.sf.qualitytest.blueprint.strategy.creation.BlueprintCreationStrategy;
37 import net.sf.qualitytest.blueprint.strategy.creation.SingleValueCreationStrategy;
38 import net.sf.qualitytest.blueprint.strategy.matching.CaseInsensitiveMethodNameMatchingStrategy;
39 import net.sf.qualitytest.blueprint.strategy.matching.TypeMatchingStrategy;
40 import net.sf.qualitytest.exception.BlueprintCycleException;
41
42 import com.google.common.collect.ImmutableList;
43 import com.google.common.collect.Lists;
44
45
46
47
48
49
50
51
52
53 class ImmutableBlueprintConfiguration implements BlueprintConfiguration {
54
55
56
57
58 private final List<StrategyPair> mapping;
59 private final List<CycleHandlingStrategy<?>> cycleHandling;
60 private final boolean withPublicAttributes;
61
62
63
64
65 public ImmutableBlueprintConfiguration() {
66 mapping = ImmutableList.of();
67 cycleHandling = ImmutableList.of();
68 withPublicAttributes = false;
69 }
70
71 protected ImmutableBlueprintConfiguration(@Nonnull final List<StrategyPair> attributeMapping,
72 @Nonnull final List<CycleHandlingStrategy<?>> attributeCycleHandling, final boolean withPublicAttributes) {
73 Check.notNull(attributeMapping, "attributeMapping");
74 Check.notNull(attributeCycleHandling, "attributeCycleHandling");
75
76 mapping = ImmutableList.copyOf(attributeMapping);
77 cycleHandling = ImmutableList.copyOf(attributeCycleHandling);
78 this.withPublicAttributes = withPublicAttributes;
79 }
80
81 @Nullable
82 @Override
83 @Throws(IllegalNullArgumentException.class)
84 public <T> T construct(@Nonnull final Class<T> clazz) {
85 return Blueprint.construct(clazz, this, new BlueprintSession());
86 }
87
88 @Nullable
89 @Override
90 @Throws(IllegalNullArgumentException.class)
91 public CreationStrategy<?> findCreationStrategyForField(@Nonnull final Field field) {
92 Check.notNull(field, "field");
93
94 for (final StrategyPair entry : Lists.reverse(mapping)) {
95 if (entry.getKey().matchesByField(field)) {
96 return entry.getValue();
97 }
98 }
99
100 return null;
101 }
102
103 @Nullable
104 @Override
105 @Throws(IllegalNullArgumentException.class)
106 public CreationStrategy<?> findCreationStrategyForMethod(@Nonnull final Method method) {
107 Check.notNull(method, "method");
108
109 for (final StrategyPair entry : Lists.reverse(mapping)) {
110 if (entry.getKey().matchesByMethod(method)) {
111 return entry.getValue();
112 }
113 }
114
115 return null;
116 }
117
118 @Nullable
119 @Override
120 @Throws(IllegalNullArgumentException.class)
121 public CreationStrategy<?> findCreationStrategyForType(@Nonnull final Class<?> clazz) {
122 Check.notNull(clazz, "clazz");
123
124 for (final StrategyPair entry : Lists.reverse(mapping)) {
125 if (entry.getKey().matchesByType(clazz)) {
126 return entry.getValue();
127 }
128 }
129
130 return null;
131 }
132
133 @SuppressWarnings("unchecked")
134 @Override
135 @Nullable
136 public <T> T handleCycle(@Nonnull final BlueprintSession session, @Nonnull final Class<T> clazz) {
137 for (final CycleHandlingStrategy<?> strategy : Lists.reverse(cycleHandling)) {
138 if (strategy.isActiveForType(clazz)) {
139 return (T) strategy.handleCycle(session, clazz);
140 }
141 }
142
143 throw new BlueprintCycleException(session, clazz);
144 }
145
146 @Override
147 public boolean isWithPublicAttributes() {
148 return withPublicAttributes;
149 }
150
151 @Override
152 @Nonnull
153 public <T> BlueprintConfiguration with(@Nonnull final Class<T> type, @Nullable final CreationStrategy<?> creator) {
154 return with(new TypeMatchingStrategy(type), creator);
155 }
156
157 @Nonnull
158 @Override
159 @Throws(IllegalNullArgumentException.class)
160 public <T> BlueprintConfiguration with(@Nonnull final Class<T> type, @Nullable final T value) {
161 return with(new TypeMatchingStrategy(type), new SingleValueCreationStrategy<T>(value));
162 }
163
164 @Throws(IllegalNullArgumentException.class)
165 @Override
166 @Nonnull
167 public <T> BlueprintConfiguration with(@Nonnull final CycleHandlingStrategy<T> cycleHandlingStrategy) {
168 Check.notNull(cycleHandlingStrategy, "cycleHandlingStrategy");
169
170 final List<CycleHandlingStrategy<?>> strategies = new ArrayList<CycleHandlingStrategy<?>>();
171 strategies.addAll(cycleHandling);
172 strategies.add(cycleHandlingStrategy);
173 return new ImmutableBlueprintConfiguration(mapping, strategies, withPublicAttributes);
174
175 }
176
177 @Nonnull
178 @Override
179 @Throws(IllegalNullArgumentException.class)
180 public <T> BlueprintConfiguration with(@Nonnull final MatchingStrategy matchingStrategy) {
181 return with(matchingStrategy, new BlueprintCreationStrategy());
182 }
183
184 @Nonnull
185 @Override
186 @Throws(IllegalNullArgumentException.class)
187 public BlueprintConfiguration with(@Nonnull final MatchingStrategy matcher, @Nonnull final CreationStrategy<?> creator) {
188 Check.notNull(matcher, "matcher");
189 Check.notNull(creator, "creator");
190
191 final List<StrategyPair> mapping = new ArrayList<StrategyPair>();
192 mapping.addAll(this.mapping);
193 mapping.add(new StrategyPair(matcher, creator));
194 return new ImmutableBlueprintConfiguration(mapping, cycleHandling, withPublicAttributes);
195 }
196
197 @Nonnull
198 @Override
199 @Throws({ IllegalNullArgumentException.class, IllegalEmptyArgumentException.class })
200 public <T> BlueprintConfiguration with(@Nonnull final String name, @Nullable final T value) {
201 Check.notEmpty(name, "name");
202 return with(new CaseInsensitiveMethodNameMatchingStrategy(name), new SingleValueCreationStrategy<T>(value));
203 }
204
205 @Nonnull
206 @Override
207 public BlueprintConfiguration withPublicAttributes(final boolean withPublicAttributes) {
208 return new ImmutableBlueprintConfiguration(mapping, cycleHandling, withPublicAttributes);
209 }
210 }