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