001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.aop.support;
018:
019: import java.io.Serializable;
020:
021: import org.springframework.aop.ClassFilter;
022: import org.springframework.aop.MethodMatcher;
023: import org.springframework.aop.Pointcut;
024: import org.springframework.util.Assert;
025: import org.springframework.util.ObjectUtils;
026:
027: /**
028: * Convenient class for building up pointcuts. All methods return
029: * ComposablePointcut, so we can use a concise idiom like:
030: *
031: * <code>
032: * Pointcut pc = new ComposablePointcut().union(classFilter).intersection(methodMatcher).intersection(pointcut);
033: * </code>
034: *
035: * @author Rod Johnson
036: * @author Juergen Hoeller
037: * @author Rob Harrop
038: * @since 11.11.2003
039: * @see Pointcuts
040: */
041: public class ComposablePointcut implements Pointcut, Serializable {
042:
043: /** use serialVersionUID from Spring 1.2 for interoperability */
044: private static final long serialVersionUID = -2743223737633663832L;
045:
046: private ClassFilter classFilter;
047:
048: private MethodMatcher methodMatcher;
049:
050: /**
051: * Create a default ComposablePointcut, with <code>ClassFilter.TRUE</code>
052: * and <code>MethodMatcher.TRUE</code>.
053: */
054: public ComposablePointcut() {
055: this .classFilter = ClassFilter.TRUE;
056: this .methodMatcher = MethodMatcher.TRUE;
057: }
058:
059: /**
060: * Create a ComposablePointcut based on the given Pointcut.
061: * @param pointcut the original Pointcut
062: */
063: public ComposablePointcut(Pointcut pointcut) {
064: Assert.notNull(pointcut, "Pointcut must not be null");
065: this .classFilter = pointcut.getClassFilter();
066: this .methodMatcher = pointcut.getMethodMatcher();
067: }
068:
069: /**
070: * Create a ComposablePointcut for the given ClassFilter,
071: * with <code>MethodMatcher.TRUE</code>.
072: * @param classFilter the ClassFilter to use
073: */
074: public ComposablePointcut(ClassFilter classFilter) {
075: Assert.notNull(classFilter, "ClassFilter must not be null");
076: this .classFilter = classFilter;
077: this .methodMatcher = MethodMatcher.TRUE;
078: }
079:
080: /**
081: * Create a ComposablePointcut for the given MethodMatcher,
082: * with <code>ClassFilter.TRUE</code>.
083: * @param methodMatcher the MethodMatcher to use
084: */
085: public ComposablePointcut(MethodMatcher methodMatcher) {
086: Assert.notNull(methodMatcher, "MethodMatcher must not be null");
087: this .classFilter = ClassFilter.TRUE;
088: this .methodMatcher = methodMatcher;
089: }
090:
091: /**
092: * Create a ComposablePointcut for the given ClassFilter and MethodMatcher.
093: * @param classFilter the ClassFilter to use
094: * @param methodMatcher the MethodMatcher to use
095: */
096: public ComposablePointcut(ClassFilter classFilter,
097: MethodMatcher methodMatcher) {
098: Assert.notNull(classFilter, "ClassFilter must not be null");
099: Assert.notNull(methodMatcher, "MethodMatcher must not be null");
100: this .classFilter = classFilter;
101: this .methodMatcher = methodMatcher;
102: }
103:
104: /**
105: * Apply a union with the given ClassFilter.
106: * @param other the ClassFilter to apply a union with
107: * @return this composable pointcut (for call chaining)
108: */
109: public ComposablePointcut union(ClassFilter other) {
110: this .classFilter = ClassFilters.union(this .classFilter, other);
111: return this ;
112: }
113:
114: /**
115: * Apply an intersection with the given ClassFilter.
116: * @param other the ClassFilter to apply an intersection with
117: * @return this composable pointcut (for call chaining)
118: */
119: public ComposablePointcut intersection(ClassFilter other) {
120: this .classFilter = ClassFilters.intersection(this .classFilter,
121: other);
122: return this ;
123: }
124:
125: /**
126: * Apply a union with the given MethodMatcher.
127: * @param other the MethodMatcher to apply a union with
128: * @return this composable pointcut (for call chaining)
129: */
130: public ComposablePointcut union(MethodMatcher other) {
131: this .methodMatcher = MethodMatchers.union(this .methodMatcher,
132: other);
133: return this ;
134: }
135:
136: /**
137: * Apply an intersection with the given MethodMatcher.
138: * @param other the MethodMatcher to apply an intersection with
139: * @return this composable pointcut (for call chaining)
140: */
141: public ComposablePointcut intersection(MethodMatcher other) {
142: this .methodMatcher = MethodMatchers.intersection(
143: this .methodMatcher, other);
144: return this ;
145: }
146:
147: /**
148: * Apply a union with the given Pointcut.
149: * <p>Note that for a Pointcut union, methods will only match if their
150: * original ClassFilter (from the originating Pointcut) matches as well.
151: * MethodMatchers and ClassFilters from different Pointcuts will never
152: * get interleaved with each other.
153: * @param other the Pointcut to apply a union with
154: * @return this composable pointcut (for call chaining)
155: */
156: public ComposablePointcut union(Pointcut other) {
157: this .methodMatcher = MethodMatchers.union(this .methodMatcher,
158: this .classFilter, other.getMethodMatcher(), other
159: .getClassFilter());
160: this .classFilter = ClassFilters.union(this .classFilter, other
161: .getClassFilter());
162: return this ;
163: }
164:
165: /**
166: * Apply an intersection with the given Pointcut.
167: * @param other the Pointcut to apply an intersection with
168: * @return this composable pointcut (for call chaining)
169: */
170: public ComposablePointcut intersection(Pointcut other) {
171: this .classFilter = ClassFilters.intersection(this .classFilter,
172: other.getClassFilter());
173: this .methodMatcher = MethodMatchers.intersection(
174: this .methodMatcher, other.getMethodMatcher());
175: return this ;
176: }
177:
178: public ClassFilter getClassFilter() {
179: return this .classFilter;
180: }
181:
182: public MethodMatcher getMethodMatcher() {
183: return this .methodMatcher;
184: }
185:
186: public boolean equals(Object other) {
187: if (this == other) {
188: return true;
189: }
190: if (!(other instanceof ComposablePointcut)) {
191: return false;
192: }
193:
194: ComposablePointcut that = (ComposablePointcut) other;
195: return ObjectUtils.nullSafeEquals(that.classFilter,
196: this .classFilter)
197: && ObjectUtils.nullSafeEquals(that.methodMatcher,
198: this .methodMatcher);
199: }
200:
201: public int hashCode() {
202: int code = 17;
203: if (this .classFilter != null) {
204: code = 37 * code + this .classFilter.hashCode();
205: }
206: if (this .methodMatcher != null) {
207: code = 37 * code + this .methodMatcher.hashCode();
208: }
209: return code;
210: }
211:
212: public String toString() {
213: return "ComposablePointcut: ClassFilter [" + this .classFilter
214: + "], MethodMatcher [" + this .methodMatcher + "]";
215: }
216:
217: }
|