}
}
protected Object dispathNodeCall(Object name, Object args) {
Object node;
Closure closure = null;
List list = InvokerHelper.asList(args);
final boolean needToPopContext;
if (getProxyBuilder().getContexts().isEmpty()) {
// should be called on first build method only
getProxyBuilder().newContext();
needToPopContext = true;
} else {
needToPopContext = false;
}
try {
Map namedArgs = Collections.EMPTY_MAP;
// the arguments come in like [named_args?, args..., closure?]
// so peel off a hashmap from the front, and a closure from the
// end and presume that is what they meant, since there is
// no way to distinguish node(a:b,c,d) {..} from
// node([a:b],[c,d], {..}), i.e. the user can deliberately confuse
// the builder and there is nothing we can really do to prevent
// that
if ((list.size() > 0)
&& (list.get(0) instanceof LinkedHashMap)) {
namedArgs = (Map) list.get(0);
list = list.subList(1, list.size());
}
if ((list.size() > 0)
&& (list.get(list.size() - 1) instanceof Closure)) {
closure = (Closure) list.get(list.size() - 1);
list = list.subList(0, list.size() - 1);
}
Object arg;
if (list.size() == 0) {
arg = null;
} else if (list.size() == 1) {
arg = list.get(0);
} else {
arg = list;
}
node = getProxyBuilder().createNode(name, namedArgs, arg);
Object current = getProxyBuilder().getCurrent();
if (current != null) {
getProxyBuilder().setParent(current, node);
}
if (closure != null) {
Factory parentFactory = getProxyBuilder().getCurrentFactory();
if (parentFactory.isLeaf()) {
throw new RuntimeException("'" + name + "' doesn't support nesting.");
}
boolean processContent = true;
if (parentFactory.isHandlesNodeChildren()) {
processContent = parentFactory.onNodeChildren(this, node, closure);
}
if (processContent) {
// push new node on stack
String parentName = getProxyBuilder().getCurrentName();
Map parentContext = getProxyBuilder().getContext();
getProxyBuilder().newContext();
try {
getProxyBuilder().getContext().put(OWNER, closure.getOwner());
getProxyBuilder().getContext().put(CURRENT_NODE, node);
getProxyBuilder().getContext().put(PARENT_FACTORY, parentFactory);
getProxyBuilder().getContext().put(PARENT_NODE, current);
getProxyBuilder().getContext().put(PARENT_CONTEXT, parentContext);
getProxyBuilder().getContext().put(PARENT_NAME, parentName);
getProxyBuilder().getContext().put(PARENT_BUILDER, parentContext.get(CURRENT_BUILDER));
getProxyBuilder().getContext().put(CURRENT_BUILDER, parentContext.get(CHILD_BUILDER));
// lets register the builder as the delegate
getProxyBuilder().setClosureDelegate(closure, node);
closure.call();
} finally {
getProxyBuilder().popContext();
}
}
}