KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > torque > engine > database > transform > SQLToAppData


1 package org.apache.torque.engine.database.transform;
2
3 /*
4  * Copyright 2001-2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import java.io.BufferedReader JavaDoc;
20 import java.io.FileReader JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.List JavaDoc;
24 import org.apache.torque.engine.database.model.Column;
25 import org.apache.torque.engine.database.model.Database;
26 import org.apache.torque.engine.database.model.ForeignKey;
27 import org.apache.torque.engine.database.model.IDMethod;
28 import org.apache.torque.engine.database.model.Table;
29 import org.apache.torque.engine.sql.ParseException;
30 import org.apache.torque.engine.sql.SQLScanner;
31 import org.apache.torque.engine.sql.Token;
32
33 /**
34  * A Class that converts an sql input file to a Database structure.
35  * The class makes use of SQL Scanner to get
36  * sql tokens and the parses these to create the Database
37  * class. SQLToAppData is in effect a simplified sql parser.
38  *
39  * @author <a HREF="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
40  * @author <a HREF="mailto:jon@latchkey.com">Jon S. Stevens</a>
41  * @version $Id: SQLToAppData.java,v 1.7 2004/02/22 06:27:19 jmcnally Exp $
42  */

43 public class SQLToAppData
44 {
45     private String JavaDoc sqlFile;
46     private List JavaDoc tokens;
47     private Token token;
48     private Database appDataDB;
49     private int count;
50     private String JavaDoc databaseType;
51
52     /**
53      * Create a new class with an input Reader
54      *
55      * @param sqlFile the sql file
56      */

57     public SQLToAppData(String JavaDoc sqlFile)
58     {
59         this.sqlFile = sqlFile;
60     }
61
62     /**
63      * Create a new class with an input Reader. This ctor is not used
64      * but putting here in the event db.props properties are found to
65      * be useful converting sql to xml, the infrastructure will exist
66      *
67      * @param sqlFile the sql file
68      * @param databaseType
69      */

70     public SQLToAppData(String JavaDoc sqlFile, String JavaDoc databaseType)
71     {
72         this.sqlFile = sqlFile;
73         this.databaseType = databaseType;
74     }
75
76     /**
77      * Get the current input sql file
78      *
79      * @return the sql file
80      */

81     public String JavaDoc getSqlFile()
82     {
83         return sqlFile;
84     }
85
86     /**
87      * Set the current input sql file
88      *
89      * @param sqlFile the sql file
90      */

91     public void setSqlFile(String JavaDoc sqlFile)
92     {
93         this.sqlFile = sqlFile;
94     }
95
96     /**
97      * Move to the next token.
98      *
99      * @throws ParseException if there is no more tokens available.
100      */

101     private void next() throws ParseException
102     {
103         if (count < tokens.size())
104         {
105             token = (Token) tokens.get(count++);
106         }
107         else
108         {
109             throw new ParseException("No More Tokens");
110         }
111     }
112
113     /**
114      * Creates an error condition and adds the line and
115      * column number of the current token to the error
116      * message.
117      *
118      * @param name name of the error
119      * @throws ParseException
120      */

121     private void err(String JavaDoc name) throws ParseException
122     {
123         throw new ParseException (name + " at [ line: " + token.getLine()
124                 + " col: " + token.getCol() + " ]");
125     }
126
127     /**
128      * Check if there is more tokens available for parsing.
129      *
130      * @return true if there are more tokens available
131      */

132     private boolean hasTokens()
133     {
134         return count < tokens.size();
135     }
136
137     /**
138      * Parses a CREATE TABLE FOO command.
139      *
140      * @throws ParseException
141      */

142     private void create() throws ParseException
143     {
144         next();
145         if (token.getStr().toUpperCase().equals("TABLE"))
146         {
147             create_Table();
148         }
149     }
150
151     /**
152      * Parses a CREATE TABLE sql command
153      *
154      * @throws ParseException error parsing the input file
155      */

156     private void create_Table() throws ParseException
157     {
158         next();
159         String JavaDoc tableName = token.getStr(); // name of the table
160
next();
161         if (!token.getStr().equals("("))
162         {
163             err("( expected");
164         }
165         next();
166
167         Table tbl = new Table (tableName);
168         //tbl.setIdMethod("none");
169
while (!token.getStr().equals(";"))
170         {
171             create_Table_Column(tbl);
172         }
173
174         if (tbl.getPrimaryKey().size() == 1)
175         {
176             tbl.setIdMethod(IDMethod.ID_BROKER);
177         }
178         else
179         {
180             tbl.setIdMethod(IDMethod.NO_ID_METHOD);
181         }
182         appDataDB.addTable (tbl);
183     }
184
185     /**
186      * Parses column information between the braces of a CREATE
187      * TABLE () sql statement.
188      *
189      * @throws ParseException error parsing the input file
190      */

191     private void create_Table_Column(Table tbl) throws ParseException
192     {
193         // The token should be the first item
194
// which is the name of the column or
195
// PRIMARY/FOREIGN/UNIQUE
196
if (token.getStr().equals(","))
197         {
198             next();
199         }
200
201         if (token.getStr().toUpperCase().equals("PRIMARY"))
202         {
203             create_Table_Column_Primary(tbl);
204         }
205         else if (token.getStr().toUpperCase().equals("FOREIGN"))
206         {
207             create_Table_Column_Foreign(tbl);
208         }
209         else if (token.getStr().toUpperCase().equals("UNIQUE"))
210         {
211             create_Table_Column_Unique(tbl);
212         }
213         else
214         {
215             create_Table_Column_Data(tbl);
216         }
217     }
218
219     /**
220      * Parses PRIMARY KEY (FOO,BAR) statement
221      *
222      * @throws ParseException error parsing the input file
223      */

224     private void create_Table_Column_Primary (Table tbl) throws ParseException
225     {
226         next();
227         if (!token.getStr().toUpperCase().equals("KEY"))
228         {
229             err("KEY expected");
230         }
231         next();
232         if (!token.getStr().toUpperCase().equals("("))
233         {
234             err("( expected");
235         }
236         next();
237
238         String JavaDoc colName = token.getStr();
239         Column c = tbl.getColumn(colName);
240         if (c == null)
241         {
242             err("Invalid column name: " + colName);
243         }
244         c.setPrimaryKey(true);
245         next();
246         while (token.getStr().equals(","))
247         {
248             next();
249             colName = token.getStr();
250             c = tbl.getColumn(colName);
251             if (c == null)
252             {
253                 err("Invalid column name: " + colName);
254             }
255             c.setPrimaryKey(true);
256             next();
257         }
258
259         if (!token.getStr().toUpperCase().equals(")"))
260         {
261             err(") expected");
262         }
263         next(); // skip the )
264
}
265
266     /**
267      * Parses UNIQUE (NAME,FOO,BAR) statement
268      *
269      * @throws ParseException error parsing the input file
270      */

271     private void create_Table_Column_Unique(Table tbl) throws ParseException
272     {
273         next();
274         if (!token.getStr().toUpperCase().equals("("))
275         {
276             err("( expected");
277         }
278         next();
279         while (!token.getStr().equals(")"))
280         {
281             if (!token.getStr().equals(","))
282             {
283                 String JavaDoc colName = token.getStr();
284                 Column c = tbl.getColumn(colName);
285                 if (c == null)
286                 {
287                     err("Invalid column name: " + colName);
288                 }
289                 c.setUnique(true);
290             }
291             next();
292         }
293         if (!token.getStr().toUpperCase().equals(")"))
294         {
295             err(") expected got: " + token.getStr());
296         }
297
298         next(); // skip the )
299
}
300
301     /**
302      * Parses FOREIGN KEY (BAR) REFERENCES TABLE (BAR) statement
303      *
304      * @throws ParseException error parsing the input file
305      */

306     private void create_Table_Column_Foreign(Table tbl) throws ParseException
307     {
308         next();
309         if (!token.getStr().toUpperCase().equals("KEY"))
310         {
311             err("KEY expected");
312         }
313         next();
314         if (!token.getStr().toUpperCase().equals("("))
315         {
316             err("( expected");
317         }
318         next();
319
320         ForeignKey fk = new ForeignKey();
321         List JavaDoc localColumns = new ArrayList JavaDoc();
322         tbl.addForeignKey(fk);
323
324         String JavaDoc colName = token.getStr();
325         localColumns.add(colName);
326         next();
327         while (token.getStr().equals(","))
328         {
329             next();
330             colName = token.getStr();
331             localColumns.add(colName);
332             next();
333         }
334         if (!token.getStr().toUpperCase().equals(")"))
335         {
336             err(") expected");
337         }
338
339         next();
340
341         if (!token.getStr().toUpperCase().equals("REFERENCES"))
342         {
343             err("REFERENCES expected");
344         }
345
346         next();
347
348         fk.setForeignTableName(token.getStr());
349
350         next();
351
352         if (token.getStr().toUpperCase().equals("("))
353         {
354             next();
355             int i = 0;
356             fk.addReference((String JavaDoc) localColumns.get(i++), token.getStr());
357             next();
358             while (token.getStr().equals(","))
359             {
360                 next();
361                 fk.addReference((String JavaDoc) localColumns.get(i++), token.getStr());
362                 next();
363             }
364             if (!token.getStr().toUpperCase().equals(")"))
365             {
366                 err(") expected");
367             }
368             next();
369         }
370     }
371
372     /**
373      * Parse the data definition of the column statement.
374      *
375      * @throws ParseException error parsing the input file
376      */

377     private void create_Table_Column_Data(Table tbl) throws ParseException
378     {
379         String JavaDoc columnSize = null;
380         String JavaDoc columnPrecision = null;
381         String JavaDoc columnDefault = null;
382         boolean inEnum = false;
383
384         String JavaDoc columnName = token.getStr();
385         next();
386         String JavaDoc columnType = token.getStr();
387
388         if (columnName.equals(")") && columnType.equals(";"))
389         {
390             return;
391         }
392
393         next();
394
395         // special case for MySQL ENUM's which are stupid anyway
396
// and not properly handled by Torque.
397
if (columnType.toUpperCase().equals("ENUM"))
398         {
399             inEnum = true;
400             next(); // skip (
401
while (!token.getStr().equals(")"))
402             {
403                 // skip until )
404
next();
405             }
406             while (!token.getStr().equals(","))
407             {
408                 if (token.getStr().toUpperCase().equals("DEFAULT"))
409                 {
410                     next();
411                     if (token.getStr().equals("'"))
412                     {
413                         next();
414                     }
415                     columnDefault = token.getStr();
416                     next();
417                     if (token.getStr().equals("'"))
418                     {
419                         next();
420                     }
421                 }
422                 // skip until ,
423
next();
424             }
425             next(); // skip ,
426
columnType = "VARCHAR";
427         }
428         else if (token.getStr().toUpperCase().equals("("))
429         {
430             next();
431             columnSize = token.getStr();
432             next();
433             if (token.getStr().equals(","))
434             {
435                 next();
436                 columnPrecision = token.getStr();
437                 next();
438             }
439
440             if (!token.getStr().equals(")"))
441             {
442                 err(") expected");
443             }
444             next();
445         }
446
447         Column col = new Column(columnName);
448         if (columnPrecision != null)
449         {
450             columnSize = columnSize + columnPrecision;
451         }
452         col.setTypeFromString(columnType, columnSize);
453         tbl.addColumn(col);
454
455         if (inEnum)
456         {
457             col.setNotNull(true);
458             if (columnDefault != null)
459             {
460                 col.setDefaultValue(columnDefault);
461             }
462         }
463         else
464         {
465             while (!token.getStr().equals(",") && !token.getStr().equals(")"))
466             {
467                 if (token.getStr().toUpperCase().equals("NOT"))
468                 {
469                     next();
470                     if (!token.getStr().toUpperCase().equals("NULL"))
471                     {
472                         err("NULL expected after NOT");
473                     }
474                     col.setNotNull(true);
475                     next();
476                 }
477                 else if (token.getStr().toUpperCase().equals("PRIMARY"))
478                 {
479                     next();
480                     if (!token.getStr().toUpperCase().equals("KEY"))
481                     {
482                         err("KEY expected after PRIMARY");
483                     }
484                     col.setPrimaryKey(true);
485                     next();
486                 }
487                 else if (token.getStr().toUpperCase().equals("UNIQUE"))
488                 {
489                     col.setUnique(true);
490                     next();
491                 }
492                 else if (token.getStr().toUpperCase().equals("NULL"))
493                 {
494                     col.setNotNull(false);
495                     next();
496                 }
497                 else if (token.getStr().toUpperCase().equals("AUTO_INCREMENT"))
498                 {
499                     col.setAutoIncrement(true);
500                     next();
501                 }
502                 else if (token.getStr().toUpperCase().equals("DEFAULT"))
503                 {
504                     next();
505                     if (token.getStr().equals("'"))
506                     {
507                         next();
508                     }
509                     col.setDefaultValue(token.getStr());
510                     next();
511                     if (token.getStr().equals("'"))
512                     {
513                         next();
514                     }
515                 }
516             }
517             next(); // eat the ,
518
}
519     }
520
521     /**
522      * Execute the parser.
523      *
524      * @throws IOException If an I/O error occurs
525      * @throws ParseException error parsing the input file
526      */

527     public Database execute() throws IOException JavaDoc, ParseException
528     {
529         count = 0;
530         appDataDB = new Database(databaseType);
531
532         FileReader JavaDoc fr = new FileReader JavaDoc(sqlFile);
533         BufferedReader JavaDoc br = new BufferedReader JavaDoc(fr);
534         SQLScanner scanner = new SQLScanner(br);
535
536         tokens = scanner.scan();
537
538         br.close();
539
540         while (hasTokens())
541         {
542             if (token == null)
543             {
544                 next();
545             }
546
547             if (token.getStr().toUpperCase().equals("CREATE"))
548             {
549                 create();
550             }
551             if (hasTokens())
552             {
553                 next();
554             }
555         }
556         return appDataDB;
557     }
558 }
559
Popular Tags