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
14
15
16
17
18
19
20
21
22
23
24
25
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 }