View Javadoc

1   package pl.aislib.tools.mapping;
2   
3   import pl.aislib.tools.mapping.db.Database;
4   
5   import java.io.File;
6   import java.io.FileInputStream;
7   import java.io.FileWriter;
8   import java.io.IOException;
9   import java.io.Writer;
10  import java.sql.SQLException;
11  import java.util.HashSet;
12  import java.util.Iterator;
13  import java.util.List;
14  import java.util.Properties;
15  import java.util.Set;
16  import java.util.Vector;
17  
18  import javax.xml.transform.OutputKeys;
19  import javax.xml.transform.Transformer;
20  import javax.xml.transform.TransformerFactory;
21  import javax.xml.transform.stream.StreamSource;
22  
23  import org.jdom.DocType;
24  import org.jdom.Document;
25  import org.jdom.Element;
26  import org.jdom.EntityRef;
27  import org.jdom.output.XMLOutputter;
28  import org.jdom.transform.JDOMResult;
29  import org.jdom.transform.JDOMSource;
30  
31  /***
32   * Generates structure.xml file from an existing database.
33   * 
34   * @author Michal Jastak, AIS.PL
35   * @author Tomasz Pik, AIS.PL
36   * @author Milosz Tylenda, AIS.PL
37   * @version $Revision: 1.6 $
38   */
39  public class Describe {
40  
41    private static final String DB_PARTS_DIR = "db_parts";
42  
43    /***
44     * When true and short version requested, the 'default' attribute will not
45     * be set in java-field element. 
46     */
47    private boolean noDefault;
48    
49    private boolean separateFiles;
50    private boolean verboseFlag;
51    private boolean fixedTableTypes;
52    private Database dBase;
53    private Properties dBaseProperties;
54    private String configFilePath;
55    private String dbCatalog;
56    private String dbDriver;
57    private String dbPassword;
58    private String dbSchema;
59    private String dbURL;
60    private String dbUser;
61  
62    private Set tables;
63  
64    /***
65     *
66     */
67  
68    public Describe() {
69      verboseFlag = false;
70      fixedTableTypes = false;
71      configFilePath = "describe.conf";
72      dBaseProperties = new Properties();
73    }
74  
75    public boolean inSeparateFiles() {
76      return separateFiles;
77    }
78  
79    /***
80     *
81     */
82  
83    public boolean verbose() {
84      return verboseFlag;
85    }
86  
87    /***
88     *
89     */
90  
91    public void initialize() throws IOException, SQLException {
92      try {
93        dBaseProperties.load(new FileInputStream(configFilePath));
94      } catch (IOException ioe) {
95  
96      }
97      if (dbCatalog == null) {
98        dbCatalog = dBaseProperties.getProperty("catalog");
99      }
100     if (dbDriver == null) {
101       dbDriver = dBaseProperties.getProperty("driver");
102     }
103     if (dbPassword == null) {
104       dbPassword = dBaseProperties.getProperty("password");
105     }
106     if (dbSchema == null) {
107       dbSchema = dBaseProperties.getProperty("schema");
108     }
109     if (dbURL == null) {
110       dbURL = dBaseProperties.getProperty("url");
111     }
112     if (dbUser == null) {
113       dbUser = dBaseProperties.getProperty("user");
114     }
115 
116     if (verboseFlag) {
117       System.err.println(
118         "\nInitialized as follows:\n"
119           + "\n\tDriver:   "
120           + dbDriver
121           + "\n\tURL:      "
122           + dbURL
123           + "\n\tUser:     "
124           + dbUser
125           + "\n\tPassword: "
126           + dbPassword
127           + "\n\tCatalog:  "
128           + dbCatalog
129           + "\n\tSchema:   "
130           + dbSchema);
131     }
132 
133     dBase = new Database(verboseFlag);
134     dBase.setCatalog(dbCatalog);
135     dBase.setDriver(dbDriver);
136     dBase.setSchema(dbSchema);
137     dBase.connect(dbURL, dbUser, dbPassword);
138   }
139 
140   /***
141    *
142    */
143   public void readTables() throws SQLException {
144     dBase.readTables(fixedTableTypes, tables);
145   }
146 
147   /***
148    *
149    */
150   public void readSequences() throws SQLException {
151     dBase.readSequences();
152   }
153 
154   /***
155    *
156    */
157   public void genericInfo() throws SQLException {
158     dBase.genericInfo();
159   }
160 
161   /***
162    *
163    */
164   public String toString() {
165     return dBase.toString();
166   }
167 
168   public void writeToSeparateFiles(boolean isShort) throws Exception {
169     List xmls = dBase.toSeparateXMLs();
170     for (Iterator iter = xmls.iterator(); iter.hasNext();) {
171       XmlDesc xmlDesc = (XmlDesc) iter.next();
172 
173       String xmlName = xmlDesc.getName();
174       Element root = xmlDesc.getElement();
175 
176       Vector cnt = new Vector();
177       cnt.add(root);
178       Document doc = new Document(cnt);
179 
180       if (isShort) {
181         TransformerFactory tFactory = TransformerFactory.newInstance();
182 
183         StreamSource style = getStyle();
184         JDOMResult result = new JDOMResult();
185         JDOMSource source = new JDOMSource(doc);
186 
187         Transformer trans = tFactory.newTransformer(style);
188         trans.setOutputProperty(OutputKeys.METHOD, "xml");
189         trans.setOutputProperty(OutputKeys.INDENT, "yes");
190         trans.transform(source, result);
191         doc = result.getDocument();
192       }
193       XMLOutputter xo = new XMLOutputter("  ", true);
194       xo.setOmitDeclaration(true);
195       //xo.setEncoding("iso-8859-2");
196       String xoDoc = xo.outputString(doc);
197 
198       Writer writer = new FileWriter(DB_PARTS_DIR + File.separatorChar + xmlName + ".xml");
199       writer.write(xoDoc.toString());
200       writer.close();
201 
202       System.out.println("Saved: " + xmlName + ".xml");
203     }
204 
205     if (tables == null) {
206       System.out.println("Saved: structure.xml");
207 
208       Element root = new Element("database");
209 
210       for (Iterator iter = xmls.iterator(); iter.hasNext();) {
211         XmlDesc xmlDesc = (XmlDesc) iter.next();
212         String xmlName = xmlDesc.getName();
213         EntityRef entityRef = new EntityRef("db_part_" + xmlName);
214         root.addContent(entityRef);
215       }
216       Vector cnt = new Vector();
217       cnt.add(root);
218       Document doc = new Document(cnt);
219 
220       DocType docType =
221         new DocType("database", "-//AIS.PL//DTD Mapping Description 0.4//EN", "http://www.ais.pl/dtds/mapping_0_4.dtd");
222 
223       StringBuffer entities = new StringBuffer();
224       for (Iterator iter = xmls.iterator(); iter.hasNext();) {
225         XmlDesc xmlDesc = (XmlDesc) iter.next();
226         String xmlName = xmlDesc.getName();
227         entities.append(
228           "<!ENTITY  db_part_" + xmlName + "   SYSTEM \"./" + DB_PARTS_DIR + "/" + xmlName + ".xml\">\n");
229       }
230       docType.setInternalSubset(entities.toString());
231 
232       doc.setDocType(docType);
233 
234       XMLOutputter xo = new XMLOutputter("  ", true);
235       xo.setEncoding("iso-8859-2");
236       String xoDoc = xo.outputString(doc);
237       Writer writer = new FileWriter("structure.xml");
238       writer.write(xoDoc.toString());
239       writer.close();
240     }
241 
242   }
243 
244   /***
245    *
246    */
247   public void writeTo(boolean isShort) throws Exception {
248     Element root = dBase.toXML();
249     Vector cnt = new Vector();
250     cnt.add(root);
251     Document doc = new Document(cnt);
252 
253     if (isShort) {
254       TransformerFactory tFactory = TransformerFactory.newInstance();
255 
256       StreamSource style = getStyle();
257       JDOMResult result = new JDOMResult();
258       JDOMSource source = new JDOMSource(doc);
259 
260       Transformer trans = tFactory.newTransformer(style);
261       trans.setOutputProperty(OutputKeys.METHOD, "xml");
262       trans.setOutputProperty(OutputKeys.INDENT, "yes");
263       trans.transform(source, result);
264       doc = result.getDocument();
265       doc.setDocType(
266         new DocType(
267           "database",
268           "-//AIS.PL//DTD Mapping Description 0.4//EN",
269           "http://www.ais.pl/dtds/mapping_0_4.dtd"));
270     }
271     XMLOutputter xo = new XMLOutputter("  ", true);
272     xo.setEncoding("iso-8859-2");
273     String xoDoc = xo.outputString(doc);
274     System.out.println(xoDoc);
275   }
276 
277   /***
278    * Returns the suitable StreamSource depending on the noDefault value.
279    */
280   private StreamSource getStyle() {
281     if (noDefault) {
282       return new StreamSource(
283         Thread.currentThread().getContextClassLoader().getResourceAsStream("pl/aislib/tools/mapping/mapping-no-default.xsl")); 
284     } else {
285       return new StreamSource(
286         Thread.currentThread().getContextClassLoader().getResourceAsStream("pl/aislib/tools/mapping/mapping.xsl")); 
287     }
288   }
289   
290   /***
291    *
292    */
293   public void parseArgs(String ArgV[]) throws ArrayIndexOutOfBoundsException {
294     int i = 0;
295     while (i < ArgV.length) {
296       if (ArgV[i].equals("--config-file") || ArgV[i].equals("-c")) {
297         i++;
298         configFilePath = ArgV[i];
299       }
300 
301       if (ArgV[i].equals("--catalog") || ArgV[i].equals("-t")) {
302         i++;
303         dbCatalog = ArgV[i];
304       }
305 
306       if (ArgV[i].equals("--driver") || ArgV[i].equals("-d")) {
307         i++;
308         dbDriver = ArgV[i];
309       }
310 
311       if (ArgV[i].equals("--password") || ArgV[i].equals("-p")) {
312         i++;
313         dbPassword = ArgV[i];
314       }
315 
316       if (ArgV[i].equals("--schema") || ArgV[i].equals("-s")) {
317         i++;
318         dbSchema = ArgV[i];
319       }
320 
321       if (ArgV[i].equals("--url") || ArgV[i].equals("-r")) {
322         i++;
323         dbURL = ArgV[i];
324       }
325 
326       if (ArgV[i].equals("--user") || ArgV[i].equals("-u")) {
327         i++;
328         dbUser = ArgV[i];
329       }
330 
331       if (ArgV[i].equals("--verbose") || ArgV[i].equals("-v")) {
332         verboseFlag = true;
333       }
334 
335       if (ArgV[i].equals("--files") || ArgV[i].equals("-f")) {
336         separateFiles = true;
337       }
338 
339       if (ArgV[i].equals("--table") || ArgV[i].equals("-T")) {
340         i++;
341         if (tables == null) {
342           tables = new HashSet();
343         }
344         tables.add(ArgV[i]);
345       }
346 
347       if (ArgV[i].equals("--fixed-table-types")) {
348         fixedTableTypes = true;
349       }
350 
351       if (ArgV[i].equals("--no-default-values")) {
352         noDefault = true;
353       }
354 
355       i++;
356     }
357   }
358 
359   /***
360    *
361    */
362 
363   public String usageDescription() {
364 
365     StringBuffer result = new StringBuffer();
366     result.append("\nUsage:\n");
367     result.append("\t-c, --config-file  config file path\n");
368     result.append("\nConfiguration options may be overwritten using following options:\n\n");
369     result.append("\t-d, --driver    JDBC driver class name\n");
370     result.append("\t-p, --password  password for database access authorization\n");
371     result.append("\t-r, --url       database URL\n");
372     result.append("\t-s, --schema    database schema\n");
373     result.append("\t-t, --catalog   database catalog\n");
374     result.append("\t-u, --user      user name for database access authorization\n");
375     result.append("\nOther options:\n\n");
376     result.append("\t--fixed-table-types   use only TABLE and VIEW as possible table types\n");
377     result.append("\t--short               short version (for tools-mapping)\n");
378     result.append("\t--no-default-values   do not output 'default' attributes in <java-field>\n");
379     result.append("\t-v, --verbose         turn on verbose mode\n");
380     result.append("\t-T, --table           generate description for one table\n");
381     result.append("\t-f, --files           create file for each table\n");
382     result.append("\nVersion: $Name:  $\n");
383     return new String(result);
384   }
385 
386   /***
387    *
388    */
389 
390   public static void main(String ArgV[]) {
391 
392     Describe describe = new Describe();
393     if (ArgV.length == 0) {
394       System.out.println(describe.usageDescription());
395       System.exit(1);
396     }
397     try {
398       describe.parseArgs(ArgV);
399     } catch (Exception ex) {
400       System.err.println(describe.usageDescription());
401       System.exit(1);
402     }
403 
404     try {
405       describe.initialize();
406     } catch (Exception ex) {
407       System.err.println("\nException caught during initialization:\n\n\t" + ex.getMessage());
408       if (describe.verbose()) {
409         ex.printStackTrace();
410       }
411       System.exit(2);
412     }
413 
414     try {
415       describe.genericInfo();
416       describe.readTables();
417       describe.readSequences();
418 
419       boolean isShort = false;
420       for (int i = 0; i < ArgV.length; i++) {
421         if ((ArgV[i].equals("--short")) || (ArgV[i].equals("-s"))) {
422           isShort = true;
423         }
424       }
425       if (describe.inSeparateFiles()) {
426         describe.writeToSeparateFiles(isShort);
427       } else {
428         describe.writeTo(isShort);
429       }
430     } catch (Exception ex) {
431       System.err.println("\nException caught:\n\n\t" + ex.getMessage());
432       if (describe.verbose()) {
433         ex.printStackTrace();
434       }
435       System.exit(3);
436     }
437   }
438 
439 } // class
440 
441 /***
442  * $Log: Describe.java,v $
443  * Revision 1.6  2004/06/24 05:46:10  milosz
444  * Class comment added.
445  *
446  * Revision 1.5  2004/01/19 14:35:02  milosz
447  * Support for --no-default-values added.
448  *
449  */