##### Coverage Report - org.apache.turbine.services.intake.IntakeTool

Classes in this File | Line Coverage | Branch Coverage | Complexity
IntakeTool |
26% | 31/115
19% | 10/52
| 2.5833333333333335;2,583
IntakeTool$PullHelper |
50% | 12/24
33% | 2/6
| 2.5833333333333335;2,583

1 |  |
     package org.apache.turbine.services.intake;
2 |  |
3 |  |
4 |  |
     /*
5 |  |
      * Licensed to the Apache Software Foundation (ASF) under one
6 |  |
      * or more contributor license agreements.  See the NOTICE file
7 |  |
      * distributed with this work for additional information
8 |  |
      * regarding copyright ownership.  The ASF licenses this file
9 |  |
      * to you under the Apache License, Version 2.0 (the
10 |  |
      * "License"); you may not use this file except in compliance
11 |  |
      * with the License.  You may obtain a copy of the License at
12 |  |
      *
13 |  |
      *   http://www.apache.org/licenses/LICENSE-2.0
14 |  |
      *
15 |  |
      * Unless required by applicable law or agreed to in writing,
16 |  |
      * software distributed under the License is distributed on an
17 |  |
      * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 |  |
      * KIND, either express or implied.  See the License for the
19 |  |
      * specific language governing permissions and limitations
20 |  |
      * under the License.
21 |  |
      */
22 |  |
23 |  |
24 |  |
     import java.util.HashMap;
25 |  |
     import java.util.Iterator;
26 |  |
     import java.util.List;
27 |  |
     import java.util.Map;
28 |  |
29 |  |
     import org.apache.commons.logging.Log;
30 |  |
     import org.apache.commons.logging.LogFactory;
31 |  |
     import org.apache.fulcrum.intake.IntakeException;
32 |  |
     import org.apache.fulcrum.intake.IntakeServiceFacade;
33 |  |
     import org.apache.fulcrum.intake.Retrievable;
34 |  |
     import org.apache.fulcrum.intake.model.Group;
35 |  |
     import org.apache.fulcrum.parser.ValueParser;
36 |  |
     import org.apache.fulcrum.pool.Recyclable;
37 |  |
     import org.apache.turbine.services.pull.ApplicationTool;
38 |  |
     import org.apache.turbine.util.RunData;
39 |  |
40 |  |
41 |  |
     /**
42 |  |
      * The main class through which Intake is accessed.  Provides easy access
43 |  |
      * to the Fulcrum Intake component.
44 |  |
      *
45 |  |
      * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
46 |  |
      * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
47 |  |
      * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
48 |  |
      * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
49 |  |
      * @version $Id: IntakeTool.java 1078552 2011-03-06 19:58:46Z tv $
50 |  |
      */
51 |  |
     public class IntakeTool
52 |  |
             implements ApplicationTool, Recyclable
53 |  |
     {
54 |  |
         /** Used for logging */
55 | 2 |
         protected static Log log = LogFactory.getLog(IntakeTool.class);
56 |  |
57 |  |
         /** Constant for default key */
58 |  |
         public static final String DEFAULT_KEY = "_0";
59 |  |
60 |  |
         /** Constant for the hidden fieldname */
61 |  |
         public static final String INTAKE_GRP = "intake-grp";
62 |  |
63 |  |
         /** Groups from intake.xml */
64 |  |
         protected HashMap<String, Group> groups;
65 |  |
66 |  |
         /** ValueParser instance */
67 |  |
         protected ValueParser pp;
68 |  |
69 | 4 |
         private final HashMap<String, Group> declaredGroups = new HashMap<String, Group>();
70 | 4 |
         private final StringBuffer allGroupsSB = new StringBuffer(256);
71 | 4 |
         private final StringBuffer groupSB = new StringBuffer(128);
72 |  |
73 |  |
         /** The cache of PullHelpers. **/
74 |  |
         private final Map<String, IntakeTool.PullHelper> pullMap;
75 |  |
76 |  |
         /**
77 |  |
          * Constructor
78 |  |
          */
79 |  |
         @SuppressWarnings("null")
80 |  |
         public IntakeTool()
81 | 4 |
         {
82 | 4 |
             String[] groupNames = IntakeServiceFacade.getGroupNames();
83 | 4 |
             int groupCount = 0;
84 | 4 |
             if (groupNames != null)
85 |  |
             {
86 | 4 |
                 groupCount = groupNames.length;
87 |  |
             }
88 | 4 |
             groups = new HashMap<String, Group>((int) (1.25 * groupCount + 1));
89 | 4 |
             pullMap = new HashMap<String, IntakeTool.PullHelper>((int) (1.25 * groupCount + 1));
90 |  |
91 | 8 |
             for (int i = groupCount - 1; i >= 0; i--)
92 |  |
             {
93 | 4 |
                 pullMap.put(groupNames[i], new PullHelper(groupNames[i]));
94 |  |
             }
95 | 4 |
         }
96 |  |
97 |  |
         /**
98 |  |
          * Prepares intake for a single request
99 |  |
          */
100 |  |
         public void init(Object runData)
101 |  |
         {
102 | 4 |
             this.pp = ((RunData) runData).getParameters();
103 |  |
104 | 4 |
             String[] groupKeys = pp.getStrings(INTAKE_GRP);
105 | 4 |
             String[] groupNames = null;
106 | 4 |
             if (groupKeys == null || groupKeys.length == 0)
107 |  |
             {
108 | 4 |
                 groupNames = IntakeServiceFacade.getGroupNames();
109 |  |
             }
110 |  |
             else
111 |  |
             {
112 | 0 |
                 groupNames = new String[groupKeys.length];
113 | 0 |
                 for (int i = groupKeys.length - 1; i >= 0; i--)
114 |  |
                 {
115 | 0 |
                     groupNames[i] = IntakeServiceFacade.getGroupName(groupKeys[i]);
116 |  |
                 }
117 |  |
118 |  |
             }
119 |  |
120 | 8 |
             for (int i = groupNames.length - 1; i >= 0; i--)
121 |  |
             {
122 |  |
                 try
123 |  |
                 {
124 | 4 |
                     List foundGroups = IntakeServiceFacade.getGroup(groupNames[i])
125 |  |
                         .getObjects(pp);
126 |  |
127 | 4 |
                     if (foundGroups != null)
128 |  |
                     {
129 | 0 |
                         for (Iterator iter = foundGroups.iterator();
130 | 0 |
                              iter.hasNext();)
131 |  |
                         {
132 | 0 |
                             Group group = (Group) iter.next();
133 | 0 |
                             groups.put(group.getObjectKey(), group);
134 | 0 |
                         }
135 |  |
                     }
136 |  |
                 }
137 | 0 |
                 catch (IntakeException e)
138 |  |
                 {
139 | 0 |
                     log.error(e);
140 | 4 |
                 }
141 |  |
             }
142 | 4 |
         }
143 |  |
144 |  |
         public void addGroupsToParameters(ValueParser vp)
145 |  |
         {
146 | 0 |
             for (Iterator i = groups.values().iterator(); i.hasNext();)
147 |  |
             {
148 | 0 |
                 Group group = (Group) i.next();
149 | 0 |
                 if (!declaredGroups.containsKey(group.getIntakeGroupName()))
150 |  |
                 {
151 | 0 |
                     declaredGroups.put(group.getIntakeGroupName(), null);
152 | 0 |
                     vp.add("intake-grp", group.getGID());
153 |  |
                 }
154 | 0 |
                 vp.add(group.getGID(), group.getOID());
155 | 0 |
             }
156 | 0 |
             declaredGroups.clear();
157 | 0 |
         }
158 |  |
159 |  |
         /**
160 |  |
          * A convenience method to write out the hidden form fields
161 |  |
          * that notify intake of the relevant groups.  It should be used
162 |  |
          * only in templates with 1 form.  In multiform templates, the groups
163 |  |
          * that are relevant for each form need to be declared using
164 |  |
          * $intake.newForm() and $intake.declareGroup($group) for the relevant
165 |  |
          * groups in the form.
166 |  |
          *
167 |  |
          */
168 |  |
         public String declareGroups()
169 |  |
         {
170 | 0 |
             allGroupsSB.setLength(0);
171 | 0 |
             for (Iterator i = groups.values().iterator(); i.hasNext();)
172 |  |
             {
173 | 0 |
                 declareGroup((Group) i.next(), allGroupsSB);
174 |  |
             }
175 | 0 |
             return allGroupsSB.toString();
176 |  |
         }
177 |  |
178 |  |
         /**
179 |  |
          * A convenience method to write out the hidden form fields
180 |  |
          * that notify intake of the group.
181 |  |
          */
182 |  |
         public String declareGroup(Group group)
183 |  |
         {
184 | 0 |
             groupSB.setLength(0);
185 | 0 |
             declareGroup(group, groupSB);
186 | 0 |
             return groupSB.toString();
187 |  |
         }
188 |  |
189 |  |
         /**
190 |  |
          * xhtml valid hidden input field(s) that notifies intake of the
191 |  |
          * group's presence.
192 |  |
          */
193 |  |
         public void declareGroup(Group group, StringBuffer sb)
194 |  |
         {
195 | 0 |
             if (!declaredGroups.containsKey(group.getIntakeGroupName()))
196 |  |
             {
197 | 0 |
                 declaredGroups.put(group.getIntakeGroupName(), null);
198 | 0 |
                 sb.append("<input type=\"hidden\" name=\"")
199 |  |
                         .append(INTAKE_GRP)
200 |  |
                         .append("\" value=\"")
201 |  |
                         .append(group.getGID())
202 |  |
                         .append("\"/>\n");
203 |  |
             }
204 | 0 |
             group.appendHtmlFormInput(sb);
205 | 0 |
         }
206 |  |
207 |  |
         public void newForm()
208 |  |
         {
209 | 0 |
             declaredGroups.clear();
210 | 0 |
             for (Iterator i = groups.values().iterator(); i.hasNext();)
211 |  |
             {
212 | 0 |
                 ((Group) i.next()).resetDeclared();
213 |  |
             }
214 | 0 |
         }
215 |  |
216 |  |
         /**
217 |  |
          * Implementation of ApplicationTool interface is not needed for this
218 |  |
          * tool as it is request scoped
219 |  |
          */
220 |  |
         public void refresh()
221 |  |
         {
222 |  |
             // empty
223 | 2 |
         }
224 |  |
225 |  |
         /**
226 |  |
          * Inner class to present a nice interface to the template designer
227 |  |
          */
228 |  |
         public class PullHelper
229 |  |
         {
230 |  |
             /** Name of the group used by the pull helper */
231 |  |
             String groupName;
232 |  |
233 |  |
             /**
234 |  |
              * Protected constructor to force use of factory method.
235 |  |
              *
236 |  |
              * @param groupName
237 |  |
              */
238 |  |
             protected PullHelper(String groupName)
239 | 4 |
             {
240 | 4 |
                 this.groupName = groupName;
241 | 4 |
             }
242 |  |
243 |  |
             /**
244 |  |
              * Populates the object with the default values from the XML File
245 |  |
              *
246 |  |
              * @return a Group object with the default values
247 |  |
              * @throws IntakeException
248 |  |
              */
249 |  |
             public Group getDefault()
250 |  |
                     throws IntakeException
251 |  |
             {
252 | 0 |
                 return setKey(DEFAULT_KEY);
253 |  |
             }
254 |  |
255 |  |
             /**
256 |  |
              * Calls setKey(key,true)
257 |  |
              *
258 |  |
              * @param key
259 |  |
              * @return an Intake Group
260 |  |
              * @throws IntakeException
261 |  |
              */
262 |  |
             public Group setKey(String key)
263 |  |
                     throws IntakeException
264 |  |
             {
265 | 2 |
                 return setKey(key, true);
266 |  |
             }
267 |  |
268 |  |
             /**
269 |  |
              *
270 |  |
              * @param key
271 |  |
              * @param create
272 |  |
              * @return an Intake Group
273 |  |
              * @throws IntakeException
274 |  |
              */
275 |  |
             public Group setKey(String key, boolean create)
276 |  |
                     throws IntakeException
277 |  |
             {
278 | 2 |
                 Group g = null;
279 |  |
280 | 2 |
                 String inputKey = IntakeServiceFacade.getGroupKey(groupName) + key;
281 | 2 |
                 if (groups.containsKey(inputKey))
282 |  |
                 {
283 | 0 |
                     g = groups.get(inputKey);
284 |  |
                 }
285 | 2 |
                 else if (create)
286 |  |
                 {
287 | 2 |
                     g = IntakeServiceFacade.getGroup(groupName);
288 | 2 |
                     groups.put(inputKey, g);
289 | 2 |
                     g.init(key, pp);
290 |  |
                 }
291 |  |
292 | 2 |
                 return g;
293 |  |
             }
294 |  |
295 |  |
             /**
296 |  |
              * maps an Intake Group to the values from a Retrievable object.
297 |  |
              *
298 |  |
              * @param obj A retrievable object
299 |  |
              * @return an Intake Group
300 |  |
              */
301 |  |
             public Group mapTo(Retrievable obj)
302 |  |
             {
303 | 0 |
                 Group g = null;
304 |  |
305 |  |
                 try
306 |  |
                 {
307 | 0 |
                     String inputKey = IntakeServiceFacade.getGroupKey(groupName)
308 |  |
                             + obj.getQueryKey();
309 | 0 |
                     if (groups.containsKey(inputKey))
310 |  |
                     {
311 | 0 |
                         g = groups.get(inputKey);
312 |  |
                     }
313 |  |
                     else
314 |  |
                     {
315 | 0 |
                         g = IntakeServiceFacade.getGroup(groupName);
316 | 0 |
                         groups.put(inputKey, g);
317 |  |
                     }
318 |  |
319 | 0 |
                     return g.init(obj);
320 |  |
                 }
321 | 0 |
                 catch (IntakeException e)
322 |  |
                 {
323 | 0 |
                     log.error(e);
324 |  |
                 }
325 |  |
326 | 0 |
                 return null;
327 |  |
             }
328 |  |
         }
329 |  |
330 |  |
         /**
331 |  |
          * get a specific group
332 |  |
          */
333 |  |
         public PullHelper get(String groupName)
334 |  |
         {
335 | 2 |
             return pullMap.get(groupName);
336 |  |
         }
337 |  |
338 |  |
         /**
339 |  |
          * Get a specific group
340 |  |
          *
341 |  |
          * @param throwExceptions if false, exceptions will be supressed.
342 |  |
          * @throws IntakeException could not retrieve group
343 |  |
          */
344 |  |
         public PullHelper get(String groupName, boolean throwExceptions)
345 |  |
                 throws IntakeException
346 |  |
         {
347 | 0 |
             return pullMap.get(groupName);
348 |  |
         }
349 |  |
350 |  |
         /**
351 |  |
          * Loops through all of the Groups and checks to see if
352 |  |
          * the data within the Group is valid.
353 |  |
          */
354 |  |
         public boolean isAllValid()
355 |  |
         {
356 | 0 |
             boolean allValid = true;
357 | 0 |
             for (Iterator iter = groups.values().iterator(); iter.hasNext();)
358 |  |
             {
359 | 0 |
                 Group group = (Group) iter.next();
360 | 0 |
                 allValid &= group.isAllValid();
361 | 0 |
             }
362 | 0 |
             return allValid;
363 |  |
         }
364 |  |
365 |  |
         /**
366 |  |
          * Get a specific group by name and key.
367 |  |
          */
368 |  |
         public Group get(String groupName, String key)
369 |  |
                 throws IntakeException
370 |  |
         {
371 | 2 |
             if (groupName == null)
372 |  |
             {
373 | 0 |
                 throw new IntakeException("IntakeServiceFacade.get: groupName == null");
374 |  |
             }
375 | 2 |
             if (key == null)
376 |  |
             {
377 | 0 |
                 throw new IntakeException("IntakeServiceFacade.get: key == null");
378 |  |
             }
379 |  |
380 | 2 |
             PullHelper ph = get(groupName);
381 | 2 |
             return (ph == null) ? null : ph.setKey(key);
382 |  |
         }
383 |  |
384 |  |
         /**
385 |  |
          * Get a specific group by name and key. Also specify
386 |  |
          * whether or not you want to create a new group.
387 |  |
          */
388 |  |
         public Group get(String groupName, String key, boolean create)
389 |  |
                 throws IntakeException
390 |  |
         {
391 | 0 |
             if (groupName == null)
392 |  |
             {
393 | 0 |
                 throw new IntakeException("IntakeServiceFacade.get: groupName == null");
394 |  |
             }
395 | 0 |
             if (key == null)
396 |  |
             {
397 | 0 |
                 throw new IntakeException("IntakeServiceFacade.get: key == null");
398 |  |
             }
399 |  |
400 | 0 |
             PullHelper ph = get(groupName);
401 | 0 |
             return (ph == null) ? null : ph.setKey(key, create);
402 |  |
         }
403 |  |
404 |  |
         /**
405 |  |
          * Removes group.  Primary use is to remove a group that has
406 |  |
          * been processed by an action and is no longer appropriate
407 |  |
          * in the view (screen).
408 |  |
          */
409 |  |
         public void remove(Group group)
410 |  |
         {
411 | 0 |
             if (group != null)
412 |  |
             {
413 | 0 |
                 groups.remove(group.getObjectKey());
414 | 0 |
                 group.removeFromRequest();
415 |  |
416 | 0 |
                 String[] groupKeys = pp.getStrings(INTAKE_GRP);
417 |  |
418 | 0 |
                 pp.remove(INTAKE_GRP);
419 |  |
420 | 0 |
                             if (groupKeys != null)
421 |  |
                             {
422 | 0 |
                             for (int i = 0; i < groupKeys.length; i++)
423 |  |
                             {
424 | 0 |
                                 if (!groupKeys[i].equals(group.getGID()))
425 |  |
                                 {
426 | 0 |
                                      pp.add(INTAKE_GRP, groupKeys[i]);
427 |  |
                                 }
428 |  |
                     }
429 |  |
                         }
430 |  |
431 |  |
432 |  |
                 try
433 |  |
                 {
434 | 0 |
                     IntakeServiceFacade.releaseGroup(group);
435 |  |
                 }
436 | 0 |
                 catch (IntakeException ie)
437 |  |
                 {
438 | 0 |
                     log.error("Tried to release unknown group "
439 |  |
                             + group.getIntakeGroupName());
440 | 0 |
                 }
441 |  |
             }
442 | 0 |
         }
443 |  |
444 |  |
         /**
445 |  |
          * Removes all groups.  Primary use is to remove groups that have
446 |  |
          * been processed by an action and are no longer appropriate
447 |  |
          * in the view (screen).
448 |  |
          */
449 |  |
         public void removeAll()
450 |  |
         {
451 | 0 |
             Object[] allGroups = groups.values().toArray();
452 | 0 |
             for (int i = allGroups.length - 1; i >= 0; i--)
453 |  |
             {
454 | 0 |
                 Group group = (Group) allGroups[i];
455 | 0 |
                 remove(group);
456 |  |
             }
457 | 0 |
         }
458 |  |
459 |  |
         /**
460 |  |
          * Get a Map containing all the groups.
461 |  |
          *
462 |  |
          * @return the Group Map
463 |  |
          */
464 |  |
         public Map getGroups()
465 |  |
         {
466 | 4 |
             return groups;
467 |  |
         }
468 |  |
469 |  |
         // ****************** Recyclable implementation ************************
470 |  |
471 |  |
         private boolean disposed;
472 |  |
473 |  |
         /**
474 |  |
          * Recycles the object for a new client. Recycle methods with
475 |  |
          * parameters must be added to implementing object and they will be
476 |  |
          * automatically called by pool implementations when the object is
477 |  |
          * taken from the pool for a new client. The parameters must
478 |  |
          * correspond to the parameters of the constructors of the object.
479 |  |
          * For new objects, constructors can call their corresponding recycle
480 |  |
          * methods whenever applicable.
481 |  |
          * The recycle methods must call their super.
482 |  |
          */
483 |  |
         public void recycle()
484 |  |
         {
485 | 0 |
             disposed = false;
486 | 0 |
         }
487 |  |
488 |  |
         /**
489 |  |
          * Disposes the object after use. The method is called
490 |  |
          * when the object is returned to its pool.
491 |  |
          * The dispose method must call its super.
492 |  |
          */
493 |  |
         public void dispose()
494 |  |
         {
495 | 0 |
             for (Iterator iter = groups.values().iterator(); iter.hasNext();)
496 |  |
             {
497 | 0 |
                 Group g = (Group) iter.next();
498 |  |
499 |  |
                 try
500 |  |
                 {
501 | 0 |
                     IntakeServiceFacade.releaseGroup(g);
502 |  |
                 }
503 | 0 |
                 catch (IntakeException ie)
504 |  |
                 {
505 | 0 |
                     log.error("Tried to release unknown group "
506 |  |
                             + g.getIntakeGroupName());
507 | 0 |
                 }
508 | 0 |
             }
509 |  |
510 | 0 |
             groups.clear();
511 | 0 |
             declaredGroups.clear();
512 | 0 |
             pp = null;
513 |  |
514 | 0 |
             disposed = true;
515 | 0 |
         }
516 |  |
517 |  |
         /**
518 |  |
          * Checks whether the recyclable has been disposed.
519 |  |
          *
520 |  |
          * @return true, if the recyclable is disposed.
521 |  |
          */
522 |  |
         public boolean isDisposed()
523 |  |
         {
524 | 0 |
             return disposed;
525 |  |
         }
526 |  |
     }