001: /**
002: * Copyright (C) 2006 Google Inc.
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: */package com.google.inject.matcher;
016:
017: import com.google.inject.util.Objects;
018:
019: import java.lang.annotation.Annotation;
020: import java.lang.reflect.AnnotatedElement;
021: import java.lang.reflect.Method;
022:
023: /**
024: * Matcher implementations. Supports matching classes and methods.
025: *
026: * @author crazybob@google.com (Bob Lee)
027: */
028: public class Matchers {
029:
030: private Matchers() {
031: }
032:
033: static Matcher<Object> ANY = new AbstractMatcher<Object>() {
034: public boolean matches(Object o) {
035: return true;
036: }
037:
038: public String toString() {
039: return "any()";
040: }
041: };
042:
043: /**
044: * Returns a matcher which matches any input.
045: */
046: public static Matcher<Object> any() {
047: return ANY;
048: }
049:
050: /**
051: * Inverts the given matcher.
052: */
053: public static <T> Matcher<T> not(final Matcher<? super T> p) {
054: Objects.nonNull(p, "p");
055: return new AbstractMatcher<T>() {
056: public boolean matches(T t) {
057: return !p.matches(t);
058: }
059:
060: public String toString() {
061: return "not(" + p + ")";
062: }
063: };
064: }
065:
066: /**
067: * Returns a matcher which matches elements (methods, classes, etc.)
068: * with a given annotation.
069: */
070: public static Matcher<AnnotatedElement> annotatedWith(
071: final Class<? extends Annotation> annotationType) {
072: Objects.nonNull(annotationType, "annotation type");
073: return new AbstractMatcher<AnnotatedElement>() {
074: public boolean matches(AnnotatedElement element) {
075: Annotation annotation = element
076: .getAnnotation(annotationType);
077: return annotation != null;
078: }
079:
080: public String toString() {
081: return "annotatedWith("
082: + annotationType.getSimpleName() + ".class)";
083: }
084: };
085: }
086:
087: /**
088: * Returns a matcher which matches elements (methods, classes, etc.)
089: * with a given annotation.
090: */
091: public static Matcher<AnnotatedElement> annotatedWith(
092: final Annotation annotation) {
093: Objects.nonNull(annotation, "annotation");
094: return new AbstractMatcher<AnnotatedElement>() {
095: public boolean matches(AnnotatedElement element) {
096: Annotation fromElement = element
097: .getAnnotation(annotation.annotationType());
098: return fromElement != null
099: && annotation.equals(fromElement);
100: }
101:
102: public String toString() {
103: return "annotatedWith(" + annotation + ")";
104: }
105: };
106: }
107:
108: /**
109: * Returns a matcher which matches subclasses of the given type (as well as
110: * the given type).
111: */
112: public static Matcher<Class> subclassesOf(final Class<?> super class) {
113: Objects.nonNull(super class, "superclass");
114: return new AbstractMatcher<Class>() {
115: public boolean matches(Class subclass) {
116: return super class.isAssignableFrom(subclass);
117: }
118:
119: public String toString() {
120: return "subclassesOf(" + super class.getSimpleName()
121: + ".class)";
122: }
123: };
124: }
125:
126: /**
127: * Returns a matcher which matches objects equal to the given object.
128: */
129: public static Matcher<Object> only(final Object o) {
130: Objects.nonNull(o, "o");
131: return new AbstractMatcher<Object>() {
132: public boolean matches(Object other) {
133: return o.equals(other);
134: }
135:
136: public String toString() {
137: return "only(" + o + ")";
138: }
139: };
140: }
141:
142: /**
143: * Returns a matcher which matches only the given object.
144: */
145: public static Matcher<Object> identicalTo(final Object o) {
146: Objects.nonNull(o, "o");
147: return new AbstractMatcher<Object>() {
148: public boolean matches(Object other) {
149: return o == other;
150: }
151:
152: public String toString() {
153: return "identicalTo(" + o + ")";
154: }
155: };
156: }
157:
158: /**
159: * Returns a matcher which matches classes in the given package.
160: */
161: public static Matcher<Class> inPackage(final Package p) {
162: Objects.nonNull(p, "package");
163: return new AbstractMatcher<Class>() {
164: public boolean matches(Class c) {
165: return c.getPackage().equals(p);
166: }
167:
168: public String toString() {
169: return "package(" + p.getName() + ")";
170: }
171: };
172: }
173:
174: /**
175: * Returns a matcher which matches methods with matching return types.
176: */
177: public static Matcher<Method> returns(
178: final Matcher<? super Class<?>> returnType) {
179: Objects.nonNull(returnType, "return type matcher");
180: return new AbstractMatcher<Method>() {
181: public boolean matches(Method m) {
182: return returnType.matches(m.getReturnType());
183: }
184:
185: public String toString() {
186: return "returns(" + returnType + ")";
187: }
188: };
189: }
190: }
|