Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
Problem |
|
| 3.2941176470588234;3.294 | ||||
Problem$ProblemRecorder |
|
| 3.2941176470588234;3.294 |
1 | /* | |
2 | * Copyright (c) 2009, Swiss Federal Department of Defence Civil Protection and Sport | |
3 | * (http://www.vbs.admin.ch) | |
4 | * Copyright (c) 2009, Ergon Informatik AG (http://www.ergon.ch) | |
5 | * All rights reserved. | |
6 | * | |
7 | * Licensed under the Open Permis License which accompanies this distribution, | |
8 | * and is available at http://www.openpermis.org/BSDlicenceKent.txt | |
9 | */ | |
10 | package org.openpermis.editor.policy.presenter; | |
11 | ||
12 | import java.util.ArrayList; | |
13 | import java.util.Arrays; | |
14 | import java.util.List; | |
15 | ||
16 | import org.slf4j.Logger; | |
17 | import org.slf4j.LoggerFactory; | |
18 | ||
19 | import org.openpermis.policy.Part; | |
20 | import org.openpermis.policy.PartProblemReporter; | |
21 | import org.openpermis.policy.Policy; | |
22 | import org.openpermis.policy.PartProblemReporter.ProblemMessage; | |
23 | import org.openpermis.policy.bean.PartBean; | |
24 | import org.openpermis.policy.bean.SerialNumber; | |
25 | ||
26 | /** | |
27 | * Describes a problem in a part. | |
28 | * @since 0.3.0 | |
29 | */ | |
30 | public class Problem { | |
31 | ||
32 | //---- Static | |
33 | ||
34 | /** | |
35 | * Creates a list of problem for the specified policy. | |
36 | * @param policy the policy for which to create the problem list. | |
37 | * @return the problem list requested, never {@code null}. | |
38 | * @since 0.3.0 | |
39 | */ | |
40 | public static final List<Problem> createProblemList (Policy policy) { | |
41 | 0 | final ProblemRecorder recorder = new ProblemRecorder(); |
42 | 0 | policy.isValid(recorder); |
43 | 0 | return recorder.getProblemList(); |
44 | } | |
45 | ||
46 | /** | |
47 | * Seed value used when combining hash codes. | |
48 | * @since 0.3.0 | |
49 | */ | |
50 | private static final int HASH_CODE_SEED = 17; | |
51 | ||
52 | /** | |
53 | * Multiplier used when combining hash codes. | |
54 | * @since 0.3.0 | |
55 | */ | |
56 | private static final int HASH_CODE_MULTIPLIER = 37; | |
57 | ||
58 | //---- State | |
59 | ||
60 | /** | |
61 | * The part that has a problem. | |
62 | * @since 0.3.0 | |
63 | */ | |
64 | private final PartBean part; | |
65 | ||
66 | /** | |
67 | * The type of problem. | |
68 | * @since 0.3.0 | |
69 | */ | |
70 | private final ProblemMessage message; | |
71 | ||
72 | /** | |
73 | * Additional parameters for the problem. | |
74 | * @since 0.3.0 | |
75 | */ | |
76 | private final Object[] parameters; | |
77 | ||
78 | //---- Constructors | |
79 | ||
80 | /** | |
81 | * Creates a new problem for the specified part, type and parameters. | |
82 | * @param part the part that has a problem. | |
83 | * @param message the type of problem. | |
84 | * @param parameters additional parameters for the problem. | |
85 | * @since 0.3.0 | |
86 | */ | |
87 | 0 | public Problem (PartBean part, ProblemMessage message, Object...parameters) { |
88 | 0 | this.part = part; |
89 | 0 | this.message = message; |
90 | 0 | this.parameters = parameters; |
91 | 0 | } |
92 | ||
93 | //---- Methods | |
94 | ||
95 | /** | |
96 | * Returns the serial number of the part that has a problem. | |
97 | * @return the serial number of the part that has a problem. | |
98 | * @since 0.3.0 | |
99 | */ | |
100 | public SerialNumber getPartSerialNumber () { | |
101 | 0 | return this.part.getSerialNumber(); |
102 | } | |
103 | ||
104 | /** | |
105 | * Returns the part that has a problem. | |
106 | * @return the part that has a problem. | |
107 | * @since 0.3.0 | |
108 | */ | |
109 | public PartBean getPart () { | |
110 | 0 | return this.part; |
111 | } | |
112 | ||
113 | /** | |
114 | * Returns the type of the problem. | |
115 | * @return the type of the problem. | |
116 | * @since 0.3.0 | |
117 | */ | |
118 | public ProblemMessage getMessage () { | |
119 | 0 | return this.message; |
120 | } | |
121 | ||
122 | /** | |
123 | * Returns the problem parameters. | |
124 | * @return the problem parameters. | |
125 | * @since 0.3.0 | |
126 | */ | |
127 | public Object[] getParameters () { | |
128 | 0 | return this.parameters; |
129 | } | |
130 | ||
131 | /** | |
132 | * Check if the other problem has the same part. | |
133 | * @param other the other problem to compare to. | |
134 | * @return {@code true} if it has the same part, {@code false} otherwise. | |
135 | * @since 0.3.0 | |
136 | */ | |
137 | private boolean equalPart (Problem other) { | |
138 | 0 | if (!getPartSerialNumber().equals(other.getPartSerialNumber())) { |
139 | 0 | return false; |
140 | } | |
141 | 0 | if ( |
142 | SerialNumber.UNDEFINED.equals(getPartSerialNumber()) && | |
143 | !getPart().equals(other.getPart()) | |
144 | ) { | |
145 | 0 | return false; |
146 | } | |
147 | 0 | return true; |
148 | } | |
149 | ||
150 | /** | |
151 | * Compare two parameters if they are equivalent. | |
152 | * <p>{@link PartBean} objects are compared by serial.</p> | |
153 | * @param o1 the first parameter, not {@code null}. | |
154 | * @param o2 the second parameter, may be {@code null}. | |
155 | * @return {@code true} if they are equivalent or have the same serial, | |
156 | * {@code false} otherwise. | |
157 | * @since 0.3.0 | |
158 | */ | |
159 | private boolean equalParameter (Object o1, Object o2) { | |
160 | 0 | if (o1 instanceof PartBean && o2 instanceof PartBean) { |
161 | 0 | return ((PartBean) o1).getSerialNumber().equals( |
162 | ((PartBean) o2).getSerialNumber() | |
163 | ); | |
164 | } | |
165 | 0 | return o1.equals(o2); |
166 | } | |
167 | ||
168 | /** | |
169 | * Check if the paramters of this problem are the same as the ones of the other problem. | |
170 | * @param other the other problem to compare the paramters to. | |
171 | * @return {@code true} if they have the same parameters, {@code false} otherwise. | |
172 | * @since 0.3.0 | |
173 | */ | |
174 | private boolean equalParameters (Problem other) { | |
175 | 0 | final Object[] p1 = getParameters(); |
176 | 0 | final Object[] p2 = getParameters(); |
177 | 0 | if (p1 == p2) { |
178 | 0 | return true; |
179 | } | |
180 | 0 | if (p1 == null || p2 == null) { |
181 | 0 | return false; |
182 | } | |
183 | 0 | final int length = p1.length; |
184 | 0 | if (length != p2.length) { |
185 | 0 | return false; |
186 | } | |
187 | 0 | for (int i = 0; i < length; i++) { |
188 | 0 | final Object o1 = p1[i]; |
189 | 0 | final Object o2 = p2[i]; |
190 | 0 | if (!(o1 == null ? o2 == null : equalParameter(o1, o2))) { |
191 | 0 | return false; |
192 | } | |
193 | } | |
194 | 0 | return true; |
195 | } | |
196 | ||
197 | /** | |
198 | * Returns the hash code of a parameter. | |
199 | * @param parameter the parameter for which to retrieve the hash code. | |
200 | * @return the hash code requested. | |
201 | * @since 0.3.0 | |
202 | */ | |
203 | private int parameterHash (Object parameter) { | |
204 | 0 | if (parameter == null) { |
205 | 0 | return 0; |
206 | } | |
207 | 0 | if (parameter instanceof PartBean) { |
208 | 0 | return ((PartBean) parameter).getSerialNumber().hashCode(); |
209 | } | |
210 | 0 | return parameter.hashCode(); |
211 | } | |
212 | ||
213 | /** | |
214 | * Creates a single hash code for all parameters. | |
215 | * @return the hash code requested. | |
216 | * @since 0.3.0 | |
217 | */ | |
218 | private int parametersHashCodes () { | |
219 | 0 | int result = HASH_CODE_SEED; |
220 | 0 | for (Object parameter : getParameters()) { |
221 | 0 | result = HASH_CODE_MULTIPLIER * result + parameterHash(parameter); |
222 | } | |
223 | 0 | return result; |
224 | } | |
225 | ||
226 | //---- Object | |
227 | ||
228 | /** | |
229 | * @since 0.3.0 | |
230 | */ | |
231 | @Override | |
232 | public int hashCode () { | |
233 | 0 | int result = HASH_CODE_SEED; |
234 | 0 | result = HASH_CODE_MULTIPLIER * result + getPartSerialNumber().hashCode(); |
235 | 0 | result = HASH_CODE_MULTIPLIER * result + getMessage().ordinal(); |
236 | 0 | result = HASH_CODE_MULTIPLIER * result + parametersHashCodes(); |
237 | 0 | return result; |
238 | } | |
239 | ||
240 | /** | |
241 | * @since 0.3.0 | |
242 | */ | |
243 | @Override | |
244 | public boolean equals (Object obj) { | |
245 | 0 | if (obj == null) { |
246 | 0 | return false; |
247 | } | |
248 | 0 | if (obj == this) { |
249 | 0 | return true; |
250 | } | |
251 | 0 | if (!(obj instanceof Problem)) { |
252 | 0 | return false; |
253 | } | |
254 | 0 | final Problem other = (Problem) obj; |
255 | 0 | if (!equalPart(other)) { |
256 | 0 | return false; |
257 | } | |
258 | 0 | if (!getMessage().equals(other.getMessage())) { |
259 | 0 | return false; |
260 | } | |
261 | 0 | if (equalParameters(other)) { |
262 | 0 | return false; |
263 | } | |
264 | 0 | return true; |
265 | } | |
266 | ||
267 | /** | |
268 | * @since 0.3.0 | |
269 | */ | |
270 | @Override | |
271 | public String toString () { | |
272 | 0 | final StringBuilder sb = new StringBuilder(getMessage().toString()); |
273 | 0 | sb.append(" [part="); |
274 | try { | |
275 | 0 | sb.append(getPart()); |
276 | 0 | } catch (Exception e) { |
277 | 0 | sb.append(getPartSerialNumber()); |
278 | 0 | } |
279 | 0 | sb.append(",parameters=").append(Arrays.toString(getParameters())).append("]"); |
280 | 0 | return sb.toString(); |
281 | } | |
282 | ||
283 | //---- ProblemRecorder | |
284 | ||
285 | /** | |
286 | * Problem reporter that creates a list of problems. | |
287 | * <p>The recorder can only be used once and should be discarded afterwards.</p> | |
288 | * @since 0.3.0 | |
289 | */ | |
290 | private static class ProblemRecorder | |
291 | implements PartProblemReporter | |
292 | { | |
293 | ||
294 | //---- Static | |
295 | ||
296 | /** | |
297 | * The logger object of this class. | |
298 | * @since 0.3.0 | |
299 | */ | |
300 | 0 | private static final Logger LOGGER = |
301 | LoggerFactory.getLogger(ProblemRecorder.class); | |
302 | ||
303 | //---- State | |
304 | ||
305 | private final List<Problem> problemList; | |
306 | ||
307 | //---- Constructors | |
308 | ||
309 | 0 | public ProblemRecorder () { |
310 | 0 | this.problemList = new ArrayList<Problem>(); |
311 | 0 | } |
312 | ||
313 | //---- Methods | |
314 | ||
315 | public List<Problem> getProblemList () { | |
316 | 0 | return this.problemList; |
317 | } | |
318 | ||
319 | //---- PartProblemReporter | |
320 | ||
321 | /** | |
322 | * @since 0.3.0 | |
323 | */ | |
324 | public void reportProblem (Part part, ProblemMessage message, Object... parameters) { | |
325 | 0 | if (!(part instanceof PartBean)) { |
326 | 0 | LOGGER.warn("Problem for a part that is not a bean encountered [{}].", part); |
327 | 0 | return; |
328 | } | |
329 | 0 | this.problemList.add(new Problem((PartBean) part, message, parameters)); |
330 | 0 | } |
331 | ||
332 | } | |
333 | ||
334 | } |