source: java/main/src/main/java/com/framsticks/params/ReflectionAccess.java @ 86

Last change on this file since 86 was 86, checked in by psniegowski, 11 years ago

HIGHLIGHTS:

  • use java annotations to mark classes and fields to be used when:
    • using java classes with ReflectionAccess? to represent remote objects with FramsClass? description found by "info ..." requests
    • to build up FramsClass? representation of objects not present at remote server
  • allow using primitive types (instead of wraping counterparts) in reflected classes
  • rework FramsClass? creation process (add FramsClassBuilder?)
  • add more tests

CHANGELOG:
Prepare model.World class.

Minor change.

Use primitive types for Genotype and Creature classes.

Use primitive types in model.Neuro* classes.

Use primitive types in model.Joint* classes.

Use primitive types in model.Part* classes.

Fix primitive values.

Extract FramsClassBuilder?.

Add tests of Model classes.

More fixes.

Refactorize out ParamCandidate?.

Several fixes.

Fix all regressions after introducing annotations.

Use annotations throughout the project.

Add exception classes.

Improve creation of FramsClass?.

More changes.

Many changes regarding annotations.

Annotate classes in com.framsticks.model package.

Remove manual FramsClass? constructor.

Construct FramsClass? for Creature. Add test.

Add default values to the ParamAnnotation?.

Add ParamBuilderTest? and ParamAnnotation?.

Add FramsClassAnnotation?.

File size: 7.7 KB
Line 
1package com.framsticks.params;
2
3import java.lang.reflect.Field;
4import java.lang.reflect.InvocationTargetException;
5import java.lang.reflect.Method;
6import java.util.HashMap;
7import java.util.Map;
8
9import org.apache.log4j.Logger;
10
11import com.framsticks.util.FramsticksException;
12
13import static com.framsticks.util.lang.Containers.*;
14
15/**
16 * The Class ReflectionAccess. Stores data in provided object using reflection.
17 *
18 * @author Mateusz Jarus <name.surname@gmail.com> (please replace name and
19 *         surname with my personal data)
20 *
21 * @author Piotr Sniegowski
22 */
23public class ReflectionAccess extends SimpleAbstractAccess {
24        private final static Logger log = Logger.getLogger(ReflectionAccess.class
25                        .getName());
26
27        protected final Class<?> reflectedClass;
28        private Object object;
29
30
31        protected interface ReflectedSetter {
32                public <T> void set(Object object, T value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException;
33        }
34
35        protected interface ReflectedGetter {
36                public abstract <T> T get(Object object, Class<T> type) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException;
37        }
38
39        protected static class ReflectedValueParam {
40                public ReflectedSetter setter;
41                public ReflectedGetter getter;
42        }
43
44        protected final Map<ValueParam, ReflectedValueParam> reflectedValueParams = new HashMap<>();
45
46        public ReflectionAccess(Class<?> reflectedClass) throws ConstructionException {
47                this(reflectedClass, FramsClassBuilder.buildForClass(reflectedClass));
48        }
49
50        public static boolean typeMatch(Class<?> a, Class<?> b) {
51                assert !b.isPrimitive();
52                if (!a.isPrimitive()) {
53                        return a.equals(b);
54                }
55
56                if (a.equals(int.class)) {
57                        return b.equals(Integer.class);
58                }
59                if (a.equals(double.class)) {
60                        return b.equals(Double.class);
61                }
62                if (a.equals(boolean.class)) {
63                        return b.equals(Boolean.class);
64                }
65                assert false;
66                return false;
67        }
68
69        public ReflectionAccess(Class<?> reflectedClass, FramsClass framsClass) throws ConstructionException {
70                this.reflectedClass = reflectedClass;
71                setFramsClass(framsClass);
72
73                Map<String, ParamCandidate> candidates = ParamCandidate.getAllCandidates(reflectedClass);
74
75                try {
76                        for (final ValueParam vp : filterInstanceof(framsClass.getParamEntries(), ValueParam.class)) {
77                                if (!candidates.containsKey(vp.getId())) {
78                                        throw new ConstructionException().msg("missing candidate for param").arg("param", vp);
79                                }
80                                ParamCandidate pc = candidates.get(vp.getId());
81                                if (pc.isReadOnly() && !vp.hasFlag(Flags.READONLY)) {
82                                        throw new ConstructionException().msg("readonly state conflict").arg("param", vp);
83                                }
84                                if (!typeMatch(pc.getRawType(), vp.getStorageType())) {
85                                        throw new ConstructionException().msg("types mismatch for param").arg("param", vp).arg("candidate", pc.getType()).arg("storage", vp.getStorageType());
86                                }
87
88                                ReflectedValueParam rvp = new ReflectedValueParam();
89                                reflectedValueParams.put(vp, rvp);
90                                final boolean primitive = pc.isPrimitive();
91                                if (pc.getField() != null) {
92                                        final Field f = pc.getField();
93                                        rvp.getter = new ReflectedGetter() {
94                                                @Override
95                                                public <T> T get(Object object, Class<T> type) throws IllegalArgumentException, IllegalAccessException {
96                                                        return type.cast(f.get(object));
97                                                }
98                                        };
99                                        if (!pc.isFinal()) {
100                                                rvp.setter = new ReflectedSetter() {
101                                                        @Override
102                                                        public <T> void set(Object object, T value) throws IllegalArgumentException, IllegalAccessException {
103                                                                if (value == null && primitive) {
104                                                                        throw new FramsticksException().msg("setting null to primitive value");
105                                                                }
106                                                                f.set(object, value);
107                                                        }
108                                                };
109                                        }
110                                } else {
111                                        final Method g = pc.getGetter();
112
113                                        rvp.getter = new ReflectedGetter() {
114                                                @Override
115                                                public <T> T get(Object object, Class<T> type) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
116                                                        return type.cast(g.invoke(object));
117                                                }
118                                        };
119
120                                        if (!pc.isFinal()) {
121                                                final Method s = pc.getSetter();
122                                                rvp.setter = new ReflectedSetter() {
123                                                        @Override
124                                                        public <T> void set(Object object, T value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
125                                                                if (value == null && primitive) {
126                                                                        throw new FramsticksException().msg("setting null to primitive value");
127                                                                }
128                                                                s.invoke(object, value);
129                                                        }
130                                                };
131                                        }
132                                }
133                        }
134                } catch (ConstructionException e) {
135                        throw e.arg("java class", reflectedClass).arg("framsClass", framsClass);
136                }
137        }
138
139        // private static String accessorName(boolean get, String id) {
140        //      return (get ? "get" : "set") + id.substring(0, 1).toUpperCase() + id.substring(1);
141        // }
142
143        @Override
144        public <T> T get(ValueParam param, Class<T> type) {
145                try {
146                        try {
147                                if (object == null) {
148                                        throw new FramsticksException().msg("no object set");
149                                }
150
151                                return reflectedValueParams.get(param).getter.get(object, type);
152                        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
153                                throw new FramsticksException().msg("failed to get").cause(e);
154                        }
155                } catch (FramsticksException e) {
156                        throw e.arg("param", param).arg("type", type).arg("access", this);
157                }
158        }
159
160        @Override
161        protected <T> void internalSet(ValueParam param, T value) {
162                setValue(param, value);
163        }
164
165        private <T> void setValue(ValueParam param, T value) {
166                try {
167                        try {
168                                if (object == null) {
169                                        throw new FramsticksException().msg("no object set");
170                                }
171                                ReflectedSetter s = reflectedValueParams.get(param).setter;
172                                if (s == null) {
173                                        throw new FramsticksException().msg("trying to set final");
174                                }
175                                s.set(object, value);
176                        } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
177                                throw new FramsticksException().msg("failed to set").cause(e);
178                        }
179                } catch (FramsticksException e) {
180                        throw e.arg("param", param).arg("value", value).arg("access", this);
181                }
182        }
183
184        void resetErrors() {
185                //TODO this replaces returnedObject.resetErrors();
186        }
187
188        @Override
189        public void clearValues() {
190                if (object == null) {
191                        return;
192                }
193
194                resetErrors();
195
196                try {
197                        for (ValueParam p : filterInstanceof(framsClass.getParamEntries(), ValueParam.class)) {
198                                setValue(p, p.getDef(Object.class));
199                        }
200                } catch (IllegalArgumentException ex) {
201                        ex.printStackTrace();
202                }
203        }
204
205        /**
206         * Sets the new object to operate on.
207         *
208         * @param object
209         *            new object to operate on
210         */
211        @Override
212        public ReflectionAccess select(Object object) {
213                assert object == null || reflectedClass.isInstance(object);
214                this.object = object;
215                return this;
216        }
217
218        @Override
219        public Object getSelected() {
220                return object;
221        }
222
223        // TODO: find a better place for it
224        public static String objectToString(Object object) {
225                StringBuilder b = new StringBuilder();
226                for (Field f : object.getClass().getFields()) {
227                        b.append(f.getName());
228                        b.append(":");
229                        try {
230                                Object value = f.get(object);
231                                b.append((value != null) ? value.toString() : "<null>");
232                        } catch (IllegalAccessException e) {
233                                e.printStackTrace();
234                        }
235                        b.append("\n");
236                }
237                return b.toString();
238        }
239
240
241        @Override
242        public ReflectionAccess cloneAccess() throws ConstructionException {
243                return new ReflectionAccess(reflectedClass, framsClass);
244        }
245
246        @Override
247        public Object createAccessee() {
248                try {
249                        return reflectedClass.newInstance();
250                } catch (InstantiationException | IllegalAccessException e) {
251                        e.printStackTrace();
252                }
253                log.fatal("failed to create reflected object of class " + reflectedClass.getCanonicalName() + " for frams type " + framsClass.getId());
254                return null;
255        }
256
257        @Override
258        public String toString() {
259                StringBuilder b = new StringBuilder();
260                b.append(framsClass);
261                if (object != null) {
262                        b.append("(").append(object).append(")");
263                }
264                return b.toString();
265        }
266
267}
268
Note: See TracBrowser for help on using the repository browser.