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;