source: java/main/src/main/java/com/framsticks/params/FramsClassBuilder.java @ 96

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

HIGHLIGHTS:

  • cleanup Instance management
    • extract Instance interface
    • extract Instance common algorithms to InstanceUtils?
  • fix closing issues: Ctrl+C or window close button

properly shutdown whole program

by Java Framsticks framework

  • fix parsing and printing of all request types
  • hide exception passing in special handle method of closures
    • substantially improve readability of closures
    • basically enable use of exception in asynchronous closures

(thrown exception is transported back to the caller)

  • implement call request on both sides

CHANGELOG:
Further improve calling.

Improve instance calling.

Calling is working on both sides.

Improve exception handling in testing.

Waiters do not supercede other apllication exception being thrown.

Finished parsing and printing of all request types (with tests).

Move implementation and tests of request parsing to Request.

Add tests for Requests.

Improve waits in asynchronours tests.

Extract more algorithms to InstanceUtils?.

Extract Instance.resolve to InstanceUtils?.

Improve naming.

Improve passing exception in InstanceClient?.

Hide calling of passed functor in StateCallback?.

Hide Exception passing in asynchronous closures.

Hide exception passing in Future.

Make ResponseCallback? an abstract class.

Make Future an abstract class.

Minor change.

Move getPath to Path.to()

Move bindAccess to InstanceUtils?.

Extract common things to InstanceUtils?.

Fix synchronization bug in Connection.

Move resolve to InstanceUtils?.

Allow names of Joinable to be dynamic.

Add support for set request server side.

More fixes in communication.

Fix issues with parsing in connection.

Cut new line characters when reading.

More improvements.

Migrate closures to FramsticksException?.

Several changes.

Extract resolveAndFetch to InstanceUtils? algorithms.

Test resolving and fetching.

More fixes with function signature deduction.

Do not print default values in SimpleAbstractAccess?.

Add test of FramsClass? printing.

Improve FramsticksException? messages.

Add explicit dispatcher synchronization feature.

Rework assertions in tests.

Previous solution was not generic enough.

Allow addition of joinables to collection after start.

Extract SimulatorInstance? from RemoteInstance?.

Remove PrivateJoinableCollection?.

Improve connections.

Move shutdown hook to inside the Monitor.

It should work in TestNG tests, but it seems that
hooks are not called.

In ServerTest? client connects to testing server.

Move socket initialization to receiver thread.

Add proper closing on Ctrl+C (don't use signals).

Fix bugs with server accepting connections.

Merge Entity into Joinable.

Reworking ServerInstance?.

Extract more algorithm to InstanceUtils?.

Extract some common functionality from AbstractInstance?.

Functions were placed in InstanceUtils?.

Hide registry of Instance.

Use ValueParam? in Instance interface.

Minor change.

Extract Instance interface.

Old Instance is now AbstractInstance?.

File size: 9.1 KB
Line 
1package com.framsticks.params;
2
3import java.io.InputStream;
4import java.lang.reflect.Field;
5import java.lang.reflect.Member;
6import java.lang.reflect.Method;
7import java.lang.reflect.ParameterizedType;
8import java.lang.reflect.Type;
9import java.util.ArrayList;
10import java.util.Collections;
11import java.util.HashMap;
12import java.util.LinkedList;
13import java.util.List;
14import java.util.Map;
15
16import org.apache.log4j.Logger;
17
18import com.framsticks.params.annotations.AutoAppendAnnotation;
19import com.framsticks.params.annotations.FramsClassAnnotation;
20import com.framsticks.params.annotations.ParamAnnotation;
21import com.framsticks.parsers.FileSource;
22import com.framsticks.parsers.Loaders;
23import com.framsticks.util.Builder;
24import com.framsticks.util.Misc;
25import com.framsticks.util.lang.Containers;
26import com.framsticks.util.lang.Strings;
27
28@FramsClassAnnotation(id = "class", name = "class")
29public class FramsClassBuilder implements Builder<FramsClass> {
30        private static final Logger log =
31                Logger.getLogger(FramsClassBuilder.class);
32
33        public static String getName(FramsClassAnnotation fca, Class<?> javaClass) {
34                return fca.name().equals("") ? javaClass.getSimpleName() : fca.name();
35        }
36
37        public static String getId(FramsClassAnnotation fca, Class<?> javaClass) {
38                return fca.id().equals("") ? javaClass.getSimpleName() : fca.id();
39        }
40
41        public static ParamBuilder induceParamType(ParamBuilder builder, Type type) {
42
43                if (type instanceof ParameterizedType) {
44                        ParameterizedType p = (ParameterizedType) type;
45                        Type rawType = p.getRawType();
46                        Type containedType = null;
47                        //TODO make implementation here
48                        boolean map = false;
49                        if (rawType.equals(Map.class)) {
50                                containedType = p.getActualTypeArguments()[1];
51                                map = true;
52                        } else if (rawType.equals(List.class)) {
53                                containedType = p.getActualTypeArguments()[0];
54                        }
55                        if (!(containedType instanceof Class)) {
56                                return builder;
57                        }
58                        Class<?> containedClass = (Class<?>) containedType;
59                        StringBuilder b = new StringBuilder();
60                        b.append("l ");
61                        FramsClassAnnotation fca = containedClass.getAnnotation(FramsClassAnnotation.class);
62                        if (fca == null) {
63                                log.error("the class is not annotated: " + containedClass);
64                                return builder;
65                        }
66                        b.append(getName(fca, containedClass));
67                        if (map) {
68                                b.append(" name");
69                        }
70
71                        builder.type(b.toString());
72                        return builder;
73                }
74
75                if (type instanceof Class) {
76
77                        Class<?> cl = (Class<?>) type;
78
79                        // TODO: future support for enum
80                        // if (cl.isEnum()) {
81                        //      Class<? extends Enum<?>> enumType = (Class<? extends Enum<?>>) cl;
82                        //      Enum<?>[] enums = enumType.getEnumConstants();
83                        //      StringBuilder b = new StringBuilder();
84
85                        //      b.append("d 0 ").append(enums.length - 1).append(" 0 ");
86                        //      for (Enum<?> e : enums) {
87                        //              b.append("~").append(e.name());
88                        //      }
89                        //      return b.toString();
90                        // }
91                        if (cl.equals(Integer.class) || cl.equals(int.class)) {
92                                builder.type("d");
93                                return builder;
94                        }
95                        if (cl.equals(String.class)) {
96                                builder.type("s");
97                                return builder;
98                        }
99                        if (cl.equals(Double.class) || cl.equals(double.class)) {
100                                builder.type("f");
101                                return builder;
102                        }
103                        if (cl.equals(Boolean.class) || cl.equals(boolean.class)) {
104                                builder.type( "d 0 1");
105                                return builder;
106                        }
107                        if (cl.equals(Object.class)) {
108                                builder.type("x");
109                                return builder;
110                        }
111
112                        // builder.type("o " + (cl).getCanonicalName());
113                        builder.type("o " + cl.getSimpleName());
114                        builder.fillStorageType(cl);
115                        return builder;
116                }
117
118                throw new ConstructionException().msg("failed to find framsticks for native type").arg("type", type);
119        }
120
121
122        public static ParamBuilder induceParamType(ParamBuilder builder, ParamCandidate candidate) {
123                Method method = candidate.getCaller();
124                if (method == null) {
125                        return induceParamType(builder, candidate.getType());
126                }
127
128                if (!method.getReturnType().equals(Void.TYPE)) {
129                        builder.resultType(induceParamType(Param.build(), method.getGenericReturnType()).finish(ValueParam.class));
130                }
131
132                List<ValueParam> arguments = new ArrayList<>();
133                int number = 0;
134                for (Type arg : method.getGenericParameterTypes()) {
135                        arguments.add(induceParamType(Param.build(), arg).idAndName("arg" + (number++)).finish(ValueParam.class));
136                }
137                builder.argumentsType(arguments);
138
139                return builder;
140        }
141
142        public static final String GENERATE_HELP_PREFIX = "automatically generated from: ";
143
144        public static FramsClass readFromStream(InputStream stream) {
145                return Loaders.loadFramsClass(new FileSource(stream));
146        }
147
148        // public static Class<? extends Param> getParamType(@Nonnull Class<?> c) {
149        //      if (c.equals(Integer.class)) {
150        //              return DecimalParam.class;
151        //      }
152        //      if (c.equals(Double.class)) {
153        //              return FloatParam.class;
154        //      }
155        //      if (c.equals(String.class)) {
156        //              return StringParam.class;
157        //      }
158        //      if (c.equals(Object.class)) {
159        //              return UniversalParam.class;
160        //      }
161        //      return null;
162        // }
163
164        public static String extractIdOf(Member member) {
165                if (member instanceof Field) {
166                        return member.getName();
167                }
168                if (member instanceof Method) {
169                        Method m = (Method) member;
170                        String n = m.getName();
171                        int argsNum = m.getParameterTypes().length;
172                        if (argsNum == 0) {
173                                return n.startsWith("get") ? Strings.uncapitalize(n.substring(3)) : n;
174                        }
175                        if (argsNum == 1) {
176                                return n.startsWith("set") ? Strings.uncapitalize(n.substring(3)) : n;
177                        }
178                        log.error("invalid number of arguments");
179                        return null;
180                }
181                log.error("invalid kind of member");
182                return null;
183        }
184        public static String getName(ParamAnnotation annotation, Member member) {
185                return annotation.name().equals("") ? Strings.capitalize(extractIdOf(member)) : annotation.name();
186        }
187
188        public static String getId(ParamAnnotation annotation, Member member) {
189                return annotation.id().equals("") ? extractIdOf(member) : annotation.id();
190        }
191
192        public static ParamBuilder fill(ParamBuilder builder, Member member, ParamAnnotation annotation) {
193                return builder
194                        .id(getId(annotation, member))
195                        .name(getName(annotation, member));
196
197        }
198
199        public static final Map<Class<?>, FramsClass> synchronizedCacheForBasedOnForJavaClass = Collections.synchronizedMap(new HashMap<Class<?>, FramsClass>());
200
201        public FramsClass forClass(Class<?> javaClass) throws ConstructionException {
202                FramsClass result = synchronizedCacheForBasedOnForJavaClass.get(javaClass);
203                if (result != null) {
204                        return result;
205                }
206
207                log.debug("building for class " + javaClass);
208
209                FramsClassAnnotation fca = javaClass.getAnnotation(FramsClassAnnotation.class);
210                if (fca == null) {
211                        throw new ConstructionException().msg("java class is not annotated with FramsClassAnnotation").arg("java", javaClass);
212                }
213
214                id(getId(fca, javaClass));
215                name(getName(fca, javaClass));
216
217                for (ParamCandidate pc : ParamCandidate.getAllCandidates(javaClass).getOrder()) {
218                        ParamBuilder builder = Param.build().id(pc.getId()).name(pc.getName()).flags(pc.getFlags());
219
220                        induceParamType(builder, pc);
221
222                        for (ParamAnnotation pa : pc.getAnnotations()) {
223                                if (!"".equals(pa.def())) {
224                                        builder.def(pa.def());
225                                }
226                                if (!"".equals(pa.help())) {
227                                        builder.help(pa.help());
228                                }
229                                if (!"".equals(pa.min())) {
230                                        builder.min(pa.min());
231                                }
232                                if (!"".equals(pa.max())) {
233                                        builder.max(pa.max());
234                                }
235                                builder.extra(pa.extra());
236                                if (!"".equals(pa.stringType())) {
237                                        builder.type(pa.stringType());
238                                }
239                                if (!pa.paramType().equals(Param.class)) {
240                                        builder.type(pa.paramType());
241                                }
242                        }
243                        param(builder);
244                }
245
246                result = finish();
247
248                synchronizedCacheForBasedOnForJavaClass.put(javaClass, result);
249
250                return result;
251        }
252
253
254        protected String id;
255
256        protected String name;
257
258        protected String description;
259
260        protected final List<Param> params = new LinkedList<>();
261
262        protected List<GroupBuilder> groupBuilders = new ArrayList<GroupBuilder>();
263
264        @ParamAnnotation
265        public FramsClassBuilder id(String id) {
266                this.id = id;
267                return this;
268        }
269
270        @ParamAnnotation
271        public FramsClassBuilder name(String name) {
272                this.name = name;
273                return this;
274        }
275
276        public FramsClassBuilder idAndName(String v) {
277                this.id = v;
278                this.name = v;
279                return this;
280        }
281
282        @ParamAnnotation(id = "desc")
283        public FramsClassBuilder description(String description) {
284                this.description = description;
285                return this;
286        }
287
288        public FramsClassBuilder() {
289        }
290
291        public FramsClass finish() {
292                return new FramsClass(this);
293        }
294
295        @AutoAppendAnnotation
296        public FramsClassBuilder param(ParamBuilder builder) {
297                Param param = builder.finish();
298
299                Integer group = param.getGroup();
300                if (group != null) {
301                        Containers.getFromList(groupBuilders, group, "group", this).addParam(param);
302                }
303
304                params.add(param);
305                return this;
306        }
307
308        @AutoAppendAnnotation
309        public FramsClassBuilder group(GroupBuilder builder) {
310                groupBuilders.add(builder);
311                return this;
312        }
313
314        /**
315         * @return the id
316         */
317        @ParamAnnotation
318        public String getId() {
319                return id;
320        }
321
322        /**
323         * @return the name
324         */
325        @ParamAnnotation
326        public String getName() {
327                return name;
328        }
329
330        /**
331         * @return the description
332         */
333        @ParamAnnotation(id = "desc")
334        public String getDescription() {
335                return description;
336        }
337
338        public FramsClassBuilder group(String group) {
339                return group(new GroupBuilder().name(group));
340        }
341
342        @Override
343        public String toString() {
344                return "FramsClassBuilder for " + Misc.returnNotNull(id, "<not yet known>");
345        }
346
347}
Note: See TracBrowser for help on using the repository browser.