Author: hlship
Date: Wed Apr 13 22:23:06 2011
New Revision: 1091944
URL: http://svn.apache.org/viewvc?rev=1091944&view=rev
Log:
TAP5-853: Begin re-implementing not operator, subexpressions
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PropertyConduitSourceImpl.java
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=1091944&r1=1091943&r2=1091944&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
Wed Apr 13 22:23:06 2011
@@ -632,7 +632,7 @@ public class PropertyConduitSourceImpl i
case IDENTIFIER:
case INVOKE:
- // So, a this point, we have the navigation method written
+ // So, at this point, we have the navigation method written
// and it covers all but the terminal
// de-reference. node is an IDENTIFIER or INVOKE. We're
// ready to use the navigation
@@ -672,7 +672,7 @@ public class PropertyConduitSourceImpl i
return;
case NOT:
- // createPlasticNotOpGetter(node);
+ createPlasticNotOpGetter(node);
createPlasticNoOpSetter();
conduitPropertyType = boolean.class;
@@ -756,9 +756,96 @@ public class PropertyConduitSourceImpl i
classFab.addMethod(Modifier.PUBLIC, GET_SIGNATURE,
builder.toString());
}
- private void createPlasticNotOpGetter()
+ /**
+ * @param node
+ * subexpression to invert
+ */
+ private void createPlasticNotOpGetter(final Tree node)
+ {
+ // Implement get() as navigate, then do a method invocation based
on node
+ // then, then pass (wrapped) result to delegate.invert()
+
+ plasticClass.introduceMethod(GET, new InstructionBuilderCallback()
+ {
+ public void doBuild(InstructionBuilder builder)
+ {
+ buildSubexpression(builder, rootType, node.getChild(0));
+
+ // Now invoke the delegate invert() method
+
+ builder.loadThis().getField(delegateField);
+
+ builder.swap().invoke(PropertyConduitDelegate.class,
boolean.class, "invert", new Class[]
+ { Object.class });
+
+ // When the dust settles, may change invert() to return
Boolean, not boolean
+
+ builder.boxPrimitive("boolean").returnResult();
+ }
+ });
+ }
+
+ /**
+ * The first part of any implementation of get() or set(): invoke the
navigation method
+ * and if the result is null, return immediately.
+ */
+ private void invokeNavigateMethod(InstructionBuilder builder)
{
+ builder.loadThis().loadArgument(0).invokeVirtual(navMethod);
+ builder.dupe(0).ifNull(RETURN_RESULT, null);
+ }
+
+ private Class buildSubexpression(InstructionBuilder builder, Class
activeType, Tree node)
+ {
+ while (node != null)
+ {
+ switch (node.getType())
+ {
+ case TRUE:
+
+ builder.loadConstant(Boolean.TRUE);
+ activeType = Boolean.class;
+
+ node = null;
+ break;
+
+ case FALSE:
+
+ builder.loadConstant(Boolean.FALSE);
+ activeType = Boolean.class;
+
+ node = null;
+ break;
+
+ case IDENTIFIER:
+ case INVOKE:
+
+ invokeNavigateMethod(builder);
+
+ ExpressionTermInfo info = infoForMember(activeType,
node);
+
+ activeType = evaluateTerm(builder, activeType, info);
+
+ node = null;
+
+ break;
+
+ case INTEGER:
+ case DECIMAL:
+ case STRING:
+ case DEREF:
+ case SAFEDEREF:
+ case LIST:
+ throw new RuntimeException("Not yet re-implemented.");
+
+ default:
+ throw unexpectedNodeType(node, TRUE, FALSE, INTEGER,
DECIMAL, STRING, DEREF, SAFEDEREF,
+ IDENTIFIER, INVOKE, LIST);
+ }
+ }
+
+ return activeType;
}
private void createNotOpGetter(Tree node, String rootName)
@@ -949,12 +1036,7 @@ public class PropertyConduitSourceImpl i
{
public void doBuild(InstructionBuilder builder)
{
-
builder.loadThis().loadArgument(0).invokeVirtual(navMethod);
-
- // When the navigation method returns null, we do nothing
(error checking is inside
- // the navigation method).
-
- builder.dupe(0).ifNull(RETURN_RESULT, null);
+ invokeNavigateMethod(builder);
String typeName =
PlasticUtils.toTypeName(GenericsUtils.asClass(info.getType()));
@@ -1056,9 +1138,7 @@ public class PropertyConduitSourceImpl i
*/
private void createPlasticGetter(final Class activeType, final
ExpressionTermInfo info)
{
- final Method method = info.getReadMethod();
-
- if (method == null && !info.isField())
+ if (info.getReadMethod() == null && !info.isField())
{
createNoOpMethod(GET, "Expression %s for class %s is
write-only.", expression, rootType.getName());
return;
@@ -1068,28 +1148,43 @@ public class PropertyConduitSourceImpl i
{
public void doBuild(InstructionBuilder builder)
{
-
builder.loadThis().loadArgument(0).invokeVirtual(navMethod);
+ invokeNavigateMethod(builder);
+
+ evaluateTerm(builder, activeType, info);
+
+ builder.returnResult();
+ }
- // I.e. due to ?. operator. The navigate method will
already have
- // checked for nulls if they are not allowed.
+ });
+ }
- builder.dupe(0).ifNull(RETURN_RESULT, null);
+ /**
+ * Extends the builder with the code to evaluate a term (which may
+ *
+ * @param builder
+ * @param activeType
+ * current type
+ * @param info
+ * about the expression term
+ * @return the new active type
+ */
+ public Class evaluateTerm(InstructionBuilder builder, Class
activeType, ExpressionTermInfo info)
+ {
+ Class termType = GenericsUtils.asClass(info.getType());
+ String termTypeName = PlasticUtils.toTypeName(termType);
- Class termType = GenericsUtils.asClass(info.getType());
- String termTypeName = PlasticUtils.toTypeName(termType);
+ if (info.isField())
+ {
+ builder.getField(PlasticUtils.toTypeName(activeType),
info.getPropertyName(), termTypeName);
+ }
+ else
+ {
+ invokeNoArgsMethod(builder, info.getReadMethod());
+ }
- if (info.isField())
- {
- builder.getField(PlasticUtils.toTypeName(activeType),
info.getPropertyName(), termTypeName);
- }
- else
- {
- invokeNoArgsMethod(builder, method);
- }
+ builder.boxPrimitive(termTypeName);
- builder.boxPrimitive(termTypeName).returnResult();
- }
- });
+ return termType;
}
private void invokeNoArgsMethod(InstructionBuilder builder, Method
method)