View Javadoc

1   package com.lexicalscope.fluentreflection;
2   
3   /*
4    * Copyright 2011 Tim Wood
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import static ch.lambdaj.Lambda.*;
20  import static com.lexicalscope.fluentreflection.ReflectionMatcher.allOf;
21  import static com.lexicalscope.fluentreflection.ReflectionMatchers.*;
22  import static org.hamcrest.Matchers.hasItem;
23  
24  import java.lang.annotation.Annotation;
25  import java.lang.reflect.ParameterizedType;
26  import java.lang.reflect.Type;
27  import java.util.List;
28  
29  import org.hamcrest.Matcher;
30  
31  import com.google.common.primitives.Primitives;
32  import com.google.inject.TypeLiteral;
33  
34  /**
35   * Not thread safe
36   *
37   * @author tim
38   *
39   * @param <T>
40   */
41  class FluentClassImpl<T> implements FluentClass<T> {
42      private final ReflectedTypeFactory reflectedTypeFactory;
43      private final Class<T> klass;
44      private final ReflectedMembers<T> members;
45      private final TypeLiteral<T> typeLiteral;
46      private final FluentAnnotatedImpl annotatedElement;
47  
48      FluentClassImpl(
49              final ReflectedTypeFactory reflectedTypeFactory,
50              final TypeLiteral<T> typeLiteral,
51              final ReflectedMembers<T> members) {
52          this.reflectedTypeFactory = reflectedTypeFactory;
53          this.klass = (Class<T>) typeLiteral.getRawType();
54          this.typeLiteral = typeLiteral;
55          this.members = members;
56          this.annotatedElement = new FluentAnnotatedImpl(reflectedTypeFactory, klass);
57      }
58  
59      @Override public Class<T> classUnderReflection() {
60          return klass;
61      }
62  
63      @Override public List<FluentMethod> methods(final Matcher<? super FluentMethod> methodMatcher) {
64          return members.methods(methodMatcher);
65      }
66  
67      @Override public FluentMethod method(final Matcher<? super FluentMethod> methodMatcher) {
68          return members.method(methodMatcher);
69      }
70  
71      @Override public FluentMethod method(final String name) {
72          return members.method(hasName(name));
73      }
74  
75      @Override public FluentMethod staticMethod(final Matcher<? super FluentMethod> methodMatcher) {
76          return method(allOf(isStatic(), methodMatcher));
77      }
78  
79      @Override public List<FluentMethod> methods() {
80          return members.methods();
81      }
82  
83      @Override public List<FluentMethod> declaredMethods() {
84          return members.declaredMethods();
85      }
86  
87      @Override public FluentObject<?> call(final String name, final Object ... args)
88      {
89          return call(hasName(name), args);
90      }
91  
92      @SuppressWarnings("unchecked") @Override public FluentObject<?> call(
93              final Matcher<? super FluentMethod> methodMatcher,
94              final Object ... args)
95      {
96          return method(allOf(methodMatcher, canBeCalledWithArguments(args))).call(args);
97      }
98  
99      @Override public List<FluentField> fields() {
100         return members.fields();
101     }
102 
103     @Override public List<FluentField> fields(final ReflectionMatcher<? super FluentField> fieldMatcher) {
104         return members.fields(fieldMatcher);
105     }
106 
107     @Override public FluentField field(final ReflectionMatcher<FluentMember> fieldMatcher) {
108         return members.field(fieldMatcher);
109     }
110 
111     @Override public List<FluentField> declaredFields() {
112         return members.declaredFields();
113     }
114 
115     @Override public List<FluentClass<?>> interfaces() {
116         return members.superclassesAndInterfaces(isAnInterface());
117     }
118 
119     @Override public List<FluentClass<?>> superclasses() {
120         return members.superclassesAndInterfaces(not(isAnInterface()));
121     }
122 
123     @Override public FluentClass<?> asType(final Matcher<FluentClass<?>> typeMatcher) {
124         if (typeMatcher.matches(this)) {
125             return this;
126         }
127         return selectFirst(members.superclassesAndInterfaces(), typeMatcher);
128     }
129 
130     @Override public boolean isType(final ReflectionMatcher<FluentClass<?>> typeMatcher) {
131         if (typeMatcher.matches(this)) {
132             return true;
133         }
134         return hasItem(typeMatcher).matches(members.superclassesAndInterfaces());
135     }
136 
137     @Override public boolean isInterface() {
138         return typeLiteral.getRawType().isInterface();
139     }
140 
141     @Override public T constructRaw(final Object... args) {
142         final FluentConstructor<T> constructor =
143                 constructor(hasArgumentList(convert(args, new ConvertObjectToClass())));
144 
145         if (constructor == null) {
146             throw new ConstructorNotFoundRuntimeException(typeLiteral.getRawType());
147         }
148 
149         return constructor.callRaw(args);
150     }
151 
152     @Override public FluentObject<T> construct(final Object... args) {
153         final T newInstance = constructRaw(args);
154         return reflectedTypeFactory.reflect(typeLiteral, newInstance);
155     }
156 
157     @Override public List<FluentConstructor<T>> constructors(
158             final Matcher<? super FluentConstructor<?>> constructorMatcher) {
159         return members.constructors(constructorMatcher);
160     }
161 
162     @Override public FluentConstructor<T> constructor(
163             final Matcher<? super FluentConstructor<?>> constructorMatcher) {
164         return members.constructor(constructorMatcher);
165     }
166 
167     @Override public boolean assignableFromObject(final Object value) {
168         return value == null
169                 || klass.isAssignableFrom(value.getClass())
170                 || canBeBoxed(value.getClass())
171                 || canBeUnboxed(value.getClass());
172     }
173 
174     @Override public boolean assignableTo(final Class<?> otherKlass) {
175         return otherKlass.isAssignableFrom(klass);
176     }
177 
178     @Override public boolean canBeBoxed(final Class<?> from) {
179         return Primitives.isWrapperType(klass)
180                 && Primitives.unwrap(klass).isAssignableFrom(from);
181     }
182 
183     @Override public boolean canBeUnboxed(final Class<?> from) {
184         return isPrimitive()
185                 && Primitives.wrap(klass).isAssignableFrom(from);
186     }
187 
188     @Override public FluentClass<T> boxedType() {
189         if (isPrimitive()) {
190             return reflectedTypeFactory.reflect(Primitives.wrap(klass));
191         }
192         return this;
193     }
194 
195     @Override public FluentClass<T> unboxedType() {
196         if (isUnboxable()) {
197             return reflectedTypeFactory.reflect(Primitives.unwrap(klass));
198         }
199         return this;
200     }
201 
202     @Override public boolean isPrimitive() {
203         return klass.isPrimitive();
204     }
205 
206     @Override public boolean isUnboxable() {
207         return Primitives.isWrapperType(klass);
208     }
209 
210     @Override public FluentClass<?> typeArgument(final int typeParameter) {
211         return reflectedTypeFactory.reflect(TypeLiteral.get(((ParameterizedType) typeLiteral.getType())
212                 .getActualTypeArguments()[typeParameter]));
213     }
214 
215     @Override public String name() {
216         return klass.getName();
217     }
218 
219     @Override public String simpleName() {
220         return klass.getSimpleName();
221     }
222 
223     @Override public FluentClass<?> annotation(final Matcher<? super FluentClass<?>> annotationMatcher) {
224         return annotatedElement.annotation(annotationMatcher);
225     }
226 
227     @Override public <A extends Annotation> A annotation(final Class<A> annotationClass) {
228         return annotatedElement.annotation(annotationClass);
229     }
230 
231     @Override public boolean annotatedWith(final Class<? extends Annotation> annotationClass) {
232         return annotatedElement.annotatedWith(annotationClass);
233     }
234 
235     @Override public boolean annotatedWith(final Matcher<? super FluentClass<?>> annotationMatcher) {
236         return annotatedElement.annotatedWith(annotationMatcher);
237     }
238 
239     @Override public Type type() {
240         return typeLiteral.getType();
241     }
242 
243     @Override public boolean equals(final Object that) {
244         if (that != null && that.getClass().equals(this.getClass())) {
245             return typeLiteral.equals(((FluentClassImpl<?>) that).typeLiteral);
246         }
247         return false;
248     }
249 
250     @Override public int hashCode() {
251         return typeLiteral.hashCode();
252     }
253 
254     @Override public String toString() {
255         return typeLiteral.toString();
256     }
257 }