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

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

HIGHLIGHTS:

  • use java annotations to mark classes and fields to be used when:
    • using java classes with ReflectionAccess? to represent remote objects with FramsClass? description found by "info ..." requests
    • to build up FramsClass? representation of objects not present at remote server
  • allow using primitive types (instead of wraping counterparts) in reflected classes
  • rework FramsClass? creation process (add FramsClassBuilder?)
  • add more tests

CHANGELOG:
Prepare model.World class.

Minor change.

Use primitive types for Genotype and Creature classes.

Use primitive types in model.Neuro* classes.

Use primitive types in model.Joint* classes.

Use primitive types in model.Part* classes.

Fix primitive values.

Extract FramsClassBuilder?.

Add tests of Model classes.

More fixes.

Refactorize out ParamCandidate?.

Several fixes.

Fix all regressions after introducing annotations.

Use annotations throughout the project.

Add exception classes.

Improve creation of FramsClass?.

More changes.

Many changes regarding annotations.

Annotate classes in com.framsticks.model package.

Remove manual FramsClass? constructor.

Construct FramsClass? for Creature. Add test.

Add default values to the ParamAnnotation?.

Add ParamBuilderTest? and ParamAnnotation?.

Add FramsClassAnnotation?.

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