Coverage Report - com.ccg.macros.at.Script
 
Classes in this File Line Coverage Branch Coverage Complexity
Script
1% 
0% 
7.833
 
 1  
 /*----------------------------------------------------------------
 2  
  * $Id: Script.java,v 1.1.1.1 2005/06/08 02:40:48 pkb Exp $
 3  
  * 
 4  
  * (c)2001 - Paul Blankenbaker */
 5  
 //----------------------------------------------------------------
 6  
 
 7  
 package com.ccg.macros.at;
 8  
 
 9  
 import com.ccg.macros.*;
 10  
 import com.ccg.io.*;
 11  
 import com.ccg.util.*;
 12  
 
 13  
 import java.io.*;
 14  
 import java.util.Vector;
 15  
 
 16  
 
 17  
 //----------------------------------------------------------------
 18  
 /** <b>&#064;macros</b> useful for "script" style processing.
 19  
  * 
 20  
  * @version $Revision: 1.1.1.1 $
 21  
  * 
 22  
  * @since 1.0
 23  
  * 
 24  
  * @author $Author: pkb $ */
 25  
 //----------------------------------------------------------------
 26  
 
 27  
 public class Script extends Base {
 28  
 
 29  
   //----------------------------------------------------------------
 30  
   /** Constructs the object and readies it for {@link #install installation}.
 31  
    * 
 32  
    * @since        1.0
 33  
    * 
 34  
    * @see #install */
 35  
   //----------------------------------------------------------------
 36  
 
 37  
   public Script() {
 38  4
     super(false);
 39  4
   }
 40  
 
 41  
 
 42  
   //----------------------------------------------------------------
 43  
   /** &#064;loadTSV(NAME,SOURCE) load a tab separated table.
 44  
    * 
 45  
    * <p>This macro is used to load the definition of a tab separated
 46  
    * table. It doesn't actually read the contents of the database
 47  
    * immediately, instead it defines a new macro named "NAME" and
 48  
    * associates a SOURCE (typically a file or URL) where we should
 49  
    * fetch the data from.
 50  
    *
 51  
    * <p>When you want to insert the data of the table into your
 52  
    * output, you then use the "@NAME(FORMAT)" macro to read each line
 53  
    * from the table and FORMAT the output of the table.
 54  
    *
 55  
    * <p>For example, if one created a table named {@link
 56  
    * <a href=doc-files/phone.tsv>phone.tsv</a>} like the following:
 57  
    *
 58  
 <pre>
 59  
 Last        First        Phone
 60  
 Blankenbaker        Paul        555-555-5555
 61  
 Brown        Megan        555-555-5555
 62  
 </pre>
 63  
    *
 64  
    * <p>And you used the following macros:
 65  
    *
 66  
    * <pre>
 67  
    * &#064;loadTSV("phoneTable","{@link <a href=doc-files/phone.tsv>phone.tsv</a>}")
 68  
    * &#064;phoneTable("@phoneTableF(1),@phoneTableF(0),@phoneTableF(2)\n")
 69  
    * </pre>
 70  
    *
 71  
    * <p>This will result in the output of one blank line followed by a
 72  
    * comma seaparated list of just the data fields. This is shown below:
 73  
    *
 74  
    * <pre>
 75  
    *
 76  
    * Paul,Blankenbaker,555-555-5555
 77  
    * Megan,Brown,555-555-5555
 78  
    * </pre>
 79  
    *
 80  
    * <p>In the example, you'll notice that the macro used to process
 81  
    * the table was called <b>&#064;phoneTable</b>. When we used this
 82  
    * macro, we accessed the specific columns within the table using a
 83  
    * new macro <b>&#064;phoneTableF(COL)</b>. This macro is defined
 84  
    * while processing each row of the table and allows one to access
 85  
    * the column fields within a row of the table. You can specify the
 86  
    * column either by its number (where 0 is the left most column), or
 87  
    * it column heading. Using column headings to pull information from
 88  
    * the table, we would have written the following:
 89  
    *
 90  
    * <pre>
 91  
    * &#064;loadTSV("phoneTable","{@link <a href=doc-files/phone.tsv>phone.tsv</a>}")
 92  
    * &#064;phoneTable("@phoneTableF("First"),@phoneTableF("Last"),@phoneTableF("Phone")\n")
 93  
    * </pre>
 94  
    *
 95  
    * <p>If you are producing HTML, you can use the table formatting
 96  
    * tags to nicely format your table data.
 97  
    * 
 98  
    * @param        out
 99  
    * 
 100  
    *         The {@link Output output device} to write the results of
 101  
    *         processing the argument to.
 102  
    * 
 103  
    * @param        args
 104  
    * 
 105  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 106  
    * 
 107  
    * @throws        IOException
 108  
    * 
 109  
    *         If there is a problem writing to the {@link Output output device}
 110  
    * 
 111  
    * @throws        InterpretException
 112  
    * 
 113  
    *         If a problem is encountered interpretting the arguments passed.
 114  
    * 
 115  
    * @since        1.0 */
 116  
   //----------------------------------------------------------------
 117  
 
 118  
   public void loadTSV(Output out, Vector args) 
 119  
     throws IOException, InterpretException {
 120  
 
 121  0
     if (args.size() < 2) {
 122  0
       throw new InterpretException("@loadTSV(NAME,SOURCE) requires "+
 123  
                                    "two arguments.");
 124  
     }
 125  
 
 126  0
     AtMacros am = getAtMacros();
 127  0
     String name = am.interpretCheck(args.elementAt(0).toString());
 128  0
     String source = am.interpretCheck(args.elementAt(1).toString());
 129  
 
 130  0
     if ((name == null) || (source == null) ||
 131  
         (name.length() == 0) || (source.length() == 0)) {
 132  0
       throw new InterpretException("null argument passed to "+
 133  
                                    "@loadTSV(NAME,SOURCE)");
 134  
     }
 135  
 
 136  0
     am.addMacro(name,new TableInsert(am,name,source));
 137  0
   }
 138  
 
 139  
 
 140  
   //----------------------------------------------------------------
 141  
   /** &#064;copyToDir(MATCH0,MATCH1,&#046;&#046;&#046;,DIR) copy one or
 142  
    * more files to directory.
 143  
    * 
 144  
    * <p>This macro is used to copy 0 or more existing files to a
 145  
    * output directory. If the directory doesn't exist, it will be
 146  
    * created. You may use the "*" as a wildcard in each of the file
 147  
    * name strings to match more than one file.
 148  
    *
 149  
    * <p>For example, to copy the ".at" and "*.properties" files from
 150  
    * the "/etc/macros" directory to the "/home/user/etc/macros"
 151  
    * directory, one could use the following:
 152  
    *
 153  
 <pre>
 154  
 &#064;defnow("sdir","/etc/macros")
 155  
 &#064;copyToDir("@sdir()/*.at","@sdir()/*.properties","/home/user/etc/macros")
 156  
 </pre>
 157  
    *
 158  
    * @param        out
 159  
    * 
 160  
    *         The {@link Output output device} to write the results of
 161  
    *         processing the argument to.
 162  
    * 
 163  
    * @param        args
 164  
    * 
 165  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 166  
    * 
 167  
    * @throws        IOException
 168  
    * 
 169  
    *         If there is a problem writing to the {@link Output output device}
 170  
    * 
 171  
    * @throws        InterpretException
 172  
    * 
 173  
    *         If a problem is encountered interpretting the arguments passed.
 174  
    * 
 175  
    * @since        1.0 */
 176  
   //----------------------------------------------------------------
 177  
 
 178  
   public void copyToDir(Output out, Vector args) 
 179  
     throws IOException, InterpretException {
 180  
 
 181  0
     int argc = args.size();
 182  0
     if (argc < 2) return;        // must have at least two arguments
 183  
 
 184  0
     argc--;                        // last argument is the output directory
 185  
     
 186  
                                 // get output directory
 187  0
     AtMacros am = getAtMacros();
 188  0
     String dstStr = am.interpretCheck(args.elementAt(argc).toString());
 189  
 
 190  0
     File dst = new File(FileName.fixSlashes(dstStr));
 191  
                                 // try to create directory - if it
 192  
                                 // doesn't exist
 193  0
     if (!dst.isDirectory()) {
 194  0
       dst.mkdirs();
 195  0
       if (!dst.isDirectory()) {
 196  0
         throw new IOException("unable to create directory \""+dst+"\"");
 197  
       }
 198  
     }
 199  
 
 200  0
     PrintWriterString pws = PrintWriterString.create();
 201  
 
 202  
                                 // now, process each of the wild-card
 203  
                                 // file name strings
 204  0
     for (int i = 0; i < argc; i++) {
 205  0
       String match = am.interpretCheck(args.elementAt(i).toString());
 206  0
       String[] list = FilenameFilterWild.list(FileName.fixSlashes(match));
 207  0
       if (list != null) for (int j = 0; j < list.length; j++) {
 208  0
         File src = new File(list[j]);
 209  
                                 // only copy existing normal files
 210  0
         if (src.exists() && src.isFile()) {
 211  0
           File ofile = new File(dst,src.getName());
 212  
 
 213  0
           pws.print("Copy:");
 214  0
           pws.print(src);
 215  0
           pws.print("  to:");
 216  0
           pws.println(dst);
 217  0
           Copy.fileToFile(src,ofile);
 218  0
         }
 219  0
         else if (Debug.ENABLED && Debug.isEnabledFor(3)) {
 220  0
           pws.print("Skip:");
 221  0
           pws.println(src);
 222  
         }
 223  
       }
 224  
     }
 225  
 
 226  0
     out.write(pws);
 227  0
   }
 228  
 
 229  
 
 230  
   //----------------------------------------------------------------
 231  
   /** &#064;atCopyToDir(MATCH0,MATCH1,&#046;&#046;&#046;,DIR) copy AND
 232  
    * interpret one or more files to directory.
 233  
    * 
 234  
    * <p>This macro is used to copy 0 or more existing files to a
 235  
    * output directory. If the directory doesn't exist, it will be
 236  
    * created. You may use the "*" as a wildcard in each of the file
 237  
    * name strings to match more than one file.
 238  
    *
 239  
    * <p>There is a HUGE difference between this command and the
 240  
    * "&#064;copyToDir". This command interprets each file that it
 241  
    * copies and evaluates any "&#064macros" which it contains. This
 242  
    * can be a VERY useful way to install HTML documents to their final
 243  
    * location and do some subsitutions during the installation process.
 244  
    *
 245  
    * <p>It should be noted that any definitions (or redefinitions)
 246  
    * made by the files processed WILL AFFECT all subsequent files
 247  
    * processed (I may add a version of this macro which saves/restores
 248  
    * the macros for each file processed).
 249  
    *
 250  
    * <p>To see the power of this function, take a look at the {@link
 251  
    * <a href=doc-files/atcopy.atmacros>atcopy.atmacros</a>}
 252  
    * "script". It does the following:
 253  
    *
 254  
    * <ul>
 255  
    *
 256  
    * <li>Makes some of its own definitions.</li>
 257  
    *
 258  
    * <li>Loads a set of definitions ({@link
 259  
    * <a href=doc-files/htmlmemo.atmacros>htmlmemo.atmacros</a>}).</li>
 260  
    *
 261  
    * <li>Then copies a set of HTML documents (both {@link
 262  
    * <a href=doc-files/memo1.html>memo1.html</a>} and  {@link
 263  
    * <a href=doc-files/memo2.html>memo2.html</a>}) using the defined macros.
 264  
    *
 265  
    * </ul>
 266  
    *
 267  
    * <p>If you have the source code installed such that the "ccg" top
 268  
    * level directory can be found under the "$COMHOME" environment
 269  
    * variable, you should be able to try this out via:
 270  
    *
 271  
    * <pre>
 272  
    * java {@link At com.ccg.macros.At} -Dcomhome=$COMHOME -Dhtmlroot=$HOME/public_html \
 273  
    *   -in {@link <a href=doc-files/atcopy.atmacros>$COMHOME/ccg/macros/doc-files/atcopy.atmacros</a>}
 274  
    * </pre>
 275  
    *
 276  
    * @param        out
 277  
    * 
 278  
    *         The {@link Output output device} to write the results of
 279  
    *         processing the argument to.
 280  
    * 
 281  
    * @param        args
 282  
    * 
 283  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 284  
    * 
 285  
    * @throws        IOException
 286  
    * 
 287  
    *         If there is a problem writing to the {@link Output output device}
 288  
    * 
 289  
    * @throws        InterpretException
 290  
    * 
 291  
    *         If a problem is encountered interpretting the arguments passed.
 292  
    * 
 293  
    * @since        1.0 */
 294  
   //----------------------------------------------------------------
 295  
 
 296  
   public void atCopyToDir(Output out, Vector args) 
 297  
     throws IOException, InterpretException {
 298  
 
 299  0
     int argc = args.size();
 300  0
     if (argc < 2) return;        // must have at least two arguments
 301  
 
 302  0
     argc--;                        // last argument is the output directory
 303  
     
 304  
                                 // get output directory
 305  0
     String dstStr = getStringParameter(args,argc);
 306  
 
 307  0
     File dst = new File(FileName.fixSlashes(dstStr));
 308  
                                 // try to create directory - if it
 309  
                                 // doesn't exist
 310  0
     if (!dst.isDirectory()) {
 311  0
       dst.mkdirs();
 312  0
       if (!dst.isDirectory()) {
 313  0
         throw new IOException("unable to create directory \""+dst+"\"");
 314  
       }
 315  
     }
 316  
 
 317  0
     PrintWriterString pws = PrintWriterString.create();
 318  
 
 319  
                                 // now, process each of the wild-card
 320  
                                 // file name strings
 321  0
     for (int i = 0; i < argc; i++) {
 322  0
       String match = getStringParameter(args,i);
 323  0
       String[] list = FilenameFilterWild.list(FileName.fixSlashes(match));
 324  
       
 325  0
           if (Debug.ENABLED && Debug.isEnabledFor(3)) {
 326  0
             int cnt = 0;
 327  0
             if (null != list) {
 328  0
               cnt = list.length;
 329  
             }
 330  0
             pws.println("Matched: " + cnt + " files via: \"" + match + "\"");
 331  
           }
 332  
 
 333  0
           if (list != null) for (int j = 0; j < list.length; j++) {
 334  0
             File src = new File(list[j]);
 335  
                                 // only copy existing normal files
 336  0
             if (src.exists() && src.isFile()) {
 337  0
               File ofile = new File(dst,src.getName());
 338  
 
 339  0
               pws.print("Interpret[" + j + "]:");
 340  0
               pws.print(src);
 341  0
               pws.print("  to:");
 342  0
               pws.println(dst);
 343  
 
 344  0
               if (Debug.ENABLED && Debug.isEnabledFor(3)) {
 345  0
                 Debug.out("Interpret:" + src + "  to:" + dst);
 346  
               }
 347  
 
 348  0
               OutputWriter ow = new OutputWriter(ofile);
 349  0
               InputReader ir = new InputReader(src);
 350  
 
 351  
                                 // and copy/interpret the files
 352  0
               getAtMacros().interpretCheck(ir,ow);
 353  0
               ow.close();                // don't forget to close (to flush out data)
 354  0
             } else if (Debug.ENABLED && Debug.isEnabledFor(3)) {
 355  0
               pws.print("Skip:");
 356  0
               pws.println(src);
 357  
             }
 358  
       }
 359  
     }
 360  
 
 361  0
     out.write(pws);
 362  0
   }
 363  
 
 364  
 
 365  
   //----------------------------------------------------------------
 366  
   /** &#064;atCopyFile(SRC,DST) copy AND interpret one file to another.
 367  
    * 
 368  
    * <p>This macro is used to copy exactly one file from one location
 369  
    * to another. If the DST is a directory, then the same file name
 370  
    * will be preserved, if DST does not include a directory, then the
 371  
    * same directory as the SRC will be assumed. The final DST must not
 372  
    * be the same as the SRC (or we will report an error and skip the
 373  
    * copy). If the destination directory doesn't exist, it will be
 374  
    * created.
 375  
    *
 376  
    * <p>There is a HUGE difference between this command and the
 377  
    * "&#064;copyFile". This command interprets each file that it
 378  
    * copies and evaluates any "&#064macros" which it contains. This
 379  
    * can be a VERY useful way to install HTML (or other text)
 380  
    * documents to their final location and do some subsitutions during
 381  
    * the installation process.
 382  
    *
 383  
    * <p>It should be noted that any definitions (or redefinitions)
 384  
    * made by the files processed WILL AFFECT all subsequent files
 385  
    * processed (I may add a version of this macro which saves/restores
 386  
    * the macros for each file processed).
 387  
    *
 388  
    * @param        out
 389  
    * 
 390  
    *         The {@link Output output device} to write the results of
 391  
    *         processing the argument to.
 392  
    * 
 393  
    * @param        args
 394  
    * 
 395  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 396  
    * 
 397  
    * @throws        IOException
 398  
    * 
 399  
    *         If there is a problem writing to the {@link Output output device}
 400  
    * 
 401  
    * @throws        InterpretException
 402  
    * 
 403  
    *         If a problem is encountered interpretting the arguments passed.
 404  
    * 
 405  
    * @since        1.0 */
 406  
   //----------------------------------------------------------------
 407  
 
 408  
   public void atCopyFile(Output out, Vector args) 
 409  
     throws IOException, InterpretException {
 410  
 
 411  0
     int argc = args.size();
 412  0
     if (argc != 2) {
 413  0
       throw new InterpretException("@atCopyToDir(SRC,DST) - "+
 414  
                                    "requires exactly 2 parameters");
 415  
     }
 416  
 
 417  0
     String srcStr = FileName.fixSlashes(getStringParameter(args,0));
 418  0
     String dstStr = FileName.fixSlashes(getStringParameter(args,1));
 419  
 
 420  0
     File src = new File(srcStr);
 421  0
     InputStream isrc = null;
 422  0
     if (!src.isFile()) {
 423  0
       isrc = com.ccg.io.Utility.getInputStream(srcStr);
 424  0
       if (isrc == null) {
 425  0
         throw new IOException("\""+srcStr+"\" is not a readable file");
 426  
       }
 427  
     }
 428  
 
 429  0
     File dst = new File(dstStr);
 430  0
     File dstDir = dst.getParentFile();
 431  0
     if (dstDir == null) {
 432  0
       dstDir = src.getParentFile();
 433  0
       if (dstDir != null) dst = new File(dstDir,dstStr);
 434  
     }
 435  0
     else if (dst.isDirectory()) {
 436  0
       dstDir = dst;
 437  0
       dst = new File(dstDir,dstStr);
 438  
     }
 439  
 
 440  0
     if ((src != null) && dst.equals(src)) {
 441  0
       throw new IOException("source & destination files are both \""+src+"\"");
 442  
     }
 443  
 
 444  
                                 // try to create directory - if it
 445  
                                 // doesn't exist
 446  0
     if (!dstDir.isDirectory()) {
 447  0
       dstDir.mkdirs();
 448  0
       if (!dstDir.isDirectory()) {
 449  0
         throw new IOException("unable to create directory \""+dstDir+"\"");
 450  
       }
 451  
     }
 452  
 
 453  0
     if (Debug.ENABLED && Debug.isEnabledFor(3)) {
 454  0
       Debug.out("Interpret copy from \""+srcStr+"\" to \""+dst+"\"");
 455  
     }
 456  
 
 457  0
     OutputWriter ow = null;
 458  0
     InputReader ir = null;
 459  
     try {
 460  0
       ow = new OutputWriter(dst);
 461  0
       if (isrc != null) {
 462  0
         ir = new InputReader(isrc);
 463  0
       }
 464  
       else {
 465  0
         ir = new InputReader(src);
 466  
       }
 467  
                                 // and copy/interpret the files
 468  0
       getAtMacros().interpretCheck(ir,ow);
 469  
     } finally {
 470  0
       if (ow != null) try { ow.close(); } catch (Throwable t) { }
 471  0
       if (ir != null) try { ir.close(); } catch (Throwable t) { }
 472  0
     }
 473  
 
 474  0
     if (Debug.ENABLED && Debug.isEnabledFor(3)) {
 475  0
       Debug.out("Successfully processed \""+srcStr+"\" to \""+dst+"\"");
 476  
     }
 477  0
   }
 478  
 
 479  
 
 480  
   //----------------------------------------------------------------
 481  
   /** &#064;copyFile(SRC,DST) copy one file to another.
 482  
    * 
 483  
    * <p>This macro is used to copy exactly one file from one location
 484  
    * to another. If the DST is a directory, then the same file name
 485  
    * will be preserved, if DST does not include a directory, then the
 486  
    * same directory as the SRC will be assumed. The final DST must not
 487  
    * be the same as the SRC (or we will report an error and skip the
 488  
    * copy). If the destination directory doesn't exist, it will be
 489  
    * created.
 490  
    *
 491  
    * <p>There is a HUGE difference between this command and the
 492  
    * "&#064;atCopyFile". This command does no interpretation (it
 493  
    * simply copies the bytes from the source file to the destination
 494  
    * file). This makes it well suited for transferring images (or any
 495  
    * file where interpretation of the file contents doesn't make
 496  
    * sense).
 497  
    *
 498  
    * @param        out
 499  
    * 
 500  
    *         The {@link Output output device} to write the results of
 501  
    *         processing the argument to.
 502  
    * 
 503  
    * @param        args
 504  
    * 
 505  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 506  
    * 
 507  
    * @throws        IOException
 508  
    * 
 509  
    *         If there is a problem writing to the {@link Output output device}
 510  
    * 
 511  
    * @throws        InterpretException
 512  
    * 
 513  
    *         If a problem is encountered interpretting the arguments passed.
 514  
    * 
 515  
    * @since        1.0 */
 516  
   //----------------------------------------------------------------
 517  
 
 518  
   public void copyFile(Output out, Vector args) 
 519  
     throws IOException, InterpretException {
 520  
 
 521  0
     int argc = args.size();
 522  0
     if (argc != 2) {
 523  0
       throw new InterpretException("@copyToDir(SRC,DST) - "+
 524  
                                    "requires exactly 2 parameters");
 525  
     }
 526  
     
 527  0
     String srcStr = FileName.fixSlashes(getStringParameter(args,0));
 528  0
     String dstStr = FileName.fixSlashes(getStringParameter(args,1));
 529  
 
 530  0
     File src = new File(srcStr);
 531  0
     if (!src.isFile()) {
 532  0
       throw new IOException("\""+src+"\" is not a readable file");
 533  
     }
 534  
 
 535  0
     File dst = new File(dstStr);
 536  0
     File dstDir = dst.getParentFile();
 537  0
     if (dstDir == null) {
 538  0
       dstDir = src.getParentFile();
 539  0
       if (dstDir != null) dst = new File(dstDir,dstStr);
 540  
     }
 541  0
     else if (dst.isDirectory()) {
 542  0
       dstDir = dst;
 543  0
       dst = new File(dstDir,dstStr);
 544  
     }
 545  
 
 546  0
     if (dst.equals(src)) {
 547  0
       throw new IOException("source & destination files are both \""+src+"\"");
 548  
     }
 549  
 
 550  
                                 // try to create directory - if it
 551  
                                 // doesn't exist
 552  0
     if (!dstDir.isDirectory()) {
 553  0
       dstDir.mkdirs();
 554  0
       if (!dstDir.isDirectory()) {
 555  0
         throw new IOException("unable to create directory \""+dstDir+"\"");
 556  
       }
 557  
     }
 558  
 
 559  0
     if (Debug.ENABLED && Debug.isEnabledFor(3)) {
 560  0
       Debug.out("About to copy \""+src+"\" to \""+dst+"\"");
 561  
     }
 562  
 
 563  0
     Copy.fileToFile(src,dst);
 564  
 
 565  0
     if (Debug.ENABLED && Debug.isEnabledFor(3)) {
 566  0
       Debug.out("Successfully copied \""+src+"\" to \""+dst+"\"");
 567  
     }
 568  0
   }
 569  
 
 570  
 
 571  
   //----------------------------------------------------------------
 572  
   /** &#064;ifFileExists(NAME,IF_EXISTS,IF_NOT) determine if file exists.
 573  
    * 
 574  
    * <p>This macro is used to make a decistion based upon whether a
 575  
    * file exists or not. If the file specified byte <b>NAME</b>
 576  
    * exists, then the <b>IF_EXISTS</b> clause is evaluated. If not,
 577  
    * then the <b>IF_NOT</b> clause is evaluated.</p>
 578  
    *
 579  
    * @param        out
 580  
    * 
 581  
    *         The {@link Output output device} to write the results of
 582  
    *         processing the argument to.
 583  
    * 
 584  
    * @param        args
 585  
    * 
 586  
    *         A {@link Vector vector} of arguments which were passed to the macro.
 587  
    * 
 588  
    * @throws        IOException
 589  
    * 
 590  
    *         If there is a problem writing to the {@link Output output device}
 591  
    * 
 592  
    * @throws        InterpretException
 593  
    * 
 594  
    *         If a problem is encountered interpretting the arguments passed.
 595  
    * 
 596  
    * @since        1.0 */
 597  
   //----------------------------------------------------------------
 598  
 
 599  
   public void ifFileExists(Output out, Vector args) 
 600  
     throws IOException, InterpretException {
 601  
 
 602  0
     int argc = args.size();
 603  0
     if ((argc != 2) && (argc != 3)) {
 604  0
       throw new InterpretException("@ifFileExists(NAME,IF_EXIST,IFNOT) - "+
 605  
                                    "requires 2 or 3 parameters");
 606  
     }
 607  
     
 608  
                                 // get output directory
 609  0
     AtMacros am = getAtMacros();
 610  
 
 611  0
     String srcStr = FileName.fixSlashes(getStringParameter(args,0));
 612  0
     File src = new File(srcStr);
 613  
 
 614  0
     if (src.exists()) {
 615  0
       out.write(am.interpretCheck(getStringParameter(args,1)));
 616  0
     }
 617  
     else {
 618  0
       out.write(am.interpretCheck(getStringParameter(args,2)));
 619  
     }
 620  0
   }
 621  
 
 622  
 }
 623  
 
 624  
 
 625  
 //----------------------------------------------------------------  
 626  
 // Helper class(es)
 627  
 //----------------------------------------------------------------
 628  
 
 629  
 
 630  
 //----------------------------------------------------------------  
 631  
 // Helper class to process each row of a data table
 632  
 //----------------------------------------------------------------
 633  
 
 634  
 class TableField implements MacroHandler {
 635  
   private AtMacros _AtMacros;
 636  
   private TableInsert _Table;
 637  
   private String _Name;
 638  
 
 639  
   TableField(AtMacros am, String name, TableInsert ti) {
 640  
     _AtMacros = am;
 641  
     _Table = ti;
 642  
     _Name = name;
 643  
   }
 644  
 
 645  
   public void process(Output out, Vector args)
 646  
     throws IOException, InterpretException {
 647  
     
 648  
     if (args.size() != 1) {
 649  
       throw new InterpretException("Error: @"+_Name+"(FIELD) requires "+
 650  
                                    "one argument");
 651  
     }
 652  
 
 653  
     String val = args.elementAt(0).toString();
 654  
     int index = -1;
 655  
 
 656  
     if (Character.isDigit(val.charAt(0))) try {
 657  
       index = Integer.parseInt(val);
 658  
     } catch (Exception e) { }
 659  
 
 660  
     if (index < 0) index = _Table.getTable().getTableColumn(val);
 661  
 
 662  
     if (index < 0) {
 663  
       throw new InterpretException("Error: @"+_Name+"("+val+") has a "+
 664  
                                    "non-integer index specified");
 665  
     }
 666  
 
 667  
     out.write(_AtMacros.interpretCheck(_Table.getTable().getFieldString(index,"")));
 668  
   }
 669  
 
 670  
 }
 671  
 
 672  
 
 673  
 class TableInsert extends TableProcessor implements MacroHandler {
 674  
 
 675  
   private AtMacros _AtMacros;
 676  
   private String _Source;
 677  
   private String _Name;
 678  
   private String _Format;
 679  
   private Output _Out;
 680  
 
 681  
   TableInsert(AtMacros am, String name, String source) {
 682  
     super(null);
 683  
 
 684  
     _AtMacros = am;
 685  
     _Name = name;
 686  
     _Source = source;
 687  
     _Format = "";
 688  
   }
 689  
 
 690  
 
 691  
   public boolean processData() {
 692  
     try {
 693  
       _Out.write(_AtMacros.interpretCheck(_Format));
 694  
     } catch (Exception ioe) {
 695  
       setDataException(ioe);
 696  
       return false;
 697  
     }
 698  
     return true;
 699  
   }
 700  
 
 701  
 
 702  
   public void process(Output out, Vector args)
 703  
     throws IOException, InterpretException {
 704  
 
 705  
     _Format = "";
 706  
     if (args.size() >= 1) _Format = args.elementAt(0).toString();
 707  
 
 708  
     if (_Format.length() == 0)
 709  
       throw new InterpretException("Error: no FORMAT specified to @"+
 710  
                                    _Name+"(FORMAT)");
 711  
 
 712  
     LineNumberReader lnr =
 713  
       new LineNumberReader(com.ccg.io.Utility.getReader(_Source));
 714  
 
 715  
     setTable(new TextTable());
 716  
 
 717  
     String fmac = _Name+"F";
 718  
 
 719  
     _AtMacros.addMacro(fmac,new TableField(_AtMacros,fmac,this));
 720  
 
 721  
     _Out = out;
 722  
 
 723  
     process(lnr);
 724  
 
 725  
     _AtMacros.addMacro(fmac,(MacroHandler) null);
 726  
 
 727  
     Exception re = getDataException();
 728  
     if (re == null) re = getHeaderException();
 729  
 
 730  
     try {
 731  
       lnr.close();
 732  
     } catch (IOException ioe) {
 733  
       re = ioe;
 734  
     }
 735  
 
 736  
     if (re != null) {
 737  
       if (re instanceof IOException) throw (IOException) re;
 738  
       else throw (InterpretException) re;
 739  
     }
 740  
   }
 741  
 
 742  
 
 743  
 }
 744