Re: A WM brain bender: The solution

"marcel.huijkman" <[email protected]>
Newsgroups gmane.comp.java.webmacro.user
Message-ID <[email protected]>
Please don't do this via the #include directive.

It's not an include and it sounds like a
workaround for a specific problem!

Don't misuse directive for other tasks as for
where they were made for.

A ex-collegue of mine made this allready and
handed me the code, to see if

it is good enough for the community (nice he),
and I'm sure he won't mind

that I put het source with this email. (and a
template too!)

The trick that you want: get a string from
somewhere and use is as a kind of

stamp and it works like this:

#evalStringTemplate
$myEvalVar to $myOutput

myOutput
:<BR>$myOutput

The $myEvalVar in this example can be
filled with:

webmacro stuff (and yes, that's cool!)

The string stays intact and the parsed string $myOutput has

the result after evaluation of the $myEvalVar.

Simple, efficient and just what you need.

Please take a good look at it, and if it's suitable, give

Mike Weerdenburg all the credits.
EvalStringTemplateDirective.java (text/plain, 6.6 KB)
/*
 * Copyright (C) 2005.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted under the terms of either of the following
 * Open Source licenses:
 *
 * The GNU General Public License, version 2, or any later version, as
 * published by the Free Software Foundation
 * (http://www.fsf.org/copyleft/gpl.html);
 *
 * This software is provided "as is", with NO WARRANTY, not even the
 * implied warranties of fitness to purpose, or merchantability. You
 * assume all risks and liabilities associated with its use.
 *
 * See www.webmacro.org for more information on the WebMacro project.
 *
 * @author Mike Weerdenburg
 *
 * @version	14-01-2005
 *
 */

package org.webmacro.directive;

import org.webmacro.*;
import org.webmacro.engine.*;

/**
 * EvalStringTemplateDirective allows you to evaluate a string just like it is a include / template against the current context.<p>
 *
 * Syntax:<pre>
 *    #EvalStringTemplate $valueToEvaluateAsString [to $variable]
 *</pre>
 *
 */
public class EvalStringTemplateDirective extends Directive
{
    /* the argument is NOT a file, but a string represending the template! */
    private static final int PARSE_VALUE = 1;
    private static final int PARSE_TO = 2;
    private static final int PARSE_TO_VARIABLE = 3;

    private Variable _varTarget = null;

    private static final UndefinedMacro UNDEF = UndefinedMacro.getInstance();

    private static final ArgDescriptor[] _args = new ArgDescriptor[]
    {
        new StringArg(PARSE_VALUE),
        new OptionalGroup(2),
        new KeywordArg(PARSE_TO, "to"),
        new LValueArg(PARSE_TO_VARIABLE),
    };

    private static final DirectiveDescriptor _desc = new DirectiveDescriptor("evalStringTemplate", null, _args, null);

    public static DirectiveDescriptor getDescriptor ()
    {
        return _desc;
    }

    //
    // these values are customized for this directive during build()
    //

    /** Logging can be good */
    protected Log _log;

    /** the value as a Macro, if the value arg is a Macro */
    protected Macro _macroValue;

    /**
     * the name given to the directive by webmacro configuration.
     */
    protected String _directiveName;

    public final Object build (DirectiveBuilder builder, BuildContext bc) throws BuildException
    {
        // Get a log-instance.
        // In webmacro.properties : LogLevel.directive=DEBUG
        _log = bc.getLog("directive");

        // name of this directive
        _directiveName = builder.getName();

        // if a target provided, then output to the target!
        if (builder.getArg(PARSE_TO_VARIABLE, bc) != null)
        {
            try
            {
                _varTarget = (Variable) builder.getArg(PARSE_TO_VARIABLE, bc);
            }
            catch (ClassCastException e)
            {
               // throw new NotVariableBuildException(myDescr.name, e);
            }
        }

        Object o = builder.getArg(PARSE_VALUE, bc);
        if (o instanceof Macro)
        {
            // The value passed to us was a Macro (needs to be evaluated later).
            // If u use : #evalStringTemplate $myDatabaseFilledStringToEvaluate
            _macroValue = (Macro) o;
        }
        else
        {
            // If it's not a Macro, then generate an BuildException.
            // If u use : #evalStringTemplate "This is a string with nothing to parse!"
            throw new BuildException("#" + _directiveName + " was expecting a non-static value to evaluate, example: #" + _directiveName + " \"$myDatabaseFilledStringToEvaluate is very interesting!\"");
        }

        return this;
    }

    /**
     * Write out the included file to the specified FastWriter.  If the
     * included file is actually a template, it is evaluated against the
     * <code>context</code> parameter before being written to the FastWriter
     */
    public void write (FastWriter out, Context context) throws PropertyException
    {
        Broker broker = context.getBroker();
        String strValue = null;

        // the value arg passed to us was a Macro, so evaluate and check it now.
        if (_macroValue != null)
        {
            Object obValue = _macroValue.evaluate(context);

            // Only set the value if the macro provided not is null and not Undefined.
            if ( (obValue != null) && (obValue != UNDEF) )
            {
                strValue = obValue.toString();
            }
        }

        if (strValue == null)
        {
            throw new PropertyException("#" + _directiveName + " value cannot be undefined or null");
        }

        // Use the current templateName as templateName for the StringTemplate.
        // exampl. c:/wwwroot/templates/test.wm
        String templateName = context.getTemplateEvaluationContext()._templateName;

        // Use the current template location & directive name, so whe can re-trace error's.
        // exampl. c:/wwwroot/templates/test.wm:46.2 #evalStringTemplate
        if (templateName.indexOf(" #" + _directiveName) == -1) templateName = context.getCurrentLocation() + " #" + _directiveName;

        if (_log.loggingDebug())
        {
            _log.debug("#" + _directiveName + " \"valueToEvaluateAsStringTemplate\""
                    + ((_varTarget == null) ? ""
                    : " to $" + _varTarget.getVariableName()));
        }

        if (_log.loggingWarning())
        {
            if (strValue.indexOf("#" + _directiveName) > -1)
            {
                // when in debug or warning  mode, output a warning if a evalStringTemplate tries to use a evalStringTemplate
                // there could be situtations where this is desired, but it's good to make
                // the user aware of what they're doing
                _log.warning("#" + _directiveName + " uses a #" + _directiveName + ", maybe itself? (endless loop!) at " + context.getCurrentLocation());
            }
        }

        // Create the new StringTemplate.
        Template tmplTemplate = new StringTemplate (broker, strValue, templateName);

        if (_varTarget != null)
        {
            // if a target variable provided, then output to the target.
            _varTarget.setValue(context, tmplTemplate.evaluateAsString(context));
        }
        else
        {
            // else output to the specified FastWriter.
            out.write(tmplTemplate.evaluateAsBytes(out.getEncoding(), context));
        }
    }

    public void accept (TemplateVisitor v)
    {
        v.beginDirective(_desc.name);
        v.visitDirectiveArg("EvalStringTemplate", _macroValue);
        if (_varTarget != null) v.visitDirectiveArg("EvalStringTemplateTarget", _varTarget);
        v.endDirective();
    }
}
EvalStringTemplateDirective.wmt (text/plain, 667 B)
#set $Response.ContentType = "text/html; charset=$CharSet"
$HTMLCopyright
<META HTTP-EQUIV="expires" CONTENT="NOW">
<html>
	<head>
		<title></title>
	</head>
<BODY>

#set $myVar1 = "number 1"
#set $myVar2 = "number 2"

#setblock $myEvalVar #begin
	#text #begin
	#foreach $item in ["aap (monkey)","noot (nut)","mies (girls name)"]
	{
		item : $item<BR>
	}
	
	myVar1 : $myVar1<BR>
	myVar2 : $myVar2<BR>
	#end
#end

<HR><PRE>$myEvalVar</PRE><HR>

#evalStringTemplate $myEvalVar

<BR><HR><BR>

## Output to a variable...
#evalStringTemplate $myEvalVar to $myOutput
\myOutput :<BR>$myOutput

#include as template "$(EngineTemplateDir)_includes/footer.inc"
</BODY>
</HTML>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.