| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
| Script |
|
| 7.833333333333333;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>@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 | /** @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 | * @loadTSV("phoneTable","{@link <a href=doc-files/phone.tsv>phone.tsv</a>}") |
|
| 68 | * @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>@phoneTable</b>. When we used this |
|
| 82 | * macro, we accessed the specific columns within the table using a |
|
| 83 | * new macro <b>@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 | * @loadTSV("phoneTable","{@link <a href=doc-files/phone.tsv>phone.tsv</a>}") |
|
| 92 | * @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 | /** @copyToDir(MATCH0,MATCH1,...,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 | @defnow("sdir","/etc/macros") |
|
| 155 | @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 | /** @atCopyToDir(MATCH0,MATCH1,...,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 | * "@copyToDir". This command interprets each file that it |
|
| 241 | * copies and evaluates any "@macros" 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 | /** @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 | * "@copyFile". This command interprets each file that it |
|
| 378 | * copies and evaluates any "@macros" 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 | /** @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 | * "@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 | /** @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 |