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: 289   Methods: 11
NCLOC: 130   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
DataSqueezerImpl.java 86.1% 84.6% 81.8% 84.8%
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.util.io;
 16   
 
 17   
 import java.io.IOException;
 18   
 
 19   
 import org.apache.hivemind.ClassResolver;
 20   
 import org.apache.hivemind.lib.util.StrategyRegistry;
 21   
 import org.apache.hivemind.lib.util.StrategyRegistryImpl;
 22   
 import org.apache.tapestry.Tapestry;
 23   
 import org.apache.tapestry.services.DataSqueezer;
 24   
 
 25   
 /**
 26   
  * A class used to convert arbitrary objects to Strings and back. This has
 27   
  * particular uses involving HTTP URLs and Cookies.
 28   
  * 
 29   
  * @author Howard Lewis Ship
 30   
  */
 31   
 
 32   
 public class DataSqueezerImpl implements DataSqueezer
 33   
 {
 34   
     private static final String NULL_PREFIX = "X";
 35   
 
 36   
     private static final char NULL_PREFIX_CH = 'X';
 37   
 
 38   
     private static final int ARRAY_SIZE = 90;
 39   
 
 40   
     private static final int FIRST_ADAPTOR_OFFSET = 33;
 41   
 
 42   
     /**
 43   
      * An array of adaptors; this is used as a cheap lookup-table when
 44   
      * unsqueezing. Each adaptor is identified by a single ASCII character, in
 45   
      * the range of 33 ('!') to 122 (the letter 'z'). The offset into this table
 46   
      * is the character minus 33.
 47   
      */
 48   
 
 49   
     private ISqueezeAdaptor[] _adaptorByPrefix = new ISqueezeAdaptor[ARRAY_SIZE];
 50   
 
 51   
     /**
 52   
      * AdaptorRegistry cache of adaptors.
 53   
      */
 54   
 
 55   
     private StrategyRegistry _adaptors = new StrategyRegistryImpl();
 56   
 
 57   
     /**
 58   
      * Resource resolver used to deserialize classes.
 59   
      */
 60   
 
 61   
     private ClassResolver _resolver;
 62   
 
 63   
     /**
 64   
      * Creates a new squeezer with the default set of adaptors.
 65   
      */
 66   
 
 67  33
     public DataSqueezerImpl(ClassResolver resolver)
 68   
     {
 69  33
         this(resolver, null);
 70   
     }
 71   
 
 72   
     /**
 73   
      * Creates a new data squeezer, which will have the default set of adaptors,
 74   
      * and may add additional adaptors.
 75   
      * 
 76   
      * @param adaptors
 77   
      *            an optional list of adaptors that will be registered to the
 78   
      *            data squeezer (it may be null or empty)
 79   
      */
 80   
 
 81  34
     public DataSqueezerImpl(ClassResolver resolver, ISqueezeAdaptor[] adaptors)
 82   
     {
 83  34
         _resolver = resolver;
 84   
 
 85  34
         registerDefaultAdaptors();
 86   
 
 87  34
         if (adaptors != null)
 88  1
             for (int i = 0; i < adaptors.length; i++)
 89  1
                 adaptors[i].register(this);
 90   
     }
 91   
 
 92  34
     private void registerDefaultAdaptors()
 93   
     {
 94  34
         new CharacterAdaptor().register(this);
 95  34
         new StringAdaptor().register(this);
 96  34
         new IntegerAdaptor().register(this);
 97  34
         new DoubleAdaptor().register(this);
 98  34
         new ByteAdaptor().register(this);
 99  34
         new FloatAdaptor().register(this);
 100  34
         new LongAdaptor().register(this);
 101  34
         new ShortAdaptor().register(this);
 102  34
         new BooleanAdaptor().register(this);
 103  34
         new SerializableAdaptor().register(this);
 104  34
         new ComponentAddressAdaptor().register(this);
 105  34
         new EnumAdaptor().register(this);
 106   
     }
 107   
 
 108   
     /**
 109   
      * Registers the adaptor with one or more single-character prefixes.
 110   
      * 
 111   
      * @param prefix
 112   
      *            one or more characters, each of which will be a prefix for the
 113   
      *            adaptor.
 114   
      * @param dataClass
 115   
      *            the class (or interface) which can be encoded by the adaptor.
 116   
      * @param adaptor
 117   
      *            the adaptor which to be registered.
 118   
      */
 119   
 
 120  414
     public synchronized void register(String prefix, Class dataClass, ISqueezeAdaptor adaptor)
 121   
     {
 122  414
         int prefixLength = prefix.length();
 123  414
         int offset;
 124   
 
 125  414
         if (prefixLength < 1)
 126  1
             throw new IllegalArgumentException(Tapestry.getMessage("DataSqueezer.short-prefix"));
 127   
 
 128  413
         if (dataClass == null)
 129  1
             throw new IllegalArgumentException(Tapestry.getMessage("DataSqueezer.null-class"));
 130   
 
 131  412
         if (adaptor == null)
 132  1
             throw new IllegalArgumentException(Tapestry.getMessage("DataSqueezer.null-adaptor"));
 133   
 
 134  411
         for (int i = 0; i < prefixLength; i++)
 135   
         {
 136  785
             char ch = prefix.charAt(i);
 137   
 
 138  785
             if (ch < '!' | ch > 'z')
 139  1
                 throw new IllegalArgumentException(Tapestry.getMessage("DataSqueezer.prefix-out-of-range"));
 140   
 
 141  784
             offset = ch - FIRST_ADAPTOR_OFFSET;
 142   
 
 143  784
             if (_adaptorByPrefix[offset] != null)
 144  1
                 throw new IllegalArgumentException(Tapestry.format("DataSqueezer.adaptor-prefix-taken", prefix
 145   
                         .substring(i, i)));
 146   
 
 147  783
             _adaptorByPrefix[offset] = adaptor;
 148   
 
 149   
         }
 150   
 
 151  409
         _adaptors.register(dataClass, adaptor);
 152   
     }
 153   
 
 154   
     /**
 155   
      * Squeezes the data object into a String by locating an appropriate adaptor
 156   
      * that can perform the conversion. data may be null.
 157   
      */
 158   
 
 159  76
     public String squeeze(Object data) throws IOException
 160   
     {
 161  76
         ISqueezeAdaptor adaptor;
 162   
 
 163  76
         if (data == null)
 164  2
             return NULL_PREFIX;
 165   
 
 166  74
         adaptor = (ISqueezeAdaptor) _adaptors.getStrategy(data.getClass());
 167   
 
 168  74
         return adaptor.squeeze(this, data);
 169   
     }
 170   
 
 171   
     /**
 172   
      * A convience; invokes {@link #squeeze(Object)}for each element in the
 173   
      * data array. If data is null, returns null.
 174   
      */
 175   
 
 176  14
     public String[] squeeze(Object[] data) throws IOException
 177   
     {
 178  14
         if (data == null)
 179  1
             return null;
 180   
 
 181  13
         int length = data.length;
 182  13
         String[] result;
 183   
 
 184  13
         result = new String[length];
 185   
 
 186  13
         for (int i = 0; i < length; i++)
 187  34
             result[i] = squeeze(data[i]);
 188   
 
 189  13
         return result;
 190   
     }
 191   
 
 192   
     /**
 193   
      * Unsqueezes the string. Note that in a special case, where the first
 194   
      * character of the string is not a recognized prefix, it is assumed that
 195   
      * the string is simply a string, and return with no change.
 196   
      */
 197   
 
 198  82
     public Object unsqueeze(String string) throws IOException
 199   
     {
 200  82
         ISqueezeAdaptor adaptor = null;
 201   
 
 202  82
         if (string.equals(NULL_PREFIX))
 203  2
             return null;
 204   
 
 205  80
         int offset = string.charAt(0) - FIRST_ADAPTOR_OFFSET;
 206   
 
 207  80
         if (offset >= 0 && offset < _adaptorByPrefix.length)
 208  80
             adaptor = _adaptorByPrefix[offset];
 209   
 
 210   
         // If the adaptor is not otherwise recognized, the it is simply
 211   
         // an encoded String (the StringAdaptor may not have added
 212   
         // a prefix).
 213   
 
 214  80
         if (adaptor == null)
 215  2
             return string;
 216   
 
 217   
         // Adaptor should never be null, because we always supply
 218   
         // an adaptor for String
 219   
 
 220  78
         return adaptor.unsqueeze(this, string);
 221   
     }
 222   
 
 223   
     /**
 224   
      * Convienience method for unsqueezing many strings (back into objects).
 225   
      * <p>
 226   
      * If strings is null, returns null.
 227   
      */
 228   
 
 229  21
     public Object[] unsqueeze(String[] strings) throws IOException
 230   
     {
 231  21
         if (strings == null)
 232  1
             return null;
 233   
 
 234  20
         int length = strings.length;
 235  20
         Object[] result;
 236   
 
 237  20
         result = new Object[length];
 238   
 
 239  20
         for (int i = 0; i < length; i++)
 240  42
             result[i] = unsqueeze(strings[i]);
 241   
 
 242  20
         return result;
 243   
     }
 244   
 
 245   
     /**
 246   
      * Checks to see if a given prefix character has a registered adaptor. This
 247   
      * is used by the String adaptor to determine whether it needs to put a
 248   
      * prefix on its String.
 249   
      */
 250   
 
 251  0
     public boolean isPrefixRegistered(char prefix)
 252   
     {
 253  0
         int offset = prefix - FIRST_ADAPTOR_OFFSET;
 254   
 
 255   
         // Special case for handling nulls.
 256   
 
 257  0
         if (prefix == NULL_PREFIX_CH)
 258  0
             return true;
 259   
 
 260  0
         if (offset < 0 || offset >= _adaptorByPrefix.length)
 261  0
             return false;
 262   
 
 263  0
         return _adaptorByPrefix[offset] != null;
 264   
     }
 265   
 
 266  0
     public String toString()
 267   
     {
 268  0
         StringBuffer buffer;
 269   
 
 270  0
         buffer = new StringBuffer();
 271  0
         buffer.append("DataSqueezer[adaptors=<");
 272  0
         buffer.append(_adaptors.toString());
 273  0
         buffer.append(">]");
 274   
 
 275  0
         return buffer.toString();
 276   
     }
 277   
 
 278   
     /**
 279   
      * Returns the resource resolver used with this squeezer.
 280   
      * 
 281   
      * @since 2.2
 282   
      */
 283   
 
 284  3
     public ClassResolver getResolver()
 285   
     {
 286  3
         return _resolver;
 287   
     }
 288   
 
 289   
 }