View Javadoc

1   package com.lexicalscope.fluentreflection;
2   
3   import static java.lang.System.arraycopy;
4   
5   import java.lang.annotation.Annotation;
6   import java.util.ArrayList;
7   import java.util.List;
8   
9   import org.apache.commons.lang3.builder.HashCodeBuilder;
10  import org.hamcrest.Matcher;
11  
12  /*
13   * Copyright 2012 Tim Wood
14   *
15   * Licensed under the Apache License, Version 2.0 (the "License");
16   * you may not use this file except in compliance with the License.
17   * You may obtain a copy of the License at
18   *
19   * http://www.apache.org/licenses/LICENSE-2.0
20   *
21   * Unless required by applicable law or agreed to in writing, software
22   * distributed under the License is distributed on an "AS IS" BASIS,
23   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24   * See the License for the specific language governing permissions and
25   * limitations under the License.
26   */
27  
28  abstract class BoundFluentMemberImpl implements FluentMember {
29      private final ReflectedTypeFactory reflectedTypeFactory;
30      private final FluentMember member;
31      private final Object instance;
32  
33      public BoundFluentMemberImpl(
34              final ReflectedTypeFactory reflectedTypeFactory,
35              final FluentMember member,
36              final Object instance) {
37          this.reflectedTypeFactory = reflectedTypeFactory;
38          if (member.isStatic()) {
39              throw new IllegalArgumentException("cannot bind static member " + member);
40          }
41          this.member = member;
42          this.instance = instance;
43      }
44  
45      @Override public final int argCount() {
46          return member.argCount();
47      }
48  
49      @Override public final List<FluentClass<?>> args() {
50          return new ArrayList<FluentClass<?>>(member.args());
51      }
52  
53      @SuppressWarnings("unchecked") @Override public FluentObject<?> call(final Object... args) {
54          final Object object = callRaw(args);
55          if(object == null) {
56              return null;
57          }
58          return reflectedTypeFactory.reflect((Class) object.getClass(), object);
59      }
60  
61      @Override public final Object callRaw(final Object... args) {
62          final Object[] argsWithInstance = new Object[args.length + 1];
63          argsWithInstance[0] = instance;
64          arraycopy(args, 0, argsWithInstance, 1, args.length);
65          return member.callRaw(argsWithInstance);
66      }
67  
68      @Override public final FluentClass<?> declarer() {
69          return member.declarer();
70      }
71  
72      @Override public final String name() {
73          return member.name();
74      }
75  
76      @Override public final boolean isStatic() {
77          return false;
78      }
79  
80      @Override public final Visibility visibility() {
81          return member.visibility();
82      }
83  
84      @Override public final boolean isFinal() {
85          return member.isFinal();
86      }
87  
88      @Override public final int hashCode() {
89          return new HashCodeBuilder().append(instance).append(member).toHashCode();
90      }
91  
92      @Override public final FluentClass<?> type() {
93          return member.type();
94      }
95  
96      @Override public final FluentClass<?> annotation(final Matcher<? super FluentClass<?>> annotationMatcher) {
97          return member.annotation(annotationMatcher);
98      }
99  
100     @Override public final <A extends Annotation> A annotation(final Class<A> annotationClass) {
101         return member.annotation(annotationClass);
102     }
103 
104     @Override public final boolean annotatedWith(final Class<? extends Annotation> annotationClass) {
105         return member.annotatedWith(annotationClass);
106     }
107 
108     @Override public boolean annotatedWith(final Matcher<? super FluentClass<?>> annotationMatcher) {
109         return member.annotatedWith(annotationMatcher);
110     }
111 
112     @Override public final String property() {
113         return member.property();
114     }
115 
116     @Override public final <T> FluentCall<T> as(final Class<T> returnType) {
117         return new AbstractCall<T>(reflectedTypeFactory) {
118             @Override public T callRaw(final Object... args) {
119                 return returnType.cast(BoundFluentMemberImpl.this.callRaw(args));
120             }
121         };
122     }
123 
124     @Override public final boolean equals(final Object that) {
125         if(this == that) {
126             return true;
127         } else  if(that != null && that.getClass().equals(this.getClass())) {
128             final BoundFluentMemberImpl castedThat = (BoundFluentMemberImpl) that;
129             return castedThat.instance.equals(this.instance) && castedThat.member.equals(this.member);
130         }
131         return false;
132     }
133 }