source: java/main/src/main/java/com/framsticks/params/ParamBuilder.java @ 87

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

HIGHLIGHTS:

  • FramsClass? and contained Param are now immutable classes (like String),

which allows to refer to them concurrently without synchronization
(which for example in turn simplifies GUI management)

  • also make Path immutable (which was earlier only assumed)
  • add global cache for FramsClasses? created solely and automatically

on base of Java classes.

representations basing on given FramsClass?

  • above changes greatly improved GUI responsivness during browsing
  • furtherly improve Param class hierarchy
  • allow to inject actions on state changes into MultiParamLoader?
  • add more tests

CHANGELOG:

Add StatusListener? to MultiParamLoader?.

Minor refactorization in MultiParamLoader?.

First step with auto append.

Add SchemaTest?.

Improve Registry.

Clean up in Registry.

Work out Registry.

Use annotations for Param.

Fix ListChange?.

Improve fluent interface of the FramsClassBuilder?.

Done caching of ReflectionAccess?.Backend

Fix hashCode of Pair.

A step on a way to cache ReflectionAccess?.Backend

Make SimpleAbstractAccess?.framsClass a final field.

Add static cache for FramsClasses? based on java.

Only classes created strictly and automatically
based on java classes are using this cache.

Make all Params immutable.

Many improvement to make Param immutable.

Make PrimitiveParam? generic type.

Several changes to make Param immutable.

Make FramsClass? immutable.

Another improvement to Path immutability.

Several improvements to Path.

Improve PathTest?.

Configurarable MutabilityDetector?.

File size: 8.6 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.FramsticksException;
7import com.framsticks.util.lang.Strings;
8
9import org.apache.log4j.Logger;
10
11import java.lang.reflect.InvocationTargetException;
12import java.util.Arrays;
13import java.util.List;
14
15/**
16 * The class ParamBuilder helps building Param objects.
17 *
18 * @author Mateusz Jarus <name.surname@gmail.com> (please replace name and
19 *         surname with my personal data)
20 *
21 * @author Piotr Śniegowski
22 */
23
24@FramsClassAnnotation(name = "prop", id = "prop")
25public class ParamBuilder {
26        private final static Logger log = Logger.getLogger(ParamBuilder.class.getName());
27
28        private static final String ID_FIELD = "id";
29        private static final String NAME_FIELD = "name";
30        private static final String HELP_FIELD = "help";
31        private static final String GROUP_FIELD = "group";
32        private static final String TYPE_FIELD = "type";
33        private static final String FLAGS_FIELD = "flags";
34
35        /** The parameter id. */
36        private String id;
37
38        /**
39         * The parameter internal id. It's set by a user to use user's own id in
40         * code
41         */
42        private String internalId;
43
44        /** The number of group, that parameter belongs to. */
45        private Integer group = 0;
46
47        /** The flags stored as a bit sum. */
48        private Integer flags = 0;
49
50        /** The parameter name. */
51        private String name;
52
53        /** The help (description) concerning parameter. */
54        private String help;
55
56        /** The type of parameter. */
57        private Class<? extends Param> paramType;
58
59        private Object min;
60
61        private Object max;
62
63        private Object def;
64
65        String containedTypeName;
66
67        protected FramsClassBuilder classBuilder;
68
69        public ParamBuilder() {
70                this(null);
71        }
72
73
74        /**
75         * @param classBuilder
76         */
77        public ParamBuilder(FramsClassBuilder classBuilder) {
78                this.classBuilder = classBuilder;
79        }
80
81
82        /**
83         * @return the min
84         */
85        public Object getMin() {
86                return min;
87        }
88
89        /**
90         * @return the max
91         */
92        public Object getMax() {
93                return max;
94        }
95
96        /**
97         * @return the def
98         */
99        public Object getDef() {
100                return def;
101        }
102
103        public String getContainedTypeName() {
104                return Strings.notEmpty(containedTypeName) ? containedTypeName : null;
105        }
106
107        /**
108         * @return the enumValues
109         */
110        public List<String> getEnumValues() {
111                return enumValues;
112        }
113
114        /**
115         * @return the procedureSignature
116         */
117        public String getProcedureSignature() {
118                return procedureSignature;
119        }
120
121        /**
122         * @return the uid
123         */
124        public String getUid() {
125                return uid;
126        }
127
128        /**
129         * Build Param based on provided data.
130         *
131         * @return Param object
132         * @throws Exception
133         *             when Param getType is not defined
134         */
135        public Param finish() {
136                try {
137                        return paramType.getConstructor(ParamBuilder.class).newInstance(this);
138                } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
139                        throw new FramsticksException().msg("failed to create param").cause(e).arg("name", name);
140                }
141        }
142
143        @ParamAnnotation
144        public ParamBuilder id(String id) {
145                this.id = id;
146                return this;
147        }
148
149        public <T extends Param> ParamBuilder type(Class<T> type) {
150                assert type != null;
151                this.paramType = type;
152                return this;
153        }
154
155        // public <T extends Param> ParamBuilder type(T param) {
156        //      return internalSetType(param.getClass(), param);
157        // }
158
159
160        /**
161         * @return the id
162         */
163        @ParamAnnotation
164        public String getId() {
165                return id;
166        }
167
168        /**
169         * @return the internalId
170         */
171        public String getInternalId() {
172                return internalId;
173        }
174
175        public ParamBuilder setInternalId(String internalId) {
176                this.internalId = internalId;
177                return this;
178        }
179
180        @ParamAnnotation
181        public ParamBuilder group(Integer group) {
182                this.group = group;
183                return this;
184        }
185
186        @ParamAnnotation
187        public ParamBuilder flags(Integer flags) {
188                this.flags = flags;
189                return this;
190        }
191
192        @ParamAnnotation
193        public ParamBuilder name(String name) {
194                this.name = name;
195                return this;
196        }
197
198        protected <T extends Number> void parseMinMaxDefNumber(Class<T> type, String second, String third) {
199                if (second != null) {
200                        min = second;
201                }
202                if (third != null) {
203                        max = third;
204                }
205        }
206
207        protected List<String> enumValues;
208
209        public ParamBuilder enums(List<String> values) {
210                enumValues = values;
211                return type(EnumParam.class);
212        }
213
214        protected String procedureSignature;
215
216        protected String uid;
217
218        @ParamAnnotation
219        public ParamBuilder type(String type) {
220                // typeString = type;
221
222                log.trace("parsing type: " + type);
223
224                String[] typeSplitted = type.split(" ");
225                String first = typeSplitted[0];
226                String second = typeSplitted.length > 1 ? typeSplitted[1] : null;
227                String third = typeSplitted.length > 2 ? typeSplitted[2] : null;
228
229                switch (first.charAt(0)) {
230                        case 'o': {
231                                containedTypeName = second != null ? second : first.substring(1);
232                                type(ObjectParam.class);
233                                break;
234                        }
235                        case 'p': {
236                                procedureSignature = type.substring(1);
237                                type(ProcedureParam.class);
238                                break;
239                        }
240                        case 'd': {
241
242                                int tildeIndex = type.indexOf("~");
243                                if (tildeIndex != -1) {
244                                        enums(Arrays.asList(type.substring(tildeIndex + 1).split("~")));
245                                } else {
246                                        if (first.length() >= 2) {
247                                                switch (first.charAt(1)) {
248                                                        case 'b': {
249                                                                type(BinaryParam.class);
250                                                                break;
251                                                        }
252                                                        case 'c': {
253                                                                type(ColorParam.class);
254                                                                break;
255                                                        }
256                                                        default: {
257                                                                log.error("unknown type: " + first);
258                                                                return this;
259                                                        }
260                                                }
261                                        }
262                                        if ("0".equals(second) && "1".equals(third)) {
263                                                type(BooleanParam.class);
264                                        }
265                                        if (paramType == null) {
266                                                type(DecimalParam.class);
267                                        }
268                                }
269                                if (DecimalParam.class.isAssignableFrom(this.paramType)) {
270                                        parseMinMaxDefNumber(Integer.class, second, third);
271                                }
272                                break;
273                        }
274                        case 'f': {
275                                type(FloatParam.class);
276                                parseMinMaxDefNumber(Double.class, second, third);
277                                break;
278                        }
279                        case 'x': {
280                                type(UniversalParam.class);
281                                break;
282                        }
283                        case 's': {
284                                type(StringParam.class);
285                                min(second);
286                                max(third);
287                                break;
288                        }
289                        case 'e': {
290                                type(EventParam.class);
291                                break;
292                        }
293                        case 'l': {
294                                containedTypeName = second;
295                                if (third != null) {
296                                        type(UniqueListParam.class);
297                                        uid = third;
298                                } else {
299                                        type(ArrayListParam.class);
300                                }
301                                break;
302                        }
303                        default:{
304                                log.error("unknown type: " + first);
305                                return this;
306                        }
307                }
308                return this;
309        }
310
311        @ParamAnnotation
312        public ParamBuilder help(String help) {
313                this.help = help;
314                return this;
315        }
316
317        /**
318         * @return the group
319         */
320        @ParamAnnotation
321        public Integer getGroup() {
322                return group;
323        }
324
325        /**
326         * @return the flags
327         */
328        @ParamAnnotation
329        public Integer getFlags() {
330                return flags;
331        }
332
333        /**
334         * @return the name
335         */
336        @ParamAnnotation
337        public String getName() {
338                return name;
339        }
340
341        /**
342         * @return the help
343         */
344        @ParamAnnotation
345        public String getHelp() {
346                return help;
347        }
348
349        @ParamAnnotation
350        public String getType() {
351                return "?";
352        }
353
354        /**
355         * @return the paramType
356         */
357        public Class<? extends Param> getParamType() {
358                return paramType;
359        }
360
361        public ParamBuilder min(Object min) {
362                this.min = min;
363                return this;
364        }
365
366        public ParamBuilder max(Object max) {
367                this.max = max;
368                return this;
369        }
370
371        public ParamBuilder def(Object def) {
372                this.def = def;
373                return this;
374        }
375
376        // public Class<?> getStorageType() {
377        //      assert param != null;
378        //      return param.getStorageType();
379        // }
380
381        public Param build(String line) throws Exception {
382                String[] paramEntryValues = line.split(",");
383
384                if (paramEntryValues.length == 0) {
385                        log.warn("field empty or wrong format (" + line
386                                        + ") - omitting");
387                        return null;
388                }
389
390                for (int i = 0; i < paramEntryValues.length; ++i) {
391                        paramEntryValues[i] = paramEntryValues[i].trim();
392                }
393
394                try {
395                        id(paramEntryValues[0]);
396                        group(Integer.valueOf(paramEntryValues[1]));
397                        flags(Flags.read(paramEntryValues[2]));
398                        name(paramEntryValues[3]);
399                        type(paramEntryValues[4]);
400                        help(paramEntryValues[6]);
401                } catch (IndexOutOfBoundsException e) {
402                        /** everything is ok, parameters have just finished*/
403                } catch (NumberFormatException ex) {
404                        log.warn("wrong format of entry: " + line
405                                        + ", omitting");
406                        return null;
407                }
408                return finish();
409        }
410
411        public void setField(String key, String value) {
412                switch (key) {
413                        case ID_FIELD:
414                                id(value);
415                                break;
416                        case NAME_FIELD:
417                                name(value);
418                                break;
419                        case TYPE_FIELD:
420                                type(value);
421                                break;
422                        case FLAGS_FIELD:
423                                flags(Flags.read(value));
424                                break;
425                        case HELP_FIELD:
426                                help(value);
427                                break;
428                        case GROUP_FIELD:
429                                group(Integer.valueOf(value));
430                                break;
431                        default:
432                                log.error("unknown field for Param: " + key);
433                                break;
434                }
435        }
436
437        public ParamBuilder defaultDef(Object def) {
438                if (this.def == null) {
439                        return def(def);
440                }
441                return this;
442        }
443
444}
Note: See TracBrowser for help on using the repository browser.