Clover coverage report - Code Coverage for tapestry release 4.0-beta-8
Coverage timestamp: Sat Sep 24 2005 11:50:34 EDT
file stats: LOC: 307   Methods: 14
NCLOC: 147   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
TapestryUtils.java 100% 100% 100% 100%
coverage
 1    // Copyright 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;
 16   
 17    import java.util.ArrayList;
 18    import java.util.List;
 19   
 20    import org.apache.hivemind.ApplicationRuntimeException;
 21    import org.apache.hivemind.HiveMind;
 22    import org.apache.hivemind.Location;
 23    import org.apache.hivemind.util.Defense;
 24   
 25    /**
 26    * Constants and static methods.
 27    *
 28    * @author Howard M. Lewis Ship
 29    * @since 4.0
 30    */
 31    public class TapestryUtils
 32    {
 33    private static final char QUOTE = '\'';
 34   
 35    private static final char BACKSLASH = '\\';
 36   
 37    /**
 38    * Stores an attribute into the request cycle, verifying that no object with that key is already
 39    * present.
 40    *
 41    * @param cycle
 42    * the cycle to store the attribute into
 43    * @param key
 44    * the key to store the attribute as
 45    * @param object
 46    * the attribute value to store
 47    * @throws IllegalStateException
 48    * if a non-null value has been stored into the cycle with the provided key.
 49    */
 50   
 51  151 public static void storeUniqueAttribute(IRequestCycle cycle, String key, Object object)
 52    {
 53  151 Defense.notNull(cycle, "cycle");
 54  151 Defense.notNull(key, "key");
 55  151 Defense.notNull(object, "object");
 56   
 57  151 Object existing = cycle.getAttribute(key);
 58  151 if (existing != null)
 59  1 throw new IllegalStateException(TapestryMessages.nonUniqueAttribute(
 60    object,
 61    key,
 62    existing));
 63   
 64  150 cycle.setAttribute(key, object);
 65    }
 66   
 67    public static final String PAGE_RENDER_SUPPORT_ATTRIBUTE = "org.apache.tapestry.PageRenderSupport";
 68   
 69    public static final String FORM_ATTRIBUTE = "org.apache.tapestry.Form";
 70   
 71    /**
 72    * Stores the support object using {@link #storeUniqueAttribute(IRequestCycle, String, Object)}.
 73    */
 74   
 75  76 public static void storePageRenderSupport(IRequestCycle cycle, PageRenderSupport support)
 76    {
 77  76 storeUniqueAttribute(cycle, PAGE_RENDER_SUPPORT_ATTRIBUTE, support);
 78    }
 79   
 80    /**
 81    * Store the IForm instance using {@link #storeUniqueAttribute(IRequestCycle, String, Object)}.
 82    */
 83   
 84  73 public static void storeForm(IRequestCycle cycle, IForm form)
 85    {
 86  73 storeUniqueAttribute(cycle, FORM_ATTRIBUTE, form);
 87    }
 88   
 89    /**
 90    * Gets the previously stored {@link org.apache.tapestry.PageRenderSupport} object.
 91    *
 92    * @param cycle
 93    * the request cycle storing the support object
 94    * @param component
 95    * the component which requires the support (used to report exceptions)
 96    * @throws ApplicationRuntimeException
 97    * if no support object has been stored
 98    */
 99   
 100  10 public static PageRenderSupport getPageRenderSupport(IRequestCycle cycle, IComponent component)
 101    {
 102  10 Defense.notNull(component, "component");
 103   
 104  10 PageRenderSupport result = getOptionalPageRenderSupport(cycle);
 105  10 if (result == null)
 106  2 throw new ApplicationRuntimeException(TapestryMessages.noPageRenderSupport(component),
 107    component.getLocation(), null);
 108   
 109  8 return result;
 110    }
 111   
 112    /**
 113    * Gets the previously stored {@link IForm} object.
 114    *
 115    * @param cycle
 116    * the request cycle storing the support object
 117    * @param component
 118    * the component which requires the form (used to report exceptions)
 119    * @throws ApplicationRuntimeException
 120    * if no form object has been stored
 121    */
 122  130 public static IForm getForm(IRequestCycle cycle, IComponent component)
 123    {
 124  130 Defense.notNull(cycle, "cycle");
 125  130 Defense.notNull(component, "component");
 126   
 127  130 IForm result = (IForm) cycle.getAttribute(FORM_ATTRIBUTE);
 128   
 129  130 if (result == null)
 130  2 throw new ApplicationRuntimeException(TapestryMessages.noForm(component), component
 131    .getLocation(), null);
 132   
 133  128 return result;
 134    }
 135   
 136  77 public static void removePageRenderSupport(IRequestCycle cycle)
 137    {
 138  77 cycle.removeAttribute(PAGE_RENDER_SUPPORT_ATTRIBUTE);
 139    }
 140   
 141  74 public static void removeForm(IRequestCycle cycle)
 142    {
 143  74 cycle.removeAttribute(FORM_ATTRIBUTE);
 144    }
 145   
 146    /**
 147    * Returns the {@link PageRenderSupport} object if previously stored, or null otherwise.
 148    * This is used in the rare case that a component wishes to adjust its behavior based on whether
 149    * the page render support services are avaiable (typically, adjust for whether enclosed by a
 150    * Body component, or not).
 151    */
 152   
 153  102 public static PageRenderSupport getOptionalPageRenderSupport(IRequestCycle cycle)
 154    {
 155  102 return (PageRenderSupport) cycle.getAttribute(PAGE_RENDER_SUPPORT_ATTRIBUTE);
 156    }
 157   
 158    /**
 159    * Splits a string using the default delimiter of ','.
 160    */
 161   
 162  452 public static String[] split(String input)
 163    {
 164  452 return split(input, ',');
 165    }
 166   
 167    /**
 168    * Splits a single string into an array of strings, using a specific delimiter character.
 169    */
 170   
 171  506 public static String[] split(String input, char delimiter)
 172    {
 173  506 if (HiveMind.isBlank(input))
 174  394 return new String[0];
 175   
 176  112 List strings = new ArrayList();
 177   
 178  112 char[] buffer = input.toCharArray();
 179   
 180  112 int start = 0;
 181  112 int length = 0;
 182   
 183  112 for (int i = 0; i < buffer.length; i++)
 184    {
 185  882 if (buffer[i] != delimiter)
 186    {
 187  814 length++;
 188  814 continue;
 189    }
 190   
 191    // Consecutive delimiters will result in a sequence
 192    // of empty strings.
 193   
 194  68 String token = new String(buffer, start, length);
 195  68 strings.add(token);
 196   
 197  68 start = i + 1;
 198  68 length = 0;
 199    }
 200   
 201    // If the string contains no delimiters, then
 202    // wrap it an an array and return it.
 203   
 204  112 if (start == 0 && length == buffer.length)
 205    {
 206  80 return new String[]
 207    { input };
 208    }
 209   
 210    // The final token.
 211  32 String token = new String(buffer, start, length);
 212  32 strings.add(token);
 213   
 214  32 return (String[]) strings.toArray(new String[strings.size()]);
 215    }
 216   
 217    /**
 218    * Enquotes a string within single quotes, ready for insertion as part of a block of JavaScript.
 219    * Single quotes and backslashes within the input string are properly escaped.
 220    */
 221   
 222  18 public static String enquote(String input)
 223    {
 224  18 Defense.notNull(input, "input");
 225   
 226  18 char[] chars = input.toCharArray();
 227   
 228    // Add room for the two quotes and a couple of escaped characters
 229   
 230  18 StringBuffer buffer = new StringBuffer(chars.length + 5);
 231   
 232  18 buffer.append(QUOTE);
 233   
 234  18 for (int i = 0; i < chars.length; i++)
 235    {
 236  308 char ch = chars[i];
 237   
 238  308 if (ch == QUOTE || ch == BACKSLASH)
 239  13 buffer.append(BACKSLASH);
 240   
 241  308 buffer.append(ch);
 242    }
 243   
 244  18 buffer.append(QUOTE);
 245   
 246  18 return buffer.toString();
 247    }
 248   
 249    /**
 250    * A Tapestry component id is a little more liberal than an XML NMTOKEN. NMTOKEN must be
 251    * [A-Za-z][A-Za-z0-9:_.-]*, but a component id might include a leading dollar sign (for an
 252    * anonymous component with a fabricated id).
 253    */
 254   
 255  171 public static String convertTapestryIdToNMToken(String baseId)
 256    {
 257  171 String result = baseId.replace('$', '_');
 258   
 259  171 while (result.startsWith("_"))
 260  78 result = result.substring(1);
 261   
 262  171 return result;
 263    }
 264   
 265    /**
 266    * Converts a clientId into a client-side DOM reference; i.e.
 267    * <code>document.getElementById('<i>id</i>')</code>.
 268    */
 269   
 270  1 public static String buildClientElementReference(String clientId)
 271    {
 272  1 Defense.notNull(clientId, "clientId");
 273   
 274  1 return "document.getElementById('" + clientId + "')";
 275    }
 276   
 277    /**
 278    * Used by some generated code; obtains a component and ensures it is of the correct type.
 279    */
 280   
 281  3 public static IComponent getComponent(IComponent container, String componentId,
 282    Class expectedType, Location location)
 283    {
 284  3 Defense.notNull(container, "container");
 285  3 Defense.notNull(componentId, "componentId");
 286  3 Defense.notNull(expectedType, "expectedType");
 287    // Don't always have a location
 288   
 289  3 IComponent component = null;
 290   
 291  3 try
 292    {
 293  3 component = container.getComponent(componentId);
 294    }
 295    catch (Exception ex)
 296    {
 297  1 throw new ApplicationRuntimeException(ex.getMessage(), location, ex);
 298    }
 299   
 300  2 if (!expectedType.isAssignableFrom(component.getClass()))
 301  1 throw new ApplicationRuntimeException(TapestryMessages.componentWrongType(
 302    component,
 303    expectedType), location, null);
 304   
 305  1 return component;
 306    }
 307    }