1
2
3
4
5
6
7
8
9
10 package com.sri.emo.wizard.completion.model;
11
12 import com.jcorporate.expresso.core.controller.ErrorCollection;
13 import com.jcorporate.expresso.core.db.DBException;
14 import com.sri.emo.dbobj.Part;
15 import org.apache.commons.lang.builder.EqualsBuilder;
16 import org.apache.commons.lang.builder.HashCodeBuilder;
17 import org.apache.log4j.Logger;
18
19 import java.io.Serializable;
20
21
22 /***
23 * Metadata for each completion part.
24 *
25 * @author Michael Rimov
26 * @version 1.0
27 */
28 public class CompletionPartsBean implements Serializable, Comparable {
29
30 /***
31 *
32 */
33 private static final long serialVersionUID = 1L;
34
35 /***
36 * Field completion type. (wizard or fixed)
37 */
38 private FieldCompletion fieldCompletion;
39
40 /***
41 * Is this a free text entry.
42 */
43 private boolean freeTextEntry;
44
45 /***
46 * Minimum number of entries.
47 */
48 private Integer minEntries;
49
50 /***
51 * Maximum number of entries.
52 */
53 private Integer maxEntries;
54
55 /***
56 * The attached part.
57 */
58 private final Part attachedPart;
59
60 /***
61 * The owning completion bean.
62 */
63 private final CompletionBean owner;
64
65 /***
66 * The step directive.
67 */
68 private String directive;
69
70 /***
71 * The step helptext.
72 */
73 private String helpText;
74
75 /***
76 * Is the step single value entry?
77 */
78 private boolean singleEntry;
79
80 /***
81 * Constructor that takes the parent bean and an associated <tt>Part</tt>
82 * object.
83 *
84 * @param myOwner CompletionBean the parent bean.
85 * @param myPart Part the associated part.
86 * @throws DBException upon Part query error.
87 */
88 public CompletionPartsBean(final CompletionBean myOwner, final Part myPart) throws DBException {
89 attachedPart = myPart;
90 owner = myOwner;
91 freeTextEntry = !(myPart.hasPicklist() || myPart.isSharedNodeAttrib() || myPart.isHaveCustomHandler());
92 if (!myPart.isSingleValued()) {
93 minEntries = new Integer(1);
94 maxEntries = new Integer(1);
95 this.setSingleEntry(false);
96 } else {
97 minEntries = new Integer(1);
98 maxEntries = new Integer(1);
99 this.setSingleEntry(true);
100 }
101
102 setDefaultDirective(myPart);
103 }
104
105 /***
106 * Sets a default directive for the given part. The text is varied
107 * depending on the metadata of the part.
108 *
109 * @param myPart Part the part to extract the computed directive for.
110 * @throws DBException upon error querying the Part.
111 */
112 private void setDefaultDirective(final Part myPart) throws DBException {
113 String partLabel = myPart.getPartLabel();
114
115 if (myPart.hasPicklist()) {
116 if (myPart.isSingleValued()) {
117 setDirective("Please select a value for " + partLabel);
118 } else {
119 setDirective("Please choose values for " + partLabel);
120 }
121 } else {
122 if (myPart.isSingleValued()) {
123 setDirective("Please enter a value for " + partLabel);
124 } else {
125 setDirective("Please set values for " + partLabel);
126 }
127 }
128 }
129
130
131 public CompletionBean getOwner() {
132 return owner;
133 }
134
135 public Part getPart() {
136 return attachedPart;
137 }
138
139
140 public void setFieldCompletion(FieldCompletion fieldCompletion) {
141 this.fieldCompletion = fieldCompletion;
142 }
143
144 public void setDirective(String directive) {
145 this.directive = directive;
146 }
147
148 public void setHelpText(String helpText) {
149 this.helpText = helpText;
150 }
151
152 public void setSingleEntry(boolean singleEntry) {
153 this.singleEntry = singleEntry;
154 }
155
156 public void setMinEntries(int minEntries) {
157 this.minEntries = new Integer(minEntries);
158 }
159
160 public void setMaxEntries(int maxEntries) {
161 this.maxEntries = new Integer(maxEntries);
162 }
163
164
165 public FieldCompletion getFieldCompletion() {
166 return fieldCompletion;
167 }
168
169 public boolean isFreeTextEntry() {
170 return freeTextEntry;
171 }
172
173 public Integer getMinEntries() {
174 return minEntries;
175 }
176
177 public Integer getMaxEntries() {
178 return maxEntries;
179 }
180
181 public String getDirective() {
182 return directive;
183 }
184
185 public String getHelpText() {
186 return helpText;
187 }
188
189 public boolean isSingleEntry() {
190 return singleEntry;
191 }
192
193 public boolean isFreeTextAllowed() throws DBException {
194 return !(this.getPart().hasPicklist() || getPart().isSharedNodeAttrib() || getPart().isHaveCustomHandler());
195 }
196
197 public boolean isMinMaxAllowed() throws DBException {
198 return !this.getPart().isSingleValued();
199 }
200
201 /***
202 * Compares this object with the specified object for order. This implementation
203 * relies on the underlying parts for comparison.
204 *
205 * @param o the Object to be compared.
206 * @return a negative integer, zero, or a positive integer as this
207 * object is less than, equal to, or greater than the specified object.
208 */
209 public int compareTo(Object o) {
210 assert o instanceof CompletionPartsBean;
211
212 int myOrderNumber = 0;
213 int otherOrderNumber = 0;
214 try {
215 CompletionPartsBean other = (CompletionPartsBean) o;
216
217
218 if (attachedPart == null && other.attachedPart != null) {
219 return -1;
220 } else if (attachedPart != null && other.attachedPart == null) {
221 return 1;
222 }
223
224
225 if ((attachedPart.getPartNum() == null
226 || attachedPart.getPartNum().length() == 0) && !(other.attachedPart.getPartNum() == null
227 || other.attachedPart.getPartNum().length() == 0)) {
228 return -1;
229 } else if (!(attachedPart.getPartNum() == null
230 || attachedPart.getPartNum().length() == 0) && (other.attachedPart.getPartNum() == null
231 || other.attachedPart.getPartNum().length() == 0)) {
232 return 1;
233 }
234
235
236
237 myOrderNumber = attachedPart.getPartNumInt();
238 otherOrderNumber = ((CompletionPartsBean) o).attachedPart.getPartNumInt();
239
240 if (myOrderNumber == otherOrderNumber) {
241 return 0;
242 } else if (myOrderNumber > otherOrderNumber) {
243 return 1;
244 } else {
245 return -1;
246 }
247 } catch (DBException ex) {
248 throw new RuntimeException("error querying part order for comparison");
249 }
250 }
251
252 /***
253 * Returns a string representation of the object.
254 *
255 * @return a string representation of the object.
256 */
257 public String toString() {
258 try {
259 return "Completion bean for Part ID: " + attachedPart.getPartNum();
260 } catch (DBException ex) {
261 return "Completion bean for Part ID (Cannot get id due to exception)";
262 }
263 }
264
265 /***
266 * Validate the properties that have been set for this HTTP request,
267 * and return an <code>ActionErrors</code> object that encapsulates any
268 * validation errors that have been found.
269 *
270 * @param toPopulate The ErrorCollection we are using to populate with errors
271 * upon validation errors.
272 * @return ActionErrors
273 * @todo This is not a side-effect free function. Redesign so that 'fixing'
274 * logic is centralized in the DBObject Converter.
275 */
276 public ErrorCollection validateAndAdjust(final ErrorCollection toPopulate) {
277
278
279
280 if (this.getFieldCompletion() == FieldCompletion.FIXED) {
281 return toPopulate;
282 }
283
284 try {
285 if (this.getPart() == null) {
286 toPopulate.addError("There is no attached part for this attribute: " + this.toString());
287 }
288
289 if (this.isMinMaxAllowed()) {
290 if (minEntries != null && minEntries.intValue() < 0) {
291 toPopulate.addError("Min Entries Value for '" + this.getPart().getPartLabel()
292 + "' must be greater than zero");
293 }
294
295 if (maxEntries != null && maxEntries.intValue() < 0) {
296 toPopulate.addError("Max Entries Value for '" + this.getPart().getPartLabel()
297 + "' must be greater than zero");
298 }
299
300 if (maxEntries.intValue() < minEntries.intValue()) {
301 toPopulate.addError("Max Entries for: " + this.getPart().getPartLabel()
302 + " must be greater than Min Entries.");
303 }
304 } else if (minEntries != null && minEntries.intValue() > 1) {
305 toPopulate.addError(
306 "Min Entries for: " + this.getPart().getPartLabel()
307 + " cannot be greater than '1'. Automatically adjusting value. Please verify and save the updated wizard.");
308 minEntries = new Integer(1);
309 } else if (maxEntries != null && maxEntries.intValue() > 1) {
310 toPopulate.addError(
311 "Max Entries for: " + this.getPart().getPartLabel()
312 + " cannot be greater than '1'. Automatically adjusting value. Please verify and save the updated wizard.");
313 maxEntries = new Integer(1);
314 }
315
316 if (!this.isFreeTextAllowed() && this.isFreeTextEntry()) {
317 toPopulate.addError(
318 "Free Text Entry is set, but free text entry is not permitted by node type definition."
319 + " This has been corrected. Please Resubmit");
320 this.freeTextEntry = false;
321 }
322
323 } catch (DBException ex) {
324 Logger.getLogger(CompletionPartsBean.class).error("Error validating part", ex);
325 throw new RuntimeException(
326 "Error grabbing part label for: " + getPart().toString() + ". (Additional information logged)");
327 }
328
329 return toPopulate;
330 }
331
332 /***
333 * Indicates whether some other object is "equal to" this one.
334 *
335 * @param obj the reference object with which to compare.
336 * @return <code>true</code> if this object is the same as the obj
337 * argument; <code>false</code> otherwise.
338 */
339 public boolean equals(Object obj) {
340 if (!(obj instanceof CompletionPartsBean)) {
341 return false;
342 }
343
344 CompletionPartsBean other = (CompletionPartsBean) obj;
345
346 EqualsBuilder equalsBuilder = new EqualsBuilder()
347 .append(attachedPart, other.attachedPart)
348 .append(directive, other.directive)
349 .append(fieldCompletion, other.fieldCompletion)
350 .append(freeTextEntry, other.freeTextEntry)
351 .append(helpText, other.helpText)
352 .append(maxEntries, other.maxEntries)
353 .append(minEntries, other.minEntries)
354 .append(singleEntry, other.singleEntry);
355
356 return equalsBuilder.isEquals();
357 }
358
359 /***
360 * Returns a hash code value for the object.
361 *
362 * @return a hash code value for this object.
363 */
364 public int hashCode() {
365 try {
366 HashCodeBuilder hashCodeBuilder = new HashCodeBuilder(481, 31)
367 .append(attachedPart.getId())
368 .append(directive)
369 .append(fieldCompletion)
370 .append(freeTextEntry)
371 .append(helpText)
372 .append(maxEntries)
373 .append(minEntries)
374 .append(singleEntry);
375
376 return hashCodeBuilder.toHashCode();
377 } catch (DBException ex) {
378 return 0;
379 }
380 }
381
382
383 }