You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by nb...@apache.org on 2008/08/18 20:29:34 UTC

svn commit: r686842 - in /velocity/engine/trunk/src: java/org/apache/velocity/runtime/defaults/ java/org/apache/velocity/runtime/directive/ test/org/apache/velocity/test/

Author: nbubna
Date: Mon Aug 18 11:29:31 2008
New Revision: 686842

URL: http://svn.apache.org/viewvc?rev=686842&view=rev
Log:
VELOCITY-612 add #break for #foreach (thanks to Jarkko Viinamaki)

Added:
    velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java   (with props)
    velocity/engine/trunk/src/test/org/apache/velocity/test/ForeachBreakTestCase.java   (with props)
Modified:
    velocity/engine/trunk/src/java/org/apache/velocity/runtime/defaults/directive.properties
    velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java

Modified: velocity/engine/trunk/src/java/org/apache/velocity/runtime/defaults/directive.properties
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/defaults/directive.properties?rev=686842&r1=686841&r2=686842&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/runtime/defaults/directive.properties (original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/runtime/defaults/directive.properties Mon Aug 18 11:29:31 2008
@@ -20,3 +20,4 @@
 directive.4=org.apache.velocity.runtime.directive.Macro
 directive.5=org.apache.velocity.runtime.directive.Literal
 directive.6=org.apache.velocity.runtime.directive.Evaluate
+directive.7=org.apache.velocity.runtime.directive.Break
\ No newline at end of file

Added: velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java?rev=686842&view=auto
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java (added)
+++ velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java Mon Aug 18 11:29:31 2008
@@ -0,0 +1,112 @@
+package org.apache.velocity.runtime.directive;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.velocity.app.event.EventCartridge;
+import org.apache.velocity.context.Context;
+import org.apache.velocity.context.InternalContextAdapter;
+import org.apache.velocity.exception.MethodInvocationException;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.velocity.exception.TemplateInitException;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.RuntimeServices;
+import org.apache.velocity.runtime.parser.node.ASTReference;
+import org.apache.velocity.runtime.parser.node.Node;
+import org.apache.velocity.runtime.parser.node.SimpleNode;
+import org.apache.velocity.runtime.resource.Resource;
+import org.apache.velocity.util.introspection.Info;
+import org.apache.velocity.util.introspection.IntrospectionCacheData;
+
+/**
+ * Break directive used for interrupting foreach loops.
+ *
+ * @author <a href="mailto:wyla@removethis.sci.fi">Jarkko Viinamaki</a>
+ * @version $Id$
+ */
+public class Break extends Directive
+{
+    /**
+     * Return name of this directive.
+     * @return The name of this directive.
+     */
+    public String getName()
+    {
+        return "break";
+    }
+
+    /**
+     * Return type of this directive.
+     * @return The type of this directive.
+     */
+    public int getType()
+    {
+        return LINE;
+    }
+
+    /**
+     *  simple init - init the tree and get the elementKey from
+     *  the AST
+     * @param rs
+     * @param context
+     * @param node
+     * @throws TemplateInitException
+     */
+    public void init(RuntimeServices rs, InternalContextAdapter context, Node node)
+        throws TemplateInitException
+    {
+        super.init(rs, context, node);
+    }
+
+    /**
+     * 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 boolean render(InternalContextAdapter context,
+                           Writer writer, Node node)
+        throws IOException,  MethodInvocationException, ResourceNotFoundException,
+        	ParseErrorException
+    {
+        throw new BreakException();
+    }
+    
+    public static class BreakException extends RuntimeException 
+    {
+        
+    }
+}

Propchange: velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java
------------------------------------------------------------------------------
    svn:keywords = Revision

Propchange: velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Break.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java?rev=686842&r1=686841&r2=686842&view=diff
==============================================================================
--- velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java (original)
+++ velocity/engine/trunk/src/java/org/apache/velocity/runtime/directive/Foreach.java Mon Aug 18 11:29:31 2008
@@ -499,28 +499,37 @@
 
         while (!maxNbrLoopsExceeded && i.hasNext())
         {
-            // TODO: JDK 1.4+ -> valueOf()
+            // TODO: JDK 1.4+ -> Integer.valueOf()
             context.localPut(counterName , new Integer(counter));
             context.localPut(hasNextName, Boolean.valueOf(i.hasNext()));
             Object value = i.next();
             context.localPut(elementKey, value);
 
-            /*
-             * If the value is null, use the special null holder context
-             */
-            if( value == null )
+            try
             {
-                if( nullHolderContext == null )
+                /*
+                 * If the value is null, use the special null holder context
+                 */
+                if (value == null)
                 {
-                    // lazy instantiation
-                    nullHolderContext = new NullHolderContext(elementKey, context);
+                    if (nullHolderContext == null)
+                    {
+                        // lazy instantiation
+                        nullHolderContext = new NullHolderContext(elementKey, context);
+                    }
+                    node.jjtGetChild(3).render(nullHolderContext, writer);
+                }
+                else
+                {
+                    node.jjtGetChild(3).render(context, writer);
                 }
-                node.jjtGetChild(3).render(nullHolderContext, writer);
             }
-            else
+            catch (Break.BreakException ex)
             {
-                node.jjtGetChild(3).render(context, writer);
+                // encountered #break directive inside #foreach loop
+                break;
             }
+            
             counter++;
 
             // Determine whether we're allowed to continue looping.

Added: velocity/engine/trunk/src/test/org/apache/velocity/test/ForeachBreakTestCase.java
URL: http://svn.apache.org/viewvc/velocity/engine/trunk/src/test/org/apache/velocity/test/ForeachBreakTestCase.java?rev=686842&view=auto
==============================================================================
--- velocity/engine/trunk/src/test/org/apache/velocity/test/ForeachBreakTestCase.java (added)
+++ velocity/engine/trunk/src/test/org/apache/velocity/test/ForeachBreakTestCase.java Mon Aug 18 11:29:31 2008
@@ -0,0 +1,102 @@
+package org.apache.velocity.test;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import junit.framework.TestCase;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.log.SystemLogChute;
+
+/**
+ * This class tests the break directive within Foreach loop.
+ */
+public class ForeachBreakTestCase extends TestCase
+{
+    private VelocityEngine engine;
+    private VelocityContext context;
+
+    public ForeachBreakTestCase(String name)
+    {
+        super(name);
+    }
+
+    public void setUp()
+        throws Exception
+    {
+        engine = new VelocityEngine();
+
+        // make the engine's log output go to the test-report
+        SystemLogChute log = new SystemLogChute();
+        log.setEnabledLevel(SystemLogChute.INFO_ID);
+        log.setSystemErrLevel(SystemLogChute.WARN_ID);
+        engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, log);
+
+        context = new VelocityContext();
+    }
+    
+    /**
+     * Tests break directive with a couple of iterations.
+     */
+    public void testConditionalBreakDirective()
+    {
+        assertEvalEquals("1, 2, 3, 4, 5",
+                         "#foreach($i in [1..10])$i#if($i > 4)#break#end, #end");
+    }
+
+    /**
+     * Tests break directive with immediate break.
+     */
+    public void testUnconditionalBreakDirective()
+    {
+        assertEvalEquals("1", "#foreach($i in [1..5])$i#break #end");
+    }
+
+    public void testNestedForeach()
+    {
+        assertEvalEquals("~~~, ~~, ~, ",
+            "#foreach($i in [1..3])#foreach($j in [2..4])#if($i*$j >= 8)#break#end~#end, #end");
+    }
+
+    protected void assertEvalEquals(String expected, String template)
+    {
+        try
+        {
+            String result = evaluate(template);
+            assertEquals(expected, result);
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private String evaluate(String template) throws Exception
+    {
+        StringWriter writer = new StringWriter();
+        // use template as its own name, since our templates are short
+        engine.evaluate(context, writer, template, template);
+        return writer.toString();
+    }
+}

Propchange: velocity/engine/trunk/src/test/org/apache/velocity/test/ForeachBreakTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: velocity/engine/trunk/src/test/org/apache/velocity/test/ForeachBreakTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Revision

Propchange: velocity/engine/trunk/src/test/org/apache/velocity/test/ForeachBreakTestCase.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain