Search |
||
Closure and groovy builderPosted by forax on April 1, 2008 at 3:47 AM PDT
One think i really like in Groovy, it's its concept of
Builder.
An HTML tree in Groovy is defined like that
html {
head {
title "hello groovy builder"
}
}
JavaFX uses a quite similar syntax but the syntax is built-in. The beauty of the groovy beast is that the builder syntax relies on closure. Closure The trick is the following:
Ok, so let's try to do the same in Java using the BGGA closure proposal. CICE is too verbose for that case and it should work seamlessly with FCM+ JCA Proxiiiiiiiiii
But before, how to define all the allowed markups of
an XML dialect ?
public interface XHTMLBuilder {
public void html(Object textOrClosure);
public void head(Object textOrClosure);
public void title(String text);
public void body(Object textOrClosure);
public void h1(Object textOrClosure);
public void br();
}
A Proxy acts as a multiplexer a call to any of its methods is redirected to a single generic method named invoke.
public class XMLBuilderFactory {
final Appendable appendable;
public XMLBuilderFactory(Appendable appendable) {
this.appendable=appendable;
}
public void text(CharSequence seq) {
try {
appendable.append(seq);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public <T> T createBuilder(Class<T> generatorInterface) {
return generatorInterface.cast(Proxy.newProxyInstance(
generatorInterface.getClassLoader(),
new Class<?>[]{generatorInterface},
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
...
return null;
}
}));
}
}
Here appendable
acts as a writable stream of characters,
something on which I can append characters.
Java Builder
Now, suppose that the method invoke is written,
we will see after how to write it.
public class Main {
public static void main(String[] args) {
XMLBuilderFactory factory=new XMLBuilderFactory(System.out);
XHTMLBuilder b=factory.createBuilder(XHTMLBuilder.class);
b.html({=>
b.head({=>
b.title("hello Java 7 builder");
});
b.body({=>
b.h1("Hello");
factory.text("Greetings from");
b.br();
factory.text("Java 7 builder");
});
});
}
}
It's even more readable if we use the control invocation syntax.
b.html() {
b.head() {
b.title("hello Java 7 builder");
}
b.body() {
b.h1("Hello");
factory.text("Greetings from");
b.br();
factory.text("Java 7 builder");
}
}
This construct has several advantages. I can't produce ill formed XML, markup are opened and closed by the same code. Because the builder uses an interface I can't create markup with the wrong name. Even better, refactoring the markup name will works ! How to write the method invoke ?
For each argument of the method, i have
to determine if it's a closure or any other objects.
If it's a closure, i have to invoke it.
If it's another object, i can append it into the
Appendable.
if (arg instanceof {=>void}) {
(({=>void})arg).invoke();
}
There is two poblem with that code.
First, there are two kinds of closure (function type),
unrestricted and restricted one.
A restricted closure is a closure that can't break the control
flow using break, continue or return.
I am not sure i want my closure be able to break the
control flow but the control invocation syntax creates
unrestricted closure, so i need unrestricted closure.
So instead of using '=>' in the function type, i have to use
'==>'
if (arg instanceof {==>void}) {
(({==>void})arg).invoke();
}
But there is another problem, currently,
{==>void} is a parameterized type and so
it's illegal to use it in an instanceof.
Here, i have ask Neal, he says
he planed to make "types such as this one non-generic".
String name=method.getName();
if (args==null || args.length==0) {
appendable.append('<'+name+"/>");
return null;
}
appendable.append('<'+name+'>');
try {
for(Object arg:args) {
if (arg instanceof javax.lang.function.unrestricted.V) {
((javax.lang.function.unrestricted.V)arg).invoke();
} else {
appendable.append(arg.toString());
}
}
} finally {
appendable.append(""+name+'>');
}
A zip containing the wole codes is here:
closure-builder.zip
Cheers,
»
Related Topics >>
Open JDK Comments
Comments are listed in date ascending order (oldest first)
Submitted by guillaumelaforge on Tue, 2008-04-01 05:18.
Nice experiment, but I still have a preference for the Groovy builder ;-)
Submitted by thefriendofpenguins on Fri, 2008-04-04 05:20.
It might be a good a Idea to create a notation software because the random notation software used for system has a lof a bugs ...
By the way it has been 125 days between the moment we ended the concurency exam and today and we still have nothing !!!
Submitted by helolboy on Fri, 2008-04-04 02:51.
I agree with akiri... what about a closure and groovy notation Builder for students ?
Submitted by javaworshiper on Fri, 2008-04-04 04:48.
Hey guy what a groovy idea you have here! Thank you akiri for sharing it with us
|
||
|
|