Clover coverage report - Code Coverage for tapestry release 4.0-beta-9
Coverage timestamp: Sat Oct 1 2005 08:36:20 EDT
file stats: LOC: 371   Methods: 31
NCLOC: 240   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
MarkupWriterImpl.java 97.5% 97.4% 93.5% 96.8%
coverage 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.markup;
 16   
 17    import java.io.PrintWriter;
 18    import java.util.ArrayList;
 19    import java.util.List;
 20   
 21    import org.apache.hivemind.ApplicationRuntimeException;
 22    import org.apache.hivemind.util.Defense;
 23    import org.apache.tapestry.IMarkupWriter;
 24    import org.apache.tapestry.NestedMarkupWriter;
 25   
 26    /**
 27    * Completely revised (for 4.0) implementation of {@link org.apache.tapestry.IMarkupWriter}. No
 28    * longer does internal buffering (since the servlet/portlet APIs support that natively) and wraps
 29    * around a {@link java.io.PrintWriter} (rather than an {@link java.io.OutputStream}).
 30    *
 31    * @author Howard M. Lewis Ship
 32    * @since 4.0
 33    */
 34    public class MarkupWriterImpl implements IMarkupWriter
 35    {
 36    /**
 37    * The underlying {@link PrintWriter}that output is sent to.
 38    */
 39   
 40    private PrintWriter _writer;
 41   
 42    /**
 43    * Filter used to "escape" characters that need any kind of special encoding for the output
 44    * content type.
 45    */
 46   
 47    private MarkupFilter _filter;
 48   
 49    /**
 50    * Indicates whether a tag is open or not. A tag is opened by {@link #begin(String)}or
 51    * {@link #beginEmpty(String)}. It stays open while calls to the <code>attribute()</code>
 52    * methods are made. It is closed (the '&gt;' is written) when any other method is invoked.
 53    */
 54   
 55    private boolean _openTag = false;
 56   
 57    /**
 58    * Indicates that the tag was opened with {@link #beginEmpty(String)}, which affects how the
 59    * tag is closed (a slash is added to indicate the lack of a body). This is compatible with
 60    * HTML, but reflects an XML/XHTML leaning.
 61    */
 62   
 63    private boolean _emptyTag = false;
 64   
 65    private String _contentType;
 66   
 67    /**
 68    * A Stack of Strings used to track the active tag elements. Elements are active until the
 69    * corresponding close tag is written. The {@link #push(String)}method adds elements to the
 70    * stack, {@link #pop()}removes them.
 71    */
 72   
 73    private List _activeElementStack;
 74   
 75  429 public MarkupWriterImpl(String contentType, PrintWriter writer, MarkupFilter filter)
 76    {
 77  429 Defense.notNull(contentType, "contentType");
 78  429 Defense.notNull(writer, "writer");
 79  429 Defense.notNull(filter, "filter");
 80   
 81  429 _contentType = contentType;
 82  429 _writer = writer;
 83  429 _filter = filter;
 84    }
 85   
 86  124 public void attribute(String name, int value)
 87    {
 88  124 checkTagOpen();
 89   
 90  123 _writer.print(' ');
 91  123 _writer.print(name);
 92  123 _writer.print("=\"");
 93  123 _writer.print(value);
 94  123 _writer.print('"');
 95    }
 96   
 97  5 public void attribute(String name, boolean value)
 98    {
 99  5 checkTagOpen();
 100   
 101  4 _writer.print(' ');
 102  4 _writer.print(name);
 103  4 _writer.print("=\"");
 104  4 _writer.print(value);
 105  4 _writer.print('"');
 106    }
 107   
 108  5519 public void attribute(String name, String value)
 109    {
 110  5519 attribute(name, value, false);
 111    }
 112   
 113  5526 public void attribute(String name, String value, boolean raw)
 114    {
 115  5526 checkTagOpen();
 116   
 117  5525 _writer.print(' ');
 118   
 119    // Could use a check here that name contains only valid characters
 120   
 121  5525 _writer.print(name);
 122  5525 _writer.print("=\"");
 123   
 124  5525 if (value != null)
 125    {
 126  5518 char[] data = value.toCharArray();
 127  5518 maybePrintFiltered(data, 0, data.length, raw, true);
 128    }
 129   
 130  5525 _writer.print('"');
 131    }
 132   
 133    /**
 134    * Prints the value, if non-null. May pass it through the filter, unless raw is true.
 135    */
 136   
 137  15677 private void maybePrintFiltered(char[] data, int offset, int length, boolean raw,
 138    boolean isAttribute)
 139    {
 140  15677 if (data == null || length <= 0)
 141  157 return;
 142   
 143  15520 if (raw)
 144    {
 145  3602 _writer.write(data, offset, length);
 146  3602 return;
 147    }
 148   
 149  11918 _filter.print(_writer, data, offset, length, isAttribute);
 150    }
 151   
 152  7 public void attributeRaw(String name, String value)
 153    {
 154  7 attribute(name, value, true);
 155    }
 156   
 157  11149 public void begin(String name)
 158    {
 159  11149 if (_openTag)
 160  3050 closeTag();
 161   
 162  11149 push(name);
 163   
 164  11149 _writer.print('<');
 165  11149 _writer.print(name);
 166   
 167  11149 _openTag = true;
 168  11149 _emptyTag = false;
 169    }
 170   
 171  786 public void beginEmpty(String name)
 172    {
 173  786 if (_openTag)
 174  45 closeTag();
 175   
 176  786 _writer.print('<');
 177  786 _writer.print(name);
 178   
 179  786 _openTag = true;
 180  786 _emptyTag = true;
 181    }
 182   
 183  0 public boolean checkError()
 184    {
 185  0 return _writer.checkError();
 186    }
 187   
 188  342 public void close()
 189    {
 190  342 if (_openTag)
 191  0 closeTag();
 192   
 193    // Close any active elements.
 194   
 195  342 while (!stackEmpty())
 196    {
 197  3 _writer.print("</");
 198  3 _writer.print(pop());
 199  3 _writer.print('>');
 200    }
 201   
 202  342 _writer.close();
 203   
 204  342 _writer = null;
 205  342 _filter = null;
 206  342 _activeElementStack = null;
 207    }
 208   
 209  11928 public void closeTag()
 210    {
 211  11928 if (_emptyTag)
 212  786 _writer.print('/');
 213   
 214  11928 _writer.print('>');
 215   
 216  11928 _openTag = false;
 217  11928 _emptyTag = false;
 218    }
 219   
 220  467 public void comment(String value)
 221    {
 222  467 if (_openTag)
 223  1 closeTag();
 224   
 225  467 _writer.print("<!-- ");
 226  467 _writer.print(value);
 227  467 _writer.println(" -->");
 228    }
 229   
 230  5060 public void end()
 231    {
 232  5060 if (_openTag)
 233  1042 closeTag();
 234   
 235  5060 if (stackEmpty())
 236  1 throw new ApplicationRuntimeException(MarkupMessages.endWithEmptyStack());
 237   
 238  5059 _writer.print("</");
 239  5059 _writer.print(pop());
 240  5059 _writer.print('>');
 241    }
 242   
 243  3081 public void end(String name)
 244    {
 245  3081 if (_openTag)
 246  8 closeTag();
 247   
 248  3081 if (_activeElementStack == null || !_activeElementStack.contains(name))
 249  1 throw new ApplicationRuntimeException(MarkupMessages.elementNotOnStack(
 250    name,
 251    _activeElementStack));
 252   
 253  3080 while (true)
 254    {
 255  6062 String tagName = pop();
 256   
 257  6062 _writer.print("</");
 258  6062 _writer.print(tagName);
 259  6062 _writer.print('>');
 260   
 261  6062 if (tagName.equals(name))
 262  3080 break;
 263    }
 264    }
 265   
 266  0 public void flush()
 267    {
 268  0 _writer.flush();
 269    }
 270   
 271  224 public NestedMarkupWriter getNestedWriter()
 272    {
 273  224 return new NestedMarkupWriterImpl(this, _filter);
 274    }
 275   
 276  2 public void print(char[] data, int offset, int length)
 277    {
 278  2 print(data, offset, length, false);
 279    }
 280   
 281  3170 public void printRaw(char[] buffer, int offset, int length)
 282    {
 283  3170 print(buffer, offset, length, true);
 284    }
 285   
 286  10159 public void print(char[] buffer, int offset, int length, boolean raw)
 287    {
 288  10159 if (_openTag)
 289  6459 closeTag();
 290   
 291  10159 maybePrintFiltered(buffer, offset, length, raw, false);
 292    }
 293   
 294  4997 public void print(String value)
 295    {
 296  4997 print(value, false);
 297    }
 298   
 299  429 public void printRaw(String value)
 300    {
 301  429 print(value, true);
 302    }
 303   
 304  6987 public void print(String value, boolean raw)
 305    {
 306  6987 if (value == null || value.length() == 0)
 307    {
 308  111 print(null, 0, 0, raw);
 309  111 return;
 310    }
 311   
 312  6876 char[] buffer = value.toCharArray();
 313   
 314  6876 print(buffer, 0, buffer.length, raw);
 315    }
 316   
 317  1 public void print(char value)
 318    {
 319  1 char[] data = new char[]
 320    { value };
 321   
 322  1 print(data, 0, 1);
 323    }
 324   
 325  184 public void print(int value)
 326    {
 327  184 if (_openTag)
 328  183 closeTag();
 329   
 330  184 _writer.print(value);
 331    }
 332   
 333  5075 public void println()
 334    {
 335  5075 if (_openTag)
 336  1091 closeTag();
 337   
 338  5075 _writer.println();
 339    }
 340   
 341  343 public String getContentType()
 342    {
 343  343 return _contentType;
 344    }
 345   
 346  5655 private void checkTagOpen()
 347    {
 348  5655 if (!_openTag)
 349  3 throw new IllegalStateException(MarkupMessages.tagNotOpen());
 350    }
 351   
 352  11149 private void push(String name)
 353    {
 354  11149 if (_activeElementStack == null)
 355  253 _activeElementStack = new ArrayList();
 356   
 357  11149 _activeElementStack.add(name);
 358    }
 359   
 360  11124 private String pop()
 361    {
 362  11124 int lastIndex = _activeElementStack.size() - 1;
 363   
 364  11124 return (String) _activeElementStack.remove(lastIndex);
 365    }
 366   
 367  5405 private boolean stackEmpty()
 368    {
 369  5405 return _activeElementStack == null || _activeElementStack.isEmpty();
 370    }
 371    }