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

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

HIGHLIGTS:

  • complete events implementation
  • add CLI in Java Framsticks server
  • add automatic registration for events in GUI
  • improve objects fetching (object are never overwritten with new instances)
  • properly react for ListChange? events
  • add ListPanel? with table view
    • columns to be shown may be statically specified in configuration
    • currently modyfying data through tables is not available
  • improve maven configuration
    • configuration file may be specified without touching pom.xml

CHANGELOG:
Extract constants from Flags into ParamFlags? and SetStateFlags?.

Extract flags I/O to FlagsUtils? class.

Configured maven to exec given resource configuration.

For example:
mvn exec:exec -Dframsticks.config=/configs/managed-console.xml

Cleanup pom.xml

Rename ObjectTree? to LocalTree? (also make LocalTree? and RemoteTree? final).

Minor change.

Add maximum number of columns in ListPanelProvider?.

Improve ColumnsConfig? interpretation.

Automatically fill FramsClass?.name if trying to construct empty.

Improve identitifer case mangling in XmlLoader?.

Introduce configurable ColumnsConfig?.

Draft working version of ListPanel?.

Table is being shown (although empty).

More improvements to table building.

Move some functionality from Frame to TreeModel?.

Move tree classes in gui to separate package.

Remove old table related classes.

Add draft implementation of TableModel?.

Redirect ParamBuilder?.forAccess to AccessInterface?.

Optimize ParamBuilder?.forAccess()

Do not clear list when loading.

Do not load fetched values directly.

Implement different AccessInterface? copying policy.

Optimize fetching values routine.

Remove Mode enum (work out get semantics).

Some improvements to ListChange? handling.

Improve UniqueListAccess?.

Add reaction for ListChanges? in the TreeNode?.

EventListeners? are being added in the TreeNode?.

Listeners for ListParams? are now very naive (they download
whole list).

Automatially register on events in GUI.

Events are working in RemoteTree? and Server.

Move listeners to the ClientSideManagedConnection?.

Remove old classes responsible for event subscriptions.

Improve event reading.

Improve events handling at server side.

Add register attribute in FramsClassAnnotation?
to automatically also register other classes.

Registering events works.

Setup for remote listeners registration.

More improvements.

Minor changes.

Add rootTree to the ClientAtServer?.

Moving CLI to the ClientAtServer?.

Fix bug: use Void.TYPE instead of Void.class

More development around CLI.

  • Improve Path resolving.

Add synthetic root to ObjectTree?.

It is needed to allow sybling for the original root
that would containg CLI.

Some work with registering events in RemoteTree?.

Draft implementation of listener registering in RemoteTree?.

Support events registration in the ObjectTree?.

Add events support to ReflectionAccess?.

EventParam? is recognized by ParamCandidate?.

Prepare interface for Events across project.

Add EventListener? and API for listeners in Tree.

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