source: java/main/src/main/java/com/framsticks/params/ParamBuilder.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: 12.0 KB
Line 
1package com.framsticks.params;
2
3import com.framsticks.params.annotations.FramsClassAnnotation;
4import com.framsticks.params.annotations.ParamAnnotation;
5import com.framsticks.params.types.*;
6import com.framsticks.util.Builder;
7import com.framsticks.util.FramsticksException;
8import com.framsticks.util.Misc;
9import com.framsticks.util.lang.FlagsUtil;
10import com.framsticks.util.lang.Strings;
11
12import org.apache.log4j.Logger;
13
14import java.lang.reflect.InvocationTargetException;
15import java.util.ArrayList;
16import java.util.Arrays;
17import java.util.List;
18import java.util.regex.Matcher;
19import java.util.regex.Pattern;
20
21import javax.annotation.Nonnull;
22
23/**
24 * The class ParamBuilder helps building Param objects.
25 *
26 * @author Mateusz Jarus <name.surname@gmail.com> (please replace name and
27 *         surname with my personal data)
28 *
29 * @author Piotr Śniegowski
30 */
31
32@FramsClassAnnotation(name = "prop", id = "prop")
33public class ParamBuilder implements Builder<Param> {
34        private final static Logger log = Logger.getLogger(ParamBuilder.class.getName());
35
36        private static final String ID_FIELD = "id";
37        private static final String NAME_FIELD = "name";
38        private static final String HELP_FIELD = "help";
39        private static final String GROUP_FIELD = "group";
40        private static final String TYPE_FIELD = "type";
41        private static final String FLAGS_FIELD = "flags";
42
43        /** The parameter id. */
44        private String id;
45
46        /** The number of group, that parameter belongs to. */
47        private Integer group;
48
49        /** The flags stored as a bit sum. */
50        private int flags = 0;
51
52        /** The parameter name. */
53        private String name;
54
55        /** The help (description) concerning parameter. */
56        private String help;
57
58        /** The type of parameter. */
59        private Class<? extends Param> paramType;
60
61        private Object min;
62
63        private Object max;
64
65        private Object def;
66
67        private int extra = 0;
68
69        protected String containedTypeName;
70
71        protected String eventArgumentTypeName;
72
73        protected Class<?> storageType;
74
75        protected FramsClassBuilder classBuilder;
76
77        public ParamBuilder() {
78                this(null);
79        }
80
81        protected ValueParam resultType;
82
83        protected List<ValueParam> argumentsType;
84
85        /**
86         * @param classBuilder
87         */
88        public ParamBuilder(FramsClassBuilder classBuilder) {
89                this.classBuilder = classBuilder;
90        }
91
92
93        /**
94         * @return the min
95         */
96        @ParamAnnotation
97        public Object getMin() {
98                return min;
99        }
100
101        /**
102         * @return the max
103         */
104        @ParamAnnotation
105        public Object getMax() {
106                return max;
107        }
108
109        /**
110         * @return the def
111         */
112        @ParamAnnotation
113        public Object getDef() {
114                return def;
115        }
116
117        public String getContainedTypeName() {
118                return Strings.notEmpty(containedTypeName) ? containedTypeName : null;
119        }
120
121        public ParamBuilder containedTypeName(String containedTypeName) {
122                this.containedTypeName = containedTypeName;
123                return this;
124        }
125
126        /**
127         * @return the resultType
128         */
129        public ValueParam getResultType() {
130                return resultType;
131        }
132
133
134        /**
135         * @param resultType the resultType to set
136         */
137        public ParamBuilder resultType(ValueParam resultType) {
138                this.resultType = resultType;
139                return this;
140        }
141
142        /**
143         * @return the argumentsType
144         */
145        public List<ValueParam> getArgumentsType() {
146                return argumentsType;
147        }
148
149
150        /**
151         * @param argumentsType the argumentsType to set
152         */
153        public ParamBuilder argumentsType(List<ValueParam> argumentsType) {
154                this.argumentsType = argumentsType;
155                return this;
156        }
157
158        /**
159         * @return the enumValues
160         */
161        public List<String> getEnumValues() {
162                return enumValues;
163        }
164
165        /**
166         * @return the uid
167         */
168        public String getUid() {
169                return uid;
170        }
171
172        public ParamBuilder uid(String uid) {
173                this.uid = uid;
174                return this;
175        }
176
177        public @Nonnull <T extends Param> T finish(Class<T> requested) {
178                Param param = finish();
179                if (!requested.isInstance(param)) {
180                        throw new FramsticksException().msg("param is of wrong type").arg("requested", requested).arg("actual", param.getClass());
181                }
182                return requested.cast(param);
183        }
184
185        /**
186         * Build Param based on provided data.
187         *
188         * @return Param object
189         * @throws Exception
190         *             when Param getType is not defined
191         */
192        public @Nonnull Param finish() {
193                try {
194                        if (paramType == null) {
195                                throw new FramsticksException().msg("trying to finish incomplete param while type is missing");
196                        }
197                        return paramType.getConstructor(ParamBuilder.class).newInstance(this);
198                } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | FramsticksException e) {
199                        throw new FramsticksException().msg("failed to create param").cause(e).arg("name", name);
200                }
201        }
202
203        @ParamAnnotation
204        public ParamBuilder id(String id) {
205                this.id = id;
206                return this;
207        }
208
209        public <T extends Param> ParamBuilder type(Class<T> type) {
210                assert type != null;
211                this.paramType = type;
212                return this;
213        }
214
215        /**
216         * @return the id
217         */
218        @ParamAnnotation
219        public String getId() {
220                return id;
221        }
222
223        @ParamAnnotation
224        public ParamBuilder group(Integer group) {
225                this.group = group;
226                return this;
227        }
228
229        @ParamAnnotation
230        public ParamBuilder flags(int flags) {
231                this.flags = flags;
232                return this;
233        }
234
235        @ParamAnnotation
236        public ParamBuilder name(String name) {
237                this.name = name;
238                return this;
239        }
240
241        protected <T extends Number> void parseMinMaxDefNumber(Class<T> type, String second, String third, String fourth) {
242                if (second != null) {
243                        min = second;
244                }
245                if (third != null) {
246                        max = third;
247                }
248                if (fourth != null) {
249                        def = fourth;
250                }
251        }
252
253        protected List<String> enumValues;
254
255        public ParamBuilder enums(List<String> values) {
256                enumValues = values;
257                return type(EnumParam.class);
258        }
259
260        protected String uid;
261
262        @ParamAnnotation
263        public ParamBuilder type(String type) {
264                // typeString = type;
265                assert type != null;
266
267                log.trace("parsing type: " + type);
268
269                String[] typeSplitted = type.split(" ");
270                String first = typeSplitted[0];
271                String second = typeSplitted.length > 1 ? typeSplitted[1] : null;
272                String third = typeSplitted.length > 2 ? typeSplitted[2] : null;
273                String fourth = typeSplitted.length > 3 ? typeSplitted[3] : null;
274
275                switch (first.charAt(0)) {
276                        case 'o': {
277                                containedTypeName = second != null ? second : first.substring(1);
278                                type(ObjectParam.class);
279                                break;
280                        }
281                        case 'p': {
282                                type(ProcedureParam.class);
283                                signature(type.substring(1));
284                                break;
285                        }
286                        case 'd': {
287
288                                int tildeIndex = type.indexOf("~");
289                                if (tildeIndex != -1) {
290                                        enums(Arrays.asList(type.substring(tildeIndex + 1).split("~")));
291                                } else {
292                                        if (first.length() >= 2) {
293                                                switch (first.charAt(1)) {
294                                                        case 'b': {
295                                                                type(BinaryParam.class);
296                                                                break;
297                                                        }
298                                                        case 'c': {
299                                                                type(ColorParam.class);
300                                                                break;
301                                                        }
302                                                        default: {
303                                                                log.error("unknown type: " + first);
304                                                                return this;
305                                                        }
306                                                }
307                                        }
308                                        if ("0".equals(second) && "1".equals(third)) {
309                                                type(BooleanParam.class);
310                                        }
311                                        if (paramType == null) {
312                                                type(DecimalParam.class);
313                                        }
314                                }
315                                if (DecimalParam.class.isAssignableFrom(this.paramType)) {
316                                        parseMinMaxDefNumber(Integer.class, second, third, fourth);
317                                }
318                                break;
319                        }
320                        case 'f': {
321                                type(FloatParam.class);
322                                parseMinMaxDefNumber(Double.class, second, third, fourth);
323                                break;
324                        }
325                        case 'x': {
326                                type(UniversalParam.class);
327                                break;
328                        }
329                        case 's': {
330                                type(StringParam.class);
331                                min(second);
332                                max(third);
333                                break;
334                        }
335                        case 'e': {
336                                type(EventParam.class);
337                        eventArgumentTypeName(second);
338                        break;
339                }
340                case 'l': {
341                        containedTypeName = second;
342                        if (third != null) {
343                                type(UniqueListParam.class);
344                                uid = third;
345                        } else {
346                                type(ArrayListParam.class);
347                        }
348                        break;
349                }
350                default: {
351                        log.error("unknown type: " + first);
352                        return this;
353                }
354                }
355                return this;
356        }
357
358        public ParamBuilder eventArgumentTypeName(String eventArgumentTypeName) {
359                this.eventArgumentTypeName = eventArgumentTypeName;
360                return this;
361        }
362
363        @ParamAnnotation
364        public ParamBuilder help(String help) {
365                this.help = help;
366                return this;
367        }
368
369        /**
370         * @return the group
371         */
372        @ParamAnnotation
373        public Integer getGroup() {
374                return group;
375        }
376
377        /**
378         * @return the flags
379         */
380        @ParamAnnotation
381        public int getFlags() {
382                return flags;
383        }
384
385        /**
386         * @return the name
387         */
388        @ParamAnnotation
389        public String getName() {
390                return name;
391        }
392
393        /**
394         * @return the help
395         */
396        @ParamAnnotation
397        public String getHelp() {
398                return help;
399        }
400
401        @ParamAnnotation
402        public String getType() {
403                return "?";
404        }
405
406        @ParamAnnotation(id = "xtra")
407        public int getExtra() {
408                return extra;
409        }
410
411        /**
412         * @return the paramType
413         */
414        public Class<? extends Param> getParamType() {
415                return paramType;
416        }
417
418        @ParamAnnotation(id = "xtra")
419        public ParamBuilder extra(int extra) {
420                this.extra = extra;
421                return this;
422        }
423
424        @ParamAnnotation
425        public ParamBuilder min(Object min) {
426                this.min = min;
427                return this;
428        }
429
430        @ParamAnnotation
431        public ParamBuilder max(Object max) {
432                this.max = max;
433                return this;
434        }
435
436        @ParamAnnotation
437        public ParamBuilder def(Object def) {
438                this.def = def;
439                return this;
440        }
441
442
443        public Param build(String line) throws Exception {
444                String[] paramEntryValues = line.split(",");
445
446                if (paramEntryValues.length == 0) {
447                        log.warn("field empty or wrong format (" + line
448                                        + ") - omitting");
449                        return null;
450                }
451
452                for (int i = 0; i < paramEntryValues.length; ++i) {
453                        paramEntryValues[i] = paramEntryValues[i].trim();
454                }
455
456                try {
457                        id(paramEntryValues[0]);
458                        group(Integer.valueOf(paramEntryValues[1]));
459                        flags(FlagsUtil.read(ParamFlags.class, paramEntryValues[2]));
460                        name(paramEntryValues[3]);
461                        type(paramEntryValues[4]);
462                        help(paramEntryValues[6]);
463                } catch (IndexOutOfBoundsException e) {
464                        /** everything is ok, parameters have just finished*/
465                } catch (NumberFormatException ex) {
466                        log.warn("wrong format of entry: " + line
467                                        + ", omitting");
468                        return null;
469                }
470                return finish();
471        }
472
473        public void setField(String key, String value) {
474                switch (key) {
475                        case ID_FIELD:
476                                id(value);
477                                break;
478                        case NAME_FIELD:
479                                name(value);
480                                break;
481                        case TYPE_FIELD:
482                                type(value);
483                                break;
484                        case FLAGS_FIELD:
485                                flags(FlagsUtil.read(ParamFlags.class, value));
486                                break;
487                        case HELP_FIELD:
488                                help(value);
489                                break;
490                        case GROUP_FIELD:
491                                group(Integer.valueOf(value));
492                                break;
493                        default:
494                                log.error("unknown field for Param: " + key);
495                                break;
496                }
497        }
498
499        public ParamBuilder fillDef(Object def) {
500                if (this.def == null) {
501                        return def(def);
502                }
503                return this;
504        }
505
506        public ParamBuilder fillStorageType(Class<?> storageType) {
507                if (this.storageType == null) {
508                        this.storageType = storageType;
509                }
510                return this;
511        }
512
513        /**
514         * @return the eventArgumentTypeName
515         */
516        public String getEventArgumentTypeName() {
517                return eventArgumentTypeName;
518        }
519
520        public Class<?> getStorageType() {
521                return storageType;
522        }
523
524        protected static ValueParam parseProcedureTypePart(String type, String name) {
525                return Param.build().type(type).name(name).id(name).finish(ValueParam.class);
526        }
527
528        private static Pattern signaturePattern = Pattern.compile("^([^\\(]+)?\\(([^\\)]*)\\)$");
529
530        public ParamBuilder signature(String signature) {
531                argumentsType = new ArrayList<>();
532
533                if (!Strings.notEmpty(signature)) {
534                        resultType = null;
535                        return this;
536                }
537                Matcher matcher = signaturePattern.matcher(signature);
538                if (!matcher.matches()) {
539                        throw new FramsticksException().msg("invalid signature");
540                }
541                String result = Strings.collapse(matcher.group(1));
542                if (result != null) {
543                        resultType = Param.build().type(result).finish(ValueParam.class);
544                } else {
545                        resultType = null;
546                }
547                String arguments = matcher.group(2);
548                if (!Strings.notEmpty(arguments)) {
549                        return this;
550                }
551                int number = 0;
552                for (String a : arguments.split(",")) {
553                        ParamBuilder arg = Param.build();
554
555                        int space = a.indexOf(' ');
556                        if (space == -1) {
557                                arg.type(a).id("arg" + number);
558                        } else {
559                                String name = a.substring(space + 1);
560                                arg.type(a.substring(0, space)).id(name).name(name);
561                        }
562                        argumentsType.add(arg.finish(ValueParam.class));
563                        ++number;
564                }
565                return this;
566        }
567
568
569        public ParamBuilder idAndName(String name) {
570                id(name);
571                name(name);
572                return this;
573        }
574
575        @Override
576        public String toString() {
577                return "ParamBuilder for " + Misc.returnNotNull(id, "<not yet known>");
578        }
579}
580
Note: See TracBrowser for help on using the repository browser.