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,583
IntakeTool$PullHelper
50%
12/24
33%
2/6
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  
 }