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