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.Node;
15 import com.sri.emo.dbobj.Part;
16 import com.sri.emo.dbobj.PartsFactory;
17 import com.sri.emo.wizard.Wizard;
18 import com.sri.emo.wizard.completion.EmoCompletionWizard;
19 import org.apache.commons.lang.builder.EqualsBuilder;
20 import org.apache.commons.lang.builder.HashCodeBuilder;
21 import org.apache.commons.lang.builder.ToStringBuilder;
22 import org.apache.log4j.Logger;
23 import org.apache.struts.action.ActionMessage;
24
25 import java.io.Serializable;
26 import java.util.Iterator;
27 import java.util.Set;
28 import java.util.TreeSet;
29
30 /***
31 * Bean for handling action form.
32 *
33 * @author Michael Rimov
34 * @version 1.0
35 * @todo Change Constructor to use NodeId for constructor to allow automatic
36 * initialization.
37 */
38 public class CompletionBean implements Serializable {
39
40 /***
41 *
42 */
43 private static final long serialVersionUID = 1L;
44
45 /***
46 * The target node id.
47 */
48 private Integer targetId = null;
49
50 /***
51 * A set of all completion parts, ordered by part-defined ordering.
52 */
53 private Set completionParts = null;
54
55 /***
56 * The current node.
57 */
58 private Node currentNode = null;
59
60 /***
61 * The wizard title.
62 */
63 private String wizardTitle;
64
65 /***
66 * The wizard directive.
67 */
68 private String summary;
69
70
71 /***
72 * The Implementation Wizard Class.
73 */
74 private Class wizardClass = EmoCompletionWizard.class;
75
76 /***
77 * Wizard id that only is set if we're editing the wizard.
78 */
79 private Integer wizardId;
80
81 /***
82 * marker for whether we got a 'dynamic' indication of id for target node. if so,
83 * we permit saving; otherwise, not.
84 */
85 private boolean isDynamicTarget = false;
86
87 /***
88 * Default constructor.
89 */
90 public CompletionBean() {
91 }
92
93 public boolean isDynamicTarget() {
94 return isDynamicTarget;
95 }
96
97 /***
98 * @todo should this just be set whenever setTargetId() is called??
99 */
100 public void setDynamicTarget(boolean dynamicTarget) {
101 isDynamicTarget = dynamicTarget;
102 }
103
104 /***
105 * Sets the target id (as integer)
106 *
107 * @param nodeId int
108 */
109 public void setTargetId(int nodeId) {
110 Integer newTargetId = new Integer(nodeId);
111
112
113 if (targetId == null || this.targetId.intValue() != newTargetId.intValue()) {
114
115
116 targetId = newTargetId;
117
118
119 currentNode = null;
120 completionParts = null;
121 }
122
123 }
124
125 /***
126 * Sets the target id.
127 *
128 * @param newTargetId String
129 */
130 public void setTargetId(String newTargetId) {
131 if (targetId != null) {
132 setTargetId(Integer.parseInt(newTargetId));
133 } else {
134 targetId = null;
135 currentNode = null;
136 completionParts = null;
137 isDynamicTarget = false;
138 }
139 }
140
141 /***
142 * Retrieve the target node id.
143 *
144 * @return Integer
145 */
146 public Integer getTargetId() {
147 return targetId;
148 }
149
150
151 /***
152 * Retrieve all completion parts.
153 *
154 * @return Set a set of all completion parts.
155 */
156 public Set getCompletionParts() {
157 return completionParts;
158 }
159
160
161 /***
162 * Retrieve a specific parts bean given the specified part.
163 *
164 * @param key Part
165 * @return CompletionPartsBean
166 */
167 public CompletionPartsBean getPartsBeanFromPart(final Part key) {
168 for (Iterator i = getCompletionParts().iterator(); i.hasNext();) {
169 CompletionPartsBean oneBean = (CompletionPartsBean) i.next();
170 if (oneBean.getPart().equals(key)) {
171 return oneBean;
172 }
173 }
174
175 throw new RuntimeException("Unable to locate completion bean by part: " + key.toString());
176 }
177
178 /***
179 * Retrieve the set of all completion parts that have the field completion
180 * value set to 'wizard'.
181 *
182 * @return Set of <tt>CompletionPartsBean</tt>s
183 */
184 public Set getWizardCompletionParts() {
185 Set returnValue = new TreeSet();
186 for (Iterator i = getCompletionParts().iterator(); i.hasNext();) {
187 CompletionPartsBean oneCompletionPart = (CompletionPartsBean) i.next();
188 if (oneCompletionPart.getFieldCompletion() == FieldCompletion.WIZARD) {
189 returnValue.add(oneCompletionPart);
190 }
191 }
192
193 return returnValue;
194 }
195
196 /***
197 * Retrieve the currently set node.
198 *
199 * @return Node
200 */
201 public Node getCurrentNode() {
202 return currentNode;
203 }
204
205 /***
206 * Get the wizard title.
207 *
208 * @return String
209 */
210 public String getWizardTitle() {
211 return wizardTitle;
212 }
213
214 /***
215 * Get the wizard directive.
216 *
217 * @return String
218 */
219 public String getSummary() {
220 return summary;
221 }
222
223
224 /***
225 * Retrieve the wizard class.
226 *
227 * @return Class
228 */
229 public Class getWizardClass() {
230 return wizardClass;
231 }
232
233 public Integer getWizardId() {
234 return wizardId;
235 }
236
237
238 /***
239 * <p>Validate the properties that have been set for this HTTP request,
240 * and return an <code>ActionErrors</code> object that encapsulates any
241 * validation errors that have been found.
242 *
243 * @param returnValue the constructed ErrorCollection to populate into.
244 * @return ActionErrors
245 */
246 public ErrorCollection validate(final ErrorCollection returnValue) {
247
248 if (targetId == null) {
249 returnValue.add("targetId", new ActionMessage("You must enter a valid node id (integer)"));
250 }
251
252 if (getWizardTitle() == null) {
253 returnValue.add("wizardTitle", new ActionMessage("You must enter a wizard title"));
254 }
255
256 if (getWizardClass() == null) {
257 returnValue.add("wizardClass", new ActionMessage("You need to specify a valid wizard class"));
258 }
259
260 if (!Wizard.class.isAssignableFrom(getWizardClass())) {
261 returnValue.add("wizardClass",
262 new ActionMessage("The wizard class specified does not implement the: " + Wizard.class.getName()
263 + " interface"));
264 }
265
266 /***
267 * Don't continue validation if we can't even get this far.
268 */
269 if (returnValue.size() > 0) {
270 return returnValue;
271 }
272
273 if (!isInitialized()) {
274 initializeFromNodeId(returnValue);
275 } else {
276
277 for (Iterator i = completionParts.iterator(); i.hasNext();) {
278 CompletionPartsBean oneBean = (CompletionPartsBean) i.next();
279 oneBean.validateAndAdjust(returnValue);
280 }
281 }
282
283 return returnValue;
284
285 }
286
287 /***
288 * Checks to make sure the bean is initialize.d
289 *
290 * @return boolean
291 */
292 public boolean isInitialized() {
293 return currentNode != null;
294 }
295
296
297 /***
298 * Initialize from the node id. Populate ErrorCollection if there is problems
299 * initializing.
300 *
301 * @param errorMessages ErrorCollection may be null, in which case the method
302 * throws IllegalArgumentExceptions if validation/construction fails.
303 */
304 public void initializeFromNodeId(final ErrorCollection errorMessages) {
305 try {
306 Node n = new Node();
307 n.setNodeId(getTargetId().toString());
308 if (!n.find()) {
309 if (errorMessages != null) {
310 errorMessages.addError("Unable to find node with id of : " + getTargetId());
311 } else {
312 throw new IllegalArgumentException("Unable to find node with id of : " + getTargetId());
313 }
314 }
315 currentNode = n;
316
317 completionParts = new TreeSet();
318
319 Part[] allParts = PartsFactory.getParts(n.getNodeType());
320 for (int i = 0; i < allParts.length; i++) {
321 Part onePart = allParts[i];
322 completionParts.add(new CompletionPartsBean(this, onePart));
323 }
324
325 } catch (DBException ex) {
326 ex.printStackTrace();
327 if (errorMessages != null) {
328 errorMessages.add("targetId",
329 new ActionMessage("Error initializing node id with id of " + getTargetId()));
330 }
331 Logger.getLogger(CompletionBean.class).error("Error initializing node id with id of " + getTargetId(), ex);
332 }
333
334 }
335
336 /***
337 * Sets the wizard title.
338 *
339 * @param wizardTitle String
340 */
341 public void setWizardTitle(String wizardTitle) {
342 this.wizardTitle = wizardTitle;
343 }
344
345 /***
346 * Sets the wizard directive.
347 *
348 * @param wizardDirective String
349 */
350 public void setSummary(String wizardDirective) {
351 this.summary = wizardDirective;
352 }
353
354
355 /***
356 * Sets the wizard class to use.
357 *
358 * @param wizardClass Class
359 */
360 public void setWizardClass(Class wizardClass) {
361 this.wizardClass = wizardClass;
362 }
363
364 /***
365 * Sets the wizard id.
366 *
367 * @param wizardId Integer.
368 */
369 public void setWizardId(Integer wizardId) {
370 this.wizardId = wizardId;
371 }
372
373
374 /***
375 * Sets the wizard class to use
376 *
377 * @param wizardClass String
378 * @throws java.lang.ClassNotFoundException
379 * if unable to load the specified
380 * class with the Thread's current context class loader.
381 */
382 public void setWizardClass(final String wizardClass) throws ClassNotFoundException {
383 assert wizardClass != null;
384 setWizardClass(Thread.currentThread().getContextClassLoader().loadClass(wizardClass.trim()));
385 }
386
387 /***
388 * Indicates whether some other object is "equal to" this one.
389 *
390 * @param obj the reference object with which to compare.
391 * @return <code>true</code> if this object is the same as the obj
392 * argument; <code>false</code> otherwise.
393 */
394 public boolean equals(Object obj) {
395 if (!(obj instanceof CompletionBean)) {
396 return false;
397 }
398
399
400 CompletionBean other = (CompletionBean) obj;
401
402 EqualsBuilder equals = new EqualsBuilder().append(completionParts, other.completionParts)
403 .append(summary, other.summary)
404 .append(targetId, other.targetId)
405 .append(wizardClass, other.wizardClass)
406 .append(wizardId, other.wizardId)
407 .append(wizardTitle, other.wizardTitle);
408
409 return equals.isEquals();
410 }
411
412 /***
413 * Returns a hash code value for the object.
414 *
415 * @return a hash code value for this object.
416 */
417 public int hashCode() {
418
419 HashCodeBuilder hashCodeBuilder = new HashCodeBuilder(131, 91)
420 .append(completionParts)
421 .append(summary)
422 .append(targetId)
423 .append(wizardClass)
424 .append(wizardId)
425 .append(wizardTitle);
426
427 return hashCodeBuilder.toHashCode();
428 }
429
430 /***
431 * Returns a string representation of the object.
432 *
433 * @return a string representation of the object.
434 */
435 public String toString() {
436 return new ToStringBuilder(this)
437 .append(completionParts)
438 .append(summary)
439 .append(targetId)
440 .append(wizardClass)
441 .append(wizardId)
442 .append(wizardTitle)
443 .toString();
444 }
445 }