package org.apache.cocoon.components.treeprocessor.sitemap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.cocoon.components.flow.Interpreter;
import org.apache.cocoon.components.flow.InterpreterSelector;
import org.apache.cocoon.components.treeprocessor.AbstractProcessingNode;
import org.apache.cocoon.components.treeprocessor.CategoryNode;
import org.apache.cocoon.components.treeprocessor.InvokeContext;
import org.apache.cocoon.components.treeprocessor.MapStackResolver;
import org.apache.cocoon.components.treeprocessor.ParameterizableProcessingNode;
import org.apache.cocoon.components.treeprocessor.ProcessingNode;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.sitemap.PatternException;
public class CallFunctionNode extends AbstractProcessingNode
implements Configurable, Composable, Initializable
{
protected String functionName;
protected ArrayList parameters;
protected MapStackResolver resourceResolver;
protected ComponentManager manager;
protected CategoryNode resources;
protected String language;
public static List resolveList(List expressions, List mapStack)
throws PatternException
{
int size;
if (expressions == null || (size = expressions.size()) == 0)
return Collections.EMPTY_LIST;
List result = new ArrayList(size);
for (int i = 0; i < size; i++) {
Interpreter.Argument arg = (Interpreter.Argument)expressions.get(i);
String value = MapStackResolver.getResolver(arg.value).resolve(mapStack);
result.add (new Interpreter.Argument(arg.name, value));
}
return result;
}
public CallFunctionNode(String funName)
{
functionName = funName;
}
public void setResources(CategoryNode resources)
throws Exception
{
this.resources = resources;
}
/**
* Obtain the configuration specific to this node type and update
* the internal state.
*
* @param config a <code>Configuration</code> value
* @exception ConfigurationException if an error occurs
*/
public void configure(Configuration config)
throws ConfigurationException
{
language = config.getAttribute("language", null);
parameters = new ArrayList();
Configuration[] params = config.getChildren("parameter");
for (int i = 0; i < params.length; i++) {
Configuration param = params[i];
String name = param.getAttribute("name", null);
String value = param.getAttribute("value", null);
parameters.add(new Interpreter.Argument(name, value));
}
try {
if (MapStackResolver.needsResolve(functionName)) {
// Will always be resolved at invoke time
this.resourceResolver = MapStackResolver.getResolver(functionName);
}
}
catch (PatternException ex) {
throw new ConfigurationException(ex.toString());
}
}
public void compose(ComponentManager manager)
{
this.manager = manager;
}
public void initialize()
throws Exception
{
InterpreterSelector selector
= (InterpreterSelector)manager.lookup(Interpreter.ROLE);
if (language == null)
language = selector.getDefaultLanguage();
// Obtain the Interpreter instance for this language
Interpreter interpreter = (Interpreter)selector.select(language);
interpreter.setResources(resources);
}
public boolean invoke(Environment env, InvokeContext context)
throws Exception
{
List params = null;
// Resolve parameters
if (this.parameters != null)
params = resolveList(this.parameters, context.getMapStack());
String name = functionName;
if (resourceResolver != null) {
// Need to resolve the function name at runtime
name = resourceResolver.resolve(context.getMapStack());
}
InterpreterSelector selector
= (InterpreterSelector)manager.lookup(Interpreter.ROLE);
if (language == null)
language = selector.getDefaultLanguage();
// Obtain the Interpreter instance for this language
Interpreter interpreter = (Interpreter)selector.select(language);
try {
interpreter.callFunction(name, params, env, context);
}
finally {
selector.release((Component)interpreter);
}
return true;
}
}