Clover coverage report - Code Coverage for tapestry release 4.0-alpha-3
Coverage timestamp: Mon May 16 2005 09:05:49 EDT
file stats: LOC: 209   Methods: 8
NCLOC: 93   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
ExpressionBinding.java 83.3% 100% 100% 97.9%
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.binding;
 16   
 
 17   
 import org.apache.hivemind.Location;
 18   
 import org.apache.tapestry.BindingException;
 19   
 import org.apache.tapestry.IComponent;
 20   
 import org.apache.tapestry.coerce.ValueConverter;
 21   
 import org.apache.tapestry.services.ExpressionCache;
 22   
 import org.apache.tapestry.services.ExpressionEvaluator;
 23   
 
 24   
 /**
 25   
  * Implements a dynamic binding, based on evaluating an expression using an expression language.
 26   
  * Tapestry's default expression language is the <a href="http://www.ognl.org/">Object Graph
 27   
  * Navigation Language </a>.
 28   
  * 
 29   
  * @see org.apache.tapestry.services.ExpressionEvaluator
 30   
  * @author Howard Lewis Ship
 31   
  * @since 2.2
 32   
  */
 33   
 
 34   
 public class ExpressionBinding extends AbstractBinding
 35   
 {
 36   
     /**
 37   
      * The root object against which the nested property name is evaluated.
 38   
      */
 39   
 
 40   
     private final IComponent _root;
 41   
 
 42   
     /**
 43   
      * The OGNL expression, as a string.
 44   
      */
 45   
 
 46   
     private String _expression;
 47   
 
 48   
     /**
 49   
      * If true, then the binding is invariant.
 50   
      */
 51   
 
 52   
     private boolean _invariant = false;
 53   
 
 54   
     /**
 55   
      * Parsed OGNL expression.
 56   
      */
 57   
 
 58   
     private Object _parsedExpression;
 59   
 
 60   
     /**
 61   
      * Flag set to true once the binding has initialized.
 62   
      */
 63   
 
 64   
     private boolean _initialized;
 65   
 
 66   
     /**
 67   
      * @since 4.0
 68   
      */
 69   
 
 70   
     private ExpressionEvaluator _evaluator;
 71   
 
 72   
     /** @since 4.0 */
 73   
 
 74   
     private ExpressionCache _cache;
 75   
 
 76   
     /**
 77   
      * Creates a {@link ExpressionBinding}from the root object and an OGNL expression.
 78   
      */
 79   
 
 80  1079
     public ExpressionBinding(String description, Location location, ValueConverter valueConverter,
 81   
             IComponent root, String expression, ExpressionEvaluator evaluator,
 82   
             ExpressionCache cache)
 83   
     {
 84  1079
         super(description, valueConverter, location);
 85   
 
 86  1079
         _root = root;
 87  1079
         _expression = expression;
 88  1079
         _evaluator = evaluator;
 89  1079
         _cache = cache;
 90   
     }
 91   
 
 92   
     /**
 93   
      * Gets the value of the property path, with the assistance of the {@link ExpressionEvaluator}.
 94   
      * 
 95   
      * @throws BindingException
 96   
      *             if an exception is thrown accessing the property.
 97   
      */
 98   
 
 99  2405
     public Object getObject()
 100   
     {
 101  2405
         initialize();
 102   
 
 103  2405
         return resolveExpression();
 104   
     }
 105   
 
 106  2405
     private Object resolveExpression()
 107   
     {
 108  2405
         try
 109   
         {
 110  2405
             return _evaluator.readCompiled(_root, _parsedExpression);
 111   
         }
 112   
         catch (Throwable t)
 113   
         {
 114  2
             throw new BindingException(t.getMessage(), this, t);
 115   
         }
 116   
     }
 117   
 
 118   
     /**
 119   
      * Returns true if the binding is expected to always return the same value.
 120   
      */
 121   
 
 122  2661
     public boolean isInvariant()
 123   
     {
 124  2661
         initialize();
 125   
 
 126  2660
         return _invariant;
 127   
     }
 128   
 
 129   
     /**
 130   
      * Sets up the helper object, but also optimizes the property path and determines if the binding
 131   
      * is invarant.
 132   
      */
 133   
 
 134  6502
     private void initialize()
 135   
     {
 136  6502
         if (_initialized)
 137  5542
             return;
 138   
 
 139  960
         _initialized = true;
 140   
 
 141  960
         try
 142   
         {
 143  960
             _parsedExpression = _cache.getCompiledExpression(_expression);
 144   
 
 145  959
             _invariant = _evaluator.isConstant(_expression);
 146   
         }
 147   
         catch (Exception ex)
 148   
         {
 149  1
             throw new BindingException(ex.getMessage(), this, ex);
 150   
         }
 151   
     }
 152   
 
 153   
     /**
 154   
      * Updates the property for the binding to the given value.
 155   
      * 
 156   
      * @throws BindingException
 157   
      *             if the property can't be updated (typically due to an security problem, or a
 158   
      *             missing mutator method).
 159   
      * @throws ReadOnlyBindingException
 160   
      *             if the binding is invariant.
 161   
      */
 162   
 
 163  1436
     public void setObject(Object value)
 164   
     {
 165  1436
         initialize();
 166   
 
 167  1436
         if (_invariant)
 168  1
             throw createReadOnlyBindingException(this);
 169   
 
 170  1435
         try
 171   
         {
 172  1435
             _evaluator.writeCompiled(_root, _parsedExpression, value);
 173   
         }
 174   
         catch (Throwable ex)
 175   
         {
 176  1
             throw new BindingException(ex.getMessage(), this, ex);
 177   
         }
 178   
     }
 179   
 
 180   
     /**
 181   
      * Returns the a String representing the property path. This includes the
 182   
      * {@link IComponent#getExtendedId() extended id}of the root component and the property path
 183   
      * ... once the binding is used, these may change due to optimization of the property path.
 184   
      */
 185   
 
 186  4
     public String toString()
 187   
     {
 188  4
         StringBuffer buffer = new StringBuffer();
 189   
 
 190  4
         buffer.append("ExpressionBinding[");
 191  4
         buffer.append(_root.getExtendedId());
 192   
 
 193  4
         if (_expression != null)
 194   
         {
 195  4
             buffer.append(' ');
 196  4
             buffer.append(_expression);
 197   
         }
 198   
 
 199  4
         buffer.append(']');
 200   
 
 201  4
         return buffer.toString();
 202   
     }
 203   
 
 204   
     /** @since 4.0 */
 205  1
     public Object getComponent()
 206   
     {
 207  1
         return _root;
 208   
     }
 209   
 }