Coverage report

  %line %branch
org.apache.turbine.services.intake.model.Group$GroupFactory
0% 
0% 

 1  
 package org.apache.turbine.services.intake.model;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2005 The Apache Software Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License")
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 import java.util.ArrayList;
 20  
 import java.util.HashMap;
 21  
 import java.util.Iterator;
 22  
 import java.util.List;
 23  
 import java.util.Map;
 24  
 
 25  
 import org.apache.commons.logging.Log;
 26  
 import org.apache.commons.logging.LogFactory;
 27  
 
 28  
 import org.apache.commons.pool.BaseKeyedPoolableObjectFactory;
 29  
 
 30  
 import org.apache.turbine.om.Retrievable;
 31  
 import org.apache.turbine.services.intake.IntakeException;
 32  
 import org.apache.turbine.services.intake.TurbineIntake;
 33  
 import org.apache.turbine.services.intake.xmlmodel.AppData;
 34  
 import org.apache.turbine.services.intake.xmlmodel.XmlField;
 35  
 import org.apache.turbine.services.intake.xmlmodel.XmlGroup;
 36  
 import org.apache.turbine.util.TurbineException;
 37  
 import org.apache.turbine.util.parser.ValueParser;
 38  
 
 39  
 /**
 40  
  * Holds a group of Fields
 41  
  *
 42  
  * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
 43  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 44  
  * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
 45  
  * @version $Id: Group.java 264148 2005-08-29 14:21:04Z henning $
 46  
  */
 47  
 public class Group
 48  
 {
 49  
     public static final String EMPTY = "";
 50  
 
 51  
     /*
 52  
      * An id representing a new object.
 53  
      */
 54  
     public static final String NEW = "_0";
 55  
 
 56  
     private static final Log log;
 57  
     private static final boolean isDebugEnabled;
 58  
 
 59  
     static
 60  
     {
 61  
         log = LogFactory.getLog(Group.class);
 62  
         isDebugEnabled = log.isDebugEnabled();
 63  
     }
 64  
 
 65  
     /**
 66  
      * The key used to represent this group in a parameter.
 67  
      * This key is usually a prefix as part of a field key.
 68  
      */
 69  
     protected final String gid;
 70  
 
 71  
     /**
 72  
      * The name used in templates and java code to refer to this group.
 73  
      */
 74  
     protected final String name;
 75  
 
 76  
     /**
 77  
      * The number of Groups with the same name that will be pooled.
 78  
      */
 79  
     private final int poolCapacity;
 80  
 
 81  
     /**
 82  
      * A map of the fields in this group mapped by field name.
 83  
      */
 84  
     protected Map fields;
 85  
 
 86  
     /**
 87  
      * Map of the fields by mapToObject
 88  
      */
 89  
     protected Map mapToObjectFields;
 90  
 
 91  
     /**
 92  
      * An array of fields in this group.
 93  
      */
 94  
     protected Field[] fieldsArray;
 95  
 
 96  
     /**
 97  
      * The object id used to associate this group to a bean
 98  
      * for one request cycle
 99  
      */
 100  
     protected String oid;
 101  
 
 102  
     /**
 103  
      * The object containing the request data
 104  
      */
 105  
     protected ValueParser pp;
 106  
 
 107  
     /**
 108  
      * A flag to help prevent duplicate hidden fields declaring this group.
 109  
      */
 110  
     protected boolean isDeclared;
 111  
 
 112  
     /**
 113  
      * Constructs a new Group based on the xml specification.  Groups are
 114  
      * instantiated and pooled by the IntakeService and should not
 115  
      * be instantiated otherwise.
 116  
      *
 117  
      * @param group a <code>XmlGroup</code> value
 118  
      * @exception IntakeException if an error occurs in other classes
 119  
      */
 120  
     public Group(XmlGroup group) throws IntakeException
 121  
     {
 122  
         gid = group.getKey();
 123  
         name = group.getName();
 124  
         poolCapacity = Integer.parseInt(group.getPoolCapacity());
 125  
 
 126  
         List inputFields = group.getFields();
 127  
         int size = inputFields.size();
 128  
         fields = new HashMap((int) (1.25 * size + 1));
 129  
         mapToObjectFields = new HashMap((int) (1.25 * size + 1));
 130  
         fieldsArray = new Field[size];
 131  
         for (int i = size - 1; i >= 0; i--)
 132  
         {
 133  
             XmlField f = (XmlField) inputFields.get(i);
 134  
             Field field = FieldFactory.getInstance(f, this);
 135  
             fieldsArray[i] = field;
 136  
             fields.put(f.getName(), field);
 137  
 
 138  
             // map fields by their mapToObject
 139  
             List tmpFields = (List) mapToObjectFields.get(f.getMapToObject());
 140  
             if (tmpFields == null)
 141  
             {
 142  
                 tmpFields = new ArrayList(size);
 143  
                 mapToObjectFields.put(f.getMapToObject(), tmpFields);
 144  
             }
 145  
             tmpFields.add(field);
 146  
         }
 147  
 
 148  
         // Change the mapToObjectFields values to Field[]
 149  
         for (Iterator keys = mapToObjectFields.keySet().iterator(); keys.hasNext();)
 150  
         {
 151  
             Object key = keys.next();
 152  
             List tmpFields = (List) mapToObjectFields.get(key);
 153  
             mapToObjectFields.put(key,
 154  
                     tmpFields.toArray(new Field[tmpFields.size()]));
 155  
         }
 156  
     }
 157  
 
 158  
     /**
 159  
      * Initializes the default Group using parameters.
 160  
      *
 161  
      * @param pp a <code>ValueParser</code> value
 162  
      * @return this Group
 163  
      */
 164  
     public Group init(ValueParser pp) throws TurbineException
 165  
     {
 166  
         return init(NEW, pp);
 167  
     }
 168  
 
 169  
     /**
 170  
      * Initializes the Group with parameters from RunData
 171  
      * corresponding to key.
 172  
      *
 173  
      * @param pp a <code>ValueParser</code> value
 174  
      * @return this Group
 175  
      */
 176  
     public Group init(String key, ValueParser pp) throws IntakeException
 177  
     {
 178  
         this.oid = key;
 179  
         this.pp = pp;
 180  
         for (int i = fieldsArray.length - 1; i >= 0; i--)
 181  
         {
 182  
             fieldsArray[i].init(pp);
 183  
         }
 184  
         return this;
 185  
     }
 186  
 
 187  
     /**
 188  
      * Initializes the group with properties from an object.
 189  
      *
 190  
      * @param obj a <code>Persistent</code> value
 191  
      * @return a <code>Group</code> value
 192  
      */
 193  
     public Group init(Retrievable obj)
 194  
     {
 195  
         this.oid = obj.getQueryKey();
 196  
 
 197  
         Class cls = obj.getClass();
 198  
         while (cls != null)
 199  
         {
 200  
             Field[] flds = (Field[]) mapToObjectFields.get(cls.getName());
 201  
             if (flds != null)
 202  
             {
 203  
                 for (int i = flds.length - 1; i >= 0; i--)
 204  
                 {
 205  
                     flds[i].init(obj);
 206  
                 }
 207  
             }
 208  
 
 209  
             cls = cls.getSuperclass();
 210  
         }
 211  
 
 212  
         return this;
 213  
     }
 214  
 
 215  
     /**
 216  
      * Gets a list of the names of the fields stored in this object.
 217  
      *
 218  
      * @return A String array containing the list of names.
 219  
      */
 220  
     public String[] getFieldNames()
 221  
     {
 222  
         String nameList[] = new String[fieldsArray.length];
 223  
         for (int i = 0; i < nameList.length; i++)
 224  
         {
 225  
             nameList[i] = fieldsArray[i].name;
 226  
         }
 227  
         return nameList;
 228  
     }
 229  
 
 230  
     /**
 231  
      * Return the name given to this group.  The long name is to
 232  
      * avoid conflicts with the get(String key) method.
 233  
      *
 234  
      * @return a <code>String</code> value
 235  
      */
 236  
     public String getIntakeGroupName()
 237  
     {
 238  
         return name;
 239  
     }
 240  
 
 241  
     /**
 242  
      * Get the number of Group objects that will be pooled.
 243  
      *
 244  
      * @return an <code>int</code> value
 245  
      */
 246  
     public int getPoolCapacity()
 247  
     {
 248  
         return poolCapacity;
 249  
     }
 250  
 
 251  
     /**
 252  
      * Get the part of the key used to specify the group.
 253  
      * This is specified in the key attribute in the xml file.
 254  
      *
 255  
      * @return a <code>String</code> value
 256  
      */
 257  
     public String getGID()
 258  
     {
 259  
         return gid;
 260  
     }
 261  
 
 262  
     /**
 263  
      * Get the part of the key that distinguishes a group
 264  
      * from others of the same name.
 265  
      *
 266  
      * @return a <code>String</code> value
 267  
      */
 268  
     public String getOID()
 269  
     {
 270  
         return oid;
 271  
     }
 272  
 
 273  
     /**
 274  
      * Concatenation of gid and oid.
 275  
      *
 276  
      * @return a <code>String</code> value
 277  
      */
 278  
     public String getObjectKey()
 279  
     {
 280  
         return gid + oid;
 281  
     }
 282  
 
 283  
     /**
 284  
      * Describe <code>getObjects</code> method here.
 285  
      *
 286  
      * @param pp a <code>ValueParser</code> value
 287  
      * @return an <code>ArrayList</code> value
 288  
      * @exception IntakeException if an error occurs
 289  
      */
 290  
     public ArrayList getObjects(ValueParser pp) throws IntakeException
 291  
     {
 292  
         ArrayList objs = null;
 293  
         String[] oids = pp.getStrings(gid);
 294  
         if (oids != null)
 295  
         {
 296  
             objs = new ArrayList(oids.length);
 297  
             for (int i = oids.length - 1; i >= 0; i--)
 298  
             {
 299  
                 objs.add(TurbineIntake.getGroup(name).init(oids[i], pp));
 300  
             }
 301  
         }
 302  
         return objs;
 303  
     }
 304  
 
 305  
     /**
 306  
      * Get the Field .
 307  
      * @return Field.
 308  
      * @throws IntakeException indicates the field could not be found.
 309  
      */
 310  
     public Field get(String fieldName)
 311  
             throws IntakeException
 312  
     {
 313  
         if (fields.containsKey(fieldName))
 314  
         {
 315  
             return (Field) fields.get(fieldName);
 316  
         }
 317  
         else
 318  
         {
 319  
             throw new IntakeException("Intake Field name: " + fieldName +
 320  
                     " not found!");
 321  
         }
 322  
     }
 323  
 
 324  
     /**
 325  
      * Performs an AND between all the fields in this group.
 326  
      *
 327  
      * @return a <code>boolean</code> value
 328  
      */
 329  
     public boolean isAllValid()
 330  
     {
 331  
         boolean valid = true;
 332  
         for (int i = fieldsArray.length - 1; i >= 0; i--)
 333  
         {
 334  
             valid &= fieldsArray[i].isValid();
 335  
             if (isDebugEnabled && !fieldsArray[i].isValid())
 336  
             {
 337  
                 log.debug("Group(" + oid + "): " + name + "; Field: "
 338  
                         + fieldsArray[i].name + "; value=" +
 339  
                         fieldsArray[i].getValue() + " is invalid!");
 340  
             }
 341  
         }
 342  
         return valid;
 343  
     }
 344  
 
 345  
     /**
 346  
      * Calls a setter methods on obj, for fields which have been set.
 347  
      *
 348  
      * @param obj Object to be set with the values from the group.
 349  
      * @throws IntakeException indicates that a failure occurred while
 350  
      * executing the setter methods of the mapped object.
 351  
      */
 352  
     public void setProperties(Object obj) throws IntakeException
 353  
     {
 354  
         Class cls = obj.getClass();
 355  
 
 356  
         while (cls != null)
 357  
         {
 358  
             if (isDebugEnabled)
 359  
             {
 360  
                 log.debug("setProperties(" + cls.getName() + ")");
 361  
             }
 362  
 
 363  
             Field[] flds = (Field[]) mapToObjectFields.get(cls.getName());
 364  
             if (flds != null)
 365  
             {
 366  
                 for (int i = flds.length - 1; i >= 0; i--)
 367  
                 {
 368  
                     flds[i].setProperty(obj);
 369  
                 }
 370  
             }
 371  
 
 372  
             cls = cls.getSuperclass();
 373  
         }
 374  
         log.debug("setProperties() finished");
 375  
     }
 376  
 
 377  
     /**
 378  
      * Calls a setter methods on obj, for fields which pass validity tests.
 379  
      * In most cases one should call Intake.isAllValid() and then if that
 380  
      * test passes call setProperties.  Use this method when some data is
 381  
      * known to be invalid, but you still want to set the object properties
 382  
      * that are valid.
 383  
      */
 384  
     public void setValidProperties(Object obj)
 385  
     {
 386  
         Class cls = obj.getClass();
 387  
         while (cls != null)
 388  
         {
 389  
             Field[] flds = (Field[]) mapToObjectFields.get(cls.getName());
 390  
             if (flds != null)
 391  
             {
 392  
                 for (int i = flds.length - 1; i >= 0; i--)
 393  
                 {
 394  
                     try
 395  
                     {
 396  
                         flds[i].setProperty(obj);
 397  
                     }
 398  
                     catch (Exception e)
 399  
                     {
 400  
                         // just move on to next field
 401  
                     }
 402  
                 }
 403  
             }
 404  
 
 405  
             cls = cls.getSuperclass();
 406  
         }
 407  
     }
 408  
 
 409  
     /**
 410  
      * Calls getter methods on objects that are known to Intake
 411  
      * so that field values in forms can be initialized from
 412  
      * the values contained in the intake tool.
 413  
      *
 414  
      * @param obj Object that will be used to as a source of data for
 415  
      * setting the values of the fields within the group.
 416  
      * @throws IntakeException indicates that a failure occurred while
 417  
      * executing the setter methods of the mapped object.
 418  
      */
 419  
     public void getProperties(Object obj) throws IntakeException
 420  
     {
 421  
         Class cls = obj.getClass();
 422  
         while (cls != null)
 423  
         {
 424  
             Field[] flds = (Field[]) mapToObjectFields.get(cls.getName());
 425  
             if (flds != null)
 426  
             {
 427  
                 for (int i = flds.length - 1; i >= 0; i--)
 428  
                 {
 429  
                     flds[i].getProperty(obj);
 430  
                 }
 431  
             }
 432  
 
 433  
             cls = cls.getSuperclass();
 434  
         }
 435  
     }
 436  
 
 437  
     /**
 438  
      * Removes references to this group and its fields from the
 439  
      * query parameters
 440  
      */
 441  
     public void removeFromRequest()
 442  
     {
 443  
         if (pp != null)
 444  
         {
 445  
             String[] groups = pp.getStrings(gid);
 446  
             if (groups != null)
 447  
             {
 448  
                 pp.remove(gid);
 449  
                 for (int i = 0; i < groups.length; i++)
 450  
                 {
 451  
                     if (groups[i] != null && !groups[i].equals(oid))
 452  
                     {
 453  
                         pp.add(gid, groups[i]);
 454  
                     }
 455  
                 }
 456  
                 for (int i = fieldsArray.length - 1; i >= 0; i--)
 457  
                 {
 458  
                     fieldsArray[i].removeFromRequest();
 459  
                 }
 460  
             }
 461  
         }
 462  
     }
 463  
 
 464  
     /**
 465  
      * To be used in the event this group is used within multiple
 466  
      * forms within the same template.
 467  
      */
 468  
     public void resetDeclared()
 469  
     {
 470  
         isDeclared = false;
 471  
     }
 472  
 
 473  
     /**
 474  
      * A xhtml valid hidden input field that notifies intake of the
 475  
      * group's presence.
 476  
      *
 477  
      * @return a <code>String</code> value
 478  
      */
 479  
     public String getHtmlFormInput()
 480  
     {
 481  
         StringBuffer sb = new StringBuffer(64);
 482  
         appendHtmlFormInput(sb);
 483  
         return sb.toString();
 484  
     }
 485  
 
 486  
     /**
 487  
      * A xhtml valid hidden input field that notifies intake of the
 488  
      * group's presence.
 489  
      */
 490  
     public void appendHtmlFormInput(StringBuffer sb)
 491  
     {
 492  
         if (!isDeclared)
 493  
         {
 494  
             isDeclared = true;
 495  
             sb.append("<input type=\"hidden\" name=\"")
 496  
                     .append(gid)
 497  
                     .append("\" value=\"")
 498  
                     .append(oid)
 499  
                     .append("\"/>\n");
 500  
         }
 501  
     }
 502  
 
 503  
     // ********** PoolableObjectFactory implementation ******************
 504  
 
 505  
     public static class GroupFactory
 506  
             extends BaseKeyedPoolableObjectFactory
 507  
     {
 508  
         private AppData appData;
 509  
 
 510  
         public GroupFactory(AppData appData)
 511  0
         {
 512  0
             this.appData = appData;
 513  0
         }
 514  
 
 515  
         /**
 516  
          * Creates an instance that can be returned by the pool.
 517  
          * @return an instance that can be returned by the pool.
 518  
          * @throws IntakeException indicates that the group could not be retreived
 519  
          */
 520  
         public Object makeObject(Object key) throws IntakeException
 521  
         {
 522  0
             return new Group(appData.getGroup((String) key));
 523  
         }
 524  
 
 525  
         /**
 526  
          * Uninitialize an instance to be returned to the pool.
 527  
          * @param obj the instance to be passivated
 528  
          */
 529  
         public void passivateObject(Object key, Object obj)
 530  
         {
 531  0
             Group group = (Group) obj;
 532  0
             group.oid = null;
 533  0
             group.pp = null;
 534  0
             for (int i = group.fieldsArray.length - 1; i >= 0; i--)
 535  
             {
 536  0
                 group.fieldsArray[i].dispose();
 537  
             }
 538  0
             group.isDeclared = false;
 539  0
         }
 540  
     }
 541  
 }
 542  
 
 543  
 

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.