View Javadoc

1   /* ===================================================================
2    * Copyright 2002-05 SRI International.
3    * Released under the MOZILLA PUBLIC LICENSE Version 1.1
4    * which can be obtained at http://www.mozilla.org/MPL/MPL-1.1.html
5    * This software is distributed on an "AS IS"
6    * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
7    * See the License for the specific language governing rights and
8    * limitations under the License.
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         //If the node id is different from previous values
113         if (targetId == null || this.targetId.intValue() != newTargetId.intValue()) {
114 
115             //Set the node ide.
116             targetId = newTargetId;
117 
118             //Reinitialize the nodes.
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             //Iterate over all the completion parts validating each one.
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 }