KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > groboutils > pmti > v1 > defimpl > AbstractEditableIssue


1 /*
2  * @(#)AbstractEditableIssue.java
3  *
4  * Copyright (C) 2002-2003 Matt Albrecht
5  * groboclown@users.sourceforge.net
6  * http://groboutils.sourceforge.net
7  *
8  * Part of the GroboUtils package at:
9  * http://groboutils.sourceforge.net
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  */

29 package net.sourceforge.groboutils.pmti.v1.defimpl;
30
31 import net.sourceforge.groboutils.pmti.v1.IIssue;
32 import net.sourceforge.groboutils.pmti.v1.IIssueState;
33 import net.sourceforge.groboutils.pmti.v1.IAttributeSet;
34 import net.sourceforge.groboutils.pmti.v1.IEditableIssue;
35 import net.sourceforge.groboutils.pmti.v1.IEditableIssueState;
36 import net.sourceforge.groboutils.pmti.v1.IEditableAttributeSet;
37 import net.sourceforge.groboutils.pmti.v1.ProblemManagerException;
38
39
40 /**
41  * Allows for editing of an issue. The only parts that can't be edited are
42  * the ID and type, since those uniquely identify the issue at hand. Editing
43  * an issue has several constraints that should be known by the user:
44  * <UL>
45  * <LI>
46  * Just like with the <tt>IIssue</tt> instances, the issue being
47  * edited will NOT be real-time updated to reflect the current
48  * tracker state. Currently, the only way to update an issue is by
49  * re-polling the <tt>ProblemManager</tt>. Individual implementations
50  * may provide for alternative means to receive synchronized issues.
51  * </LI>
52  * <LI>
53  * No changes to an editable issue will be committed to the problem
54  * tracker is to call <tt>commit()</tt> on the issue.
55  * </LI>
56  * </UL>
57  *
58  * @author Matt Albrecht <a HREF="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
59  * @version $Date: 2003/02/10 22:51:57 $
60  * @since July 12, 2002
61  */

62 public abstract class AbstractEditableIssue implements IEditableIssue
63 {
64     private IIssue baseIssue;
65     
66     private String JavaDoc newDesc;
67     private boolean changedDesc;
68     
69     private IIssueState newState;
70     private boolean changedState;
71     
72     private IEditableAttributeSet nextSet;
73     
74     
75     
76     public AbstractEditableIssue( IIssue base )
77     {
78         if (base == null)
79         {
80             throw new IllegalArgumentException JavaDoc("no null arguments");
81         }
82         this.baseIssue = base;
83     }
84
85     
86     //-------------------------------------------------------------------------
87
// IIssue
88

89     
90     public String JavaDoc getID()
91     {
92         return this.baseIssue.getID();
93     }
94     
95     
96     public String JavaDoc getType()
97     {
98         return this.baseIssue.getType();
99     }
100     
101     
102     public String JavaDoc getShortDescription()
103     {
104         if (this.changedDesc)
105         {
106             return this.newDesc;
107         }
108         else
109         {
110             return this.baseIssue.getShortDescription();
111         }
112     }
113     
114     
115     public IIssueState getState()
116     {
117         if (this.changedState)
118         {
119             return this.newState;
120         }
121         else
122         {
123             return this.baseIssue.getState();
124         }
125     }
126     
127     
128     public IAttributeSet getAttributes()
129     {
130         return getEditableAttributes();
131     }
132     
133     
134     public abstract IIssue reload()
135             throws ProblemManagerException;
136
137     
138     //-------------------------------------------------------------------------
139
// IEditableIssue
140

141     
142     /**
143      *
144      */

145     public void setShortDescription( String JavaDoc desc )
146     {
147         String JavaDoc orig = this.baseIssue.getShortDescription();
148         if ( desc == orig || ( desc != null && desc.equals( orig ) ) )
149         {
150             // they're the same - ensure the state is correct
151
this.changedDesc = false;
152         }
153         else
154         {
155             // changed
156
this.changedDesc = true;
157             this.newDesc = desc;
158         }
159     }
160     
161     
162     
163     
164     /**
165      * @return <tt>true</tt> if <tt>setShortDescription( String )</tt> was
166      * called with a different description string than the original
167      * issue, otherwise <tt>false</tt>.
168      */

169     public boolean hasShortDescriptionChanged()
170     {
171         return this.changedDesc;
172     }
173     
174     
175     /**
176      * Returns the list of all states that this issue can move to next.
177      * This is part of the workflow logic of the underlying PMT. The returned
178      * states may be safely edited without any affect; the only effect will be
179      * when the state is explicitly set. This will always return, in index 0,
180      * a <b>copy</b> of the current state as editable.
181      */

182     public IEditableIssueState[] getNextStates()
183     {
184         return createNextEditableIssueStates( getState() );
185     }
186     
187     
188     /**
189      * Sets the current state. Since there is no getEditableState() method,
190      * use this method if any information in the current state needs to be
191      * updated. You can retrieve the current state as an editable state
192      * using <tt>getNextStates()[0]</tt>, but note that any changes to that
193      * editable version will not affect the tracker's state unless that
194      * editable instance is explicitly set in this method.
195      *
196      * @exception ProblemManagerException if the input state is not a valid
197      * next state.
198      */

199     public void setState( IIssueState state )
200             throws ProblemManagerException
201     {
202         assertStateCanBeNext( state );
203         
204         if (state instanceof IEditableIssueState)
205         {
206             state = createImmutableIssueState( (IEditableIssueState)state );
207         }
208         this.newState = state;
209         this.changedState = true;
210     }
211     
212     
213     /**
214      * @return <tt>true</tt> if the <tt>setState( IIssueState )</tt> method
215      * has been invoked and did not throw an exception, otherwise
216      * <tt>false</tt>. Note that even if the set state is an unchanged
217      * version of the current issue's state, this will still return
218      * <tt>true</tt>.
219      */

220     public boolean hasStateChanged()
221     {
222         return this.changedState;
223     }
224     
225     
226     /**
227      * This is a synonymn for <tt>getAttributes()</tt>, but this explicitly
228      * sets the returned value as an editable set, without the need for an
229      * extra cast. The returned attribute set may be safely edited, and
230      * changes there will affect the issue that returned them.
231      */

232     public IEditableAttributeSet getEditableAttributes()
233     {
234         if (this.nextSet == null)
235         {
236             // create the editable set
237
IAttributeSet s = this.baseIssue.getAttributes();
238             this.nextSet = createEditableAttributeSet( s );
239         }
240         return this.nextSet;
241     }
242     
243     
244     /**
245      * Commits all changes from the issue to the tracker.
246      * <P>
247      * In theory, issues should never be removed. However, some systems allow
248      * them to be deleted (say, if there was an accidental creation). In this
249      * case, an <tt>IssueRemovedException</tt> will be thrown.
250      *
251      * @exception ProblemManagerException if there was an underlying tracker
252      * error.
253      */

254     public abstract void commit()
255             throws ProblemManagerException;
256             
257
258     
259     //-------------------------------------------------------------------------
260
// protected methods
261

262     
263     /**
264      * Creates a set of editable issue states that can be set as 'next' for
265      * <tt>is</tt>. Note that it is required that the input <tt>is</tt>
266      * <i>must</i> be returned in index 0 of the returned array.
267      */

268     protected abstract IEditableIssueState[] createNextEditableIssueStates(
269             IIssueState is );
270     
271     
272     /**
273      * Creates an editable set of attributes based on the immutable attribute
274      * set. The new set of attributes should accurately reflect the input
275      * attribute set's values.
276      */

277     protected abstract IEditableAttributeSet createEditableAttributeSet(
278             IAttributeSet as );
279     
280     
281     /**
282      * Create a non-editable version of <tt>eis</tt>.
283      */

284     protected abstract IIssueState createImmutableIssueState(
285             IEditableIssueState eis );
286     
287     
288     
289     protected void assertStateCanBeNext( IIssueState state )
290             throws ProblemManagerException
291     {
292         IEditableIssueState[] eis = getNextStates();
293         if (eis == null || eis.length < 1)
294         {
295             throw new IllegalStateException JavaDoc("Invalid set of next states.");
296         }
297         
298         String JavaDoc name = null;
299         if (state != null)
300         {
301             name = state.getName();
302         }
303         
304         for (int i = 0; i < eis.length; ++i)
305         {
306             if (eis[i] == null)
307             {
308                 if (state == null)
309                 {
310                     // they are the same - null state supported.
311
return;
312                 }
313             }
314             else
315             // allow for a null name for the input state,
316
// but the non-null state must have a non-null name.
317
if (eis[i].getName().equals( name ))
318             {
319                 // found the requested state in the next state list,
320
// so the requested state is valid.
321
return;
322             }
323         }
324         // never found the requested state in the next state list.
325
throw new ProblemManagerException( "State "+state+
326             " cannot be a next state for "+getState() );
327     }
328 }
329
330
Popular Tags