Clover coverage report - Code Coverage for tapestry release 3.1-alpha-1
Coverage timestamp: Mon Feb 21 2005 09:16:14 EST
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.AdapterRegistry;
 21   
 import org.apache.hivemind.lib.util.AdapterRegistryImpl;
 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 AdapterRegistry _adaptors = new AdapterRegistryImpl();
 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  42
     public DataSqueezerImpl(ClassResolver resolver)
 68   
     {
 69  42
         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  43
     public DataSqueezerImpl(ClassResolver resolver, ISqueezeAdaptor[] adaptors)
 82   
     {
 83  43
         _resolver = resolver;
 84   
 
 85  43
         registerDefaultAdaptors();
 86   
 
 87  43
         if (adaptors != null)
 88  1
             for (int i = 0; i < adaptors.length; i++)
 89  1
                 adaptors[i].register(this);
 90   
     }
 91   
 
 92  43
     private void registerDefaultAdaptors()
 93   
     {
 94  43
         new CharacterAdaptor().register(this);
 95  43
         new StringAdaptor().register(this);
 96  43
         new IntegerAdaptor().register(this);
 97  43
         new DoubleAdaptor().register(this);
 98  43
         new ByteAdaptor().register(this);
 99  43
         new FloatAdaptor().register(this);
 100  43
         new LongAdaptor().register(this);
 101  43
         new ShortAdaptor().register(this);
 102  43
         new BooleanAdaptor().register(this);
 103  43
         new SerializableAdaptor().register(this);
 104  43
         new ComponentAddressAdaptor().register(this);
 105  43
         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  522
     public synchronized void register(String prefix, Class dataClass, ISqueezeAdaptor adaptor)
 121   
     {
 122  522
         int prefixLength = prefix.length();
 123  522
         int offset;
 124   
 
 125  522
         if (prefixLength < 1)
 126  1
             throw new IllegalArgumentException(Tapestry.getMessage("DataSqueezer.short-prefix"));
 127   
 
 128  521
         if (dataClass == null)
 129  1
             throw new IllegalArgumentException(Tapestry.getMessage("DataSqueezer.null-class"));
 130   
 
 131  520
         if (adaptor == null)
 132  1
             throw new IllegalArgumentException(Tapestry.getMessage("DataSqueezer.null-adaptor"));
 133   
 
 134  519
         for (int i = 0; i < prefixLength; i++)
 135   
         {
 136  992
             char ch = prefix.charAt(i);
 137   
 
 138  992
             if (ch < '!' | ch > 'z')
 139  1
                 throw new IllegalArgumentException(Tapestry.getMessage("DataSqueezer.prefix-out-of-range"));
 140   
 
 141  991
             offset = ch - FIRST_ADAPTOR_OFFSET;
 142   
 
 143  991
             if (_adaptorByPrefix[offset] != null)
 144  1
                 throw new IllegalArgumentException(Tapestry.format("DataSqueezer.adaptor-prefix-taken", prefix
 145   
                         .substring(i, i)));
 146   
 
 147  990
             _adaptorByPrefix[offset] = adaptor;
 148   
 
 149   
         }
 150   
 
 151  517
         _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  113
     public String squeeze(Object data) throws IOException
 160   
     {
 161  113
         ISqueezeAdaptor adaptor;
 162   
 
 163  113
         if (data == null)
 164  2
             return NULL_PREFIX;
 165   
 
 166  111
         adaptor = (ISqueezeAdaptor) _adaptors.getAdapter(data.getClass());
 167   
 
 168  111
         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  52
     public String[] squeeze(Object[] data) throws IOException
 177   
     {
 178  52
         if (data == null)
 179  1
             return null;
 180   
 
 181  51
         int length = data.length;
 182  51
         String[] result;
 183   
 
 184  51
         result = new String[length];
 185   
 
 186  51
         for (int i = 0; i < length; i++)
 187  72
             result[i] = squeeze(data[i]);
 188   
 
 189  51
         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  108
     public Object unsqueeze(String string) throws IOException
 199   
     {
 200  108
         ISqueezeAdaptor adaptor = null;
 201   
 
 202  108
         if (string.equals(NULL_PREFIX))
 203  2
             return null;
 204   
 
 205  106
         int offset = string.charAt(0) - FIRST_ADAPTOR_OFFSET;
 206   
 
 207  106
         if (offset >= 0 && offset < _adaptorByPrefix.length)
 208  106
             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  106
         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  104
         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  48
     public Object[] unsqueeze(String[] strings) throws IOException
 230   
     {
 231  48
         if (strings == null)
 232  1
             return null;
 233   
 
 234  47
         int length = strings.length;
 235  47
         Object[] result;
 236   
 
 237  47
         result = new Object[length];
 238   
 
 239  47
         for (int i = 0; i < length; i++)
 240  69
             result[i] = unsqueeze(strings[i]);
 241   
 
 242  47
         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  2
     public ClassResolver getResolver()
 285   
     {
 286  2
         return _resolver;
 287   
     }
 288   
 
 289   
 }