EMMA Coverage Report (generated Mon Apr 21 23:56:41 GMT 2008)
[all classes][org.sqlorm.metadatadumper]

COVERAGE SUMMARY FOR SOURCE FILE [ConstantsDump.java]

nameclass, %method, %block, %line, %
ConstantsDump.java100% (1/1)20%  (3/15)19%  (164/870)20%  (25,7/128)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ConstantsDump100% (1/1)20%  (3/15)19%  (164/870)20%  (25,7/128)
<static initializer> 100% (1/1)100% (22/22)100% (2/2)
ConstantsDump (): void 100% (1/1)100% (19/19)100% (6/6)
ConstantsDump (ConnectionInfo, FormatInfo): void 0%   (0/1)0%   (0/25)0%   (0/8)
connect (): Connection 0%   (0/1)0%   (0/66)0%   (0/7)
createFileHandle (String, String): PrintWriter 0%   (0/1)0%   (0/27)0%   (0/5)
dumpMetaData (): void 0%   (0/1)0%   (0/35)0%   (0/7)
ensureOutputDirExistence (String): void 0%   (0/1)0%   (0/35)0%   (0/7)
generateColumnConstant (String, String, String, String, String): String 0%   (0/1)0%   (0/29)0%   (0/1)
generateStaticConstant (String, String, String, String): String 0%   (0/1)0%   (0/25)0%   (0/1)
getMetaData (ConnectionInfo, Connection): ThreeDHashMap 0%   (0/1)0%   (0/58)0%   (0/12)
log (String, Object []): void 0%   (0/1)0%   (0/8)0%   (0/3)
main (String []): void 0%   (0/1)0%   (0/65)0%   (0/14)
parseArguments (String []): void 100% (1/1)100% (123/123)100% (20/20)
processSchema (String, HashMap): void 0%   (0/1)0%   (0/311)0%   (0/37)
reconnect (String, Connection): Connection 0%   (0/1)0%   (0/22)0%   (0/2)

1package org.sqlorm.metadatadumper;
2 
3import java.io.File;
4import java.io.FileNotFoundException;
5import java.io.FileOutputStream;
6import java.io.PrintWriter;
7import java.sql.Connection;
8import java.sql.DriverManager;
9import java.sql.ResultSet;
10import java.sql.SQLException;
11import java.util.ArrayList;
12import java.util.Arrays;
13import java.util.Date;
14import java.util.HashMap;
15import java.util.Iterator;
16import java.util.Map;
17import java.util.Properties;
18import java.util.TreeMap;
19 
20/**
21 * Class to read meta data from a database and create classes containing constants based upon that meta data.
22 * <p>
23 * This class is written in Java5 style, but can easily be translated to Java 4 style.
24 * 
25 * @author Kasper B. Graversen, (c) 2007-2008
26 */
27public class ConstantsDump {
28private static final String CLASS_HEADER = "\n" //
29                + "/**\n" //
30                + " * This class is auto generated by SQL ORM.\n" //
31                + " * Generated: " + new Date() + "\n" // 
32                + " * \n" //
33                + " * DO NOT EDIT UNLESS WHILST REFACTORING!!\n" //
34                + " */";
35private final String IND = "\t\t";
36private final String INDD = "\t\t\t";
37 
38static boolean verbose = false;
39ConnectionInfo connInfo = new ConnectionInfo();
40FormatInfo formatInfo = new FormatInfo();
41 
42public ConstantsDump(ConnectionInfo connInfo, FormatInfo formatInfo) throws Exception {
43        this.connInfo = connInfo;
44        this.formatInfo = formatInfo;
45}
46 
47public ConstantsDump() throws Exception {
48}
49 
50private static PrintWriter createFileHandle(String outputDir, String outputFileName) throws FileNotFoundException {
51        ensureOutputDirExistence(outputDir);
52        File file = new File(outputDir, outputFileName);
53        log("Creating file '%s'", file.toString());
54        PrintWriter out = new PrintWriter(new FileOutputStream(file));
55        return out;
56}
57 
58private static void ensureOutputDirExistence(String outputDir) {
59        File dir = new File(outputDir);
60        if(dir.exists()) {
61                return;
62        }
63        log("'%s' non-existing, trying to create it.", outputDir);
64        if(dir.mkdirs() == false) {
65                throw new RuntimeException("Cannot create the dir '" + outputDir + "'");
66        }
67}
68 
69private void processSchema(String schema, HashMap<String, HashMap<String, Object>> metaData)
70                throws FileNotFoundException {
71        schema = schema.substring(0, 1).toUpperCase() + schema.substring(1);
72        final String CLASS_NAME = formatInfo.getClassNamePrefix() + schema + "MetaData";
73        final String outputFileName = CLASS_NAME + ".java";
74        final PrintWriter out = createFileHandle(formatInfo.getOutputDir() + formatInfo.getPackageName().replace('.', '/'),
75                        outputFileName);
76        log("package '%s'", formatInfo.getPackageName());
77        out.println("package " + formatInfo.getPackageName() + ";");
78        out.println(CLASS_HEADER);
79        out.println("public class " + CLASS_NAME + " {");
80 
81        // put the definitions of the column name classes at they are not used when refactoring
82        ArrayList<String> ColumnNameClasses = new ArrayList<String>();
83 
84        // sort tables in a schema alpha asc.
85        Map<String, HashMap<String, Object>> sortedMetaData = new TreeMap<String, HashMap<String, Object>>(metaData);
86 
87        for(Iterator<String> dbTables = sortedMetaData.keySet().iterator(); dbTables.hasNext();) {
88                String tableName = dbTables.next();
89                log("table '%s'", tableName);
90 
91                // generate method name class for table constants
92                final String TableNameClassName = schema + tableName.toUpperCase() + "_TABLE";
93 
94                // generate table constant
95                out.println(generateStaticConstant(TableNameClassName, tableName.toUpperCase(), tableName, "\t"));
96 
97                // generate column name inner classes
98                final String COLUMN_CLASS = tableName.toUpperCase() + "_COL";
99                ColumnNameClasses.add("\tpublic static class " + COLUMN_CLASS
100                                + " implements org.sqlorm.metadatadumper.IColumnName {\n" //
101                                + IND + "private String tableName, columnName;\n" //
102                                + IND + "private " + COLUMN_CLASS + "(String tableName, String columnName) { \n" //
103                                + INDD + "this.tableName = tableName;\n" //
104                                + INDD + "this.columnName = columnName;\n" //
105                                + IND + "}\n" //
106                                + IND + "public String _() { return columnName; }\n" //
107                                + IND + "public String at(String tablePrefix) { return tablePrefix+\".\"+columnName; }\n" //
108                                + IND + "public String toString() { return tableName +\".\"+columnName; }\n" //
109                                + "\t}\n");
110 
111                // generate table name class containing all the fields
112                out.println("\tpublic static class " + TableNameClassName
113                                + " implements org.sqlorm.metadatadumper.ITableName {");
114 
115                // generate column constants
116                out.println(generateColumnConstant(COLUMN_CLASS, "_STAR", tableName, "*", IND));
117                Map<String, Object> sortedColumnsMetaData = new TreeMap<String, Object>(metaData.get(tableName));
118                for(Iterator<String> dbColumns = sortedColumnsMetaData.keySet().iterator(); dbColumns.hasNext();) {
119                        String columnName = dbColumns.next();
120                        log(" -> column '%s'", columnName);
121 
122                        out.println(generateColumnConstant(COLUMN_CLASS, columnName.toUpperCase(), tableName, columnName, IND));
123                }
124                // generate end of class and its functionality
125                out.println(IND + "// implementation\n" //
126                                + IND + "private String tableName;\n" //
127                                + IND + "private " + TableNameClassName + "(String tableName) { this.tableName = tableName; }\n" //
128                                + IND + "public String toString() { return tableName; }");
129                out.println("\t}");
130                out.println("");
131                out.println("");
132        }
133 
134        // generate all the column names
135 
136        out.println("\n\n\t // uninteresting stuff below... \n\n\n\n\n\n\n\n\n\n");
137        for(String columnClassName : ColumnNameClasses) {
138                out.println(columnClassName);
139        }
140        ColumnNameClasses.clear();
141        out.print("}");
142        out.close();
143}
144 
145private static String generateStaticConstant(String type, String name, String value, String tabs) {
146        return String.format("%spublic static final %s %s = new %s(\"%s\");",//
147                        tabs, type, name, type, value);
148}
149 
150private static String generateColumnConstant(String type, String name, String tableArg, String columnArg, String tabs) {
151        return String.format("%spublic final %s %-15s = new %s(\"%s\",\"%s\");",//
152                        tabs, type, name, type, tableArg, columnArg);
153}
154 
155// old way.. generating javadoc as well.. but finding this too verbose to read..with little added value
156// private static String generateColumnConstant(String type, String name, String tableArg, String columnArg, String
157// tabs) {
158// return String.format("%s/** constant = '%s' */\n" //
159// + "%spublic final %s %s = new %s(\"%s\",\"%s\");\n",//
160// tabs, columnArg,//
161// tabs, type, name, type, tableArg, columnArg);
162// }
163 
164/**
165 * get meta data for all schemas
166 */
167private ThreeDHashMap<String, String, String, Object> getMetaData(ConnectionInfo connInfo, Connection connection)
168                throws Exception, SQLException {
169        ThreeDHashMap<String, String, String, Object> metaInfo = new ThreeDHashMap<String, String, String, Object>();
170 
171        for(String schema : connInfo.getSchemaNames()) {
172                log("Processing schema '%s' accepted", schema);
173                connection = reconnect(schema, connection);
174                ResultSet rs = connection.getMetaData().getColumns(schema, null, "%", "%");
175                while(rs.next()) {
176                        // String schemaname = rs.getString(1);
177                        String tablename = rs.getString(3);
178                        String columnname = rs.getString(4);
179                        metaInfo.set(schema, tablename, columnname, null);
180                }
181        }
182        return metaInfo;
183}
184 
185private Connection connect() throws InstantiationException, IllegalAccessException, ClassNotFoundException,
186                SQLException {
187        Class.forName(connInfo.getDriverClass()).newInstance();
188 
189        final Properties dbConnection = new Properties();
190        dbConnection.put("user", connInfo.getUserName());
191        dbConnection.put("password", connInfo.getPassword());
192        final String url = connInfo.getUrl() + "/" + connInfo.getSchemaNames().get(0);
193        log("Connecting to '%s' as %s:%s", url, connInfo.getUserName(), connInfo.getPassword());
194 
195        return DriverManager.getConnection(url, dbConnection);
196        // old way return DriverManager.getConnection(url, connInfo.getUserName(), connInfo.getPassword());
197}
198 
199private static void log(String message, Object... args) {
200        if(verbose) {
201                System.out.println(String.format(message, args));
202        }
203}
204 
205/**
206 * for each schema we need to re-connect to the database in order to properly read the meta data
207 */
208private Connection reconnect(String schema, Connection con) throws Exception {
209        con.close();
210        return DriverManager
211                        .getConnection(connInfo.getUrl() + "/" + schema, connInfo.getUserName(), connInfo.getPassword());
212}
213 
214public static void main(String[] args) throws Exception {
215        try {
216                ConstantsDump dumper = new ConstantsDump();
217                dumper.parseArguments(args);
218                dumper.dumpMetaData();
219        }
220        catch(Exception e) {
221                System.err.println("Error!");
222                System.err.println(e.toString() + "\n-----------------------------");
223                System.err.println("The following arguments: ");
224                for(String arg : args) {
225                        System.err.print("'" + arg + "' ");
226                }
227                System.err.println("\n\nApplication arguments are\n");
228                System.err
229                                .println("  -driver xxx          Java.class.driver (e.g. com.mysql.jdbc.Driver)\n"//
230                                                + "  -url xxx             Url to db e.g. jdbc:mysql://127.0.0.1:3306\n"//
231                                                + "  -user xxx            Db user, e.g. scott\n" // 
232                                                + "  -password xxx        Db password, e.g. tiger\n" //
233                                                + "  -schema xxx,xxx,...  Db schema.. for several schemas separate using ',' and no spaces!\n"//
234                                                + "  -outputdir xxx       Destination folder to place the generated files (not the top src folder!). \n" //
235                                                + "  -javapackage xxx     Destination package for the generated classes (must match the '-outputdir')\n"//
236                                                + "  -verbose             (optional) Output much more info\n" //
237                                                + "  -overwrite           (optional) Overwrite generated classes (false pr. default)\n");
238                throw e;
239        }
240}
241 
242public void parseArguments(String... args) {
243        for(int i = 0; i < args.length; i++) {
244                // control info
245                if(args[i].equals("-driver")) {
246                        connInfo.setDriverClass(args[++i]);
247                }
248                if(args[i].equals("-password")) {
249                        connInfo.setPassword(args[++i]);
250                }
251                if(args[i].equals("-user")) {
252                        connInfo.setUserName(args[++i]);
253                }
254                if(args[i].equals("-url")) {
255                        connInfo.setUrl(args[++i]);
256                }
257 
258                if(args[i].equals("-schema")) {
259                        connInfo.getSchemaNames().addAll(Arrays.asList(args[++i].split(",")));
260                }
261                // formatter settings
262                if(args[i].equals("-outputdir")) {
263                        formatInfo.setOutputDir(args[++i]);
264                }
265                if(args[i].equals("-javapackage")) {
266                        formatInfo.setPackageName(args[++i]);
267                }
268 
269                // other
270                if(args[i].equals("-verbose")) {
271                        verbose = true;
272                }
273                if(args[i].equals("-overwrite")) {
274                        formatInfo.setOverwrite(true);
275                }
276        }
277}
278 
279/**
280 * When calling this method, you must have set the connection info and the format info or call
281 * <code>parseArguments()</code>.
282 * 
283 * @see parseArguments(String...)
284 */
285public void dumpMetaData() throws Exception {
286        connInfo.validate();
287        formatInfo.validate();
288        Connection connection = connect();
289        // schema, table, column -> null
290        ThreeDHashMap<String, String, String, Object> metaData = getMetaData(connInfo, connection);
291 
292        for(String schema : connInfo.getSchemaNames()) {
293                processSchema(schema, metaData.get(schema));
294        }
295}
296}

[all classes][org.sqlorm.metadatadumper]
EMMA 2.0.5312 (C) Vladimir Roubtsov