Author: hlship
Date: Thu Jan  8 14:46:48 2009
New Revision: 732861

URL: http://svn.apache.org/viewvc?rev=732861&view=rev
Log:
TAP5-79: Improve Tapestry's property expression language to include OGNL-like 
features
- Add '!' (boolean not) operator

Added:
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/Switch.java
Modified:
    tapestry/tapestry5/trunk/src/site/apt/guide/propexp.apt
    
tapestry/tapestry5/trunk/tapestry-core/src/main/antlr/org/apache/tapestry5/internal/antlr/PropertyExpressionLexer.g
    
tapestry/tapestry5/trunk/tapestry-core/src/main/antlr/org/apache/tapestry5/internal/antlr/PropertyExpressionParser.g
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BasePropertyConduit.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/tapestry-core.iml
    
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java

Modified: tapestry/tapestry5/trunk/src/site/apt/guide/propexp.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/src/site/apt/guide/propexp.apt?rev=732861&r1=732860&r2=732861&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/src/site/apt/guide/propexp.apt (original)
+++ tapestry/tapestry5/trunk/src/site/apt/guide/propexp.apt Thu Jan  8 14:46:48 
2009
@@ -47,7 +47,7 @@
 Grammar
 
 ---
-expression : keyword | rangeOp | constant | propertyChain | list;
+expression : keyword | rangeOp | constant | propertyChain | list | notOp;
 
 keyword : 'null' | 'true' | 'false' | 'this';
 
@@ -67,7 +67,9 @@
 list : '[' expressionList? ']';
 
 expressionList : expression (',' expression)*;
-     
+
+notOpt : '!' expression;
+
 ---
 
   Notes:
@@ -90,6 +92,8 @@
   
   * 'this' is the root object (i.e., the containing component).
 
+  * The not operator coerces the expression to a boolean (so it can be used on 
strings, numbers, etc.).
+  
   []
 
   Method matching is based on method name and number of parameters, but not 
parameter types.  The

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/antlr/org/apache/tapestry5/internal/antlr/PropertyExpressionLexer.g
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/antlr/org/apache/tapestry5/internal/antlr/PropertyExpressionLexer.g?rev=732861&r1=732860&r2=732861&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/antlr/org/apache/tapestry5/internal/antlr/PropertyExpressionLexer.g
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/antlr/org/apache/tapestry5/internal/antlr/PropertyExpressionLexer.g
 Thu Jan  8 14:46:48 2009
@@ -53,6 +53,7 @@
 LBRACKET:      '[';
 RBRACKET:      ']';
 COMMA  :       ',';
+BANG    :      '!';
 
 fragment QUOTE
        :       '\'';

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/antlr/org/apache/tapestry5/internal/antlr/PropertyExpressionParser.g
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/antlr/org/apache/tapestry5/internal/antlr/PropertyExpressionParser.g?rev=732861&r1=732860&r2=732861&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/antlr/org/apache/tapestry5/internal/antlr/PropertyExpressionParser.g
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/antlr/org/apache/tapestry5/internal/antlr/PropertyExpressionParser.g
 Thu Jan  8 14:46:48 2009
@@ -29,6 +29,8 @@
        INVOKE;
        // A List (top level, or as method parameter)
        LIST;
+       // Not operation (invert a boolean)
+       NOT;
 }
 
 @header
@@ -45,6 +47,7 @@
        |       constant
        |       propertyChain
        |       list
+       |       notOp
        ;
        
 keyword        :       NULL | TRUE | FALSE | THIS;
@@ -76,7 +79,13 @@
        
 rangeopArg 
        :       INTEGER
-       |       propertyChain;  
+       |       propertyChain
+       ;       
        
 list   :       LBRACKET RBRACKET -> ^(LIST)
-       |       LBRACKET expressionList RBRACKET -> ^(LIST expressionList);     
+       |       LBRACKET expressionList RBRACKET -> ^(LIST expressionList)
+       ;       
+       
+       
+notOp  :       BANG expression -> ^(NOT expression)
+       ;

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BasePropertyConduit.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BasePropertyConduit.java?rev=732861&r1=732860&r2=732861&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BasePropertyConduit.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/BasePropertyConduit.java
 Thu Jan  8 14:46:48 2009
@@ -75,4 +75,9 @@
     {
         return typeCoercer.coerce(value, type);
     }
+
+    public final Boolean invert(Object value)
+    {
+        return coerce(value, Boolean.class).equals(Boolean.FALSE);
+    }
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java?rev=732861&r1=732860&r2=732861&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java
 Thu Jan  8 14:46:48 2009
@@ -56,11 +56,14 @@
 
     private static final Method RANGE;
 
+    private static final Method INVERT;
+
     static
     {
         try
         {
             RANGE = BasePropertyConduit.class.getMethod("range", int.class, 
int.class);
+            INVERT = BasePropertyConduit.class.getMethod("invert", 
Object.class);
         }
         catch (NoSuchMethodException ex)
         {
@@ -457,8 +460,16 @@
 
                     return;
 
+                case NOT:
+                    createNotOpGetter(node);
+                    createNoOpSetter();
+
+                    conduitPropertyType = boolean.class;
+
+                    return;
+
                 default:
-                    throw unexpectedNodeType(node, IDENTIFIER, INVOKE, 
RANGEOP, LIST);
+                    throw unexpectedNodeType(node, IDENTIFIER, INVOKE, 
RANGEOP, LIST, NOT);
             }
         }
 
@@ -475,6 +486,20 @@
             classFab.addMethod(Modifier.PUBLIC, GET_SIGNATURE, 
builder.toString());
         }
 
+        private void createNotOpGetter(Tree node)
+        {
+            BodyBuilder builder = new BodyBuilder().begin();
+
+            addRootVariable(builder);
+
+            builder.addln("return %s;", createMethodInvocation(builder, node, 
0, INVERT));
+
+            builder.end();
+
+            classFab.addMethod(Modifier.PUBLIC, GET_SIGNATURE, 
builder.toString());
+        }
+
+
         public void createListGetter(Tree node)
         {
             BodyBuilder builder = new BodyBuilder().begin();
@@ -506,12 +531,22 @@
             return listName;
         }
 
+        private String createNotOp(BodyBuilder builder, Tree node)
+        {
+            String flagName = nextVariableName(Boolean.class);
+            GeneratedTerm term = subexpression(builder, node.getChild(0));
+
+            builder.addln("Boolean %s = invert(($w) %s);", flagName, 
term.getVariableName());
+
+            return flagName;
+        }
+
         /**
          * Evalutates the node as a sub expression, storing the result into a 
new variable, whose name is returned.
          *
          * @param builder to receive generated code
          * @param node    root of tree of nodes to be evaluated
-         * @return name of variable containing expression
+         * @return GeneratedTerm identifying the name of the variable and its 
type
          */
         private GeneratedTerm subexpression(BodyBuilder builder, Tree node)
         {
@@ -579,6 +614,15 @@
 
                         break;
 
+                    case NOT:
+
+                        previousVariableName = createNotOp(builder, node);
+                        activeType = boolean.class;
+
+                        node = null;
+
+                        break;
+
                     case LIST:
 
                         previousVariableName = createListConstructor(builder, 
node);
@@ -715,6 +759,8 @@
 
                 Class parameterType = parameterTypes[i];
 
+                boolean needsUnwrap = false;
+
                 if (!parameterType.isAssignableFrom(actualType))
                 {
                     String coerced = nextVariableName(parameterType);
@@ -729,12 +775,19 @@
 
                     variableName = coerced;
                 }
-
-                // TODO: Casting, coercing, unwrapping primitives.
+                else
+                {
+                    needsUnwrap = parameterType.isPrimitive();
+                }
 
                 if (i > 0) builder.append(", ");
 
                 builder.append(variableName);
+
+                if (needsUnwrap)
+                {
+                    
builder.append(".").append(ClassFabUtils.getUnwrapMethodName(parameterType)).append("()");
+                }
             }
 
             return builder.append(")").toString();

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java?rev=732861&r1=732860&r2=732861&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImplTest.java
 Thu Jan  8 14:46:48 2009
@@ -368,4 +368,31 @@
 
         assertListsEquals(l, new Long(1), new Double(2.0), "Bart");
     }
+
+    @Test
+    public void not_operator()
+    {
+        PropertyConduit conduit = source.create(IntegerHolder.class, "! 
value");
+        IntegerHolder holder = new IntegerHolder();
+
+        assertEquals(conduit.get(holder), Boolean.TRUE);
+
+        holder.setValue(99);
+
+        assertEquals(conduit.get(holder), Boolean.FALSE);
+    }
+
+    @Test
+    public void no_operator_in_subexpression()
+    {
+        PropertyConduit conduit = source.create(Switch.class, "label(! 
value)");
+
+        Switch sw = new Switch();
+
+        assertEquals(conduit.get(sw), "aye");
+
+        sw.setValue(true);
+
+        assertEquals(conduit.get(sw), "nay");
+    }
 }

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/Switch.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/Switch.java?rev=732861&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/Switch.java
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/Switch.java
 Thu Jan  8 14:46:48 2009
@@ -0,0 +1,35 @@
+// Copyright 2009 The Apache Software Foundation
+//
+// Licensed 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.
+
+package org.apache.tapestry5.internal.services;
+
+public class Switch
+{
+    private boolean value;
+
+    public boolean isValue()
+    {
+        return value;
+    }
+
+    public void setValue(boolean value)
+    {
+        this.value = value;
+    }
+
+    public String label(boolean flag)
+    {
+        return flag ? "aye" : "nay";
+    }
+}

Modified: tapestry/tapestry5/trunk/tapestry-core/tapestry-core.iml
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/tapestry-core.iml?rev=732861&r1=732860&r2=732861&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/tapestry-core.iml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/tapestry-core.iml Thu Jan  8 
14:46:48 2009
@@ -9,7 +9,6 @@
       <sourceFolder url="file://$MODULE_DIR$/src/test/java" 
isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/src/test/resources" 
isTestSource="true" />
       <sourceFolder url="file://$MODULE_DIR$/target/generated-sources/antlr" 
isTestSource="false" />
-      <excludeFolder url="file://$MODULE_DIR$/target" />
       <excludeFolder url="file://$MODULE_DIR$/test-output" />
     </content>
     <orderEntry type="inheritedJdk" />

Modified: 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java?rev=732861&r1=732860&r2=732861&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/services/ClassFabUtils.java
 Thu Jan  8 14:46:48 2009
@@ -204,6 +204,17 @@
         return String.format("(%s)%s", desiredType, reference);
     }
 
+    /**
+     * Given a primitive type, finds the unwrap method of the corresponding 
wrapper type.
+     *
+     * @param primitiveType
+     * @return method name
+     */
+    public static String getUnwrapMethodName(Class primitiveType)
+    {
+        return 
PRIMITIVE_TYPE_NAME_TO_PRIMITIVE_INFO.get(primitiveType.getName()).unwrapMethod;
+    }
+
 
     /**
      * Given a type name, determines if that is the name of a primitive type.
@@ -244,7 +255,7 @@
     {
         classFab.addField("_creator", Modifier.PRIVATE | Modifier.FINAL, 
ObjectCreator.class);
 
-        classFab.addConstructor(new Class[] { ObjectCreator.class }, null, 
"_creator = $1;");
+        classFab.addConstructor(new Class[] {ObjectCreator.class}, null, 
"_creator = $1;");
 
         String body = format("return (%s) _creator.createObject();", 
serviceInterface.getName());
 


Reply via email to