First incarnation of property bindings
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 19 Apr 2013 19:00:39 +0200
changeset 9e77b0d6cee20
parent 8 7aca06d79b78
child 10 2df9abc1dbda
First incarnation of property bindings
json/src/main/java/net/java/html/json/Context.java
json/src/main/java/org/apidesign/html/json/impl/Bindings.java
json/src/main/java/org/apidesign/html/json/impl/ContextAccessor.java
json/src/main/java/org/apidesign/html/json/impl/PropertyBindingAccessor.java
json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java
json/src/main/java/org/apidesign/html/json/spi/Technology.java
json/src/test/java/net/java/html/json/MapModelTest.java
json/src/test/java/net/java/html/json/ModelTest.java
     1.1 --- a/json/src/main/java/net/java/html/json/Context.java	Fri Apr 19 15:44:44 2013 +0200
     1.2 +++ b/json/src/main/java/net/java/html/json/Context.java	Fri Apr 19 19:00:39 2013 +0200
     1.3 @@ -21,6 +21,7 @@
     1.4  package net.java.html.json;
     1.5  
     1.6  import org.apidesign.html.json.impl.ContextAccessor;
     1.7 +import org.apidesign.html.json.spi.PropertyBinding;
     1.8  import org.apidesign.html.json.spi.Technology;
     1.9  
    1.10  /** Represents context where the {@link Model} and other objects
    1.11 @@ -66,5 +67,9 @@
    1.12          @Override
    1.13          public void valueHasMutated(Object data, String propertyName) {
    1.14          }
    1.15 +
    1.16 +        @Override
    1.17 +        public void bind(PropertyBinding b, Object model, Object data) {
    1.18 +        }
    1.19      }
    1.20  }
     2.1 --- a/json/src/main/java/org/apidesign/html/json/impl/Bindings.java	Fri Apr 19 15:44:44 2013 +0200
     2.2 +++ b/json/src/main/java/org/apidesign/html/json/impl/Bindings.java	Fri Apr 19 19:00:39 2013 +0200
     2.3 @@ -20,6 +20,9 @@
     2.4   */
     2.5  package org.apidesign.html.json.impl;
     2.6  
     2.7 +import java.util.Arrays;
     2.8 +import java.util.List;
     2.9 +import org.apidesign.html.json.spi.PropertyBinding;
    2.10  import net.java.html.json.Context;
    2.11  import org.apidesign.html.json.spi.Technology;
    2.12  
    2.13 @@ -47,12 +50,20 @@
    2.14      ) {
    2.15          Data d = bp.wrapModel(model);
    2.16          
    2.17 +        List<String> arr = Arrays.asList(propsAndGetters);
    2.18 +        for (int i = 0; i < propsAndGetters.length; i += 4) {
    2.19 +            PropertyBinding pb = PropertyBindingAccessor.create(
    2.20 +                arr.subList(i, i + 4)
    2.21 +            );
    2.22 +            bp.bind(pb, model, d);
    2.23 +        }
    2.24 +        
    2.25          return new Bindings<>(d, bp);
    2.26      }
    2.27      
    2.28      
    2.29 -    public Object koData() {
    2.30 -        return this;
    2.31 +    public Data koData() {
    2.32 +        return data;
    2.33      }
    2.34  
    2.35      public void valueHasMutated(String firstName) {
     3.1 --- a/json/src/main/java/org/apidesign/html/json/impl/ContextAccessor.java	Fri Apr 19 15:44:44 2013 +0200
     3.2 +++ b/json/src/main/java/org/apidesign/html/json/impl/ContextAccessor.java	Fri Apr 19 19:00:39 2013 +0200
     3.3 @@ -1,3 +1,23 @@
     3.4 +/**
     3.5 + * HTML via Java(tm) Language Bindings
     3.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.7 + *
     3.8 + * This program is free software: you can redistribute it and/or modify
     3.9 + * it under the terms of the GNU General Public License as published by
    3.10 + * the Free Software Foundation, version 2 of the License.
    3.11 + *
    3.12 + * This program is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU General Public License for more details. apidesign.org
    3.16 + * designates this particular file as subject to the
    3.17 + * "Classpath" exception as provided by apidesign.org
    3.18 + * in the License file that accompanied this code.
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License
    3.21 + * along with this program. Look for COPYING file in the top folder.
    3.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    3.23 + */
    3.24  package org.apidesign.html.json.impl;
    3.25  
    3.26  import net.java.html.json.Context;
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/json/src/main/java/org/apidesign/html/json/impl/PropertyBindingAccessor.java	Fri Apr 19 19:00:39 2013 +0200
     4.3 @@ -0,0 +1,56 @@
     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 java.util.List;
    4.27 +import org.apidesign.html.json.spi.PropertyBinding;
    4.28 +
    4.29 +/**
    4.30 + *
    4.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    4.32 + */
    4.33 +public abstract class PropertyBindingAccessor {
    4.34 +    private static PropertyBindingAccessor DEFAULT;
    4.35 +
    4.36 +    protected PropertyBindingAccessor() {
    4.37 +        if (DEFAULT != null) throw new IllegalStateException();
    4.38 +        DEFAULT = this;
    4.39 +    }
    4.40 +    
    4.41 +    static {
    4.42 +        try {
    4.43 +            // run initializers
    4.44 +            Class.forName(PropertyBinding.class.getName(), 
    4.45 +                true, PropertyBinding.class.getClassLoader());
    4.46 +        } catch (Exception ex) {
    4.47 +            // OK
    4.48 +            throw new IllegalStateException(ex);
    4.49 +        }
    4.50 +    }
    4.51 +
    4.52 +    protected abstract PropertyBinding newBinding(List<String> params);
    4.53 +    
    4.54 +    public static PropertyBinding create(
    4.55 +        List<String> params
    4.56 +    ) {
    4.57 +        return DEFAULT.newBinding(params);
    4.58 +    }
    4.59 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/PropertyBinding.java	Fri Apr 19 19:00:39 2013 +0200
     5.3 @@ -0,0 +1,59 @@
     5.4 +/**
     5.5 + * HTML via Java(tm) Language Bindings
     5.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     5.7 + *
     5.8 + * This program is free software: you can redistribute it and/or modify
     5.9 + * it under the terms of the GNU General Public License as published by
    5.10 + * the Free Software Foundation, version 2 of the License.
    5.11 + *
    5.12 + * This program is distributed in the hope that it will be useful,
    5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 + * GNU General Public License for more details. apidesign.org
    5.16 + * designates this particular file as subject to the
    5.17 + * "Classpath" exception as provided by apidesign.org
    5.18 + * in the License file that accompanied this code.
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License
    5.21 + * along with this program. Look for COPYING file in the top folder.
    5.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    5.23 + */
    5.24 +package org.apidesign.html.json.spi;
    5.25 +
    5.26 +import java.util.List;
    5.27 +import org.apidesign.html.json.impl.PropertyBindingAccessor;
    5.28 +
    5.29 +/** Describes a property when one is asked to 
    5.30 + * bind it 
    5.31 + *
    5.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    5.33 + */
    5.34 +public final class PropertyBinding {
    5.35 +    private final List<String> params;
    5.36 +    
    5.37 +    private PropertyBinding(List<String> p) {
    5.38 +        this.params = p;
    5.39 +    }
    5.40 +
    5.41 +    static {
    5.42 +        new PropertyBindingAccessor() {
    5.43 +            @Override
    5.44 +            protected PropertyBinding newBinding(List<String> params) {
    5.45 +                return new PropertyBinding(params);
    5.46 +            }
    5.47 +        };
    5.48 +    }
    5.49 +
    5.50 +    public String getPropertyName() {
    5.51 +        return params.get(0);
    5.52 +    }
    5.53 +    
    5.54 +    public String getGetterName() {
    5.55 +        final String g = params.get(1);
    5.56 +        int end = g.indexOf("__");
    5.57 +        if (end == -1) {
    5.58 +            end = g.length();
    5.59 +        }
    5.60 +        return g.substring(0, end);
    5.61 +    }
    5.62 +}
     6.1 --- a/json/src/main/java/org/apidesign/html/json/spi/Technology.java	Fri Apr 19 15:44:44 2013 +0200
     6.2 +++ b/json/src/main/java/org/apidesign/html/json/spi/Technology.java	Fri Apr 19 19:00:39 2013 +0200
     6.3 @@ -1,3 +1,23 @@
     6.4 +/**
     6.5 + * HTML via Java(tm) Language Bindings
     6.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     6.7 + *
     6.8 + * This program is free software: you can redistribute it and/or modify
     6.9 + * it under the terms of the GNU General Public License as published by
    6.10 + * the Free Software Foundation, version 2 of the License.
    6.11 + *
    6.12 + * This program is distributed in the hope that it will be useful,
    6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.15 + * GNU General Public License for more details. apidesign.org
    6.16 + * designates this particular file as subject to the
    6.17 + * "Classpath" exception as provided by apidesign.org
    6.18 + * in the License file that accompanied this code.
    6.19 + *
    6.20 + * You should have received a copy of the GNU General Public License
    6.21 + * along with this program. Look for COPYING file in the top folder.
    6.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    6.23 + */
    6.24  package org.apidesign.html.json.spi;
    6.25  
    6.26  import net.java.html.json.Model;
    6.27 @@ -17,6 +37,14 @@
    6.28       * @return 
    6.29       */
    6.30      public Data wrapModel(Object model);
    6.31 +    
    6.32 +    /** Binds a property between the model and the data as used by the technology.
    6.33 +     * 
    6.34 +     * @param b the description of the requested binding
    6.35 +     * @param model the original instance of the model
    6.36 +     * @param data the data to bind with the model
    6.37 +     */
    6.38 +    public void bind(PropertyBinding b, Object model, Data data);
    6.39  
    6.40      /** Model for given data has changed its value. The technology is
    6.41       * supposed to update its state (for example DOM nodes associated
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/json/src/test/java/net/java/html/json/MapModelTest.java	Fri Apr 19 19:00:39 2013 +0200
     7.3 @@ -0,0 +1,106 @@
     7.4 +/**
     7.5 + * HTML via Java(tm) Language Bindings
     7.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     7.7 + *
     7.8 + * This program is free software: you can redistribute it and/or modify
     7.9 + * it under the terms of the GNU General Public License as published by
    7.10 + * the Free Software Foundation, version 2 of the License.
    7.11 + *
    7.12 + * This program is distributed in the hope that it will be useful,
    7.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.15 + * GNU General Public License for more details. apidesign.org
    7.16 + * designates this particular file as subject to the
    7.17 + * "Classpath" exception as provided by apidesign.org
    7.18 + * in the License file that accompanied this code.
    7.19 + *
    7.20 + * You should have received a copy of the GNU General Public License
    7.21 + * along with this program. Look for COPYING file in the top folder.
    7.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
    7.23 + */
    7.24 +package net.java.html.json;
    7.25 +
    7.26 +import java.lang.reflect.InvocationTargetException;
    7.27 +import java.lang.reflect.Method;
    7.28 +import java.util.HashMap;
    7.29 +import java.util.Map;
    7.30 +import java.util.logging.Level;
    7.31 +import java.util.logging.Logger;
    7.32 +import org.apidesign.html.json.spi.ContextBuilder;
    7.33 +import org.apidesign.html.json.spi.PropertyBinding;
    7.34 +import org.apidesign.html.json.spi.Technology;
    7.35 +import org.testng.annotations.BeforeMethod;
    7.36 +import org.testng.annotations.Test;
    7.37 +import static org.testng.Assert.*;
    7.38 +
    7.39 +/**
    7.40 + *
    7.41 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    7.42 + */
    7.43 +public class MapModelTest {
    7.44 +    private MapTechnology t;
    7.45 +    private Context c;
    7.46 +
    7.47 +    @BeforeMethod public void initTechnology() {
    7.48 +        t = new MapTechnology();
    7.49 +        c = ContextBuilder.create().withTechnology(t).build();
    7.50 +    }
    7.51 +    
    7.52 +    @Test public void isThereABinding() throws Exception {
    7.53 +        Person p = new Person(c);
    7.54 +        p.setFirstName("Jarda");
    7.55 +        
    7.56 +        Map m = (Map)p.koData();
    7.57 +        Object v = m.get("firstName");
    7.58 +        assertNotNull(v, "Value should be in the map");
    7.59 +        assertEquals(v.getClass(), One.class, "It is instance of One");
    7.60 +        One o = (One)v;
    7.61 +        assertEquals(o.changes, 1, "One change so far");
    7.62 +        
    7.63 +        assertEquals(o.get(), "Jarda", "Value should be in the map");
    7.64 +    }
    7.65 +    
    7.66 +    
    7.67 +
    7.68 +    private static final class One {
    7.69 +        int changes;
    7.70 +        private final Method getter;
    7.71 +        private final Object model;
    7.72 +    
    7.73 +        One(Object m, String get) throws NoSuchMethodException {
    7.74 +            this.model = m;
    7.75 +            this.getter = m.getClass().getMethod(get);
    7.76 +        }
    7.77 +        
    7.78 +        Object get() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    7.79 +            return getter.invoke(model);
    7.80 +        }
    7.81 +    }
    7.82 +    
    7.83 +    private static final class MapTechnology implements Technology<Map<String,One>> {
    7.84 +
    7.85 +        @Override
    7.86 +        public Map<String, One> wrapModel(Object model) {
    7.87 +            return new HashMap<>();
    7.88 +        }
    7.89 +
    7.90 +        @Override
    7.91 +        public void valueHasMutated(Map<String, One> data, String propertyName) {
    7.92 +            One p = data.get(propertyName);
    7.93 +            if (p != null) {
    7.94 +                p.changes++;
    7.95 +            }
    7.96 +        }
    7.97 +
    7.98 +        @Override
    7.99 +        public void bind(PropertyBinding b, Object model, Map<String, One> data) {
   7.100 +            try {
   7.101 +                One o = new One(model, b.getGetterName());
   7.102 +                data.put(b.getPropertyName(), o);
   7.103 +            } catch (NoSuchMethodException ex) {
   7.104 +                throw new IllegalStateException(ex);
   7.105 +            }
   7.106 +        }
   7.107 +    
   7.108 +    }
   7.109 +}
     8.1 --- a/json/src/test/java/net/java/html/json/ModelTest.java	Fri Apr 19 15:44:44 2013 +0200
     8.2 +++ b/json/src/test/java/net/java/html/json/ModelTest.java	Fri Apr 19 19:00:39 2013 +0200
     8.3 @@ -26,6 +26,7 @@
     8.4  import java.util.List;
     8.5  import java.util.ListIterator;
     8.6  import org.apidesign.html.json.spi.ContextBuilder;
     8.7 +import org.apidesign.html.json.spi.PropertyBinding;
     8.8  import org.apidesign.html.json.spi.Technology;
     8.9  import static org.testng.Assert.*;
    8.10  import org.testng.annotations.BeforeMethod;
    8.11 @@ -235,5 +236,9 @@
    8.12          public void valueHasMutated(Object data, String propertyName) {
    8.13              mutated.add(propertyName);
    8.14          }
    8.15 +
    8.16 +        @Override
    8.17 +        public void bind(PropertyBinding b, Object model, Object data) {
    8.18 +        }
    8.19      }
    8.20  }