001: package com.opensymphony.webwork.views.velocity.components;
002:
003: import com.opensymphony.webwork.ServletActionContext;
004: import com.opensymphony.webwork.components.Component;
005: import com.opensymphony.xwork.util.OgnlValueStack;
006: import org.apache.velocity.context.InternalContextAdapter;
007: import org.apache.velocity.exception.MethodInvocationException;
008: import org.apache.velocity.exception.ParseErrorException;
009: import org.apache.velocity.exception.ResourceNotFoundException;
010: import org.apache.velocity.runtime.directive.Directive;
011: import org.apache.velocity.runtime.parser.node.Node;
012:
013: import javax.servlet.http.HttpServletRequest;
014: import javax.servlet.http.HttpServletResponse;
015: import java.io.IOException;
016: import java.io.Writer;
017: import java.util.HashMap;
018: import java.util.Map;
019:
020: public abstract class AbstractDirective extends Directive {
021: public String getName() {
022: return "ww" + getBeanName();
023: }
024:
025: public abstract String getBeanName();
026:
027: /**
028: * All components, unless otherwise stated, are LINE-level directives.
029: */
030: public int getType() {
031: return LINE;
032: }
033:
034: protected abstract Component getBean(OgnlValueStack stack,
035: HttpServletRequest req, HttpServletResponse res);
036:
037: public boolean render(InternalContextAdapter ctx, Writer writer,
038: Node node) throws IOException, ResourceNotFoundException,
039: ParseErrorException, MethodInvocationException {
040: // get the bean
041: OgnlValueStack stack = (OgnlValueStack) ctx.get("stack");
042: HttpServletRequest req = (HttpServletRequest) stack
043: .getContext().get(ServletActionContext.HTTP_REQUEST);
044: HttpServletResponse res = (HttpServletResponse) stack
045: .getContext().get(ServletActionContext.HTTP_RESPONSE);
046: Component bean = getBean(stack, req, res);
047:
048: // get the parameters
049: Map params = createPropertyMap(ctx, node);
050: bean.copyParams(params);
051: //bean.addAllParameters(params);
052: bean.start(writer);
053:
054: if (getType() == BLOCK) {
055: Node body = node.jjtGetChild(node.jjtGetNumChildren() - 1);
056: body.render(ctx, writer);
057: }
058:
059: bean.end(writer, "");
060: return true;
061: }
062:
063: /**
064: * create a Map of properties that the user has passed in. for example,
065: * <pre>
066: * #xxx("name=hello" "value=world" "template=foo")
067: * </pre>
068: * would yield a params that contains {["name", "hello"], ["value", "world"], ["template", "foo"]}
069: *
070: * @param node the Node passed in to the render method
071: * @return a Map of the user specified properties
072: * @throws org.apache.velocity.exception.ParseErrorException
073: * if the was an error in the format of the property
074: */
075: protected Map createPropertyMap(
076: InternalContextAdapter contextAdapter, Node node)
077: throws ParseErrorException, MethodInvocationException {
078: Map propertyMap = new HashMap();
079:
080: int children = node.jjtGetNumChildren();
081: if (getType() == BLOCK) {
082: children--;
083: }
084:
085: for (int index = 0, length = children; index < length; index++) {
086: this .putProperty(propertyMap, contextAdapter, node
087: .jjtGetChild(index));
088: }
089:
090: return propertyMap;
091: }
092:
093: /**
094: * adds a given Node's key/value pair to the propertyMap. For example, if this Node contained the value "rows=20",
095: * then the key, rows, would be added to the propertyMap with the String value, 20.
096: *
097: * @param propertyMap a params containing all the properties that we wish to set
098: * @param node the parameter to set expressed in "name=value" format
099: */
100: protected void putProperty(Map propertyMap,
101: InternalContextAdapter contextAdapter, Node node)
102: throws ParseErrorException, MethodInvocationException {
103: // node.value uses the WebWorkValueStack to evaluate the directive's value parameter
104: String param = node.value(contextAdapter).toString();
105:
106: int idx = param.indexOf("=");
107:
108: if (idx != -1) {
109: String property = param.substring(0, idx);
110:
111: String value = param.substring(idx + 1);
112: propertyMap.put(property, value);
113: } else {
114: throw new ParseErrorException(
115: "#"
116: + this .getName()
117: + " arguments must include an assignment operator! For example #tag( Component \"template=mytemplate\" ). #tag( TextField \"mytemplate\" ) is illegal!");
118: }
119: }
120: }
|