View Javadoc

1   /*
2    * $Source: /usr/cvsroot/melati/maven-dsd-plugin/src/main/java/org/melati/poem/prepro/DSD.java,v $
3    * $Revision: 1.70 $
4    *
5    * Copyright (C) 2000 William Chesters
6    *
7    * Part of Melati (http://melati.org), a framework for the rapid
8    * development of clean, maintainable web applications.
9    *
10   * Melati is free software; Permission is granted to copy, distribute
11   * and/or modify this software under the terms either:
12   *
13   * a) the GNU General Public License as published by the Free Software
14   *    Foundation; either version 2 of the License, or (at your option)
15   *    any later version,
16   *
17   *    or
18   *
19   * b) any version of the Melati Software License, as published
20   *    at http://melati.org
21   *
22   * You should have received a copy of the GNU General Public License and
23   * the Melati Software License along with this program;
24   * if not, write to the Free Software Foundation, Inc.,
25   * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
26   * GNU General Public License and visit http://melati.org to obtain the
27   * Melati Software License.
28   *
29   * Feel free to contact the Developers of Melati (http://melati.org),
30   * if you would like to work out a different arrangement than the options
31   * outlined here.  It is our intention to allow Melati to be used by as
32   * wide an audience as possible.
33   *
34   * This program is distributed in the hope that it will be useful,
35   * but WITHOUT ANY WARRANTY; without even the implied warranty of
36   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37   * GNU General Public License for more details.
38   *
39   * Contact details for copyright holder:
40   *
41   *     William Chesters <williamc At paneris.org>
42   *     http://paneris.org/~williamc
43   *     Obrechtstraat 114, 2517VX Den Haag, The Netherlands
44   */
45  
46  package org.melati.poem.prepro;
47  
48  import java.util.Enumeration;
49  import java.util.Vector;
50  import java.io.FileNotFoundException;
51  import java.io.InputStreamReader;
52  import java.io.Writer;
53  import java.io.File;
54  import java.io.FileWriter;
55  import java.io.FileReader;
56  import java.io.BufferedWriter;
57  import java.io.Reader;
58  import java.io.BufferedReader;
59  import java.io.StreamTokenizer;
60  import java.io.IOException;
61  
62  /**
63   * The <code>DSD</code> class is an application which parses a DSD
64   * (Data Structure Definition) file and outputs Java code, creating
65   * a POEM view of a database.
66   * <p>
67   * The generated files are placed in the current directory, which is
68   * assumed to be similar to <code>org/paneris/myapp/model/</code> and
69   * also in a new directory below it called <code>generated</code>.
70   * 
71   * If a file with the same name as a file that is about to be generated already exists, 
72   * then the file is checked for the presence of a magic string. If the string is present 
73   * then the file is replaced.
74   *
75   * @author  William Chesters
76   */
77  
78  public class DSD {
79  
80    static final String autogenStamp =
81    "// Do not edit this file!  " +
82    "It was generated by Melati POEM's DSD preprocessor.";
83    
84    static final String deleteMe = "// Delete this line to prevent overwriting of this file";
85  
86    private final Vector<String> packageComponents = new Vector<String>();
87    final String packageName;
88    private final File dsdFile, dsdDir, dsdDirGen;
89    private final String name;
90    final String databaseClassName, databaseBaseClassName;
91    final String databaseTablesClassName, databaseTablesBaseClassName;
92    /** The project name*/
93    final String projectName;
94    TableNamingStore tableNamingStore;
95  
96    /* All tables defined in this DSD */
97    final Vector<TableDef> tablesInPackage = new Vector<TableDef>();
98  
99    /* All tables defined in this, and any imported, DSDs including Poem.dsd */
100   final Vector<TableDef> tablesInDatabase = new Vector<TableDef>();
101 
102   /* A list of imported DSDs */
103   final Vector<DSD> importedDSDs = new Vector<DSD>();
104 
105   public boolean hasAnExtenedTable;
106 
107   static void expect(StreamTokenizer tokens, String what)
108                                       throws ParsingDSDException {
109     if (tokens.ttype != StreamTokenizer.TT_WORD || !tokens.sval.equals(what))
110       throw new ParsingDSDException(what, tokens);
111   }
112 
113   static void expect(StreamTokenizer tokens, char what)
114                                       throws ParsingDSDException {
115     if (tokens.ttype != what)
116       throw new ParsingDSDException("" + what, tokens);
117   }
118 
119  /**
120   * Constructor.
121   *
122   * @param file  the name of the DSD file to open
123   * @throws ResourceNotFoundException
124   *    if a DSD file cannot be found
125   * @throws ParsingDSDException
126   *    if an unexpected token is encountered
127   * @throws IllegalityException
128   *    if a semantic incoherence is detected
129   * @throws IOException
130   *    if a problem with the file system is encountered
131   */
132   public DSD(String file) throws IOException, ParsingDSDException,
133                             IllegalityException, ResourceNotFoundException {
134     this(file, new TableNamingStore(), true);
135   }
136 
137  /**
138   * Constructor.
139   *
140   * @param file  the name of the DSD file to open
141   * @param names a {@link TableNamingStore} containing names encountered so far
142   * @param includePoem whether to include the Poem tables
143   * @throws ResourceNotFoundException
144   *    if a DSD file cannot be found
145   * @throws ParsingDSDException
146   *    if an unexpected token is encountered
147   * @throws IllegalityException
148   *    if a semantic incoherence is detected
149   * @throws IOException
150   *    if a problem with the file system is encountered
151   */
152   public DSD(String file, TableNamingStore names, boolean includePoem)
153       throws ResourceNotFoundException, ParsingDSDException,
154              IllegalityException, IOException {
155     tableNamingStore = names;
156     dsdFile = new File(file);
157     String dsdFileName = dsdFile.getName();
158     int dot = dsdFileName.lastIndexOf('.');
159     name = dot == -1 ? dsdFileName : dsdFileName.substring(0, dot);
160 
161     projectName = StringUtils.capitalised(name);
162     databaseClassName = projectName + "Database";
163     databaseBaseClassName = projectName + "DatabaseBase";
164     databaseTablesClassName = projectName + "DatabaseTables";
165     databaseTablesBaseClassName = projectName + "DatabaseTablesBase";
166     dsdDir = new File(new File(dsdFile.getAbsolutePath()).getParent());
167     dsdDirGen = new File(
168                   dsdDir.getAbsolutePath() + File.separator + "generated");
169 
170     /* Read in the default Poem tables, if appropriate */
171     if (includePoem && !"Poem".equals(projectName)) {
172       DSD poemDSD = new DSD(filePath("org.melati.poem.Poem.dsd"),
173                             tableNamingStore, false);
174       Vector <TableDef>poemTables = poemDSD.tablesInPackage;
175       for(int i = 0; i < poemTables.size(); i++)
176         tablesInDatabase.addElement(poemTables.elementAt(i));
177     }
178     Reader reader = null;
179     try {
180       reader = new BufferedReader(new FileReader(file));
181     } catch (FileNotFoundException e) {
182       if (file.indexOf("!") != -1) {
183         String resourceName = file.substring(file.indexOf("!") + 2);
184         reader = new BufferedReader(
185                    new InputStreamReader(Thread.currentThread()
186                         .getContextClassLoader()
187                           .getResourceAsStream(resourceName)));
188       } else
189         throw e;
190     }
191     try {
192       StreamTokenizer tokens = new StreamTokenizer(reader);
193       tokens.slashSlashComments(true);
194       tokens.slashStarComments(true);
195       tokens.wordChars('_', '_');
196 
197       tokens.nextToken();
198       expect(tokens, "package");
199 
200       StringBuffer packageBuffer = new StringBuffer();
201       for (;;) {
202         if (tokens.nextToken() != StreamTokenizer.TT_WORD)
203           throw new ParsingDSDException("<package component>", tokens);
204         packageComponents.addElement(tokens.sval);
205         packageBuffer.append(tokens.sval);
206         if (tokens.nextToken() != '.') break;
207         packageBuffer.append('.');
208       }
209       packageName = packageBuffer.toString();
210 
211       expect(tokens, ';');
212       tokens.nextToken();
213 
214       /* Read in imported databases */
215       while (tokens.ttype != StreamTokenizer.TT_EOF) {
216 
217         if (!tokens.sval.equals("import"))
218           break;
219 
220         if (tokens.nextToken() != StreamTokenizer.TT_WORD)
221           throw new ParsingDSDException("<import component>", tokens);
222 
223         String importDSD = tokens.sval;
224         tokens.nextToken();
225         expect(tokens, ';');
226         tokens.nextToken();
227 
228         DSD dsd = new DSD(filePath(importDSD), tableNamingStore, false);
229         importedDSDs.addElement(dsd);
230 
231         Vector<TableDef> packageTables = dsd.tablesInPackage;
232         for(int i = 0; i < packageTables.size(); i++)
233           tablesInDatabase.addElement(packageTables.elementAt(i));
234       }
235 
236       /* Read in tables */
237       for (int t = 0; tokens.ttype != StreamTokenizer.TT_EOF; ++t) {
238         boolean isAbstract;
239 
240         if (tokens.ttype != StreamTokenizer.TT_WORD)
241           throw new ParsingDSDException("table", tokens);
242 
243         if (tokens.sval.equals("abstract")) {
244           isAbstract = true;
245           tokens.nextToken();
246         } else
247           isAbstract = false;
248 
249         expect(tokens, "table");
250 
251         tokens.nextToken();
252         TableDef table = new TableDef(this, tokens, t, isAbstract, tableNamingStore);
253         tablesInPackage.addElement(table);
254         tablesInDatabase.addElement(table);
255       }
256     } finally {
257       reader.close();
258     }
259 
260   }
261 
262   void createJava(String nameP, Generator proc, boolean overwrite)
263       throws IOException {
264     if (!dsdDirGen.exists()) {
265       dsdDirGen.mkdir();
266     }
267     File f = null;
268     // FIXME flag tied to directory
269     if (overwrite) {
270       f = new File(dsdDirGen, nameP + ".java");
271     } else {
272       f = new File(dsdDir, nameP + ".java");
273     }
274     if (f.exists())
275       if (overwrite) { // FIXME Nasty - overwrite here meaning generating base package
276         if(containsText(f, autogenStamp))
277           System.err.println("Replacing " + f);
278         else
279           throw new TargetExistsDSDException(f);
280       } else {
281         if (containsText(f, deleteMe))
282           System.err.println("Replacing unmodified " + f);
283         else {
284           System.err.println("Leaving existing " + f);
285           return;
286         }
287       }
288     else
289       System.err.println("Creating " + f);
290 
291     Writer w = new BufferedWriter(new FileWriter(f));
292     try {
293       if (overwrite) { // FIXME Nasty - overwrite here meaning generating base package
294         w.write(autogenStamp + "\n" + "\n");
295         w.write("package " + packageName + ".generated;\n" );
296       } else {
297         w.write(deleteMe + "\n" + "\n");
298         w.write("package " + packageName + ";\n" );
299       }
300       w.write("\n\n");
301       proc.process(w);
302     } catch (IOException e) {
303       try {
304         w.close();
305       } catch (Exception ee) {
306         // If we fail here the cause is reported below
307         ee = null; // shut PMD up
308       }
309       try {
310         f.delete();
311       } catch (Exception ee) {
312         // If we fail here the cause is reported below
313         ee = null; // shut PMD up
314       }
315       throw e;
316     }
317     w.write("\n");
318     w.close();
319   }
320 
321   private boolean containsText(File file, String text) throws FileNotFoundException, IOException, TargetExistsDSDException {
322     BufferedReader r = new BufferedReader(new FileReader(file));
323     boolean found = true;
324     try {
325       String firstLine = r.readLine();
326       if (firstLine != null && !firstLine.equals(text))
327         found = false;
328     } finally {
329       r.close();
330     }
331     return found;
332   }
333 
334   void createPackageHTML(Generator proc, boolean overwrite)
335       throws IOException {
336     File f = null;
337     if (overwrite) {
338       f = new File(dsdDirGen, "package.html");
339     } else {
340       f = new File(dsdDir, "package.html");
341     }
342     if (f.exists()) {
343       if (overwrite) {
344         BufferedReader r = new BufferedReader(new FileReader(f));
345         try {
346           for(int i = 0; i < 8; i++) {r.readLine(); }
347           String ninthLine = r.readLine();
348           if (ninthLine == null || ninthLine.indexOf(autogenStamp) != -1)
349             System.err.println("Replacing " + f);
350           else {
351             System.err.println(ninthLine);
352             throw new TargetExistsDSDException(f);
353           }
354         } finally {
355           r.close();
356         }
357       } else {
358         System.err.println("Leaving existing " + f);
359         return;
360       }
361     } else
362       System.err.println("Creating " + f);
363 
364     Writer w = new BufferedWriter(new FileWriter(f));
365     try {
366       w.write("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" +
367               "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n" +
368               "   \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" +
369               "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
370               "<head>\n" +
371               " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=us-ascii\" />\n" +
372               " <title>" + packageName);
373       if (overwrite)
374         w.write(".generated");
375       w.write("</title>\n" +
376               "</head>\n" +
377               "<!-- " + autogenStamp + "-->\n" +
378               "<body>\n");
379       proc.process(w);
380 
381       w.write("</body>\n" +
382               "</html>\n" +
383               "\n");
384     } catch (IOException e) {
385       try {
386         w.close();
387       } catch (Exception ee) {
388         // If we fail here the cause is reported below
389         ee = null; // shut PMD up
390       }
391       try {
392         f.delete();
393       } catch (Exception ee) {
394         // If we fail here the cause is reported below
395         ee = null; // shut PMD up
396       }
397       throw e;
398     }
399     w.write("\n");
400     w.close();
401   }
402 
403 
404   void generateDatabaseBaseJava(Writer w) throws IOException {
405     if (packageName.equals("org.melati.poem")) {
406       w.write("import org.melati.poem.Database;\n");
407     } else {
408       w.write("import org.melati.poem.PoemDatabase;\n");
409     }
410     w.write("import org.melati.poem.DefinitionSource;\n");
411 
412     for (Enumeration<TableDef> t = tablesInDatabase.elements(); t.hasMoreElements();) {
413       TableDef td = t.nextElement();
414       if (!(td.tableNamingInfo.hidden || td.isAbstract)) {
415         w.write(td.tableNamingInfo.importPersistentString());
416         w.write(td.tableNamingInfo.importTableString());
417       }
418     }
419 
420     w.write("\n" +
421             "/**\n" +
422             " * Melati POEM generated Database base class.\n" +
423             " */\n");
424     w.write("public class " + databaseBaseClassName + " extends " +
425             (packageName.equals("org.melati.poem") &&
426                  name.equalsIgnoreCase("Poem") ?
427                "Database" : "PoemDatabase") +" {\n\n");
428 
429     for (Enumeration<TableDef> t = tablesInDatabase.elements(); t.hasMoreElements();) {
430       TableDef td = t.nextElement();
431       if (!td.tableNamingInfo.hidden)
432         td.generateTableDeclarationJava(w);
433     }
434     
435     w.write("\n"); 
436     if(hasAnExtenedTable)
437       w.write("  @SuppressWarnings({ \"unchecked\", \"rawtypes\" })\n");
438     w.write("  protected " + databaseBaseClassName + "() {\n");
439 
440     for (Enumeration<TableDef> t = tablesInDatabase.elements(); t.hasMoreElements();) {
441       TableDef td = t.nextElement();
442       if (!td.tableNamingInfo.hidden)
443         td.generateTableDefinitionJava(w);
444     }
445 
446     w.write("  }\n");
447 
448     for (Enumeration<TableDef> t = tablesInDatabase.elements(); t.hasMoreElements();) {
449       TableDef td = t.nextElement();
450       if (!td.tableNamingInfo.hidden) {
451         w.write('\n');
452         td.generateTableAccessorJava(w);
453       }
454     }
455     w.write("}\n\n");
456   }
457 
458   void generateDatabaseJava(Writer w) throws IOException {
459     w.write("import " + packageName + ".generated." +
460               databaseBaseClassName + ";\n");
461     w.write("\n" +
462             "/**\n" +
463             " * Melati POEM generated, programmer modifiable stub.\n" +
464             " */\n");
465     w.write("public class " + databaseClassName +
466             " extends " + databaseBaseClassName +
467             "\n                            implements " + databaseTablesClassName);
468     w.write(" {\n" +
469             "  // programmer's domain-specific code here\n" +
470             "}\n\n");
471   }
472 
473   void generateDatabaseTablesBaseJava(Writer w) throws IOException {
474     w.write("// " + tablesInDatabase.size() + " tables in database\n");
475     for (Enumeration<TableDef> t = tablesInDatabase.elements(); t.hasMoreElements();) {
476       TableDef td = t.nextElement();
477       if (td.isAbstract) w.write("// abstract ");
478       if (td.tableNamingInfo.hidden) w.write ("// hidden ");
479       if (td.tableNamingInfo.hidesOther) w.write ("// hides ");
480       w.write(td.tableNamingInfo.importTableString());
481       if (td.isAbstract) w.write("// abstract ");
482       w.write(td.tableNamingInfo.importPersistentString());
483     }
484     for (int j = 0; j < importedDSDs.size(); j++) {
485       DSD dsd = importedDSDs.elementAt(j);
486       w.write("import " + dsd.packageName + "."+
487               dsd.databaseTablesClassName + ";\n");
488     }
489 
490     w.write("\n" +
491             "/**\n" +
492             " * Melati POEM generated base interface to the tables in \n" +
493             " * " + packageName + ".\n" +
494             " */\n");
495     w.write("public interface " + databaseTablesBaseClassName);
496     boolean first = true;
497     for (Enumeration<DSD> t = importedDSDs.elements(); t.hasMoreElements();) {
498       DSD dsd = t.nextElement();
499       if (first) {
500         w.write("\n                       extends " + dsd.databaseTablesClassName);
501         first = false;
502       }
503       else {
504         w.write(",\n                               " +
505                 dsd.databaseTablesClassName);
506       }
507     }
508     w.write(" {\n\n");
509     for (Enumeration<TableDef> t = tablesInDatabase.elements(); t.hasMoreElements();) {
510       TableDef td = t.nextElement();
511       if (!td.tableNamingInfo.hidden)
512         td.generateTableAccessorDefnJava(w);
513     }
514     w.write("}\n\n");
515   }
516 
517   void generateDatabaseTablesJava(Writer w) throws IOException {
518     w.write("import " + packageName + ".generated." +
519               databaseTablesBaseClassName + ";\n");
520     w.write("\n" +
521             "/**\n" +
522             " * Melati POEM generated, " +
523             "programmer modifiable interface stub.\n" +
524             " */\n");
525     w.write("public interface " + databaseTablesClassName +
526             " extends " + databaseTablesBaseClassName + " {\n" +
527             "  // programmer's domain-specific code here\n" +
528             "  // Don't forget to delete first line to prevent overwriting\n" +
529             "}\n\n");
530   }
531 
532   /**
533    * Generate the project table from which all project tables inherit. 
534    * 
535    * @param w the project table writer
536    */
537   void generateProjectTableJava(Writer w) throws IOException {
538     w.write("import org.melati.poem.JdbcTable;\n");
539     w.write("import org.melati.poem.DefinitionSource;\n");
540     w.write("import org.melati.poem.Database;\n");
541     w.write("import org.melati.poem.Persistent;\n");
542     w.write("import org.melati.poem.PoemException;\n");
543 
544     w.write("\n" +
545             "/**\n" +
546             " * Melati POEM generated, " +
547             "programmer modifyable inheritance hook.\n" +
548             " */\n");
549     w.write("public class " + getProjectTableClassName() +
550             "<P extends Persistent> extends JdbcTable<P> {\n");
551     
552     w.write("\n /**\n" + "  * Constructor. \n" + "  * \n" 
553             + "  * @see " + "org.melati.poem.prepro.DSD" + "#generateProjectTableJava \n"
554             + "  * @param database          the POEM database we are using\n"
555             + "  * @param name              the name of this <code>Table</code>\n"
556             + "  * @param definitionSource  which definition is being used\n"
557             + "  * @throws PoemException    if anything goes wrong\n" + "  */\n");
558 
559     w.write("\n" + "  public " + getProjectTableClassName() + "(\n"
560             + "      Database database, String name,\n"
561             + "      DefinitionSource definitionSource)"
562             + " throws PoemException {\n"
563             + "    super(database, name, definitionSource);\n" + "  }\n" + "\n");
564 
565     //w.write("\n /**\n" + "  * Constructor.\n" + "  *\n" 
566     //        + "  * @see " + "org.melati.poem.prepro.DSD" + "#generateProjectTableJava \n"
567     //        + "  * @param database          the POEM database we are using\n"
568     //        + "  * @param name              the name of this <code>Table</code>\n"
569     //        + "  * @throws PoemException    if anything goes wrong\n" + "  */\n");
570     //w.write("  public " + getProjectTableClassName() + "(\n"
571     //        + "      Database database, String name)" + " throws PoemException {\n"
572     //        + "    this(database, name, DefinitionSource.dsd);\n" + "  }\n" + "\n");
573 
574     w.write("  // programmer's domain-specific code here\n" +
575     "}\n\n");
576   }
577   
578   /**
579    * Generate the java files.
580    */
581   void generateJava() throws IOException, IllegalityException {
582     final DSD this_ = this;
583 
584     createJava(databaseBaseClassName,
585                new Generator() {
586                  public void process(Writer w) throws IOException {
587                    this_.generateDatabaseBaseJava(w);
588                  }
589                },
590                true);
591 
592     createJava(databaseClassName,
593                new Generator() {
594                  public void process(Writer w) throws IOException {
595                    this_.generateDatabaseJava(w);
596                  }
597                },
598                false);
599 
600     createJava(databaseTablesBaseClassName,
601                new Generator() {
602                  public void process(Writer w) throws IOException {
603                    this_.generateDatabaseTablesBaseJava(w);
604                  }
605                },
606                true);
607 
608     createJava(databaseTablesClassName,
609             new Generator() {
610               public void process(Writer w) throws IOException {
611                 this_.generateDatabaseTablesJava(w);
612               }
613             },
614             false);
615 
616     createJava(getProjectTableClassName(),
617             new Generator() {
618               public void process(Writer w) throws IOException {
619                 this_.generateProjectTableJava(w);
620               }
621             },
622             false);
623     
624     // Create a default package.html if it does not exist
625     createPackageHTML(new Generator() {
626       public void process(Writer w) throws IOException {
627         w.write("<p>The POEM-generated model classes for " +
628         packageName + ".</p>\n");
629       }
630     }, false);
631 
632     // Create a package.html for the generated files
633     createPackageHTML(new Generator() {
634       public void process(Writer w) throws IOException {
635         w.write("<p>The POEM-generated support classes for " +
636         packageName + ".</p>\n");
637       }
638     }, true);
639 
640     for (Enumeration<TableDef> t = tablesInPackage.elements(); t.hasMoreElements();)
641       t.nextElement().generateJava();
642   }
643 
644   /**
645    * This returns the path to a file (which we assume is a DSD) by
646    * finding the Database class it generated and which the user has
647    * compiled.
648    */
649   String filePath(String resource) throws ResourceNotFoundException {
650     int ext = resource.lastIndexOf('.');
651     if (ext == -1)
652       throw new ResourceNotFoundException(resource,
653         "I can't find the type of this resource (i.e. the file's extension)");
654     int file = resource.lastIndexOf('.', ext - 1);
655     if (file == -1)
656       throw new ResourceNotFoundException(resource,
657                   "I can't find a package name for this resource");
658     String packageNameLocal = resource.substring(0, file);
659     String fileName = resource.substring(file + 1, ext);
660     String extension = resource.substring(ext + 1);
661     String fileToLookFor = fileName + "." + extension;
662     String databaseName = StringUtils.capitalised(fileName.toLowerCase()) +
663                             "Database";
664     Class<?> database;
665     try {
666       database = Class.forName(packageNameLocal + "." + databaseName);
667     } catch (Exception e) {
668       throw new ResourceNotFoundException(resource,
669                   "I can't find the database class associated with this "+
670                   "resource (" + packageNameLocal + "." + databaseName + "). " +
671                   "Is it in your classpath?", e);
672     }
673     java.net.URL url = database.getResource(fileToLookFor);
674     if (url == null || url.getFile() == null || url.getFile().equals(""))
675       throw new ResourceNotFoundException(resource,
676                   "I can't find the resource from the database class file. "+
677                   "Is " + fileToLookFor +" in your classpath?");
678     return url.getFile();
679   }
680 
681 
682   static String javadocFormat(String indent2,
683                                      String string) {
684       return javadocFormat(2,Integer.parseInt(indent2), string);
685   }
686   static String javadocFormat(String string) {
687       return javadocFormat(2, 1, string);
688   }
689   static String javadocFormat(String indent1, String indent2,
690                                      String string) {
691       return javadocFormat(Integer.parseInt(indent1),Integer.parseInt(indent2),
692                            string);
693   }
694  /**
695   * Format a string to fit an indented javadoc comment.
696   *
697   * @param indent1 the indentation before the asterisk
698   * @param indent2 the indentation after  the asterisk
699   * @param string  the <code>String</code> to format
700   * @return the formatted string
701   */
702   static String javadocFormat(int indent1, int indent2, String string) {
703     int lineWidth = 77;
704     int index = indent1;
705     StringBuffer b = new StringBuffer();
706     for (int i = 0; i < indent1; i++) b.append(" ");
707     b.append("*");
708     index += 1;
709     for (int i = 0; i < indent2; i++)b.append(" ");
710     index += indent2;
711     int available = lineWidth - index;
712     if (string.length() <= available) {
713       b.append(string);
714       b.append(" \n");
715     } else {
716       int prevSpace = string.lastIndexOf(' ',available);
717       int incision = available;
718       if (prevSpace != -1)
719         incision = prevSpace + 1;
720       b.append(string.substring(0, incision));
721       b.append("\n");
722       b.append(javadocFormat(indent1, indent2, string.substring(incision)));
723     }
724     return b.toString();
725   }
726 
727 
728  /**
729   * Run me.
730   * @param args the arument array
731   * @throws Exception if an exception occurs
732   */
733   public static void main(String[] args) throws Exception {
734     if (args.length == 1) {
735       DSD dsd = new DSD(args[0]);
736       dsd.generateJava();
737     } else if (args.length == 2) {
738       DSD dsd = new DSD(args[0], new TableNamingStore(), false);
739       dsd.generateJava();
740     } else {
741        System.err.println(
742           "Usage: java org.melati.poem.prepro.DSD <dsd file> [false]");
743     }
744   }
745 
746   /**
747    * @return the name of the class from which all project tables inherit
748    */
749   public String getProjectTableClassName() {
750     return projectName + "Table";
751   }
752 
753   /**
754    * @return the project name
755    */
756   public String getProjectName() {
757     return projectName;
758   }
759 
760 }
761 
762 
763 
764 
765 
766 
767 
768 
769