public Expression transform(Expression exp) {
   if (exp == null) return null;
   if (exp.getClass() == VariableExpression.class) {
     return transformVariableExpression((VariableExpression) exp);
   }
   if (exp.getClass() == BinaryExpression.class) {
     return transformBinaryExpression((BinaryExpression) exp);
   }
   if (exp.getClass() == PropertyExpression.class) {
     return transformPropertyExpression((PropertyExpression) exp);
   }
   if (exp.getClass() == MethodCallExpression.class) {
     return transformMethodCallExpression((MethodCallExpression) exp);
   }
   if (exp.getClass() == ClosureExpression.class) {
     return transformClosureExpression((ClosureExpression) exp);
   }
   if (exp.getClass() == ConstructorCallExpression.class) {
     return transformConstructorCallExpression((ConstructorCallExpression) exp);
   }
   if (exp.getClass() == ArgumentListExpression.class) {
     Expression result = exp.transformExpression(this);
     if (inPropertyExpression) {
       foundArgs = result;
     }
     return result;
   }
   if (exp instanceof ConstantExpression) {
     Expression result = exp.transformExpression(this);
     if (inPropertyExpression) {
       foundConstant = result;
     }
     if (inAnnotation && exp instanceof AnnotationConstantExpression) {
       ConstantExpression ce = (ConstantExpression) result;
       if (ce.getValue() instanceof AnnotationNode) {
         // replicate a little bit of AnnotationVisitor here
         // because we can't wait until later to do this
         AnnotationNode an = (AnnotationNode) ce.getValue();
         Map<String, Expression> attributes = an.getMembers();
         for (Map.Entry<String, Expression> entry : attributes.entrySet()) {
           Expression attrExpr = transform(entry.getValue());
           entry.setValue(attrExpr);
         }
       }
     }
     return result;
   }
   return exp.transformExpression(this);
 }