I was probably spouting off a bit too abstractly, but here's an example of what I was getting at. I hope it shows how component trees can be constructed efficiently and how bindings can be compiled rather than reflected.

I think it's somewhat interesting that this pushes the controller out of the component hierarchy. If all of the components know how to reset securely at the end of a request cycle, then all that's necessary is to have the component null out the controller, and reinstantiate it the next request cycle. So the component tree can be reused, and the controller can be ignorant.

I'm sure all this is nonsense, but it's what I'd like to see…

===== mydogs_en.html =====
01 <html>
02 <body>
03 <table>
04   <tr>
05     <th>Name</th>
06     <th>Breed</th>
07   </tr>
08   <tbody jwcid="dogLoop"><tr>
09     <td><span jwcid="dogName">Name</span></td>
10     <td><span jwcid="dogBreed">breed</span></td>
11   </tr></tbody>
12 </table>
13 </body>
14 </html>

===== mydogs.page =====
01  <page-specification>
02    <component id="dogLoop" type="For">
03      <binding name="source">dogs</binding>
04      <binding name="value">dog</binding>
05    </component>
06    <component id="dogName" type="Insert">
07      <binding name="value">dog.name</binding>
08    </component>
09    <component id="dogBreed" type="Insert">
10      <binding name="value">dog.breed</binding>
11    </component>
12  </page-specification>

===== mydogs.java =====
01 public class mydogs {
02     List<Dog> dogs = new ArrayList<Dog>();
03     public Example() {
04         dogs.add(new Dog(1, "Tammy", "Sheltie"));
05         dogs.add(new Dog(2, "Hagar", "Yellow Lab"));
06         dogs.add(new Dog(3, "Conrad", "Lab Mix"));
07     }
08     public List<Dog> getDogs() { return dogs; }
09     public Dog getDog() { return dog; }
10     public void setDog(Dog value) { dog = value; }
11 }

===== Runtime Codegen =====
// This is a translation of the component specification.
abstract class _mydogs_page extends Component {
    mydogs controller;

    For dogLoop;
    Insert dogName;
    Insert dogBreed;

    public _mydogs_page() {
        controller = new Dogs();

        nameHeader = new Insert();
nameHeader.setMessage("Name"); // Presumably to be read from the messages file…
        breedHeader = new Insert();
breedHeader.setMessage("Breed"); // Presumably read from the messages file…
        dogLoop = new For();
        dogName = new Insert();
        dogBreed = new Insert();

// There are a bunch of obvious fiddly little details to this that I'm glossing over. // But the point is that bindings can be built without using reflection.
        dogLoop.addBinding(new Binding(
            public void read() {
                // #line 03 Dogs.page
                dogLoop.setSource(controller.getDogs());
            }
            public void write() {
                // #line 03 Dogs.page
                controller.setDogs(dogLoop.getSource());
            }
        ));
        dogLoop.getContent().addBinding(new Binding(
            public void read() {
                // #line 04 Dogs.page
                controller.setDog(dogLoop.value());
            }
            public void write() {
                // #line 03 Dogs.page
                dogLoop.setValue(controller.getDog());
            }
        ));
        dogName.addBinding(new Binding{
            public void read() {
                // #line 07 Dogs.page
                dogName.setValue(controller.getDog().getName());
            }
            public void write() {
                // #line 07 Dogs.page
controller.getDog().setName((String) dogName.getValue ());
            }
        });
        dogBreed.addBinding(new Binding{
            public void read() {
                // #line 10 Dogs.page
                dogBreed.setValue(controller.getDog().getBreed());
            }
            public void write() {
                // #line 10 Dogs.page
controller.getDog().setBreed((String) dogBreed.getValue());
            }
        });
    }
}

// And this is a translation of the template.
class _mydogs_en_html extends _mydogs_page {
    public _mydogs_en_html() {
// Here, we build literals for all the static text from the template Literal _c1 = new Literal("<html>\r\n<body>\r\n<table>\r\n <tr>\r\n <th>Name</th>\r\n <th>Breed</th>\r\n </tr>\r\n ");
        Literal _c2 = new Literal("<tr>\r\n    <td>");
        Literal _c3 = new Literal("</td>\r\n    <td>");
        Literal _c4 = new Literal("</td>\r\n  </tr>");
Literal _c5 = new Literal("\r\n</table>\r\n</body>\r\n</html> \r\n");

// Then we interleave them with the component specification according to the order in the file.
        setChildren(new Component[]{_c1, dogLoop, _c5});
dogLoop.getContent().setChildren(new Component[]{_c2, dogName, _c3, dogBreed, _c4});
    }
}

— G

Reply via email to