Clover coverage report - Code Coverage for tapestry release 4.0-beta-2
Coverage timestamp: Sat Jul 9 2005 22:02:17 EDT
file stats: LOC: 385   Methods: 14
NCLOC: 255   Classes: 1
30 day Evaluation License registered to hlship@comcast.net Your 30 day evaluation period has expired. Please visit http://www.cenqua.com to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
ForBean.java 40% 47.8% 42.9% 45%
coverage coverage
 1    // Copyright 2004, 2005 The Apache Software Foundation
 2    //
 3    // Licensed under the Apache License, Version 2.0 (the "License");
 4    // you may not use this file except in compliance with the License.
 5    // You may obtain a copy of the License at
 6    //
 7    // http://www.apache.org/licenses/LICENSE-2.0
 8    //
 9    // Unless required by applicable law or agreed to in writing, software
 10    // distributed under the License is distributed on an "AS IS" BASIS,
 11    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    // See the License for the specific language governing permissions and
 13    // limitations under the License.
 14   
 15    package org.apache.tapestry.components;
 16   
 17    import java.io.IOException;
 18    import java.util.ArrayList;
 19    import java.util.HashMap;
 20    import java.util.Iterator;
 21    import java.util.List;
 22    import java.util.Map;
 23   
 24    import org.apache.hivemind.ApplicationRuntimeException;
 25    import org.apache.tapestry.IBinding;
 26    import org.apache.tapestry.IForm;
 27    import org.apache.tapestry.IMarkupWriter;
 28    import org.apache.tapestry.IRequestCycle;
 29    import org.apache.tapestry.Tapestry;
 30    import org.apache.tapestry.TapestryUtils;
 31    import org.apache.tapestry.coerce.ValueConverter;
 32    import org.apache.tapestry.form.AbstractFormComponent;
 33    import org.apache.tapestry.services.DataSqueezer;
 34    import org.apache.tapestry.services.ExpressionEvaluator;
 35   
 36    /**
 37    * @author mb
 38    */
 39    public abstract class ForBean extends AbstractFormComponent {
 40    private static final char DESC_VALUE = 'V';
 41    private static final char DESC_PRIMARY_KEY = 'P';
 42   
 43    // parameters
 44    public abstract Object getSource();
 45    public abstract Object getFullSource();
 46    public abstract String getElement();
 47    public abstract boolean getVolatile();
 48    public abstract Object getDefaultValue();
 49    public abstract String getPrimaryKey();
 50    public abstract IPrimaryKeyConverter getConverter();
 51    public abstract String getKeyExpression();
 52   
 53    // properties
 54    public abstract Map getPrimaryKeyMap();
 55    public abstract void setPrimaryKeyMap(Map primaryKeys);
 56   
 57    // injects
 58    public abstract DataSqueezer getDataSqueezer();
 59    public abstract ValueConverter getValueConverter();
 60    public abstract ExpressionEvaluator getExpressionEvaluator();
 61   
 62   
 63    private Object _value;
 64    private int _index;
 65    private boolean _rendering;
 66   
 67    /**
 68    * Gets the source binding and returns an {@link Iterator}
 69    * representing
 70    * the values identified by the source. Returns an empty {@link Iterator}
 71    * if the binding, or the binding value, is null.
 72    *
 73    * <p>Invokes {@link Tapestry#coerceToIterator(Object)} to perform
 74    * the actual conversion.
 75    *
 76    **/
 77   
 78  4 protected Iterator getSourceData()
 79    {
 80  4 Object source = getSource();
 81  4 if (source == null)
 82  0 return null;
 83   
 84  4 Iterator iteratorSource = (Iterator) getValueConverter().coerceValue(source, Iterator.class);
 85   
 86  4 return iteratorSource;
 87    }
 88   
 89  3 protected Iterator storeSourceData(IForm form, String name)
 90    {
 91  3 Iterator iteratorSource = getSourceData();
 92  3 if (iteratorSource == null)
 93  0 return null;
 94   
 95    // extract primary keys from data
 96  3 StringBuffer pkDesc = new StringBuffer();
 97  3 List data = new ArrayList();
 98  3 List pks = new ArrayList();
 99  3 while (iteratorSource.hasNext()) {
 100  6 Object value = iteratorSource.next();
 101  6 data.add(value);
 102   
 103  6 Object pk = getPrimaryKeyFromValue(value);
 104  6 if (pk == null) {
 105  2 pk = value;
 106  2 pkDesc.append(DESC_VALUE);
 107    }
 108    else
 109  4 pkDesc.append(DESC_PRIMARY_KEY);
 110  6 pks.add(pk);
 111    }
 112   
 113    // store primary keys
 114  3 form.addHiddenValue(name, pkDesc.toString());
 115  3 for (Iterator it = pks.iterator(); it.hasNext();) {
 116  6 Object pk = it.next();
 117  6 try {
 118  6 String stringRep = getDataSqueezer().squeeze(pk);
 119  6 form.addHiddenValue(name, stringRep);
 120    } catch (IOException ex) {
 121  0 throw new ApplicationRuntimeException(
 122    Tapestry.format("For.unable-to-convert-value", pk),
 123    this,
 124    null,
 125    ex);
 126    }
 127    }
 128   
 129  3 return data.iterator();
 130    }
 131   
 132  0 protected Iterator getStoredData(IRequestCycle cycle, String name)
 133    {
 134  0 String[] submittedPrimaryKeys = cycle.getParameters(name);
 135  0 String pkDesc = submittedPrimaryKeys[0];
 136   
 137    // unsqueeze data
 138  0 List data = new ArrayList(submittedPrimaryKeys.length-1);
 139  0 List pks = new ArrayList(submittedPrimaryKeys.length-1);
 140  0 for (int i = 1; i < submittedPrimaryKeys.length; i++) {
 141  0 String stringRep = submittedPrimaryKeys[i];
 142  0 try {
 143  0 Object value = getDataSqueezer().unsqueeze(stringRep);
 144  0 data.add(value);
 145  0 if (i <= pkDesc.length() && pkDesc.charAt(i-1) == DESC_PRIMARY_KEY)
 146  0 pks.add(value);
 147    } catch (IOException ex) {
 148  0 throw new ApplicationRuntimeException(
 149    Tapestry.format("For.unable-to-convert-string", stringRep),
 150    this,
 151    null,
 152    ex);
 153    }
 154    }
 155   
 156    // update the binding with the list of primary keys
 157  0 IBinding primaryKeysBinding = getBinding("primaryKeys");
 158  0 if (primaryKeysBinding != null)
 159  0 primaryKeysBinding.setObject(pks);
 160   
 161    // convert from primary keys to data
 162  0 for (int i = 0; i < data.size(); i++) {
 163  0 if (i <= pkDesc.length() && pkDesc.charAt(i) == DESC_PRIMARY_KEY) {
 164  0 Object pk = data.get(i);
 165  0 Object value = getValueFromPrimaryKey(pk);
 166  0 data.set(i, value);
 167    }
 168    }
 169   
 170  0 return data.iterator();
 171    }
 172   
 173    /**
 174    * Gets the source binding and iterates through
 175    * its values. For each, it updates the value binding and render's its wrapped elements.
 176    *
 177    **/
 178   
 179  4 protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
 180    {
 181    // form may be null if component is not located in a form
 182  4 IForm form = (IForm) cycle.getAttribute(TapestryUtils.FORM_ATTRIBUTE);
 183   
 184    // If the cycle is rewinding, but not this particular form,
 185    // then do nothing (don't even render the body).
 186  4 boolean cycleRewinding = cycle.isRewinding();
 187  4 if (cycleRewinding && form != null && !form.isRewinding())
 188  0 return;
 189   
 190  4 boolean bInForm = (form != null && !getVolatile());
 191   
 192  4 String name = "";
 193  4 if (form != null)
 194  3 name = form.getElementId(this);
 195   
 196    // Get the data to be iterated upon. Store in form if needed.
 197  4 Iterator dataSource;
 198  4 if (!bInForm)
 199  1 dataSource = getSourceData();
 200  3 else if (cycleRewinding)
 201  0 dataSource = getStoredData(cycle, name);
 202    else
 203  3 dataSource = storeSourceData(form, name);
 204   
 205   
 206    // Do not iterate if dataSource is null.
 207    // The dataSource was either not convertable to Iterator, or was empty.
 208  4 if (dataSource == null)
 209  0 return;
 210   
 211  4 String element = getElement();
 212   
 213    // Perform the iterations
 214  4 try
 215    {
 216  4 _index = 0;
 217  4 _rendering = true;
 218   
 219  4 while (dataSource.hasNext())
 220    {
 221    // Get current value
 222  8 _value = dataSource.next();
 223   
 224    // Update output component parameters
 225  8 IBinding indexBinding = getBinding("index");
 226  8 if (indexBinding != null)
 227  0 indexBinding.setObject(new Integer(_index));
 228   
 229  8 IBinding valueBinding = getBinding("value");
 230  8 if (valueBinding != null)
 231  0 valueBinding.setObject(_value);
 232   
 233    // Render component
 234  8 if (element != null)
 235    {
 236  0 writer.begin(element);
 237  0 renderInformalParameters(writer, cycle);
 238    }
 239   
 240  8 renderBody(writer, cycle);
 241   
 242  8 if (element != null)
 243  0 writer.end();
 244   
 245  8 _index++;
 246    }
 247    }
 248    finally
 249    {
 250  4 _rendering = false;
 251  4 _value = null;
 252    }
 253    }
 254   
 255  0 private Object restoreValue(IForm form, String name, Object primaryKey)
 256    {
 257  0 return getValueFromPrimaryKey(primaryKey);
 258    }
 259   
 260  0 private void storeValue(IForm form, String name, Object value)
 261    {
 262  0 Object convertedValue = getPrimaryKeyFromValue(value);
 263   
 264  0 try
 265    {
 266  0 String externalValue = getDataSqueezer().squeeze(convertedValue);
 267  0 form.addHiddenValue(name, externalValue);
 268    }
 269    catch (IOException ex)
 270    {
 271  0 throw new ApplicationRuntimeException(
 272    Tapestry.format("For.unable-to-convert-value", value),
 273    this,
 274    null,
 275    ex);
 276    }
 277    }
 278   
 279  6 private Object getPrimaryKeyFromValue(Object value) {
 280  6 Object primaryKey = null;
 281   
 282  6 String keyExpression = getKeyExpression();
 283  6 if (keyExpression != null)
 284  4 primaryKey = getExpressionEvaluator().read(value, keyExpression);
 285   
 286  6 if (primaryKey == null) {
 287  2 IPrimaryKeyConverter converter = getConverter();
 288  2 if (converter != null)
 289  0 primaryKey = converter.getPrimaryKey(value);
 290    }
 291   
 292  6 return primaryKey;
 293    }
 294   
 295  0 private Object getValueFromPrimaryKey(Object primaryKey) {
 296  0 Object value = null;
 297   
 298  0 if (value == null && getKeyExpression() != null) {
 299  0 String keyExpression = getKeyExpression();
 300  0 if (keyExpression != null) {
 301  0 Map primaryKeys = getPrimaryKeyMap();
 302  0 if (primaryKeys == null)
 303  0 primaryKeys = initializePrimaryKeysFromSource(keyExpression);
 304  0 value = primaryKeys.get(primaryKeys);
 305    }
 306    }
 307   
 308  0 if (value == null) {
 309  0 IPrimaryKeyConverter converter = getConverter();
 310  0 if (converter != null)
 311  0 value = converter.getValue(primaryKey);
 312    }
 313   
 314  0 if (value == null)
 315  0 value = getDefaultValue();
 316   
 317  0 return value;
 318    }
 319   
 320  0 private Map initializePrimaryKeysFromSource(String keyExpression)
 321    {
 322  0 Map primaryKeys = new HashMap();
 323   
 324  0 Object fullSource = getFullSource();
 325  0 if (fullSource == null)
 326  0 fullSource = getSource();
 327  0 if (fullSource == null)
 328  0 return primaryKeys;
 329   
 330  0 ExpressionEvaluator evaluator = getExpressionEvaluator();
 331   
 332  0 Iterator iteratorSource = (Iterator) getValueConverter().coerceValue(fullSource, Iterator.class);
 333  0 while (iteratorSource.hasNext()) {
 334  0 Object value = iteratorSource.next();
 335  0 Object primaryKey = evaluator.read(value, keyExpression);
 336  0 if (primaryKey != null)
 337  0 primaryKeys.put(primaryKey, value);
 338    }
 339   
 340  0 setPrimaryKeyMap(primaryKeys);
 341  0 return primaryKeys;
 342    }
 343   
 344    /**
 345    * Returns the most recent value extracted from the source parameter.
 346    *
 347    * @throws org.apache.tapestry.ApplicationRuntimeException if the Foreach is not currently rendering.
 348    *
 349    **/
 350   
 351  8 public final Object getValue()
 352    {
 353  8 if (!_rendering)
 354  0 throw Tapestry.createRenderOnlyPropertyException(this, "value");
 355   
 356  8 return _value;
 357    }
 358   
 359    /**
 360    * The index number, within the {@link #getSource() source}, of the
 361    * the current value.
 362    *
 363    * @throws org.apache.tapestry.ApplicationRuntimeException if the Foreach is not currently rendering.
 364    *
 365    * @since 2.2
 366    *
 367    **/
 368   
 369  8 public int getIndex()
 370    {
 371  8 if (!_rendering)
 372  0 throw Tapestry.createRenderOnlyPropertyException(this, "index");
 373   
 374  8 return _index;
 375    }
 376   
 377  0 public boolean isDisabled()
 378    {
 379  0 return false;
 380    }
 381   
 382    // Do nothing in those methods, but make the JVM happy
 383  0 protected void renderFormComponent(IMarkupWriter writer, IRequestCycle cycle) { }
 384  0 protected void rewindFormComponent(IMarkupWriter writer, IRequestCycle cycle) { }
 385    }