Re: #properties directive

Lane Sharman <[email protected]> Sun, 31 Jul 2005 16:17:31 -0700
Newsgroups gmane.comp.java.webmacro.user
Message-ID <[email protected]>
Hi Keats,

Do you really want to include this in the pending 2.1 release?

Have you considered that you now have to document 2 ways to set a 
property, #properties and #set? Will this confuse a new person to 
WebMacro? Is your #property ... a big advantage over #set 
$Object.Property = "foo"

It is certainly a nice convenience. Just not sure that its inclusion 
will improve more than its support and documentation demands will warrant.

-Lane



Keats Kirsch wrote:

> I created a new directive called Properties directive.  This can be 
> handy if you want to set a bunch of properties on an object within a 
> template; essentially providing a abbreviated, readable syntax.  You 
> can also combine it with the #include directive for processing a 
> properties file.  (Just be careful of comments: use "##" or "# " to 
> keep them from confusing the parser.)
>
> I'm attaching the source and I will commit it to the core if folks 
> agree it is worthy.
>
> Here's some test WMScript that illustrates the usage:
>
> ## Test using default object: java.util.Properties
> #set $Name="Keats Kirsch"
> #set $Age=45
> <h3>\#properties test</h3>
> #properties $p {
>    Name: $Name
>    Age = $Age
> }
> My age is $p.Age<br>
> My name is $p.Name<br>
> ## Test using a pre-existing POJO (non-map)
> <h3>More \#properties</h3>
> #bean $Cal="java.util.Calendar" scope=static
> #set $GCal=$Cal.Instance
> Today: $GCal.Time, FirstDayOfWeek: $GCal.FirstDayOfWeek, Lenient: 
> $GCal.Lenient
> <br>
> #properties $GCal {
>    FirstDayOfWeek=0
>    Lenient=false
> }
> Today: $GCal.Time, FirstDayOfWeek: $GCal.FirstDayOfWeek, Lenient: 
> $GCal.Lenient
> <br>
>
>------------------------------------------------------------------------
>
>/*
> * Copyright (C) 2005 Semiotek Inc.  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);
> *
> *  or
> *
> * The Semiotek Public License (http://webmacro.org/LICENSE.)
> *
> * 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.
> */
>
>package org.webmacro.directive;
>
>import org.webmacro.*;
>import org.webmacro.engine.BuildContext;
>import org.webmacro.engine.BuildException;
>import org.webmacro.engine.StringTemplate;
>import org.webmacro.engine.Variable;
>import org.webmacro.servlet.TextTool;
>
>import java.io.IOException;
>import java.util.Hashtable;
>
>/*
> * 
> * @author Keats Kirsch
> * Set properties on an object using Java properties file type syntax
> *
> */
>public class PropertiesDirective extends Directive
>{
>
>   private static final String DEFAULT_CLASS_NAME = "java.util.Hashtable";
>   private static final int PROPS_TARGET = 1;
>   private static final int PROPS_CLASS = 2;
>   private static final int PROPS_CLASSNAME = 3;
>   private static final int PROPS_RESULT = 4;
>
>   private Variable target;
>   private Object result;
>   private String _className;
>   //private boolean asMacro = false;
>
>   private static final ArgDescriptor[] myArgs =
>      new ArgDescriptor[] {
>         new LValueArg(PROPS_TARGET),
>         new OptionalGroup(3),
>         new KeywordArg(PROPS_CLASS, "class"),
>         new AssignmentArg(),
>         new QuotedStringArg(PROPS_CLASSNAME),
>         new BlockArg(PROPS_RESULT)};
>
>   private static final DirectiveDescriptor myDescr =
>      new DirectiveDescriptor("properties", null, myArgs, null);
>
>   public static DirectiveDescriptor getDescriptor()
>   {
>      return myDescr;
>   }
>
>   public PropertiesDirective()
>   {
>   }
>
>   public Object build(DirectiveBuilder builder, BuildContext bc)
>      throws BuildException
>   {
>      try
>      {
>         target = (Variable) builder.getArg(PROPS_TARGET, bc);
>      }
>      catch (ClassCastException e)
>      {
>         throw new NotVariableBuildException(myDescr.name, e);
>      }
>      _className = (String) builder.getArg(PROPS_CLASSNAME, bc);
>      if (_className == null)
>         _className = DEFAULT_CLASS_NAME;
>      // 
>
>      //        asMacro = (macroKeyword != null);
>      result = builder.getArg(PROPS_RESULT, bc);
>      return this;
>   }
>
>   public void write(FastWriter out, Context context)
>      throws PropertyException, IOException
>   {
>
>      try
>      {
>         if (!context.containsKey(target.getName()))
>         {
>            // target doesn't exist. Must create.
>            try
>            {
>               Class c = Class.forName(_className);
>               Object o = c.newInstance();
>               target.setValue(context, o);
>            }
>            catch (RuntimeException re)
>            {
>               throw new PropertyException(
>                  "Failed to create instance of "
>                     + _className
>                     + " for the #properties directive. "
>                     + re,
>                  re);
>            }
>
>         }
>         //            if (result instanceof Macro && !asMacro)
>         //                target.setValue(context, ((Macro) result).evaluate(context));
>         //            else
>         // evaluate result macro
>         Object o = ((Macro) result).evaluate(context);
>         String res = (String) ((Macro) result).evaluate(context);
>         String[] lines = TextTool.getLines(res);
>         String s, prop, val;
>         String prefix = "#set $" + target.getVariableName() + ".";
>         for (int i = 0; i < lines.length; i++)
>         {
>            s = lines[i].trim();
>            if (s.length() > 0 && !s.startsWith("#"))
>            {
>               for (int j = 0; j < s.length(); j++)
>               {
>                  char ch = s.charAt(j);
>                  if (ch == ':' || ch == '=')
>                  {
>                     prop = s.substring(0, j).trim();
>                     //TODO check if valid property name?
>                     val = s.substring(j + 1).trim();
>                     // convert to WM syntax and evaluate
>                     // TODO determine if quotes are needed, i.e., is it a number?
>                     if (val.length() > 0)
>                     {
>                        // try first as a string
>                        s = prefix + prop + "=\"" + val + "\"";
>                        try
>                        {
>                           new StringTemplate(
>                              context.getBroker(),
>                              s).evaluateAsString(
>                              context);
>                        }
>                        catch (WebMacroException wme)
>                        {
>                           // try again without quotes.
>									s = prefix + prop + "=" + val;
>									try
>									{
>										new StringTemplate(context.getBroker(),s)
>										.evaluateAsString(context);
>									}
>									catch (WebMacroException wme2)
>									{
>										// TODO utilize the EEH from the context?
>										throw new PropertyException("Failed to set property \"" 
>										+ prop + "\" to value \"" + val + "\" on variable \""
>										+ target.getVariableName() + "\" of type " 
>										+ target.getClass().getName(),
>										wme2);
>									}
>                        }
>                        break;
>                     }
>                  }
>               }
>            }
>            //target.setValue(context, result);
>            // parse the 
>         }
>      }
>      catch (PropertyException e)
>      {
>         throw e;
>      }
>      catch (Exception e)
>      {
>         String errorText = "#properties: Unable to set " + target;
>         writeWarning(errorText, context, out);
>      }
>   }
>
>   public void accept(TemplateVisitor v)
>   {
>      v.beginDirective(myDescr.name);
>      v.visitDirectiveArg("PropertiesClassKeyword", "class");
>      v.visitDirectiveArg("PropertiesClassName", _className);
>      v.visitDirectiveArg("PropertiesTarget", target);
>      v.visitDirectiveArg("PropertiesValue", result);
>      v.endDirective();
>   }
>
>}
>  
>

-- 
Lane Sharman
Providing Private and SPAM-Free Email
http://www.opendoors.com
858-755-2868