More flexibility in converting strings to various values
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 12 Jul 2013 14:25:50 +0200
changeset 1978001b95941ab
parent 196 0aa1301562e3
child 198 ef298c2f84b2
More flexibility in converting strings to various values
json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java
json/src/main/java/org/apidesign/html/json/impl/JSON.java
json/src/main/java/org/apidesign/html/json/impl/ModelProcessor.java
     1.1 --- a/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java	Fri Jul 12 12:21:53 2013 +0200
     1.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java	Fri Jul 12 14:25:50 2013 +0200
     1.3 @@ -38,10 +38,59 @@
     1.4      @Property(name="results", type=String.class, array = true),
     1.5      @Property(name="callbackCount", type=int.class),
     1.6      @Property(name="people", type=PersonImpl.class, array = true),
     1.7 -    @Property(name="enabled", type=boolean.class)
     1.8 +    @Property(name="enabled", type=boolean.class),
     1.9 +    @Property(name="latitude", type=double.class)
    1.10  }) 
    1.11  public final class KnockoutTest {
    1.12      
    1.13 +    @KOTest public void modifyValueAssertChangeInModelOnDouble() throws Throwable {
    1.14 +        Object exp = Utils.exposeHTML(KnockoutTest.class, 
    1.15 +            "Latitude: <input id='input' data-bind=\"value: latitude\"></input>\n"
    1.16 +        );
    1.17 +        try {
    1.18 +
    1.19 +            KnockoutModel m = Models.bind(new KnockoutModel(), newContext());
    1.20 +            m.setLatitude(50.5);
    1.21 +            m.applyBindings();
    1.22 +
    1.23 +            String v = getSetInput(null);
    1.24 +            assert "50.5".equals(v) : "Value is really 50.5: " + v;
    1.25 +
    1.26 +            getSetInput("49.5");
    1.27 +            triggerEvent("input", "change");
    1.28 +
    1.29 +            assert 49.5 == m.getLatitude() : "Double property updated: " + m.getLatitude();
    1.30 +        } catch (Throwable t) {
    1.31 +            throw t;
    1.32 +        } finally {
    1.33 +            Utils.exposeHTML(KnockoutTest.class, "");
    1.34 +        }
    1.35 +    }
    1.36 +    
    1.37 +    @KOTest public void modifyValueAssertChangeInModelOnBoolean() throws Throwable {
    1.38 +        Object exp = Utils.exposeHTML(KnockoutTest.class, 
    1.39 +            "Latitude: <input id='input' data-bind=\"value: enabled\"></input>\n"
    1.40 +        );
    1.41 +        try {
    1.42 +
    1.43 +            KnockoutModel m = Models.bind(new KnockoutModel(), newContext());
    1.44 +            m.setEnabled(true);
    1.45 +            m.applyBindings();
    1.46 +
    1.47 +            String v = getSetInput(null);
    1.48 +            assert "true".equals(v) : "Value is really true: " + v;
    1.49 +
    1.50 +            getSetInput("false");
    1.51 +            triggerEvent("input", "change");
    1.52 +
    1.53 +            assert false == m.isEnabled(): "Boolean property updated: " + m.isEnabled();
    1.54 +        } catch (Throwable t) {
    1.55 +            throw t;
    1.56 +        } finally {
    1.57 +            Utils.exposeHTML(KnockoutTest.class, "");
    1.58 +        }
    1.59 +    }
    1.60 +    
    1.61      @KOTest public void modifyValueAssertChangeInModel() throws Exception {
    1.62          Object exp = Utils.exposeHTML(KnockoutTest.class, 
    1.63              "<h1 data-bind=\"text: helloMessage\">Loading Bck2Brwsr's Hello World...</h1>\n" +
     2.1 --- a/json/src/main/java/org/apidesign/html/json/impl/JSON.java	Fri Jul 12 12:21:53 2013 +0200
     2.2 +++ b/json/src/main/java/org/apidesign/html/json/impl/JSON.java	Fri Jul 12 14:25:50 2013 +0200
     2.3 @@ -20,7 +20,6 @@
     2.4   */
     2.5  package org.apidesign.html.json.impl;
     2.6  
     2.7 -import org.apidesign.html.context.impl.CtxAccssr;
     2.8  import java.io.IOException;
     2.9  import java.io.InputStream;
    2.10  import java.util.HashMap;
    2.11 @@ -101,6 +100,41 @@
    2.12          return aClass.cast(o);
    2.13      }
    2.14  
    2.15 +    public static <T> T extractValue(Class<T> type, Object val) {
    2.16 +        if (Number.class.isAssignableFrom(type)) {
    2.17 +            val = numberValue(val);
    2.18 +        }
    2.19 +        if (Boolean.class == type) {
    2.20 +            val = boolValue(val);
    2.21 +        }
    2.22 +        return type.cast(val);
    2.23 +    }
    2.24 +    
    2.25 +    public static String stringValue(Object val) {
    2.26 +        return (String)val;
    2.27 +    }
    2.28 +
    2.29 +    public static Number numberValue(Object val) {
    2.30 +        if (val instanceof String) {
    2.31 +            try {
    2.32 +                return Double.valueOf((String)val);
    2.33 +            } catch (NumberFormatException ex) {
    2.34 +                return Double.NaN;
    2.35 +            }
    2.36 +        }
    2.37 +        return (Number)val;
    2.38 +    }
    2.39 +
    2.40 +    public static Character charValue(Object val) {
    2.41 +        return (Character)val;
    2.42 +    }
    2.43 +
    2.44 +    public static Boolean boolValue(Object val) {
    2.45 +        if (val instanceof String) {
    2.46 +            return Boolean.parseBoolean((String)val);
    2.47 +        }
    2.48 +        return Boolean.TRUE.equals(val);
    2.49 +    }
    2.50      
    2.51      public static void loadJSON(
    2.52          BrwsrCtx c, Runnable whenDone, Object[] result, 
     3.1 --- a/json/src/main/java/org/apidesign/html/json/impl/ModelProcessor.java	Fri Jul 12 12:21:53 2013 +0200
     3.2 +++ b/json/src/main/java/org/apidesign/html/json/impl/ModelProcessor.java	Fri Jul 12 14:25:50 2013 +0200
     3.3 @@ -227,7 +227,7 @@
     3.4                          }
     3.5                      }
     3.6                      if (set != null) {
     3.7 -                        w.append("        case " + (i / 5) + ": data." + strip(set) + "((" + tn + ")value); return;\n");
     3.8 +                        w.append("        case " + (i / 5) + ": data." + strip(set) + "(org.apidesign.html.json.impl.JSON.extractValue(" + tn + ".class, value)); return;\n");
     3.9                      }
    3.10                  }
    3.11                  w.append("      }\n");
    3.12 @@ -296,10 +296,10 @@
    3.13                          } else if (isEnum[0]) {
    3.14                              w.append("        this.prop_").append(pn);
    3.15                              w.append(".add(e == null ? null : ");
    3.16 -                            w.append(type).append(".valueOf((String)e));\n");
    3.17 +                            w.append(type).append(".valueOf(org.apidesign.html.json.impl.JSON.stringValue(e)));\n");
    3.18                          } else {
    3.19                              if (isPrimitive(type)) {
    3.20 -                                w.append("        this.prop_").append(pn).append(".add(((Number)e).");
    3.21 +                                w.append("        this.prop_").append(pn).append(".add(org.apidesign.html.json.impl.JSON.numberValue(e).");
    3.22                                  w.append(type).append("Value());\n");
    3.23                              } else {
    3.24                                  w.append("        this.prop_").append(pn).append(".add((");
    3.25 @@ -312,18 +312,18 @@
    3.26                          if (isEnum[0]) {
    3.27                              w.append("    this.prop_").append(pn);
    3.28                              w.append(" = ret[" + cnt + "] == null ? null : ");
    3.29 -                            w.append(type).append(".valueOf((String)ret[" + cnt + "]);\n");
    3.30 +                            w.append(type).append(".valueOf(org.apidesign.html.json.impl.JSON.stringValue(ret[" + cnt + "]));\n");
    3.31                          } else if (isPrimitive(type)) {
    3.32                              w.append("    this.prop_").append(pn);
    3.33                              w.append(" = ret[" + cnt + "] == null ? ");
    3.34                              if ("char".equals(type)) {
    3.35 -                                w.append("0 : ((Character)");
    3.36 +                                w.append("0 : (org.apidesign.html.json.impl.JSON.charValue(");
    3.37                              } else if ("boolean".equals(type)) {
    3.38 -                                w.append("false : ((Boolean)");
    3.39 +                                w.append("false : (org.apidesign.html.json.impl.JSON.boolValue(");
    3.40                              } else {
    3.41 -                                w.append("0 : ((Number)");
    3.42 +                                w.append("0 : (org.apidesign.html.json.impl.JSON.numberValue(");
    3.43                              }
    3.44 -                            w.append("ret[" + cnt + "]).");
    3.45 +                            w.append("ret[" + cnt + "])).");
    3.46                              w.append(type).append("Value();\n");
    3.47                          } else if (isModel[0]) {
    3.48                              w.append("    this.prop_").append(pn).append(" = org.apidesign.html.json.impl.JSON.read");