Velocity
  1. Velocity
  2. VELOCITY-532

$velocityCount in macro not processed

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Cannot Reproduce
    • Affects Version/s: 1.5
    • Fix Version/s: 1.6
    • Component/s: None
    • Labels:
      None

      Description

      ---------- Forwarded message ----------
      From: mraible <matt@raibledesigns.com>
      Date: Mar 22, 2007 11:28 AM
      Subject: Issue with $velocityCount in 1.5
      To: user@velocity.apache.org

      I've been using Velocity 1.4 for a couple of years now with great success.
      Today, I tried to use Struts Menu 2.4.2 with Velocity 1.5 and found an issue
      with $velocityCount not being properly processed. My template is below.

      The problem occurs on the following line:

      #if ($velocityCount == $menu.parent.components.size())
      <li class="last">
      #else

      With 1.4, $velocityCount turns into a number when the displayCssMenu macro
      is called from #foreach. However, in 1.5, it's never turned into a number.

      Any ideas?

      Thanks,

      Matt

      #macro( displayCssMenu $menu )
      #if ($displayer.isAllowed($menu))

        1. set menu title
          #set ($title = $displayer.getMessage($menu.title))

      #if (!$menu.url) #set ($url="javascript:void(0)") #else #set
      ($url=$menu.url) #end

        1. create a single menu item
          #if ($menu.components.size() == 0)
          #if ($velocityCount == $menu.parent.components.size())
          <li class="last">
          #else
          <li>
          #end
          #if ($menu.name == $currentMenu)
          $url $ {title}
          #else
          $url ${title}

          #end
          #else ## create multiple menu items in a menu
          #if ($menu.components.size() > 0)
          #set ($hasViewableChildren = false)
          #foreach ($menuIt in $menu.components)
          #if ($displayer.isAllowed($menuIt))
          #set($hasViewableChildren = true)
          #end
          #end
          #end

      <li#if ($hasViewableChildren) class="menubar"#end>
      $url $

      {title}

      #end

      #if ($menu.components.size() > 0)
      #if ($hasViewableChildren)
      <ul>
      #end

      #foreach ($menuIt in $menu.components)
      #displayCssMenu($menuIt)
      #end

      #if ($hasViewableChildren && ($velocityCount ==
      $menu.parent.components.size()))
      </ul>
      #else
      </li>
      #end
      #else
      </li>
      #if ($velocityCount == $menu.parent.components.size())
      </ul>
      #end
      #end
      #end
      #end

      #displayCssMenu($menu)

      View this message in context: http://www.nabble.com/Issue-with-%24velocityCount-in-1.5-tf3449438.html#a9621118
      Sent from the Velocity - User mailing list archive at Nabble.com.

      ---------------------------------------------------------------------
      To unsubscribe, e-mail: user-unsubscribe@velocity.apache.org
      For additional commands, e-mail: user-help@velocity.apache.org


      Forio Business Simulations

      Will Glass-Husain
      wglass@forio.com
      www.forio.com

        Issue Links

          Activity

          Hide
          Nathan Bubna added a comment -

          I can't reproduce this with the current trunk (1.6-dev). Appears to have been fixed. Or else there's some nuance to the example code that i haven't replicated.

          Show
          Nathan Bubna added a comment - I can't reproduce this with the current trunk (1.6-dev). Appears to have been fixed. Or else there's some nuance to the example code that i haven't replicated.
          Hide
          Nathan Bubna added a comment -

          Seems like this is likely to be related to VELOCITY-62. There appears to have been some regression here from 1.4; i'm not sure what caused this change.

          I would still like to note that i consider this bad practice. If $velocityCount is relevant to the macro, it would be best passed in as an argument, rather than just hoping it is present.

          Show
          Nathan Bubna added a comment - Seems like this is likely to be related to VELOCITY-62 . There appears to have been some regression here from 1.4; i'm not sure what caused this change. I would still like to note that i consider this bad practice. If $velocityCount is relevant to the macro, it would be best passed in as an argument, rather than just hoping it is present.
          Hide
          Matt Raible added a comment -

          Here's my velocity.properties:

          1. specify resource loaders to use
            resource.loader = class, webapp
          1. NOTE: Change cache settings to set to false while developing - change to true when deploying to production.
          2. You'll need to copy this entire file into WEB-INF/classes to override any attributes.
          1. for the loader we call 'class', use the ClasspathResourceLoader
            class.resource.loader.description = Velocity Classpath Resource Loader
            class.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
            class.resource.loader.cache = true
            class.resource.loader.modificationCheckInterval = 60
          1. for the loader we call 'webapp', use the WebappLoader
            webapp.resource.loader.description = Velocity Webapp Loader
            webapp.resource.loader.class = org.apache.velocity.tools.view.servlet.WebappLoader
            webapp.resource.loader.cache = true
            webapp.resource.loader.modificationCheckInterval = 60
          1. log invalid template references?
          2. set this to false to have a quieter velocity.log
            runtime.log.invalid.reference=false
          1. velocimacro settings
            velocimacro.library = net/sf/navigator/displayer/globalMacros.vm,menuMacros.vm
            velocimacro.library.autoreload = true
            velocimacro.permissions.allow.inline.to.replace.global = true
          1. load the local directive
            userdirective=net.sf.navigator.displayer.LocalDirective

          And LocalDirective.java:

          /*

          • The Apache Software License, Version 1.1
            *
          • Copyright (c) 2003 The Apache Software Foundation. All rights
          • reserved.
            *
          • Redistribution and use in source and binary forms, with or without
          • modification, are permitted provided that the following conditions
          • are met:
            *
          • 1. Redistributions of source code must retain the above copyright
          • notice, this list of conditions and the following disclaimer.
            *
          • 2. Redistributions in binary form must reproduce the above copyright
          • notice, this list of conditions and the following disclaimer in
          • the documentation and/or other materials provided with the
          • distribution.
            *
          • 3. The end-user documentation included with the redistribution, if
          • any, must include the following acknowlegement:
          • "This product includes software developed by the
          • Apache Software Foundation (http://www.apache.org/)."
          • Alternately, this acknowlegement may appear in the software itself,
          • if and wherever such third-party acknowlegements normally appear.
            *
          • 4. The names "The Jakarta Project", "Velocity", and "Apache Software
          • Foundation" must not be used to endorse or promote products derived
          • from this software without prior written permission. For written
          • permission, please contact apache@apache.org.
            *
          • 5. Products derived from this software may not be called "Apache"
          • nor may "Apache" appear in their names without prior written
          • permission of the Apache Group.
            *
          • THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
          • WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
          • OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
          • DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
          • ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
          • SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
          • LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
          • USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
          • ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
          • OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
          • OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
          • SUCH DAMAGE.
          • ====================================================================
            *
          • This software consists of voluntary contributions made by many
          • individuals on behalf of the Apache Software Foundation. For more
          • information on the Apache Software Foundation, please see
          • <http://www.apache.org/>.
            */

          package net.sf.navigator.displayer;

          import org.apache.velocity.context.InternalContextAdapter;
          import org.apache.velocity.runtime.parser.node.Node;
          import org.apache.velocity.runtime.parser.node.SimpleNode;
          import org.apache.velocity.runtime.directive.Directive;
          import org.apache.velocity.runtime.parser.ParserTreeConstants;
          import org.apache.velocity.exception.MethodInvocationException;
          import org.apache.velocity.exception.ResourceNotFoundException;
          import org.apache.velocity.exception.ParseErrorException;

          import org.apache.velocity.runtime.parser.node.ASTReference;

          import java.io.Writer;
          import java.io.IOException;
          import java.util.Map;
          import java.util.HashMap;
          import java.util.Iterator;

          /**

          • Simple directive to provide ability to trap a local value for
          • iteration.
            *
          • Ex :
            *
          • #set($foo = 1)
          • $foo
          • #local($foo)
          • #set($foo = 2)
          • $foo
          • #end
          • $foo
            *
          • should output
            *
          • 1
          • 2
          • 1
            *
          • @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
          • @version $Id: LocalDirective.java,v 1.1 2003/10/31 05:59:06 mraible Exp $
            */
            public class LocalDirective extends Directive
            {
            public String getName() { return "local"; }

          public int getType()

          { return BLOCK; }

          public boolean render(InternalContextAdapter context,
          Writer writer, Node node)
          throws IOException, MethodInvocationException, ResourceNotFoundException,
          ParseErrorException
          {
          Map data = new HashMap();

          int num = node.jjtGetNumChildren();

          /*

          • get the references
            */

          for (int i=0; i < num; i++)
          {
          SimpleNode child = (SimpleNode) node.jjtGetChild;

          /*

          • if a block, just execute
            */

          if (child.getType() == ParserTreeConstants.JJTBLOCK)

          { child.render(context, writer); break; }

          else
          {
          /* save the values - for now, just w/ ref to test */

          if (child.getType() == ParserTreeConstants.JJTREFERENCE)

          { data.put(child, child.execute(null, context)); }

          else

          { System.out.println("unhandled type"); }

          }
          }

          Iterator it = data.keySet().iterator();

          while(it.hasNext())

          { ASTReference ref = (ASTReference) it.next(); ref.setValue(context, data.get(ref)); }

          return true;
          }
          }

          Show
          Matt Raible added a comment - Here's my velocity.properties: specify resource loaders to use resource.loader = class, webapp NOTE: Change cache settings to set to false while developing - change to true when deploying to production. You'll need to copy this entire file into WEB-INF/classes to override any attributes. for the loader we call 'class', use the ClasspathResourceLoader class.resource.loader.description = Velocity Classpath Resource Loader class.resource.loader.class = org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader class.resource.loader.cache = true class.resource.loader.modificationCheckInterval = 60 for the loader we call 'webapp', use the WebappLoader webapp.resource.loader.description = Velocity Webapp Loader webapp.resource.loader.class = org.apache.velocity.tools.view.servlet.WebappLoader webapp.resource.loader.cache = true webapp.resource.loader.modificationCheckInterval = 60 log invalid template references? set this to false to have a quieter velocity.log runtime.log.invalid.reference=false velocimacro settings velocimacro.library = net/sf/navigator/displayer/globalMacros.vm,menuMacros.vm velocimacro.library.autoreload = true velocimacro.permissions.allow.inline.to.replace.global = true load the local directive userdirective=net.sf.navigator.displayer.LocalDirective And LocalDirective.java: /* The Apache Software License, Version 1.1 * Copyright (c) 2003 The Apache Software Foundation. All rights reserved. * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * 3. The end-user documentation included with the redistribution, if any, must include the following acknowlegement: "This product includes software developed by the Apache Software Foundation ( http://www.apache.org/ )." Alternately, this acknowlegement may appear in the software itself, if and wherever such third-party acknowlegements normally appear. * 4. The names "The Jakarta Project", "Velocity", and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact apache@apache.org. * 5. Products derived from this software may not be called "Apache" nor may "Apache" appear in their names without prior written permission of the Apache Group. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ==================================================================== * This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation. For more information on the Apache Software Foundation, please see < http://www.apache.org/ >. */ package net.sf.navigator.displayer; import org.apache.velocity.context.InternalContextAdapter; import org.apache.velocity.runtime.parser.node.Node; import org.apache.velocity.runtime.parser.node.SimpleNode; import org.apache.velocity.runtime.directive.Directive; import org.apache.velocity.runtime.parser.ParserTreeConstants; import org.apache.velocity.exception.MethodInvocationException; import org.apache.velocity.exception.ResourceNotFoundException; import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.runtime.parser.node.ASTReference; import java.io.Writer; import java.io.IOException; import java.util.Map; import java.util.HashMap; import java.util.Iterator; /** Simple directive to provide ability to trap a local value for iteration. * Ex : * #set($foo = 1) $foo #local($foo) #set($foo = 2) $foo #end $foo * should output * 1 2 1 * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a> @version $Id: LocalDirective.java,v 1.1 2003/10/31 05:59:06 mraible Exp $ */ public class LocalDirective extends Directive { public String getName() { return "local"; } public int getType() { return BLOCK; } public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException, MethodInvocationException, ResourceNotFoundException, ParseErrorException { Map data = new HashMap(); int num = node.jjtGetNumChildren(); /* get the references */ for (int i=0; i < num; i++) { SimpleNode child = (SimpleNode) node.jjtGetChild ; /* if a block, just execute */ if (child.getType() == ParserTreeConstants.JJTBLOCK) { child.render(context, writer); break; } else { /* save the values - for now, just w/ ref to test */ if (child.getType() == ParserTreeConstants.JJTREFERENCE) { data.put(child, child.execute(null, context)); } else { System.out.println("unhandled type"); } } } Iterator it = data.keySet().iterator(); while(it.hasNext()) { ASTReference ref = (ASTReference) it.next(); ref.setValue(context, data.get(ref)); } return true; } }

            People

            • Assignee:
              Unassigned
              Reporter:
              Will Glass-Husain
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development