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