Introducing special JSON receiver rather than using tricks with Runnable and Object[]
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Sun, 25 Aug 2013 09:36:33 +0200
changeset 25562f7dafef4cf
parent 254 ec06d7725d5b
child 256 59202f396b49
Introducing special JSON receiver rather than using tricks with Runnable and Object[]
json/src/main/java/org/apidesign/html/json/impl/JSON.java
json/src/main/java/org/apidesign/html/json/impl/ModelProcessor.java
json/src/main/java/org/apidesign/html/json/impl/PropertyBindingAccessor.java
json/src/main/java/org/apidesign/html/json/impl/RcvrJSON.java
json/src/main/java/org/apidesign/html/json/spi/JSONCall.java
json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java
     1.1 --- a/json/src/main/java/org/apidesign/html/json/impl/JSON.java	Sat Aug 24 18:00:08 2013 +0200
     1.2 +++ b/json/src/main/java/org/apidesign/html/json/impl/JSON.java	Sun Aug 25 09:36:33 2013 +0200
     1.3 @@ -37,9 +37,6 @@
     1.4   * @author Jaroslav Tulach <jtulach@netbeans.org>
     1.5   */
     1.6  public final class JSON {
     1.7 -    /** represents null exception value */
     1.8 -    public static final Exception NULL = new NullPointerException();
     1.9 -    
    1.10      private JSON() {
    1.11      }
    1.12  
    1.13 @@ -52,7 +49,7 @@
    1.14          Transfer t = Contexts.find(c, Transfer.class);
    1.15          return t == null ? EmptyTech.EMPTY : t;
    1.16      }
    1.17 -    
    1.18 +
    1.19      public static void runInBrowser(BrwsrCtx c, Runnable runnable) {
    1.20          findTechnology(c).runSafe(runnable);
    1.21      }
    1.22 @@ -136,16 +133,6 @@
    1.23          return (Character)val;
    1.24      }
    1.25      
    1.26 -    public static Exception excValue(Object val) {
    1.27 -        if (val == NULL) {
    1.28 -            return null;
    1.29 -        }
    1.30 -        if (val instanceof Exception) {
    1.31 -            return (Exception)val;
    1.32 -        }
    1.33 -        return new Exception(val.toString());
    1.34 -    }
    1.35 -
    1.36      public static Boolean boolValue(Object val) {
    1.37          if (val instanceof String) {
    1.38              return Boolean.parseBoolean((String)val);
    1.39 @@ -154,18 +141,11 @@
    1.40      }
    1.41      
    1.42      public static void loadJSON(
    1.43 -        BrwsrCtx c, Runnable whenDone, Object[] result, 
    1.44 -        String urlBefore, String urlAfter
    1.45 -    ) {
    1.46 -        loadJSON(c, whenDone, result, urlBefore, urlAfter, null, null);
    1.47 -    }
    1.48 -
    1.49 -    public static void loadJSON(
    1.50 -        BrwsrCtx c, Runnable whenDone, Object[] result,
    1.51 +        BrwsrCtx c, RcvrJSON callback,
    1.52          String urlBefore, String urlAfter, String method,
    1.53          Object data
    1.54      ) {
    1.55 -        JSONCall call = PropertyBindingAccessor.createCall(whenDone, result, urlBefore, urlAfter, method, data);
    1.56 +        JSONCall call = PropertyBindingAccessor.createCall(callback, urlBefore, urlAfter, method, data);
    1.57          Transfer t = findTransfer(c);
    1.58          t.loadJSON(call);
    1.59      }
     2.1 --- a/json/src/main/java/org/apidesign/html/json/impl/ModelProcessor.java	Sat Aug 24 18:00:08 2013 +0200
     2.2 +++ b/json/src/main/java/org/apidesign/html/json/impl/ModelProcessor.java	Sun Aug 25 09:36:33 2013 +0200
     2.3 @@ -982,40 +982,39 @@
     2.4                  }
     2.5              }
     2.6              body.append(") {\n");
     2.7 -            body.append("    final Object[] result = { null };\n");
     2.8              body.append(
     2.9 -                "    class ProcessResult implements Runnable {\n" +
    2.10 +                "    class ProcessResult extends org.apidesign.html.json.impl.RcvrJSON {\n" +
    2.11                  "      @Override\n" +
    2.12 -                "      public void run() {\n" +
    2.13 -                "        Object value = result[0];\n" +
    2.14 -                "        if (value instanceof Throwable) {\n");
    2.15 +                "      public void onError(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n" +
    2.16 +                "        Exception value = ev.getException();\n"
    2.17 +            );
    2.18              if (onR.onError().isEmpty()) {
    2.19                  body.append(
    2.20 -                "          ((Throwable)value).printStackTrace(); return;\n"
    2.21 +                "        value.printStackTrace();\n"
    2.22                  );
    2.23              } else {
    2.24                  if (!findOnError(e, ((TypeElement)clazz), onR.onError(), className)) {
    2.25                      return false;
    2.26                  }
    2.27 -                body.append("          ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
    2.28 -                body.append(className).append(".this, org.apidesign.html.json.impl.JSON.excValue(value)); return;\n");
    2.29 +                body.append("        ").append(clazz.getSimpleName()).append(".").append(onR.onError()).append("(");
    2.30 +                body.append(className).append(".this, value);\n");
    2.31              }
    2.32              body.append(
    2.33 -                "        }\n"
    2.34 +                "      }\n" +
    2.35 +                "      @Override\n" +
    2.36 +                "      public void onMessage(org.apidesign.html.json.impl.RcvrJSON.MsgEvnt ev) {\n"
    2.37              );
    2.38 +            if (expectsList) {
    2.39 +                body.append(
    2.40 +                    "        " + modelClass + "[] arr = new " + modelClass + "[ev.dataSize()];\n"
    2.41 +                );
    2.42 +            } else {
    2.43 +                body.append(
    2.44 +                    "        " + modelClass + "[] arr = { null };\n"
    2.45 +                );
    2.46 +            }
    2.47              body.append(
    2.48 -                "        " + modelClass + "[] arr;\n");
    2.49 -            body.append(
    2.50 -                "        if (value instanceof Object[]) {\n" +
    2.51 -                "          Object[] data = ((Object[])value);\n" +
    2.52 -                "          arr = new " + modelClass + "[data.length];\n" +
    2.53 -                "          for (int i = 0; i < data.length; i++) {\n" +
    2.54 -                "            arr[i] = org.apidesign.html.json.impl.JSON.read(context, " + modelClass + ".class, data[i]);\n" +
    2.55 -                "          }\n" +
    2.56 -                "        } else {\n" +
    2.57 -                "          arr = new " + modelClass + "[1];\n" +
    2.58 -                "          arr[0] = org.apidesign.html.json.impl.JSON.read(context, " + modelClass + ".class, value);\n" +
    2.59 -                "        }\n"
    2.60 +                "        ev.dataRead(context, " + modelClass + ".class, arr);\n"
    2.61              );
    2.62              {
    2.63                  body.append("        ").append(clazz.getSimpleName()).append(".").append(n).append("(");
    2.64 @@ -1032,7 +1031,7 @@
    2.65                  "    }\n"
    2.66              );
    2.67              body.append("    ProcessResult pr = new ProcessResult();\n");
    2.68 -            body.append("    org.apidesign.html.json.impl.JSON.loadJSON(context, pr, result,\n        ");
    2.69 +            body.append("    org.apidesign.html.json.impl.JSON.loadJSON(context, pr,\n        ");
    2.70              body.append(urlBefore).append(", ");
    2.71              if (jsonpVarName != null) {
    2.72                  body.append(urlAfter);
    2.73 @@ -1046,6 +1045,8 @@
    2.74                  } else {
    2.75                      body.append(", null");
    2.76                  }
    2.77 +            } else {
    2.78 +                body.append(", null, null");
    2.79              }
    2.80              body.append(");\n");
    2.81  //            body.append("  ").append(clazz.getSimpleName()).append(".").append(n).append("(");
     3.1 --- a/json/src/main/java/org/apidesign/html/json/impl/PropertyBindingAccessor.java	Sat Aug 24 18:00:08 2013 +0200
     3.2 +++ b/json/src/main/java/org/apidesign/html/json/impl/PropertyBindingAccessor.java	Sun Aug 25 09:36:33 2013 +0200
     3.3 @@ -43,7 +43,7 @@
     3.4      protected abstract <M> PropertyBinding newBinding(PBData<M> d);
     3.5      protected abstract <M> FunctionBinding newFunction(FBData<M> d);
     3.6      protected abstract JSONCall newCall(
     3.7 -        Runnable whenDone, Object[] result, String urlBefore, String urlAfter, String method, Object data);
     3.8 +        RcvrJSON callback, String urlBefore, String urlAfter, String method, Object data);
     3.9  
    3.10      
    3.11      static <M> PropertyBinding create(PBData<M> d) {
    3.12 @@ -53,8 +53,8 @@
    3.13          return DEFAULT.newFunction(d);
    3.14      }
    3.15      static JSONCall createCall(
    3.16 -        Runnable whenDone, Object[] result, String urlBefore, String urlAfter, String method, Object data) {
    3.17 -        return DEFAULT.newCall(whenDone, result, urlBefore, urlAfter, method, data);
    3.18 +        RcvrJSON callback, String urlBefore, String urlAfter, String method, Object data) {
    3.19 +        return DEFAULT.newCall(callback, urlBefore, urlAfter, method, data);
    3.20      }
    3.21  
    3.22      public static final class PBData<M> {
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/json/src/main/java/org/apidesign/html/json/impl/RcvrJSON.java	Sun Aug 25 09:36:33 2013 +0200
     4.3 @@ -0,0 +1,127 @@
     4.4 +/**
     4.5 + * HTML via Java(tm) Language Bindings
     4.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     4.7 + *
     4.8 + * This program is free software: you can redistribute it and/or modify
     4.9 + * it under the terms of the GNU General Public License as published by
    4.10 + * the Free Software Foundation, version 2 of the License.
    4.11 + *
    4.12 + * This program is distributed in the hope that it will be useful,
    4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.15 + * GNU General Public License for more details. apidesign.org
    4.16 + * designates this particular file as subject to the
    4.17 + * "Classpath" exception as provided by apidesign.org
    4.18 + * in the License file that accompanied this code.
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License
    4.21 + * along with this program. Look for COPYING file in the top folder.
    4.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    4.23 + */
    4.24 +package org.apidesign.html.json.impl;
    4.25 +
    4.26 +import net.java.html.BrwsrCtx;
    4.27 +
    4.28 +/** Super type for those who wish to receive JSON messages.
    4.29 + *
    4.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    4.31 + */
    4.32 +public abstract class RcvrJSON {
    4.33 +    protected void onOpen(MsgEvnt msg) {}
    4.34 +    protected abstract void onMessage(MsgEvnt msg);
    4.35 +    protected void onClose(MsgEvnt msg) {}
    4.36 +    protected abstract void onError(MsgEvnt msg);
    4.37 +    
    4.38 +    public abstract static class MsgEvnt {
    4.39 +        MsgEvnt() {
    4.40 +        }
    4.41 +        
    4.42 +        public Throwable getError() {
    4.43 +            return null;
    4.44 +        }
    4.45 +        
    4.46 +        public final Exception getException() {
    4.47 +            Throwable t = getError();
    4.48 +            if (t instanceof Exception) {
    4.49 +                return (Exception)t;
    4.50 +            }
    4.51 +            if (t == null) {
    4.52 +                return null;
    4.53 +            }
    4.54 +            return new Exception(t);
    4.55 +        }
    4.56 +        
    4.57 +        public int dataSize() {
    4.58 +            return -1;
    4.59 +        }
    4.60 +        
    4.61 +        public <Data> void dataRead(BrwsrCtx ctx, Class<? extends Data> type, Data[] fillTheArray) {
    4.62 +        }
    4.63 +        
    4.64 +        public abstract void dispatch(RcvrJSON r);
    4.65 +        
    4.66 +        public static MsgEvnt createError(final Throwable t) {
    4.67 +            return new MsgEvnt() {
    4.68 +                @Override
    4.69 +                public Throwable getError() {
    4.70 +                    return t;
    4.71 +                }
    4.72 +
    4.73 +                @Override
    4.74 +                public void dispatch(RcvrJSON r) {
    4.75 +                    r.onError(this);
    4.76 +                }
    4.77 +            };
    4.78 +        }
    4.79 +        
    4.80 +        public static MsgEvnt createMessage(final Object value) {
    4.81 +            return new MsgEvnt() {
    4.82 +                @Override
    4.83 +                public int dataSize() {
    4.84 +                    if (value instanceof Object[]) {
    4.85 +                        return ((Object[])value).length;
    4.86 +                    } else {
    4.87 +                        return 1;
    4.88 +                    }
    4.89 +                }
    4.90 +                
    4.91 +                @Override
    4.92 +                public <Data> void dataRead(BrwsrCtx context, Class<? extends Data> type, Data[] arr) {
    4.93 +                    if (value instanceof Object[]) {
    4.94 +                        Object[] data = ((Object[]) value);
    4.95 +                        for (int i = 0; i < data.length && i < arr.length; i++) {
    4.96 +                            arr[i] = org.apidesign.html.json.impl.JSON.read(context, type, data[i]);
    4.97 +                        }
    4.98 +                    } else {
    4.99 +                        if (arr.length > 0) {
   4.100 +                            arr[0] = org.apidesign.html.json.impl.JSON.read(context, type, value);
   4.101 +                        }
   4.102 +                    }
   4.103 +                }
   4.104 +                
   4.105 +                @Override
   4.106 +                public void dispatch(RcvrJSON r) {
   4.107 +                    r.onMessage(this);
   4.108 +                }
   4.109 +            };
   4.110 +        }
   4.111 +        
   4.112 +        public static MsgEvnt createOpen() {
   4.113 +            return new MsgEvnt() {
   4.114 +                @Override
   4.115 +                public void dispatch(RcvrJSON r) {
   4.116 +                    r.onOpen(this);
   4.117 +                }
   4.118 +            };
   4.119 +        }
   4.120 +
   4.121 +        public static MsgEvnt createClose() {
   4.122 +            return new MsgEvnt() {
   4.123 +                @Override
   4.124 +                public void dispatch(RcvrJSON r) {
   4.125 +                    r.onClose(this);
   4.126 +                }
   4.127 +            };
   4.128 +        }
   4.129 +    } // end MsgEvnt
   4.130 +}
     5.1 --- a/json/src/main/java/org/apidesign/html/json/spi/JSONCall.java	Sat Aug 24 18:00:08 2013 +0200
     5.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/JSONCall.java	Sun Aug 25 09:36:33 2013 +0200
     5.3 @@ -24,6 +24,7 @@
     5.4  import java.io.IOException;
     5.5  import java.io.OutputStream;
     5.6  import org.apidesign.html.json.impl.JSON;
     5.7 +import org.apidesign.html.json.impl.RcvrJSON;
     5.8  
     5.9  /** Description of a JSON call request that is supposed to be processed
    5.10   * by {@link Transfer#loadJSON(org.apidesign.html.json.spi.JSONCall)} implementors.
    5.11 @@ -31,16 +32,14 @@
    5.12   * @author Jaroslav Tulach <jtulach@netbeans.org>
    5.13   */
    5.14  public final class JSONCall {
    5.15 -    private final Runnable whenDone;
    5.16 -    private final Object[] result;
    5.17 +    private final RcvrJSON whenDone;
    5.18      private final String urlBefore;
    5.19      private final String urlAfter;
    5.20      private final String method;
    5.21      private final Object data;
    5.22  
    5.23 -    JSONCall(Runnable whenDone, Object[] result, String urlBefore, String urlAfter, String method, Object data) {
    5.24 +    JSONCall(RcvrJSON whenDone, String urlBefore, String urlAfter, String method, Object data) {
    5.25          this.whenDone = whenDone;
    5.26 -        this.result = result;
    5.27          this.urlBefore = urlBefore;
    5.28          this.urlAfter = urlAfter;
    5.29          this.method = method;
    5.30 @@ -84,12 +83,14 @@
    5.31      }
    5.32  
    5.33      public void notifySuccess(Object result) {
    5.34 -        this.result[0] = result;
    5.35 -        this.whenDone.run();
    5.36 +        RcvrJSON.MsgEvnt.createMessage(result).dispatch(whenDone);
    5.37      }
    5.38      
    5.39      public void notifyError(Throwable error) {
    5.40 -        this.result[0] = error == null ? JSON.NULL : error;
    5.41 -        this.whenDone.run();
    5.42 +        RcvrJSON.MsgEvnt.createError(error).dispatch(whenDone);
    5.43 +    }
    5.44 +
    5.45 +    public String getMessage() {
    5.46 +        return this.data.toString();
    5.47      }
    5.48  }
     6.1 --- a/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java	Sat Aug 24 18:00:08 2013 +0200
     6.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java	Sun Aug 25 09:36:33 2013 +0200
     6.3 @@ -22,6 +22,7 @@
     6.4  
     6.5  import org.apidesign.html.json.impl.PropertyBindingAccessor;
     6.6  import org.apidesign.html.json.impl.PropertyBindingAccessor.PBData;
     6.7 +import org.apidesign.html.json.impl.RcvrJSON;
     6.8  import org.apidesign.html.json.impl.WrapperObject;
     6.9  
    6.10  /** Describes a property when one is asked to 
    6.11 @@ -49,8 +50,8 @@
    6.12              }
    6.13  
    6.14              @Override
    6.15 -            protected JSONCall newCall(Runnable whenDone, Object[] result, String urlBefore, String urlAfter, String method, Object data) {
    6.16 -                return new JSONCall(whenDone, result, urlBefore, urlAfter, method, data);
    6.17 +            protected JSONCall newCall(RcvrJSON callback, String urlBefore, String urlAfter, String method, Object data) {
    6.18 +                return new JSONCall(callback, urlBefore, urlAfter, method, data);
    6.19              }
    6.20          };
    6.21      }