/// <summary> Returns an array of the literal rep of the AST /// </summary> private static IList getASTAsStringArray(Node rootNode) { /* * this assumes that we are passed in the root * node of the code block */ Token t = rootNode.FirstToken; Token tLast = rootNode.LastToken; /* * now, run down the part of the tree bounded by * our first and last tokens */ ArrayList list = new ArrayList(); t = rootNode.FirstToken; while (t != tLast) { list.Add(NodeUtils.tokenLiteral(t)); t = t.next; } /* * make sure we get the last one... */ list.Add(NodeUtils.tokenLiteral(t)); return(list); }
/// <summary> /// Used by Parser.java to process VMs withing the parsing process /// /// processAndRegister() doesn't actually render the macro to the output /// Processes the macro body into the internal representation used by the /// VelocimacroProxy objects, and if not currently used, adds it /// to the macro Factory /// </summary> public static void processAndRegister(RuntimeServices rs, Node node, String sourceTemplate) { /* * There must be at least one arg to #macro, * the name of the VM. Note that 0 following * args is ok for naming blocks of HTML */ int numArgs = node.jjtGetNumChildren(); /* * this number is the # of args + 1. The + 1 * is for the block tree */ if (numArgs < 2) { /* * error - they didn't name the macro or * define a block */ rs.error("#macro error : Velocimacro must have name as 1st " + "argument to #macro()"); return; } /* * get the arguments to the use of the VM */ String[] argArray = getArgArray(node); /* * now, try and eat the code block. Pass the root. */ IList macroArray = getASTAsStringArray(node.jjtGetChild(numArgs - 1)); /* * make a big string out of our macro */ StringBuilder temp = new StringBuilder(); for (int i = 0; i < macroArray.Count; i++) { temp.Append(macroArray[i]); } String macroBody = temp.ToString(); /* * now, try to add it. The Factory controls permissions, * so just give it a whack... */ bool bRet = rs.addVelocimacro(argArray[0], macroBody, argArray, sourceTemplate); return; }
/// <summary> creates an array containing the literal /// strings in the macro arguement /// </summary> private static String[] getArgArray(Node node) { /* * remember : this includes the block tree */ int numArgs = node.jjtGetNumChildren(); numArgs--; // avoid the block tree... String[] argArray = new String[numArgs]; int i = 0; /* * eat the args */ while (i < numArgs) { argArray[i] = node.jjtGetChild(i).FirstToken.image; /* * trim off the leading $ for the args after the macro name. * saves everyone else from having to do it */ if (i > 0) { if (argArray[i].StartsWith("$")) { argArray[i] = argArray[i].Substring(1, (argArray[i].Length) - (1)); } } i++; } if (debugMode) { Console.Out.WriteLine("Macro.getArgArray() : #args = " + numArgs); Console.Out.Write(argArray[0] + "("); for (i = 1; i < numArgs; i++) { Console.Out.Write(" " + argArray[i]); } Console.Out.WriteLine(" )"); } return(argArray); }
/// <summary> /// iterates through the argument list and renders every /// argument that is appropriate. Any non appropriate /// arguments are logged, but render() continues. /// </summary> public override bool Render(IInternalContextAdapter context, TextWriter writer, Node node) { // did we get an argument? if (!AssertArgument(node)) { return false; } // does it have a value? If you have a null reference, then no. Object value_; if (!AssertNodeHasValue(node, context, out value_)) { return false; } // get the path String arg = value_.ToString(); AssertTemplateStack(context); Resource current = context.CurrentResource; // get the resource, and assume that we use the encoding of the current template // the 'current resource' can be null if we are processing a stream.... String encoding = null; if (current != null) { encoding = current.Encoding; } else { encoding = (String) rsvc.GetProperty(RuntimeConstants.INPUT_ENCODING); } // now use the Runtime resource loader to get the template Template t = null; t = GetTemplate(arg, encoding, context); if (t == null) { return false; } // and render it if (!RenderTemplate(t, arg, writer, context)) { return false; } return true; }
public override void init(RuntimeServices rs, InternalContextAdapter context, Node node) { base.init(rs, context, node); /* * again, don't do squat. We want the AST of the macro * block to hang off of this but we don't want to * init it... it's useless... */ return; }
/// <summary> Return name of this directive. /// </summary> /// <summary> Return type of this directive. /// </summary> /// <summary> render() doesn't do anything in the final output rendering. /// There is no output from a #macro() directive. /// </summary> public override bool render(InternalContextAdapter context, TextWriter writer, Node node) { /* * do nothing : We never render. The VelocimacroProxy object does that */ return(true); }
/** * Break directive does not actually do any rendering. * * This directive throws a BreakException (RuntimeException) which * signals foreach directive to break out of the loop. Note that this * directive does not verify that it is being called inside a foreach * loop. * * @param context * @param writer * @param node * @return true if the directive rendered successfully. * @throws IOException * @throws MethodInvocationException * @throws ResourceNotFoundException * @throws ParseErrorException */ public override bool Render(IInternalContextAdapter context, TextWriter writer, NVelocity.Runtime.Parser.Node.INode node) { throw new BreakException(); }
private bool AssertNodeHasValue(Node node, IInternalContextAdapter context, out Object value) { bool result = true; value = node.GetChild(0).Value(context); if (value == null) { rsvc.Error("#parse() error : null argument"); result = false; } return result; }
private bool AssertArgument(Node node) { bool result = true; if (node.GetChild(0) == null) { rsvc.Error("#parse() error : null argument"); result = false; } return result; }