javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java
branchmodel
changeset 879 af170d42b5b3
parent 878 ecbd252fd3a7
child 887 13dc5ada296b
     1.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Fri Mar 22 17:03:32 2013 +0100
     1.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Mon Mar 25 11:50:36 2013 +0100
     1.3 @@ -55,6 +55,7 @@
     1.4  import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
     1.5  import org.apidesign.bck2brwsr.htmlpage.api.Model;
     1.6  import org.apidesign.bck2brwsr.htmlpage.api.On;
     1.7 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
     1.8  import org.apidesign.bck2brwsr.htmlpage.api.Page;
     1.9  import org.apidesign.bck2brwsr.htmlpage.api.Property;
    1.10  import org.openide.util.lookup.ServiceProvider;
    1.11 @@ -68,6 +69,7 @@
    1.12  @SupportedAnnotationTypes({
    1.13      "org.apidesign.bck2brwsr.htmlpage.api.Model",
    1.14      "org.apidesign.bck2brwsr.htmlpage.api.Page",
    1.15 +    "org.apidesign.bck2brwsr.htmlpage.api.OnFunction",
    1.16      "org.apidesign.bck2brwsr.htmlpage.api.On"
    1.17  })
    1.18  public final class PageProcessor extends AbstractProcessor {
    1.19 @@ -164,6 +166,7 @@
    1.20          try {
    1.21              StringWriter body = new StringWriter();
    1.22              List<String> propsGetSet = new ArrayList<>();
    1.23 +            List<String> functions = new ArrayList<>();
    1.24              Map<String, Collection<String>> propsDeps = new HashMap<>();
    1.25              if (!generateComputedProperties(body, p.properties(), e.getEnclosedElements(), propsGetSet, propsDeps)) {
    1.26                  ok = false;
    1.27 @@ -171,6 +174,9 @@
    1.28              if (!generateProperties(e, body, p.properties(), propsGetSet, propsDeps)) {
    1.29                  ok = false;
    1.30              }
    1.31 +            if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
    1.32 +                ok = false;
    1.33 +            }
    1.34              
    1.35              FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
    1.36              w = new OutputStreamWriter(java.openOutputStream());
    1.37 @@ -208,6 +214,13 @@
    1.38                          }
    1.39                          sep = ",\n";
    1.40                      }
    1.41 +                    w.write("\n  }, new String[] {\n");
    1.42 +                    sep = "";
    1.43 +                    for (String n : functions) {
    1.44 +                        w.write(sep);
    1.45 +                        w.write(n);
    1.46 +                        sep = ",\n";
    1.47 +                    }
    1.48                      w.write("\n  });\n  return this;\n}\n");
    1.49  
    1.50                      w.write("public void triggerEvent(Element e, OnEvent ev) {\n");
    1.51 @@ -275,46 +288,7 @@
    1.52                              continue;
    1.53                          }
    1.54                          ExecutableElement ee = (ExecutableElement)method;
    1.55 -                        StringBuilder params = new StringBuilder();
    1.56 -                        {
    1.57 -                            boolean first = true;
    1.58 -                            for (VariableElement ve : ee.getParameters()) {
    1.59 -                                if (!first) {
    1.60 -                                    params.append(", ");
    1.61 -                                }
    1.62 -                                first = false;
    1.63 -                                if (ve.asType() == stringType) {
    1.64 -                                    if (ve.getSimpleName().contentEquals("id")) {
    1.65 -                                        params.append('"').append(id).append('"');
    1.66 -                                        continue;
    1.67 -                                    }
    1.68 -                                    params.append("org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toString(ev, \"");
    1.69 -                                    params.append(ve.getSimpleName().toString());
    1.70 -                                    params.append("\")");
    1.71 -                                    continue;
    1.72 -                                }
    1.73 -                                if (processingEnv.getTypeUtils().getPrimitiveType(TypeKind.DOUBLE) == ve.asType()) {
    1.74 -                                    params.append("org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toDouble(ev, \"");
    1.75 -                                    params.append(ve.getSimpleName().toString());
    1.76 -                                    params.append("\")");
    1.77 -                                    continue;
    1.78 -                                }
    1.79 -                                String rn = ve.asType().toString();
    1.80 -                                int last = rn.lastIndexOf('.');
    1.81 -                                if (last >= 0) {
    1.82 -                                    rn = rn.substring(last + 1);
    1.83 -                                }
    1.84 -                                if (rn.equals(className)) {
    1.85 -                                    params.append(className).append(".this");
    1.86 -                                    continue;
    1.87 -                                }
    1.88 -                                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
    1.89 -                                    "@On method can only accept String named 'id' or " + className + " arguments",
    1.90 -                                    ee
    1.91 -                                );
    1.92 -                                return false;
    1.93 -                            }
    1.94 -                        }
    1.95 +                        CharSequence params = wrapParams(ee, id, className, "ev", null);
    1.96                          if (!ee.getModifiers().contains(Modifier.STATIC)) {
    1.97                              processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method has to be static", ee);
    1.98                              ok = false;
    1.99 @@ -659,4 +633,105 @@
   1.100              e = e.getEnclosingElement();
   1.101          }
   1.102      }
   1.103 +
   1.104 +    private boolean generateFunctions(
   1.105 +        Element clazz, StringWriter body, String className, 
   1.106 +        List<? extends Element> enclosedElements, List<String> functions
   1.107 +    ) {
   1.108 +        for (Element m : enclosedElements) {
   1.109 +            if (m.getKind() != ElementKind.METHOD) {
   1.110 +                continue;
   1.111 +            }
   1.112 +            ExecutableElement e = (ExecutableElement)m;
   1.113 +            OnFunction onF = e.getAnnotation(OnFunction.class);
   1.114 +            if (onF == null) {
   1.115 +                continue;
   1.116 +            }
   1.117 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
   1.118 +                processingEnv.getMessager().printMessage(
   1.119 +                    Diagnostic.Kind.ERROR, "@OnFunction method needs to be static", e
   1.120 +                );
   1.121 +                return false;
   1.122 +            }
   1.123 +            if (e.getModifiers().contains(Modifier.PRIVATE)) {
   1.124 +                processingEnv.getMessager().printMessage(
   1.125 +                    Diagnostic.Kind.ERROR, "@OnFunction method cannot be private", e
   1.126 +                );
   1.127 +                return false;
   1.128 +            }
   1.129 +            if (e.getReturnType().getKind() != TypeKind.VOID) {
   1.130 +                processingEnv.getMessager().printMessage(
   1.131 +                    Diagnostic.Kind.ERROR, "@OnFunction method should return void", e
   1.132 +                );
   1.133 +                return false;
   1.134 +            }
   1.135 +            String n = e.getSimpleName().toString();
   1.136 +            body.append("private void ").append(n).append("(Object data, Object ev) {\n");
   1.137 +            body.append("  ").append(clazz.getSimpleName()).append(".").append(n).append("(");
   1.138 +            body.append(wrapParams(e, null, className, "ev", "data"));
   1.139 +            body.append(");\n");
   1.140 +            body.append("}\n");
   1.141 +            
   1.142 +            functions.add('\"' + n + '\"');
   1.143 +            functions.add('\"' + n + "__VLjava_lang_Object_2Ljava_lang_Object_2" + '\"');
   1.144 +        }
   1.145 +        return true;
   1.146 +    }
   1.147 +
   1.148 +    private CharSequence wrapParams(
   1.149 +        ExecutableElement ee, String id, String className, String evName, String dataName
   1.150 +    ) {
   1.151 +        TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
   1.152 +        StringBuilder params = new StringBuilder();
   1.153 +        boolean first = true;
   1.154 +        for (VariableElement ve : ee.getParameters()) {
   1.155 +            if (!first) {
   1.156 +                params.append(", ");
   1.157 +            }
   1.158 +            first = false;
   1.159 +            String toCall = null;
   1.160 +            if (ve.asType() == stringType) {
   1.161 +                if (ve.getSimpleName().contentEquals("id")) {
   1.162 +                    params.append('"').append(id).append('"');
   1.163 +                    continue;
   1.164 +                }
   1.165 +                toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toString";
   1.166 +            }
   1.167 +            if (ve.asType().getKind() == TypeKind.DOUBLE) {
   1.168 +                toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toDouble";
   1.169 +            }
   1.170 +            if (ve.asType().getKind() == TypeKind.INT) {
   1.171 +                toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toInt";
   1.172 +            }
   1.173 +
   1.174 +            if (toCall != null) {
   1.175 +                params.append(toCall).append('(');
   1.176 +                if (dataName != null && ve.getSimpleName().contentEquals("data")) {
   1.177 +                    params.append(dataName);
   1.178 +                    params.append(", null");
   1.179 +                } else {
   1.180 +                    params.append(evName);
   1.181 +                    params.append(", \"");
   1.182 +                    params.append(ve.getSimpleName().toString());
   1.183 +                    params.append("\"");
   1.184 +                }
   1.185 +                params.append(")");
   1.186 +                continue;
   1.187 +            }
   1.188 +            String rn = ve.asType().toString();
   1.189 +            int last = rn.lastIndexOf('.');
   1.190 +            if (last >= 0) {
   1.191 +                rn = rn.substring(last + 1);
   1.192 +            }
   1.193 +            if (rn.equals(className)) {
   1.194 +                params.append(className).append(".this");
   1.195 +                continue;
   1.196 +            }
   1.197 +            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
   1.198 +                "@On method can only accept String named 'id' or " + className + " arguments",
   1.199 +                ee
   1.200 +            );
   1.201 +        }
   1.202 +        return params;
   1.203 +    }
   1.204  }