Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTStringLiteral.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTStringLiteral.java?rev=1616957&r1=1616956&r2=1616957&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTStringLiteral.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ASTStringLiteral.java Sat Aug 9 14:12:09 2014 @@ -17,6 +17,8 @@ package org.apache.commons.jexl3.parser; public final class ASTStringLiteral extends JexlNode implements JexlNode.Constant<String> { + /** The actual literal value; the inherited 'value' member may host a cached getter. */ + private String literal = null; ASTStringLiteral(int id) { super(id); @@ -28,7 +30,7 @@ public final class ASTStringLiteral exte @Override public String toString() { - return value.toString(); + return this.literal; } /** @@ -37,7 +39,7 @@ public final class ASTStringLiteral exte */ @Override public String getLiteral() { - return value.toString(); + return this.literal; } @@ -48,7 +50,7 @@ public final class ASTStringLiteral exte } void setLiteral(String literal) { - value = literal; + this.literal = literal; }
Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java?rev=1616957&r1=1616956&r2=1616957&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/JexlParser.java Sat Aug 9 14:12:09 2014 @@ -175,6 +175,10 @@ public abstract class JexlParser extends } } + protected void throwParsingException(JexlNode node) { + throwParsingException(null, node); + } + /** * Throws a parsing exception. * @param xclazz the class of exception Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt?rev=1616957&r1=1616956&r2=1616957&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/Parser.jjt Sat Aug 9 14:12:09 2014 @@ -38,6 +38,8 @@ import org.apache.commons.jexl3.internal public final class Parser extends JexlParser { + private int loopCount = 0; + public ASTJexlScript parse(JexlInfo info, String jexlSrc, Scope scope, boolean registers, boolean expr) { try { // If registers are allowed, the default parser state has to be REGISTERS. @@ -99,6 +101,8 @@ PARSER_END(Parser) | < RETURN : "return" > | < FUNCTION : "function" > | < LAMBDA : "->" > + | < BREAK : "break" > + | < CONTINUE : "continue" > } <FOR_EACH_IN> TOKEN : /* foreach in */ @@ -233,6 +237,8 @@ void Statement() #void : {} | WhileStatement() | ExpressionStatement() | ReturnStatement() + | Continue() + | Break() | Var() } @@ -256,7 +262,7 @@ void IfStatement() : {} void WhileStatement() : {} { - <WHILE> <LPAREN> Expression() <RPAREN> Statement() + <WHILE> <LPAREN> Expression() <RPAREN> { loopCount += 1; } Statement() { loopCount -= 1; } } void ReturnStatement() : {} @@ -264,11 +270,21 @@ void ReturnStatement() : {} <RETURN> Expression() } +void Continue() #Continue : {} +{ + <CONTINUE> { if (loopCount == 0) { throwParsingException(jjtThis); } } +} + +void Break() #Break : {} +{ + <BREAK> { if (loopCount == 0) { throwParsingException(jjtThis); } } +} + void ForeachStatement() : {} { - <FOR> <LPAREN> ForEachVar() <COLON> Expression() <RPAREN> Statement() + <FOR> <LPAREN> ForEachVar() <COLON> Expression() <RPAREN> { loopCount += 1; } Statement() { loopCount -= 1; } | - <FOREACH> <LPAREN> ForEachVar() <IN> Expression() <RPAREN> Statement() + <FOREACH> <LPAREN> ForEachVar() <IN> Expression() <RPAREN> { loopCount += 1; } Statement() { loopCount -= 1; } } void ForEachVar() #Reference : {} Modified: commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java?rev=1616957&r1=1616956&r2=1616957&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java (original) +++ commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl3/parser/ParserVisitor.java Sat Aug 9 14:12:09 2014 @@ -48,6 +48,10 @@ public abstract class ParserVisitor { protected abstract Object visit(ASTWhileStatement node, Object data); + protected abstract Object visit(ASTContinue node, Object data); + + protected abstract Object visit(ASTBreak node, Object data); + protected abstract Object visit(ASTForeachStatement node, Object data); protected abstract Object visit(ASTReturnStatement node, Object data); Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ForEachTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ForEachTest.java?rev=1616957&r1=1616956&r2=1616957&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ForEachTest.java (original) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/ForEachTest.java Sat Aug 9 14:12:09 2014 @@ -96,7 +96,7 @@ public class ForEachTest extends JexlTes } public void testForEachWithBlock() throws Exception { - JexlScript exs0 = JEXL.createScript("for(in : list) { x = x + in; }"); + JexlScript exs0 = JEXL.createScript("for(var in : list) { x = x + in; }"); JexlScript exs1 = JEXL.createScript("foreach(item in list) { x = x + item; }"); JexlScript []exs = { exs0, exs1 }; JexlContext jc = new MapContext(); @@ -110,7 +110,7 @@ public class ForEachTest extends JexlTes } public void testForEachWithListExpression() throws Exception { - JexlScript e = JEXL.createScript("for(item : list.keySet()) item"); + JexlScript e = JEXL.createScript("for(var item : list.keySet()) item"); JexlContext jc = new MapContext(); Map<?, ?> map = System.getProperties(); String lastKey = (String) new ArrayList<Object>(map.keySet()).get(System.getProperties().size() - 1); @@ -120,7 +120,7 @@ public class ForEachTest extends JexlTes } public void testForEachWithProperty() throws Exception { - JexlScript e = JEXL.createScript("for(item : list.cheeseList) item"); + JexlScript e = JEXL.createScript("for(var item : list.cheeseList) item"); JexlContext jc = new MapContext(); jc.set("list", new Foo()); Object o = e.execute(jc); @@ -128,10 +128,50 @@ public class ForEachTest extends JexlTes } public void testForEachWithIteratorMethod() throws Exception { - JexlScript e = JEXL.createScript("for(item : list.cheezy) item"); + JexlScript e = JEXL.createScript("for(var item : list.cheezy) item"); JexlContext jc = new MapContext(); jc.set("list", new Foo()); Object o = e.execute(jc); assertEquals("Result is not last evaluated expression", "brie", o); } + + public void testForEachBreakMethod() throws Exception { + JexlScript e = JEXL.createScript( + "var rr = -1; for(var item : [1, 2, 3 ,4 ,5, 6]) { if (item == 3) { rr = item; break; }} rr" + ); + JexlContext jc = new MapContext(); + jc.set("list", new Foo()); + Object o = e.execute(jc); + assertEquals("Result is not last evaluated expression", 3, o); + } + + public void testForEachContinueMethod() throws Exception { + JexlScript e = JEXL.createScript( + "var rr = 0; for(var item : [1, 2, 3 ,4 ,5, 6]) { if (item <= 3) continue; rr = rr + item;}" + ); + JexlContext jc = new MapContext(); + jc.set("list", new Foo()); + Object o = e.execute(jc); + assertEquals("Result is not last evaluated expression", 15, o); + } + + public void testForEachContinueBroken() throws Exception { + try { + JexlScript e = JEXL.createScript("var rr = 0; continue;"); + fail("continue is out of loop!"); + } catch (JexlException.Parsing xparse) { + String str = xparse.detailedMessage(); + assertTrue(str.contains("continue")); + } + } + + public void testForEachBreakBroken() throws Exception { + try { + JexlScript e = JEXL.createScript("if (true) { break; }"); + fail("break is out of loop!"); + } catch (JexlException.Parsing xparse) { + String str = xparse.detailedMessage(); + assertTrue(str.contains("break")); + } + } } \ No newline at end of file Modified: commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JXLTTest.java URL: http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JXLTTest.java?rev=1616957&r1=1616956&r2=1616957&view=diff ============================================================================== --- commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JXLTTest.java (original) +++ commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl3/JXLTTest.java Sat Aug 9 14:12:09 2014 @@ -27,6 +27,7 @@ import java.io.Writer; import java.util.Arrays; import java.util.List; import java.util.Set; +import junit.framework.Assert; /** * Test cases for the UnifiedEL. @@ -205,6 +206,42 @@ public class JXLTTest extends JexlTestCa assertEquals(source, getSource(expr.toString())); } + public void testConstant2() throws Exception { + JexlContext none = null; + final String source = "${size({'map':123,'map2':456})}"; + JxltEngine.Expression expr = JXLT.createExpression(source); + //assertTrue("prepare should return same expression", expr.prepare(none) == expr); + Object o = expr.evaluate(none); + assertTrue("expression should be immediate", expr.isImmediate()); + assertEquals(2, o); + + assertEquals(source, getSource(expr.toString())); + } + + public void testConstant3() throws Exception { + JexlContext none = null; + final String source = "#{size({'map':123,'map2':456})}"; + JxltEngine.Expression expr = JXLT.createExpression(source); + //assertTrue("prepare should return same expression", expr.prepare(none) == expr); + Object o = expr.evaluate(none); + assertTrue("expression should be deferred", expr.isDeferred()); + assertEquals(2, o); + + assertEquals(source, getSource(expr.toString())); + } + + public void testConstant4() throws Exception { + JexlContext none = null; + final String source = "#{ ${size({'1':2,'2': 3})} }"; + JxltEngine.Expression expr = JXLT.createExpression(source); + //assertTrue("prepare should return same expression", expr.prepare(none) == expr); + Object o = expr.evaluate(none); + assertTrue("expression should be deferred", expr.isDeferred()); + assertEquals(2, o); + + assertEquals(source, getSource(expr.toString())); + } + public void testDeferred() throws Exception { JexlContext none = null; final String source = "#{'world'}"; @@ -340,6 +377,20 @@ public class JXLTTest extends JexlTestCa String dstr = t.toString(); assertNotNull(dstr); } + public void testTemplate10() throws Exception { + String source = "$$(x)->{ if(x) {\nx is ${x}\n$$ } else {\n${'no x'}\n$$ } }\n"; + StringWriter strw; + String output; + + JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(source), (String[])null); + String dstr = t.asString(); + assertNotNull(dstr); + + strw = new StringWriter(); + t.evaluate(context, strw, 42); + output = strw.toString(); + assertEquals("x is 42\n", output); + } public void testTemplate1() throws Exception { String source = "$$ if(x) {\nx is ${x}\n$$ } else {\n${'no x'}\n$$ }\n"; @@ -462,6 +513,29 @@ public class JXLTTest extends JexlTestCa assertEquals(ctl, output); } + public void testReport1() throws Exception { + String rpt = + "<report>\n" + + "this is ${x}\n" + + "${x + 1}\n" + + "${x + 2}\n" + + "${x + 3}\n" + + "</report>\n"; + JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader(rpt)); + StringWriter strw = new StringWriter(); + context.set("x", 42); + t.evaluate(context, strw, 42); + String output = strw.toString(); + int count = 0; + for(int i = 0; i < output.length(); ++i) { + char c = output.charAt(i); + if ('\n' == c) { + count += 1; + } + } + assertEquals(6, count); + } + public void testOneLiner() throws Exception { JxltEngine.Template t = JXLT.createTemplate("$$", new StringReader("fourty-two"));