Coverage Report - org.webmacro.directive.DirectiveBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
DirectiveBuilder
71%
43/60
57%
23/40
3.214
 
 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.directive;
 24  
 
 25  
 import org.webmacro.engine.BuildContext;
 26  
 import org.webmacro.engine.BuildException;
 27  
 import org.webmacro.engine.Builder;
 28  
 
 29  
 import java.util.Vector;
 30  
 
 31  
 /**
 32  
  * DirectiveBuilder manages the building of directives.  It is created
 33  
  * by the parser, which populates it with the directive arguments, and
 34  
  * the DirectiveBuilder.build() method calls the build() method for the
 35  
  * appropriate directive.
 36  
  * @author Brian Goetz
 37  
  */
 38  
 
 39  
 public final class DirectiveBuilder implements Builder, DirectiveArgs
 40  
 {
 41  
 
 42  
     // The descriptor for the directive we're building
 43  
     private final DirectiveDescriptor desc;
 44  
 
 45  
     // The directive arguments
 46  
     private ArgsHolder buildArgs;
 47  
 
 48  
     // This is an array of either ArgsHolders (for nonrepeating subdirectives)
 49  
     // or Vectors of ArgsHolders (for repeating subdirectives)
 50  
     private Object[] subdirectives;
 51  
 
 52  35
     private static final ArgsHolder[] aha = new ArgsHolder[0];
 53  
     private static final String
 54  
             EXC_GETSUBD_NOTREPEATING = "getSubdirective: attempt to get repeating "
 55  
             + "subdirective -- use getRepeatingSubdirective() instead",
 56  
     EXC_GETSUBD_REPEATING = "getRepeatingSubdirective: attempt to get "
 57  
             + "nonrepeating subdirective -- use getSubdirective() instead";
 58  
 
 59  
     public DirectiveBuilder (DirectiveDescriptor desc)
 60  5404
     {
 61  5404
         this.desc = desc;
 62  5404
         if (desc.args != null
 63  
                 && desc.args.length > 0)
 64  5403
             buildArgs = new ArgsHolder(desc.args);
 65  5404
         if (desc.subdirectives != null
 66  
                 && desc.subdirectives.length > 0)
 67  1317
             subdirectives = new Object[desc.subdirectives.length];
 68  5404
     }
 69  
 
 70  
     private int findSubdirectiveIndex (int id)
 71  
             throws BuildException
 72  
     {
 73  6831
         for (int i = 0; i < desc.subdirectives.length; i++)
 74  
         {
 75  6831
             if (desc.subdirectives[i].id == id)
 76  4071
                 return i;
 77  
         }
 78  0
         throw new BuildException("Invalid argument ID " + id
 79  
                 + " requested for directive " + desc.name);
 80  
     }
 81  
 
 82  
     public Object getExactArg (int idx) throws BuildException
 83  
     {
 84  0
         if (buildArgs == null)
 85  0
             return null;
 86  
         else
 87  0
             return buildArgs.getExactArg(idx);
 88  
     }
 89  
 
 90  
     /**
 91  
      * How many arguments does this builder have?
 92  
      */
 93  
     public int getArgCount ()
 94  
     {
 95  0
         if (buildArgs == null)
 96  0
             return 0;
 97  
         else
 98  0
             return buildArgs.getArgCount();
 99  
     }
 100  
 
 101  
     /**
 102  
      * Retrieve the argument whose id is the specified id.
 103  
      */
 104  
     public Object getArg (int argId)
 105  
             throws BuildException
 106  
     {
 107  507
         if (buildArgs == null)
 108  0
             return null;
 109  
         else
 110  507
             return buildArgs.getArg(argId);
 111  
     }
 112  
 
 113  
     /**
 114  
      * Retrieve the argument whose id is the specified id, and if it is a
 115  
      * Builder, build it with the specified build context.
 116  
      */
 117  
     public Object getArg (int argId, BuildContext bc)
 118  
             throws BuildException
 119  
     {
 120  14207
         if (buildArgs == null)
 121  0
             return null;  // FIXME Should throw exception here, as non-null branch does
 122  
         else
 123  14207
             return buildArgs.getArg(argId, bc);
 124  
     }
 125  
 
 126  
     /**
 127  
      * Find out how many subdirectives of the specified id were present.
 128  
      */
 129  
     public int getSubdirectiveCount (int subdId)
 130  
             throws BuildException
 131  
     {
 132  0
         int i = findSubdirectiveIndex(subdId);
 133  0
         if (subdirectives[i] == null)
 134  0
             return 0;
 135  
         else
 136  0
             return (desc.subdirectives[i].repeating)
 137  
                     ? ((ArgsHolder[]) (subdirectives[i])).length
 138  
                     : 1;
 139  
     }
 140  
 
 141  
     /**
 142  
      * Set the argument whose id is the specified id.  If the argument has
 143  
      * already been set, it is overwritten.  Generally not used by directives,
 144  
      * only used by the parser.
 145  
      */
 146  
     public void setArg (int argId, Object arg)
 147  
             throws BuildException
 148  
     {
 149  14743
         buildArgs.setArg(argId, arg);
 150  14743
     }
 151  
 
 152  
     /**
 153  
      * Create a new subdirective of the specified id and create an ArgsHolder
 154  
      * for its arguments.  Not used by directives.
 155  
      */
 156  
     public DirectiveArgs newSubdirective (int subdId)
 157  
             throws BuildException
 158  
     {
 159  810
         ArgsHolder ah = null;
 160  810
         int index = findSubdirectiveIndex(subdId);
 161  810
         if (!desc.subdirectives[index].repeating)
 162  
         {
 163  767
             if (subdirectives[index] == null)
 164  767
                 subdirectives[index] = new ArgsHolder(desc.subdirectives[index].args);
 165  767
             ah = (ArgsHolder) subdirectives[index];
 166  
         }
 167  
         else
 168  
         {
 169  
             Vector v;
 170  43
             if (subdirectives[index] == null)
 171  43
                 subdirectives[index] = new Vector();
 172  43
             v = (Vector) subdirectives[index];
 173  43
             ah = new ArgsHolder(desc.subdirectives[index].args);
 174  43
             v.addElement(ah);
 175  
         }
 176  
 
 177  810
         return ah;
 178  
     }
 179  
 
 180  
     /**
 181  
      * Check to see if the specified subdirective is OK at this point.
 182  
      * The only reason it wouldn't be is because we've already got one
 183  
      * and its not a repeating subdirective
 184  
      */
 185  
     public boolean subdirectiveOk (int subdId) throws BuildException
 186  
     {
 187  811
         int index = findSubdirectiveIndex(subdId);
 188  811
         return desc.subdirectives[index].repeating || subdirectives[index] == null;
 189  
     }
 190  
 
 191  
     /**
 192  
      * Retrieves the ArgsHolder for the associated subdirective so that the
 193  
      * subdirective arguments can be retrieved.  Only valid if the specified
 194  
      * subdirective is not repeating.
 195  
      */
 196  
     public ArgsHolder getSubdirective (int subdId)
 197  
             throws BuildException
 198  
     {
 199  1225
         int index = findSubdirectiveIndex(subdId);
 200  1225
         if (desc.subdirectives[index].repeating)
 201  0
             throw new BuildException(EXC_GETSUBD_NOTREPEATING);
 202  1225
         return (ArgsHolder) subdirectives[index];
 203  
     }
 204  
 
 205  
     /**
 206  
      * Retrieves an array of ArgsHolders for the associated subdirective
 207  
      * so that the subdirective arguments can be retrieved.  Only valid
 208  
      * if the specified subdirective is repeating.
 209  
      */
 210  
     public ArgsHolder[] getRepeatingSubdirective (int subdId)
 211  
             throws BuildException
 212  
     {
 213  1225
         int index = findSubdirectiveIndex(subdId);
 214  1225
         if (!desc.subdirectives[index].repeating)
 215  0
             throw new BuildException(EXC_GETSUBD_REPEATING);
 216  1225
         if (subdirectives[index] == null)
 217  1182
             return null;
 218  
         else
 219  43
             return (ArgsHolder[]) ((Vector) subdirectives[index]).toArray(aha);
 220  
     }
 221  
 
 222  
     /**
 223  
      * Build the directive.  Calls the build() method of the directive.
 224  
      */
 225  
     public Object build (BuildContext bc) throws BuildException
 226  
     {
 227  
         Directive d;
 228  
         try
 229  
         {
 230  5394
             d = (Directive) desc.dirClass.newInstance();
 231  
         }
 232  0
         catch (Exception e)
 233  
         {
 234  0
             throw new BuildException("Error instantiating Directive object for #"
 235  
                     + desc.name);
 236  5394
         }
 237  
         ;
 238  5394
         return d.build(this, bc);
 239  
     }
 240  
 
 241  
     /**
 242  
      * Get the name this directive was registered as
 243  
      */
 244  
     public String getName ()
 245  
     {
 246  891
         return desc.name;
 247  
     }
 248  
 }
 249  
 
 250  
 
 251