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

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

HIGHLIGHTS:

CHANGELOG:
Get data also on tree expansion.

Use nice framstick icon for empty nodes.

Update panel after reload if it is current.

Add shallow reload procedure.

Cut Gui prefix from several tree classes.

Bring back counter of GuiTreeNode?.

Use IdentityHashMap? were it is more appriopriate.

Remove TreeListener?.

Do not use TreeListener? in GUI.

Minor change.

Done migration to GuiTreeModel?.

BrowserTest? in that version always crashes frams.linux.

Move rendering implementation into GuiAbstractNode?.

Use hand-crafted list in GuiTreeNode?.

Generally, it would be a great place for WeakIdentityHashMap?
(but there is none in Java Collection Framework).

Remove superfluous logging.

Fix bug in GuiTreeNode?.

Use IdentityHashMap? instead of HashMap?.

Improve structure update.

Filter out invalid uids in UniqueListAccess?.

Improve TreeCellRenderer?.

Add filtering in TrackConsole?.

Improve TreeModel?.

More changes.

More improvements.

More changes.

Remove TreeNode?.

Support MetaNode? in the GuiTreeModel?.

Implement more in GuiTreeModel?.

Add CompositeParam? interface to FramsClass? and AccessInterface?.

Allow access by number to UniqueList?.

Add UidComparator?.

Use TreeMap? as a default accessee in unique list.

It keeps order of keys.

Introduce classes to use with new TreeModel?.

Another step.

Migrate from TreeNode? to Node in many places.

Remove some uses of TreeNode? as DefaultMutableTreeNode?.

Remove Path from TreeNode? interface.

Remove Path from TreeNode?.

Add Path recration from node feature.

Reworking TreeCellRenderer?.

Minor change of TreeOperations? interface.

Remove last methods from TreeNode?.

Another minor step.

Do not store reference to TreeAtFrame? in TreeNode?.

Add proxy exceptionHandler to StatusBar?.

Move panels management to TreeAtFrame?.

Store localChanges in the NodeAtFrame?.

More cleanup.

Move name computing to TreeCellRenderer?.

Move tooltip and icon computations to TreeCellRenderer?.

More dispatches removed.

Remove most dispatching from TreeNode?.

TreeNode? does not actually redispatch tasks.

Make Tree embedded in Browser use SwingDispatcher?.

Make lazy binding of Tree with Dispatcher.

Minor changes.

Organizational change in AbstractTree?.

Make AbstractTree? compose from Thread instead of inherit from it.

Make SwingDispatcher? and AtOnceDispatcher? Joinable compatible.

Add ListPanelProvider?.

Improve Controls readonly and enabled handling.

Properly pass ExceptionHandlers? in more places.

Make Tree.get accept ValueParam?.

  • This is to allow access number of list elements.

Remove not needed get redirection in ClientAtServer?.

Rename tryResolve to tryGet.

Unify tryResolveAndGet into tryResolve.

Remove resolveTop from Tree interface.

Make Tree.get accept Future<Path>.

Use get to implement resolveTop also in ObjectTree?.

Unify resolveTop and get in RemoteTree?.

Another minor step.

More minor changes in tree operations.

Minor organizational changes.

In RemoteTree? first fetch info for root.

Reworking resolving.

Minor changes.

Make ListAccess? return proxy iterators (instead of creating temporary collection).

Let AccessInterface? return Iterable<Param>.

Improve resolving.

More improvements.

First working completion in ManagedConsole?.

Rename resolve to resolveTop.

This reflects the actuall functionality.

Change semantic of tryResolve and tryResolveAndGet.

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.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
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 IdentityHashMap<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.