1 package com.lexicalscope.fluentreflection;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import static com.lexicalscope.fluentreflection.Visibility.visibilityFromModifiers;
20 import static java.lang.String.format;
21
22 import java.lang.reflect.Field;
23 import java.lang.reflect.Modifier;
24 import java.util.ArrayList;
25 import java.util.List;
26
27 import org.apache.commons.lang3.builder.EqualsBuilder;
28 import org.apache.commons.lang3.builder.HashCodeBuilder;
29
30 import com.google.inject.TypeLiteral;
31
32 final class FluentFieldImpl extends AbstractFluentAnnotated implements FluentField {
33 private final ReflectedTypeFactory reflectedTypeFactory;
34 private final FluentClass<?> reflectedClass;
35 private final TypeLiteral<?> typeLiteral;
36 private final Field field;
37
38 public FluentFieldImpl(
39 final ReflectedTypeFactory reflectedTypeFactory,
40 final FluentClass<?> reflectedClass,
41 final TypeLiteral<?> typeLiteral,
42 final Field field) {
43 super(reflectedTypeFactory, field);
44 this.reflectedTypeFactory = reflectedTypeFactory;
45 this.reflectedClass = reflectedClass;
46 this.typeLiteral = typeLiteral;
47 this.field = field;
48
49 try { field.setAccessible(true); } catch(final SecurityException e)
50 {
51 }
52
53 @Override public String name() {
54 return field.getName();
55 }
56
57 @Override public FluentClass<?> declarer() {
58 return reflectedTypeFactory.reflect(typeLiteral);
59 }
60
61 @Override public boolean isStatic() {
62 return Modifier.isStatic(field.getModifiers());
63 }
64
65 @Override public boolean isFinal() {
66 return Modifier.isFinal(field.getModifiers());
67 }
68
69 @Override public String property() {
70 return field.getName();
71 }
72
73 @Override public Field member() {
74 return field;
75 }
76
77 @Override public Visibility visibility() {
78 return visibilityFromModifiers(field.getModifiers());
79 }
80
81 @Override public String toString() {
82 final String visibility;
83 if (visibility().toString().isEmpty())
84 {
85 visibility = visibility().toString();
86 }
87 else
88 {
89 visibility = visibility().toString() + " ";
90 }
91
92 final String staticModifier;
93 if (isStatic())
94 {
95 staticModifier = "static ";
96 }
97 else
98 {
99 staticModifier = "";
100 }
101
102 final String finalModifier;
103 if (isFinal())
104 {
105 finalModifier = "final ";
106 }
107 else
108 {
109 finalModifier = "";
110 }
111
112 return format(
113 "%s%s%s%s %s",
114 visibility,
115 staticModifier,
116 finalModifier,
117 type(),
118 field.getName());
119 }
120
121 @Override public boolean equals(final Object obj) {
122 if (obj != null && this.getClass().equals(obj.getClass())) {
123 final FluentFieldImpl that = (FluentFieldImpl) obj;
124 return new EqualsBuilder()
125 .append(this.field, that.field)
126 .append(this.typeLiteral, that.typeLiteral)
127 .isEquals();
128 }
129 return false;
130 }
131
132 @Override public int hashCode() {
133 return new HashCodeBuilder().append(field).append(typeLiteral).toHashCode();
134 }
135
136 @Override public int argCount() {
137 return 1;
138 }
139
140 @Override public List<FluentClass<?>> args() {
141 return new ArrayList<FluentClass<?>>();
142 }
143
144 @Override public FluentClass<?> type() {
145 final TypeLiteral<?> returnType = typeLiteral.getFieldType(field);
146 if (returnType == null) {
147 return null;
148 }
149 return reflectedTypeFactory.reflect(returnType);
150 }
151
152 @Override public Object callRaw(final Object... args) {
153 if(args == null || args.length == 0 || args[0] == null) {
154 throw new ReflectionRuntimeException("reading a field requires an instance argument");
155 } else if (args.length > 2) {
156 throw new ReflectionRuntimeException("reading a field requires one argument, writing a field requires two arguments. Got " + args.length + " arguments");
157 }
158
159 try {
160 final Object fieldValue = field.get(args[0]);
161 if(args.length == 2)
162 {
163 field.set(args[0], args[1]);
164 }
165 return fieldValue;
166 } catch (final IllegalArgumentException e) {
167 throw new IllegalArgumentRuntimeException(e, field, args[0]);
168 } catch (final IllegalAccessException e) {
169 throw new IllegalAccessRuntimeException(e, field);
170 }
171 }
172
173 @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public FluentObject<?> call(final Object... args) {
174 final Object object = callRaw(args);
175 if(object == null) {
176 return null;
177 }
178 return reflectedTypeFactory.reflect((Class) object.getClass(), object);
179 }
180
181 @Override public <T> FluentCall<T> as(final Class<T> returnType) {
182 return new AbstractCall<T>(reflectedTypeFactory) {
183 @Override public T callRaw(final Object... args) {
184 return returnType.cast(FluentFieldImpl.this.callRaw(args));
185 }
186 };
187 }
188 }