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
66
67
68
69 if (context.inCflowSubAST()) {
70
71 return match.booleanValue();
72 } else if (context.hasBeenVisitingCflow()) {
73
74 m_hasCflowPointcut = true;
75 return context.getCflowEvaluation();
76 }
77 return false;
78 }
79
80
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
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
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 }