Coverage Report - org.webmacro.engine.BlockBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
BlockBuilder
81%
62/76
72%
13/18
1.6
BlockBuilder$BBIterator
90%
9/10
100%
2/2
1.6
BlockBuilder$BlockIterator
N/A
N/A
1.6
 
 1  
 /*
 2  
  * Copyright (C) 1998-2000 Semiotek Inc.  All Rights Reserved.
 3  
  *
 4  
  * Redistribution and use in source and binary forms, with or without
 5  
  * modification, are permitted under the terms of either of the following
 6  
  * Open Source licenses:
 7  
  *
 8  
  * The GNU General Public License, version 2, or any later version, as
 9  
  * published by the Free Software Foundation
 10  
  * (http://www.fsf.org/copyleft/gpl.html);
 11  
  *
 12  
  *  or
 13  
  *
 14  
  * The Semiotek Public License (http://webmacro.org/LICENSE.)
 15  
  *
 16  
  * This software is provided "as is", with NO WARRANTY, not even the
 17  
  * implied warranties of fitness to purpose, or merchantability. You
 18  
  * assume all risks and liabilities associated with its use.
 19  
  *
 20  
  * See www.webmacro.org for more information on the WebMacro project.
 21  
  */
 22  
 
 23  
 package org.webmacro.engine;
 24  
 
 25  
 import org.webmacro.Context;
 26  
 import org.webmacro.Macro;
 27  
 
 28  
 import java.util.ArrayList;
 29  
 import java.util.Iterator;
 30  
 import java.util.Stack;
 31  
 
 32  
 /**
 33  
  * A block represents the text between two {}'s in a template, or else
 34  
  * the text that begins at the start of the template and runs until its
 35  
  * end ({}'s around the whole document are not required). It contains
 36  
  * all of the other directives, strings, etc. that can be in a template.
 37  
  */
 38  30024
 public class BlockBuilder implements Builder
 39  
 {
 40  
 
 41  
     private static final int INITIAL_SIZE = 64;
 42  
 
 43  2
     private static Macro[] mArray = new Macro[0];
 44  2
     private static String[] sArray = new String[0];
 45  
 
 46  1488
     private ArrayList elements = new ArrayList();
 47  1488
     private int[] lineNos = new int[INITIAL_SIZE];
 48  1488
     private int[] colNos = new int[INITIAL_SIZE];
 49  
 
 50  1488
     private String name = "unknown";
 51  
 
 52  
     public BlockBuilder ()
 53  0
     {
 54  0
     }
 55  
 
 56  
     public BlockBuilder (String name)
 57  1488
     {
 58  1488
         this.name = name;
 59  1488
     }
 60  
 
 61  
     /** Iterate over a Block.   */
 62  
     public interface BlockIterator extends Iterator
 63  
     {
 64  
 
 65  
         public String getName ();
 66  
 
 67  
         public int getLineNo ();
 68  
 
 69  
         public int getColNo ();
 70  
     }
 71  
 
 72  
     /** BlockBuilder iterator.   */
 73  
     public class BBIterator implements BlockIterator
 74  
     {
 75  
 
 76  
         private int size, i;
 77  
 
 78  
         public BBIterator ()
 79  1484
         {
 80  1484
             size = elements.size();
 81  1484
             i = 0;
 82  1484
         }
 83  
 
 84  
         public String getName ()
 85  
         {
 86  3782
             return name;
 87  
         }
 88  
 
 89  
         public boolean hasNext ()
 90  
         {
 91  20744
             return (i < size);
 92  
         }
 93  
 
 94  
         public Object next ()
 95  
         {
 96  9630
             return elements.get(i++);
 97  
         }
 98  
 
 99  
         public int getLineNo ()
 100  
         {
 101  7564
             return lineNos[i - 1];
 102  
         }
 103  
 
 104  
         public int getColNo ()
 105  
         {
 106  7564
             return colNos[i - 1];
 107  
         }
 108  
 
 109  
         public void remove ()
 110  
         {
 111  0
             throw new UnsupportedOperationException();
 112  
         }
 113  
     }
 114  
 
 115  
     final public Object build (BuildContext bc) throws BuildException
 116  
     {
 117  1484
         ArrayList strings = new ArrayList((elements.size()));
 118  1484
         ArrayList macros = new ArrayList((elements.size()));
 119  1484
         int[] ln = new int[elements.size()];
 120  1484
         int[] cn = new int[elements.size()];
 121  1484
         Stack iterStack = new Stack();
 122  1484
         StringBuffer s = new StringBuffer();
 123  1484
         Context.TemplateEvaluationContext tec = bc.getTemplateEvaluationContext();
 124  
 
 125  
         // flatten everything and view the content as being:
 126  
         //        string (macro string)* string
 127  
         // store that as an array of strings and an array of
 128  
         // Macro objects and create a block.
 129  
 
 130  1484
         BlockIterator iter = new BBIterator();
 131  11114
         while (iter.hasNext())
 132  
         {
 133  9630
             Object o = iter.next();
 134  
 
 135  9630
             if (o instanceof Builder)
 136  
             {
 137  
                 // track line/column numbers in the build context
 138  
                 // so that bc.getCurrentLocation() stays current
 139  3782
                 tec._templateName = iter.getName();
 140  3782
                 tec._lineNo = iter.getLineNo();
 141  3782
                 tec._columnNo = iter.getColNo();
 142  
 
 143  
                 try
 144  
                 {
 145  3782
                     o = ((Builder) o).build(bc);
 146  
                 }
 147  0
                 catch (BuildException be)
 148  
                 {
 149  
                     // restore line/column info to what it was before
 150  
                     // we tried to build the block
 151  0
                     tec._templateName = iter.getName();
 152  0
                     tec._lineNo = iter.getLineNo();
 153  0
                     tec._columnNo = iter.getColNo();
 154  
 
 155  
                     // and rethrow the exception
 156  0
                     throw be;
 157  3782
                 }
 158  
             }
 159  
 
 160  9630
             if (o instanceof Block)
 161  
             {
 162  0
                 iterStack.push(iter);
 163  0
                 iter = ((Block) o).getBlockIterator();
 164  
             }
 165  
             else
 166  
             {
 167  9630
                 if (o instanceof Macro)
 168  
                 {
 169  3782
                     strings.add(s.toString());
 170  3782
                     s = new StringBuffer();
 171  
                     // do not reuse StringBuffer,
 172  
                     // otherwise all strings will contain char[] of max length!!
 173  3782
                     macros.add(o);
 174  
 
 175  
                     // Now deal with the line numbers
 176  3782
                     int size = macros.size();
 177  3782
                     if (ln.length < size)
 178  
                     {
 179  0
                         ln = resizeIntArray(ln, ln.length * 2);
 180  0
                         cn = resizeIntArray(cn, cn.length * 2);
 181  
                     }
 182  3782
                     ln[size - 1] = iter.getLineNo();
 183  3782
                     cn[size - 1] = iter.getColNo();
 184  3782
                 }
 185  5848
                 else if (o != null)
 186  
                 {
 187  5848
                     s.append(o.toString());
 188  
                 }
 189  
             }
 190  9630
             while (!iter.hasNext() && !iterStack.empty())
 191  0
                 iter = (BlockIterator) iterStack.pop();
 192  9630
         }
 193  1484
         strings.add(s.toString());
 194  
 
 195  1484
         Macro finalMacros[] = (Macro[]) macros.toArray(mArray);
 196  1484
         String finalStrings[] = (String[]) strings.toArray(sArray);
 197  1484
         int finalLines[] = resizeIntArray(ln, macros.size());
 198  1484
         int finalCols[] = resizeIntArray(cn, macros.size());
 199  1484
         return new Block(name, finalStrings, finalMacros, finalLines, finalCols);
 200  
     }
 201  
 
 202  
     private static int[] resizeIntArray (int[] ia, int size)
 203  
     {
 204  2968
         int[] temp = new int[size];
 205  2968
         System.arraycopy(ia, 0, temp, 0, Math.min(ia.length, size));
 206  2968
         return temp;
 207  
     }
 208  
 
 209  
     // Methods that look like Vector methods
 210  
 
 211  
     public void addElement (Object o)
 212  
     {
 213  13096
         elements.add(o);
 214  13096
     }
 215  
 
 216  
     public void addElement (Object o, int lineNo, int colNo)
 217  
     {
 218  3890
         elements.add(o);
 219  
 
 220  3890
         int size = elements.size();
 221  3890
         if (lineNos.length < size)
 222  
         {
 223  0
             lineNos = resizeIntArray(lineNos, Math.max(lineNos.length * 2,
 224  
                     size + INITIAL_SIZE));
 225  0
             colNos = resizeIntArray(colNos, Math.max(colNos.length * 2,
 226  
                     size + INITIAL_SIZE));
 227  
         }
 228  3890
         lineNos[size - 1] = lineNo;
 229  3890
         colNos[size - 1] = colNo;
 230  3890
     }
 231  
 
 232  
     public int size ()
 233  
     {
 234  44016
         return elements.size();
 235  
     }
 236  
 
 237  
     public void remove (int i)
 238  
     {
 239  7356
         elements.remove(i);
 240  7356
     }
 241  
 
 242  
     public Object elementAt (int i)
 243  
     {
 244  17620
         return elements.get(i);
 245  
     }
 246  
 
 247  
     public Object setElementAt (Object o, int i)
 248  
     {
 249  1184
         return elements.set(i, o);
 250  
     }
 251  
 
 252  
 }
 253