View Javadoc

1   /***************************************************************************************
2    * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved.                 *
3    * http://aspectwerkz.codehaus.org                                                    *
4    * ---------------------------------------------------------------------------------- *
5    * The software in this package is published under the terms of the LGPL license      *
6    * a copy of which has been included with this distribution in the license.txt file.  *
7    **************************************************************************************/
8   package org.codehaus.aspectwerkz.expression;
9   
10  import org.codehaus.aspectwerkz.expression.ast.ASTAnd;
11  import org.codehaus.aspectwerkz.expression.ast.ASTCflow;
12  import org.codehaus.aspectwerkz.expression.ast.ASTCflowBelow;
13  import org.codehaus.aspectwerkz.expression.ast.ASTNot;
14  import org.codehaus.aspectwerkz.expression.ast.ASTOr;
15  import org.codehaus.aspectwerkz.expression.ast.ASTPointcutReference;
16  import org.codehaus.aspectwerkz.expression.ast.ASTRoot;
17  
18  import java.io.ObjectInputStream;
19  import java.io.Serializable;
20  
21  /***
22   * The Cflow visitor.
23   *
24   * @TODO why is this class serializable? no other visitor is that and they are always used together
25   * 
26   * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
27   */
28  public class CflowExpressionVisitor extends ExpressionVisitor implements Serializable {
29      /***
30       * Do we have a cflow pointcut in the expression?
31       */
32      private boolean m_hasCflowPointcut = true;
33  
34      /***
35       * Creates a new cflow expression.
36       * 
37       * @param expression the expression as a string
38       * @param namespace the namespace
39       * @param root the AST root
40       */
41      public CflowExpressionVisitor(final ExpressionInfo expressionInfo,
42                                    final String expression,
43                                    final String namespace,
44                                    final ASTRoot root) {
45          super(expressionInfo, expression, namespace, root);
46      }
47  
48      /***
49       * Checks if the expression has a cflow pointcut.
50       * 
51       * @return
52       */
53      public boolean hasCflowPointcut() {
54          return m_hasCflowPointcut;
55      }
56  
57      /***
58       * Matches the cflow epression
59       * 
60       * @param context
61       * @return
62       */
63      public boolean match(final ExpressionContext context) {
64          Boolean match = (Boolean) visit(m_root, context);
65          // we first check incflowSubAst() - AW-226
66          // since we might have already been visited OTHER cflow expression like in
67          // "pc AND cflow1 AND cflow2", current is cflow2
68          //TODO this algo should be rewritten like the runtimeVisitor.
69          if (context.inCflowSubAST()) {
70              // we are in a referenced expression within a cflow subtree
71              return match.booleanValue();
72          } else if (context.hasBeenVisitingCflow()) {
73              // we have been visiting and evaluated a cflow sub expression
74              m_hasCflowPointcut = true;
75              return context.getCflowEvaluation();
76          }
77          return false;
78      }
79  
80      // ============ Logical operators =============
81      public Object visit(ASTOr node, Object data) {
82          ExpressionContext context = (ExpressionContext) data;
83          int nrOfChildren = node.jjtGetNumChildren();
84          if (context.inCflowSubAST()) {
85              return super.visit(node, data);
86          } else {
87              for (int i = 0; i < nrOfChildren; i++) {
88                  node.jjtGetChild(i).jjtAccept(this, data);
89              }
90              return Boolean.TRUE;
91          }
92      }
93  
94      public Object visit(ASTAnd node, Object data) {
95          ExpressionContext context = (ExpressionContext) data;
96          int nrOfChildren = node.jjtGetNumChildren();
97          if (context.inCflowSubAST()) {
98              return super.visit(node, data);
99          } else {
100             for (int i = 0; i < nrOfChildren; i++) {
101                 node.jjtGetChild(i).jjtAccept(this, data);
102             }
103             return Boolean.TRUE;
104         }
105     }
106 
107     public Object visit(ASTNot node, Object data) {
108         Boolean match = (Boolean) node.jjtGetChild(0).jjtAccept(this, data);
109         if (match.equals(Boolean.TRUE)) {
110             return Boolean.FALSE;
111         } else {
112             return Boolean.TRUE;
113         }
114     }
115 
116     // ============ Cflow pointcut types =============
117     public Object visit(ASTCflow node, Object data) {
118         ExpressionContext context = (ExpressionContext) data;
119         context.setInCflowSubAST(true);
120         Boolean result = (Boolean) node.jjtGetChild(0).jjtAccept(this, context);
121         if (context.getCflowEvaluation() == false) {
122             context.setCflowEvaluation(result.booleanValue());
123         }
124         context.setHasBeenVisitingCflow(true);
125         context.setInCflowSubAST(false);
126         return new Boolean(context.getCflowEvaluation());
127     }
128 
129     public Object visit(ASTCflowBelow node, Object data) {
130         ExpressionContext context = (ExpressionContext) data;
131         context.setInCflowSubAST(true);
132         Boolean result = (Boolean) node.jjtGetChild(0).jjtAccept(this, context);
133         if (context.getCflowEvaluation() == false) {
134             context.setCflowEvaluation(result.booleanValue());
135         }
136         context.setHasBeenVisitingCflow(true);
137         context.setInCflowSubAST(false);
138         return new Boolean(context.getCflowEvaluation());
139     }
140 
141     // ============ Pointcut reference =============
142     public Object visit(ASTPointcutReference node, Object data) {
143         ExpressionContext context = (ExpressionContext) data;
144         ExpressionNamespace namespace = ExpressionNamespace.getNamespace(m_namespace);
145         return new Boolean(namespace.getCflowExpression(node.getName()).match(context));
146     }
147 
148     /***
149      * Provides custom deserialization.
150      * 
151      * @param stream the object input stream containing the serialized object
152      * @throws Exception in case of failure
153      */
154     private void readObject(final ObjectInputStream stream) throws Exception {
155         ObjectInputStream.GetField fields = stream.readFields();
156         m_expression = (String) fields.get("m_annotation", null);
157         m_namespace = (String) fields.get("m_namespace", null);
158         m_hasCflowPointcut = fields.get("m_namespace", false);
159         m_root = ExpressionInfo.getParser().parse(m_expression);
160     }
161 }