samples/livedb/src/org/apidesign/livedb/impl/LiveDBProcessor.java
author Jaroslav Tulach <jtulach@netbeans.org>
Fri, 30 Jul 2010 14:13:25 +0200
changeset 363 cbeeeb6ae9c6
parent 361 6507a9474b6d
child 365 0b7ec6ef8a72
permissions -rw-r--r--
Shorter lines and less scary code of the processor
jtulach@355
     1
package org.apidesign.livedb.impl;
jtulach@355
     2
jtulach@355
     3
import java.io.IOException;
jtulach@355
     4
import java.io.Writer;
jtulach@357
     5
import java.sql.CallableStatement;
jtulach@357
     6
import java.sql.Connection;
jtulach@357
     7
import java.sql.Driver;
jtulach@357
     8
import java.sql.ResultSet;
jtulach@357
     9
import java.sql.ResultSetMetaData;
jtulach@357
    10
import java.sql.SQLException;
jtulach@358
    11
import java.util.Properties;
jtulach@358
    12
import java.util.ServiceLoader;
jtulach@355
    13
import java.util.Set;
jtulach@355
    14
import javax.annotation.processing.AbstractProcessor;
jtulach@363
    15
import javax.annotation.processing.Filer;
jtulach@355
    16
import javax.annotation.processing.Processor;
jtulach@355
    17
import javax.annotation.processing.RoundEnvironment;
jtulach@355
    18
import javax.annotation.processing.SupportedAnnotationTypes;
jtulach@355
    19
import javax.annotation.processing.SupportedSourceVersion;
jtulach@355
    20
import javax.lang.model.SourceVersion;
jtulach@355
    21
import javax.lang.model.element.Element;
jtulach@355
    22
import javax.lang.model.element.PackageElement;
jtulach@355
    23
import javax.lang.model.element.TypeElement;
jtulach@355
    24
import javax.tools.JavaFileObject;
jtulach@355
    25
import org.apidesign.livedb.LiveDB;
jtulach@355
    26
import org.openide.util.lookup.ServiceProvider;
jtulach@355
    27
jtulach@355
    28
/**
jtulach@355
    29
 *
jtulach@355
    30
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jtulach@355
    31
 */
jtulach@361
    32
// BEGIN: livedb.processor
jtulach@355
    33
@SupportedAnnotationTypes("org.apidesign.livedb.LiveDB")
jtulach@355
    34
@SupportedSourceVersion(SourceVersion.RELEASE_6)
jtulach@355
    35
@ServiceProvider(service=Processor.class)
jtulach@361
    36
public final class LiveDBProcessor extends AbstractProcessor {
jtulach@355
    37
    @Override
jtulach@363
    38
    public boolean process(
jtulach@363
    39
        Set<? extends TypeElement> annotations, RoundEnvironment roundEnv
jtulach@363
    40
    ) {
jtulach@363
    41
        final Filer filer = processingEnv.getFiler();
jtulach@355
    42
        for (Element e : roundEnv.getElementsAnnotatedWith(LiveDB.class)) {
jtulach@355
    43
            LiveDB db = e.getAnnotation(LiveDB.class);
jtulach@355
    44
            PackageElement pe = (PackageElement)e;
jtulach@363
    45
            String clsName = pe.getQualifiedName() + "." + db.classname();
jtulach@355
    46
            try {
jtulach@363
    47
                JavaFileObject src = filer.createSourceFile(clsName, pe);
jtulach@355
    48
                Writer w = src.openWriter();
jtulach@363
    49
                Connection c = getConnection(
jtulach@363
    50
                    db.url(), db.user(), db.password()
jtulach@363
    51
                );
jtulach@357
    52
                CallableStatement s = c.prepareCall(db.query());
jtulach@357
    53
                ResultSet rs = s.executeQuery();
jtulach@357
    54
                ResultSetMetaData md = rs.getMetaData();
jtulach@363
    55
                generateClassHeader(w, pe, db);
jtulach@355
    56
                w.append("class " + db.classname() + " {\n");
jtulach@357
    57
                for (int i = 1; i <= md.getColumnCount(); i++) {
jtulach@363
    58
                    generateField(w, md, i);
jtulach@357
    59
                }
jtulach@363
    60
                generateConstructor(w, db, md);
jtulach@363
    61
                generateQueryMethod(w, db, md);
jtulach@355
    62
                w.append("}");
jtulach@355
    63
                w.close();
jtulach@355
    64
            } catch (IOException ex) {
jtulach@355
    65
                throw new IllegalStateException(ex);
jtulach@357
    66
            } catch (SQLException ex) {
jtulach@357
    67
                throw new IllegalStateException(ex);
jtulach@355
    68
            }
jtulach@355
    69
        }
jtulach@355
    70
        return true;
jtulach@355
    71
    }
jtulach@361
    72
// FINISH: livedb.processor
jtulach@363
    73
jtulach@363
    74
    private void generateQueryMethod(Writer w, LiveDB db, ResultSetMetaData md) throws SQLException, IOException {
jtulach@363
    75
        w.append("  public static List<" + db.classname() + "> ")
jtulach@363
    76
         .append("query() throws SQLException {\n");
jtulach@363
    77
        w.append("    Connection c = DriverManager.getConnection(\"")
jtulach@363
    78
         .append(db.url()).append("\", \"")
jtulach@363
    79
         .append(db.user()).append("\", \"")
jtulach@363
    80
         .append(db.password()).append("\");\n");
jtulach@363
    81
        w.append("    List<").append(db.classname())
jtulach@363
    82
         .append("> res = new ArrayList<")
jtulach@363
    83
         .append(db.classname()).append(">();\n");
jtulach@363
    84
        w.append("    CallableStatement s = c.prepareCall(\"")
jtulach@363
    85
         .append(db.query()).append("\");\n");
jtulach@363
    86
        w.append("    ResultSet rs = s.executeQuery();\n");
jtulach@363
    87
        w.append("    ResultSetMetaData md = rs.getMetaData();\n");
jtulach@363
    88
        w.append("    while (rs.next()) {\n");
jtulach@363
    89
        w.append("      res.add(new " + db.classname() + "(\n");
jtulach@363
    90
        for (int i = 1; i <= md.getColumnCount(); i++) {
jtulach@363
    91
            w.append("        (")
jtulach@363
    92
             .append(md.getColumnClassName(i))
jtulach@363
    93
             .append(")rs.getObject(" + i).append(")");
jtulach@363
    94
            if (i < md.getColumnCount()) {
jtulach@363
    95
                w.append(",\n");
jtulach@363
    96
            } else {
jtulach@363
    97
                w.append("\n");
jtulach@363
    98
            }
jtulach@363
    99
        }
jtulach@363
   100
        w.append("      ));\n");
jtulach@363
   101
        w.append("    };\n");
jtulach@363
   102
        w.append("    return res;\n");
jtulach@363
   103
        w.append("  }");
jtulach@363
   104
    }
jtulach@363
   105
jtulach@363
   106
    private void generateConstructor(Writer w, LiveDB db, ResultSetMetaData md) throws SQLException, IOException {
jtulach@363
   107
        w.append("  private " + db.classname() + "(\n");
jtulach@363
   108
        for (int i = 1; i <= md.getColumnCount(); i++) {
jtulach@363
   109
            w.append("    ").append(md.getColumnClassName(i))
jtulach@363
   110
             .append(" ").append(md.getColumnName(i));
jtulach@363
   111
            if (i < md.getColumnCount()) {
jtulach@363
   112
                w.append(",\n");
jtulach@363
   113
            } else {
jtulach@363
   114
                w.append("\n");
jtulach@363
   115
            }
jtulach@363
   116
        }
jtulach@363
   117
        w.append("  ) {\n");
jtulach@363
   118
        for (int i = 1; i <= md.getColumnCount(); i++) {
jtulach@363
   119
            w.append("    this.")
jtulach@363
   120
             .append(md.getColumnName(i))
jtulach@363
   121
             .append(" = ")
jtulach@363
   122
             .append(md.getColumnName(i))
jtulach@363
   123
             .append(";\n");
jtulach@363
   124
        }
jtulach@363
   125
        w.append("  }\n");
jtulach@363
   126
    }
jtulach@363
   127
jtulach@363
   128
    private void generateField(Writer w, ResultSetMetaData md, int i) throws IOException, SQLException {
jtulach@363
   129
        w.append("  public final ")
jtulach@363
   130
         .append(md.getColumnClassName(i))
jtulach@363
   131
         .append(" ")
jtulach@363
   132
         .append(md.getColumnName(i))
jtulach@363
   133
         .append(";\n");
jtulach@363
   134
    }
jtulach@363
   135
jtulach@363
   136
    private void generateClassHeader(Writer w, PackageElement pe, LiveDB db) throws IOException {
jtulach@363
   137
        w.append("package " + pe.getQualifiedName() + ";\n");
jtulach@363
   138
        w.append("import java.util.List;\n");
jtulach@363
   139
        w.append("import java.util.ArrayList;\n");
jtulach@363
   140
        w.append("import java.sql.*;\n");
jtulach@363
   141
    }
jtulach@358
   142
    private static Connection getConnection(String url, String user, String password) 
jtulach@358
   143
    throws SQLException {
jtulach@358
   144
        final ClassLoader cl = LiveDBProcessor.class.getClassLoader();
jtulach@358
   145
        for (Driver d : ServiceLoader.load(Driver.class, cl)) {
jtulach@358
   146
//            System.out.println("looked up: " + d);
jtulach@358
   147
            if (d.acceptsURL(url)) {
jtulach@358
   148
                //System.out.println("accepts: " + d);
jtulach@358
   149
                Properties p = new Properties();
jtulach@358
   150
                p.put("user", user);
jtulach@358
   151
                p.put("password", password);
jtulach@358
   152
                return d.connect(url, p);
jtulach@358
   153
            }
jtulach@357
   154
        }
jtulach@358
   155
        throw new SQLException("No driver found for " + url);
jtulach@357
   156
    }
jtulach@355
   157
}