javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java
branchelements
changeset 1073 9321b4016d5c
parent 1010 e2d1dc505c24
child 1078 fc4fc1633445
     1.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Thu Apr 18 17:34:28 2013 +0200
     1.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Thu May 02 10:08:35 2013 +0200
     1.3 @@ -299,109 +299,85 @@
     1.4          }
     1.5          String pkg = findPkgName(e);
     1.6  
     1.7 -        ProcessPage pp;
     1.8 -        try (InputStream is = openStream(pkg, p.xhtml())) {
     1.9 -            pp = ProcessPage.readPage(is);
    1.10 -            is.close();
    1.11 -        } catch (IOException iOException) {
    1.12 -            error("Can't read " + p.xhtml() + " as " + iOException.getMessage(), e);
    1.13 -            ok = false;
    1.14 -            pp = null;
    1.15 -        }
    1.16 -        Writer w;
    1.17 -        String className = p.className();
    1.18 -        if (className.isEmpty()) {
    1.19 -            int indx = p.xhtml().indexOf('.');
    1.20 -            className = p.xhtml().substring(0, indx);
    1.21 -        }
    1.22 -        try {
    1.23 -            StringWriter body = new StringWriter();
    1.24 -            List<String> propsGetSet = new ArrayList<>();
    1.25 -            List<String> functions = new ArrayList<>();
    1.26 -            Map<String, Collection<String>> propsDeps = new HashMap<>();
    1.27 -            Map<String, Collection<String>> functionDeps = new HashMap<>();
    1.28 -            
    1.29 -            Prprt[] props = createProps(e, p.properties());
    1.30 -            if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
    1.31 -                ok = false;
    1.32 +            ProcessPage pp;
    1.33 +            ElementGenerator eGen = new ElementGenerator(processingEnv);
    1.34 +            try {
    1.35 +                InputStream is = openStream(pkg, p.xhtml());
    1.36 +                pp = ProcessPage.readPage(is);
    1.37 +                is.close();
    1.38 +            } catch (IOException iOException) {
    1.39 +                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't read " + p.xhtml(), e);
    1.40 +                return false;
    1.41              }
    1.42 -            if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
    1.43 -                ok = false;
    1.44 +            Writer w;
    1.45 +            String className = p.className();
    1.46 +            if (className.isEmpty()) {
    1.47 +                int indx = p.xhtml().indexOf('.');
    1.48 +                className = p.xhtml().substring(0, indx);
    1.49              }
    1.50 -            if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
    1.51 -                ok = false;
    1.52 -            }
    1.53 -            if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
    1.54 -                ok = false;
    1.55 -            }
    1.56 -            if (!generateReceive(e, body, className, e.getEnclosedElements(), functions)) {
    1.57 -                ok = false;
    1.58 -            }
    1.59 -            
    1.60 -            FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
    1.61 -            w = new OutputStreamWriter(java.openOutputStream());
    1.62              try {
    1.63 -                w.append("package " + pkg + ";\n");
    1.64 -                w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
    1.65 -                w.append("import org.apidesign.bck2brwsr.htmlpage.KOList;\n");
    1.66 -                w.append("final class ").append(className).append(" {\n");
    1.67 -                w.append("  private boolean locked;\n");
    1.68 -                if (!initializeOnClick(className, (TypeElement) e, w, pp)) {
    1.69 -                    ok = false;
    1.70 -                } else {
    1.71 -                    if (pp != null) for (String id : pp.ids()) {
    1.72 +                FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
    1.73 +                w = new OutputStreamWriter(java.openOutputStream());
    1.74 +                try {
    1.75 +                    w.append("package " + pkg + ";\n");
    1.76 +                    w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
    1.77 +                    w.append("final class ").append(className).append(" {\n");
    1.78 +                    w.append("  private boolean locked;\n");
    1.79 +                    if (!initializeOnClick(className, (TypeElement) e, w, pp)) {
    1.80 +                        return false;
    1.81 +                    }
    1.82 +                    for (String id : pp.ids()) {
    1.83                          String tag = pp.tagNameForId(id);
    1.84 -                        String type = type(tag);
    1.85 +                        String type = eGen.getType(pkg, tag, e);
    1.86                          w.append("  ").append("public final ").
    1.87                              append(type).append(' ').append(cnstnt(id)).append(" = new ").
    1.88                              append(type).append("(\"").append(id).append("\");\n");
    1.89                      }
    1.90 +                    List<String> propsGetSet = new ArrayList<String>();
    1.91 +                    Map<String, Collection<String>> functionDeps = new HashMap<>();
    1.92 +                    Map<String,Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
    1.93 +                    List<String> functions = new ArrayList<>();
    1.94 +                    Prprt[] props = createProps(e, p.properties());
    1.95 +                    if (!generateComputedProperties(w, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
    1.96 +                        ok = false;
    1.97 +                    }
    1.98 +                    if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
    1.99 +                        ok = false;
   1.100 +                    }
   1.101 +                    if (!generateProperties(e, w, props, propsGetSet, propsDeps, functionDeps)) {
   1.102 +                        ok = false;
   1.103 +                    }
   1.104 +                    if (!generateFunctions(e, w, className, e.getEnclosedElements(), functions)) {
   1.105 +                        ok = false;
   1.106 +                    }
   1.107 +                    if (!generateReceive(e, w, className, e.getEnclosedElements(), functions)) {
   1.108 +                        ok = false;
   1.109 +                    }                    
   1.110 +                    w.append("  private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
   1.111 +                    if (!propsGetSet.isEmpty()) {
   1.112 +                        w.write("public " + className + " applyBindings() {\n");
   1.113 +                        w.write("  ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings(");
   1.114 +                        w.write(className + ".class, this, ");
   1.115 +                        writeStringArray(propsGetSet, w);
   1.116 +                        w.append(", ");
   1.117 +                        writeStringArray(functions, w);
   1.118 +                        w.write(");\n  return this;\n}\n");
   1.119 +
   1.120 +                        w.write("public void triggerEvent(Element e, OnEvent ev) {\n");
   1.121 +                        w.write("  org.apidesign.bck2brwsr.htmlpage.Knockout.triggerEvent(e.getId(), ev.getElementPropertyName());\n");
   1.122 +                        w.write("}\n");
   1.123 +                    }
   1.124 +                    w.append("}\n");
   1.125 +                } finally {
   1.126 +                    w.close();
   1.127                  }
   1.128 -                w.append("  private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
   1.129 -                w.append(body.toString());
   1.130 -                if (!propsGetSet.isEmpty()) {
   1.131 -                    w.write("public " + className + " applyBindings() {\n");
   1.132 -                    w.write("  ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings(");
   1.133 -                    w.write(className + ".class, this, ");
   1.134 -                    writeStringArray(propsGetSet, w);
   1.135 -                    w.append(", ");
   1.136 -                    writeStringArray(functions, w);
   1.137 -                    w.write(");\n  return this;\n}\n");
   1.138 -
   1.139 -                    w.write("public void triggerEvent(Element e, OnEvent ev) {\n");
   1.140 -                    w.write("  org.apidesign.bck2brwsr.htmlpage.Knockout.triggerEvent(e.getId(), ev.getElementPropertyName());\n");
   1.141 -                    w.write("}\n");
   1.142 -                }
   1.143 -                w.append("}\n");
   1.144 -            } finally {
   1.145 -                w.close();
   1.146 +            } catch (IOException ex) {
   1.147 +                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't create " + className + ".java", e);
   1.148 +                return false;
   1.149              }
   1.150 -        } catch (IOException ex) {
   1.151 -            error("Can't create " + className + ".java", e);
   1.152 -            return false;
   1.153 -        }
   1.154          return ok;
   1.155      }
   1.156  
   1.157 -    private static String type(String tag) {
   1.158 -        if (tag.equals("title")) {
   1.159 -            return "Title";
   1.160 -        }
   1.161 -        if (tag.equals("button")) {
   1.162 -            return "Button";
   1.163 -        }
   1.164 -        if (tag.equals("input")) {
   1.165 -            return "Input";
   1.166 -        }
   1.167 -        if (tag.equals("canvas")) {
   1.168 -            return "Canvas";
   1.169 -        }
   1.170 -        if (tag.equals("img")) {
   1.171 -            return "Image";
   1.172 -        }
   1.173 -        return "Element";
   1.174 -    }
   1.175 -
   1.176      private static String cnstnt(String id) {
   1.177          return id.replace('.', '_').replace('-', '_');
   1.178      }
   1.179 @@ -409,7 +385,6 @@
   1.180      private boolean initializeOnClick(
   1.181          String className, TypeElement type, Writer w, ProcessPage pp
   1.182      ) throws IOException {
   1.183 -        boolean ok = true;
   1.184          TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
   1.185          { //for (Element clazz : pe.getEnclosedElements()) {
   1.186            //  if (clazz.getKind() != ElementKind.CLASS) {
   1.187 @@ -422,27 +397,58 @@
   1.188                  On oc = method.getAnnotation(On.class);
   1.189                  if (oc != null) {
   1.190                      for (String id : oc.id()) {
   1.191 -                        if (pp == null) {
   1.192 -                            error("id = " + id + " not found in HTML page.", method);
   1.193 -                            ok = false;
   1.194 -                            continue;
   1.195 -                        }
   1.196                          if (pp.tagNameForId(id) == null) {
   1.197 -                            error("id = " + id + " does not exist in the HTML page. Found only " + pp.ids(), method);
   1.198 -                            ok = false;
   1.199 -                            continue;
   1.200 +                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "id = " + id + " does not exist in the HTML page. Found only " + pp.ids(), method);
   1.201 +                            return false;
   1.202                          }
   1.203                          ExecutableElement ee = (ExecutableElement)method;
   1.204 -                        CharSequence params = wrapParams(ee, id, className, "ev", null);
   1.205 +                        StringBuilder params = new StringBuilder();
   1.206 +                        {
   1.207 +                            boolean first = true;
   1.208 +                            for (VariableElement ve : ee.getParameters()) {
   1.209 +                                if (!first) {
   1.210 +                                    params.append(", ");
   1.211 +                                }
   1.212 +                                first = false;
   1.213 +                                if (ve.asType() == stringType) {
   1.214 +                                    if (ve.getSimpleName().contentEquals("id")) {
   1.215 +                                        params.append('"').append(id).append('"');
   1.216 +                                        continue;
   1.217 +                                    }
   1.218 +                                    params.append("org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toString(ev, \"");
   1.219 +                                    params.append(ve.getSimpleName().toString());
   1.220 +                                    params.append("\")");
   1.221 +                                    continue;
   1.222 +                                }
   1.223 +                                if (processingEnv.getTypeUtils().getPrimitiveType(TypeKind.DOUBLE) == ve.asType()) {
   1.224 +                                    params.append("org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toDouble(ev, \"");
   1.225 +                                    params.append(ve.getSimpleName().toString());
   1.226 +                                    params.append("\")");
   1.227 +                                    continue;
   1.228 +                                }
   1.229 +                                String rn = ve.asType().toString();
   1.230 +                                int last = rn.lastIndexOf('.');
   1.231 +                                if (last >= 0) {
   1.232 +                                    rn = rn.substring(last + 1);
   1.233 +                                }
   1.234 +                                if (rn.equals(className)) {
   1.235 +                                    params.append(className).append(".this");
   1.236 +                                    continue;
   1.237 +                                }
   1.238 +                                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
   1.239 +                                    "@On method can only accept String named 'id' or " + className + " arguments",
   1.240 +                                    ee
   1.241 +                                );
   1.242 +                                return false;
   1.243 +                            }
   1.244 +                        }
   1.245                          if (!ee.getModifiers().contains(Modifier.STATIC)) {
   1.246 -                            error("@On method has to be static", ee);
   1.247 -                            ok = false;
   1.248 -                            continue;
   1.249 +                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method has to be static", ee);
   1.250 +                            return false;
   1.251                          }
   1.252                          if (ee.getModifiers().contains(Modifier.PRIVATE)) {
   1.253 -                            error("@On method can't be private", ee);
   1.254 -                            ok = false;
   1.255 -                            continue;
   1.256 +                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method can't be private", ee);
   1.257 +                            return false;
   1.258                          }
   1.259                          w.append("  OnEvent." + oc.event()).append(".of(").append(cnstnt(id)).
   1.260                              append(").perform(new OnDispatch(" + dispatchCnt + "));\n");
   1.261 @@ -473,7 +479,7 @@
   1.262              
   1.263  
   1.264          }
   1.265 -        return ok;
   1.266 +        return true;
   1.267      }
   1.268  
   1.269      @Override
   1.270 @@ -487,7 +493,8 @@
   1.271          
   1.272          Element cls = findClass(element);
   1.273          Page p = cls.getAnnotation(Page.class);
   1.274 -        String pkg = findPkgName(cls);
   1.275 +        PackageElement pe = (PackageElement) cls.getEnclosingElement();
   1.276 +        String pkg = pe.getQualifiedName().toString();
   1.277          ProcessPage pp;
   1.278          try {
   1.279              InputStream is = openStream(pkg, p.xhtml());
   1.280 @@ -497,7 +504,7 @@
   1.281              return Collections.emptyList();
   1.282          }
   1.283          
   1.284 -        List<Completion> cc = new ArrayList<>();
   1.285 +        List<Completion> cc = new ArrayList<Completion>();
   1.286          userText = userText.substring(1);
   1.287          for (String id : pp.ids()) {
   1.288              if (id.startsWith(userText)) {
   1.289 @@ -771,9 +778,9 @@
   1.290      }
   1.291  
   1.292      private boolean generateFunctions(
   1.293 -        Element clazz, StringWriter body, String className, 
   1.294 +        Element clazz, Writer body, String className, 
   1.295          List<? extends Element> enclosedElements, List<String> functions
   1.296 -    ) {
   1.297 +    ) throws IOException {
   1.298          for (Element m : enclosedElements) {
   1.299              if (m.getKind() != ElementKind.METHOD) {
   1.300                  continue;
   1.301 @@ -868,9 +875,9 @@
   1.302      }
   1.303      
   1.304      private boolean generateReceive(
   1.305 -        Element clazz, StringWriter body, String className, 
   1.306 +        Element clazz, Writer body, String className, 
   1.307          List<? extends Element> enclosedElements, List<String> functions
   1.308 -    ) {
   1.309 +    ) throws IOException {
   1.310          for (Element m : enclosedElements) {
   1.311              if (m.getKind() != ElementKind.METHOD) {
   1.312                  continue;