1 package org.apache.maven.werkz;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 import java.util.Collection;
68 import java.util.Collections;
69 import java.util.HashMap;
70 import java.util.Iterator;
71 import java.util.LinkedList;
72 import java.util.List;
73 import java.util.Map;
74
75 /** General <code>Goal</code> manager.
76 *
77 * <p>
78 * It is not strictly necessary to maintain a <code>Goal</code>
79 * graph, it does assist in organizing and administering a
80 * group of <code>Goal</code>s.
81 *
82 * @see Goal
83 *
84 * @author <a href="mailto:bob@eng.werken.com">bob mcwhirter</a>
85 */
86 public class WerkzProject
87 {
88
89
90
91
92 /** Goal index. */
93 private Map goals;
94
95 /** Name of the default gual, or null. */
96 private String defaultGoalName;
97
98
99
100
101
102 /** Construct.
103 */
104 public WerkzProject()
105 {
106 this.goals = new HashMap();
107 }
108
109
110
111
112
113 /** Retrieve a valid execution chain to attain the specified goal.
114 *
115 * <p>
116 * This method returns one of possibly many different valid
117 * execution chains. All chains will be of the same length.
118 * This implementation happens to perform a breadth-first
119 * walk, so the chain will grow from the deepest sections
120 * to the showllowest instead of plunging/surging upwards.
121 * <p>
122 *
123 * <p>
124 * <pre>
125 * B - D
126 * / \
127 * A F
128 * \ /
129 * C - E
130 * </pre>
131 *
132 * will result in either FEDCBA or FDEBCA but will
133 * not result in the equally valid FECDBA or FDBECA
134 * sequences.
135 * </p>
136 *
137 * <p>
138 * The ordering of the array is such that the index
139 * <code>length - 1</code> (the last index of the array)
140 * points to the <code>Goal</code> specified as the
141 * parameter to the method.
142 * </p>
143 *
144 * @param name The name of the goal.
145 *
146 * @return The array of goals in the execution chain, terminating
147 * with the requested goal as the last member.
148 *
149 * @throws NoSuchGoalException if the <code>name</code> refers to no known goal.
150 */
151
152 public Goal[] getExecutionChain( String name )
153 throws NoSuchGoalException
154 {
155 Goal goal = getGoal( name );
156
157 LinkedList chain = new LinkedList();
158 LinkedList stack = new LinkedList();
159
160 stack.addLast( goal );
161
162 while ( !stack.isEmpty() )
163 {
164 goal = (Goal) stack.removeFirst();
165
166 if ( chain.contains( goal ) )
167 {
168 continue;
169 }
170
171 chain.addFirst( goal );
172
173 List precursors = goal.getPrecursors();
174
175 for ( Iterator precursorIter = precursors.iterator(); precursorIter.hasNext(); )
176 {
177 Goal eachPrecursor = (Goal) precursorIter.next();
178
179 if ( !chain.contains( eachPrecursor ) )
180 {
181 stack.addLast( eachPrecursor );
182 }
183 }
184
185 }
186
187 return (Goal[]) chain.toArray( Goal.EMPTY_ARRAY );
188 }
189
190 /** Attempt to attain the specified goal.
191 *
192 * @param name The name of the goal to attain.
193 * @param session The context in which to attain goals.
194 *
195 * @throws NoSuchGoalException if the <code>name</code> refers to no known goal.
196 * @throws UnattainableGoalException if a precursor or the goal itself had an error.
197 * @throws NoActionDefinitionException if a goal contains no action definition.
198 */
199 public void attainGoal( String name, Session session )
200 throws NoSuchGoalException, UnattainableGoalException, NoActionDefinitionException
201 {
202 Goal goal = getGoal( name );
203
204 if ( goal == null )
205 {
206 throw new NoSuchGoalException( name );
207 }
208
209 goal.attain( session );
210 }
211
212 /** Attempt to percolate the specified goal.
213 *
214 * @param name The name of the goal to percolate.
215 * @param session The context in which to percolate goals.
216 *
217 * @throws NoSuchGoalException if the <code>name</code> refers to no known goal.
218 * @throws UnattainableGoalException if a postcursor or the goal itself had an error.
219 * @throws NoActionDefinitionException if a goal contains no action definition.
220 */
221 public void percolateGoal( String name, Session session )
222 throws NoSuchGoalException, UnattainableGoalException, NoActionDefinitionException
223 {
224 Goal goal = getGoal( name );
225
226 if ( goal == null )
227 {
228 throw new NoSuchGoalException( name );
229 }
230
231 goal.percolate( session );
232 }
233
234 /** Attempt to attain the specified goal.
235 *
236 * @param name The name of the goal to attain.
237 *
238 * @throws NoSuchGoalException if the <code>name</code> refers to no known goal.
239 * @throws UnattainableGoalException if a precursor or the goal itself had an error.
240 * @throws NoActionDefinitionException if a goal contains no action definition.
241 */
242 public void attainGoal( String name )
243 throws NoSuchGoalException, UnattainableGoalException, NoActionDefinitionException
244 {
245 attainGoal( name, new Session() );
246 }
247
248 /** Attempt to percolate the specified goal.
249 *
250 * @param name The name of the goal to percolate.
251 *
252 * @throws NoSuchGoalException if the <code>name</code> refers to no known goal.
253 * @throws UnattainableGoalException if a postcursor or the goal itself had an error.
254 * @throws NoActionDefinitionException if a goal contains no action definition.
255 */
256 public void percolateGoal( String name )
257 throws NoSuchGoalException, UnattainableGoalException, NoActionDefinitionException
258 {
259 percolateGoal( name, new Session() );
260 }
261
262 /** Add a <code>Goal</code> to this manager.
263 *
264 * @param goal The <code>Goal</code> to add.
265 */
266 public void addGoal( Goal goal )
267 {
268 this.goals.put( goal.getName(), goal );
269 }
270
271 /** Retrieve a <code>Goal</code> by name from this manager.
272 *
273 * @param name The name of the goal to retrieve.
274 *
275 * @return The <code>Goal</code> associated with the <code>name</code>,
276 * or <code>null</code> if there is no such <code>Goal</code>.
277 */
278 public Goal getGoal( String name )
279 {
280 return (Goal) this.goals.get( name );
281 }
282
283 /** Retrieve a <code>Goal</code> by name from this manager.
284 *
285 * @param name The name of the goal to retrieve.
286 * @param create Flag indicating if a new <code>Goal</code> should
287 * be created and returned if none currently exists
288 * bound to <code>name</code>.
289 *
290 * @return The existing <code>Goal</code> associated with the <code>name</code>,
291 * or a new <code>Goal</code> if none was previously associated with
292 * <code>name</code>.
293 */
294 public Goal getGoal( String name, boolean create )
295 {
296 Goal goal = getGoal( name );
297
298 if ( ( goal == null ) && create )
299 {
300 goal = new Goal( name );
301 addGoal( goal );
302 }
303
304 return goal;
305 }
306
307 /** Set the default goal name.
308 *
309 * @param defaultGoalName The name of the default goal.
310 */
311 public void setDefaultGoalName( String defaultGoalName )
312 {
313 this.defaultGoalName = defaultGoalName;
314 }
315
316 /** Retrieve the default goal name.
317 *
318 * @return The namee of the default goal, or
319 * <code>null</code> if not set.
320 */
321 public String getDefaultGoalName()
322 {
323 return this.defaultGoalName;
324 }
325
326 /** Retrieve the default goal.
327 *
328 * @return The default <code>Goal</code> or
329 * <code>null</code> if a valid default
330 * goal name has not been previously
331 * specified using {@link #setDefaultGoalName}.
332 */
333 public Goal getDefaultGoal()
334 {
335 return getGoal( getDefaultGoalName() );
336 }
337
338 /** Retrieve an unmodifiable collection of all <code>Goal</code>s
339 * that are a part of this <code>Project</code>.
340 *
341 * @return An unmodifiable collection of all <code>Goal</code>s
342 * that are members of this <code>Project</code>.
343 */
344 public Collection getGoals()
345 {
346 return Collections.unmodifiableCollection( this.goals.values() );
347 }
348
349 /** Produce a textual representation suitable for debugging.
350 *
351 * @return A textual representation suitable for debugging.
352 */
353 public String toString()
354 {
355 return "[Werkz: goals=" + this.goals + ";]";
356 }
357
358 public void removeGoal( String name )
359 {
360 goals.remove( name );
361 }
362 }