source: java/main/src/main/java/com/framsticks/params/ParamsUtil.java @ 107

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

HIGHLIGHTS:

  • add SimultorProviders? hierarchy
  • start Framsticks server over SSH
  • FJF compatible with Framsticks 4.0rc3
  • reading and writing of standard.expt
  • a proof-of-concept implementation of StandardExperiment?

CHANGELOG:
Optionally return FreeAccess? from registry.

Add SimulatorRange?.

StandardExperiment? with genotypes circulation.

Automate registration around StandardState?.

More improvements to StandardExperiment?.

Skeleton version of StandardExperiment?.

Test saving of StandardState?.

Standard experiment state is being loaded.

More development towards StandardState? reading.

Work on reading standard experiment state.

Add classes for standard experiment.

Update example standard.expt

Add FreeAccess? and FreeObject?.

Made compatible with version 4.0rc3

Change deserialization policy.

Improve SSH support.

Working running simulator over SSH.

Fix joining bug in Experiment.

Working version of SimulatorRunner?.

Add more SimulatorProviders?.

Working PrimeExperimentTest? with 4.0rc3

Add references to deserialization.

Add OpaqueObject? and it's serialization.

Add deserialization of dictionaries.

Partial implementation of deserialization.

Add more tests for deserialization.

Prepare tests for deserialization.

Add proper result to prime experiment test.

Minor fixes to simulators providers.

Draft version of SimulatorProvider?.

Add SimulatorProvider? interface.

File size: 11.2 KB
Line 
1package com.framsticks.params;
2
3import java.util.ArrayList;
4// import java.util.HashMap;
5import java.util.List;
6import java.util.Map;
7import java.util.TreeMap;
8import java.util.regex.Matcher;
9import java.util.regex.Pattern;
10
11import javax.annotation.Nonnull;
12
13// import org.apache.logging.log4j.Logger;
14// import org.apache.logging.log4j.LogManager;
15
16import com.framsticks.util.FramsticksException;
17import com.framsticks.util.lang.Numbers;
18
19
20import static com.framsticks.util.lang.Containers.filterInstanceof;
21
22/**
23 * @author Piotr Sniegowski
24 */
25public abstract class ParamsUtil {
26        // private final static Logger log = LogManager.getLogger(ParamsUtil.class.getName());
27
28
29        public static String readSourceToString(Source source) {
30                StringBuilder result = new StringBuilder();
31                String line;
32                while ((line = source.readLine()) != null) {
33                        result.append(line).append(" ");
34                }
35                source.close();
36                return result.toString();
37        }
38
39        public static <T> List<T> stripAccess(List<Access> accesses, Class<T> type) {
40                List<T> result = new ArrayList<T>();
41                for (Access a : accesses) {
42                        Object object = a.getSelected();
43                        if (!type.isInstance(object)) {
44                                throw new FramsticksException().msg("extracted object is of invalid type").arg("object", object).arg("desired", type).arg("actual", object.getClass()).arg("access", a);
45                        }
46                        result.add(type.cast(object));
47                }
48                return result;
49        }
50
51        public static int takeAllNonNullValues(Access to, Access from) {
52                int copied = 0;
53                for (ValueParam f : filterInstanceof(from.getParams(), ValueParam.class)) {
54                        Object v = from.get(f, Object.class);
55                        if (v == null) {
56                                continue;
57                        }
58                        // if (to.get(f, Object.class) != null) {
59                        //      continue;
60                        // }
61                        to.set(f, v);
62                        ++copied;
63                }
64                return copied;
65        }
66
67        public static int copyExistingParamsTypeSafe(Access to, Access from) {
68                int copied = 0;
69                for (ValueParam f : filterInstanceof(from.getParams(), ValueParam.class)) {
70                        Param t = from.getParam(f.getId());
71                        if (!(t instanceof ValueParam)) {
72                                continue;
73                        }
74                        if (to.getClass() != f.getClass()) {
75                                continue;
76                        }
77                        to.set((ValueParam) t, from.get(f, Object.class));
78                        ++copied;
79                }
80                return copied;
81        }
82
83        public static <T> T selectObjectForAccess(Access access, Object object, Class<T> type) {
84                if (object == null) {
85                        return null;
86                }
87                if (!type.isInstance(object)) {
88                        throw new FramsticksException().msg("trying to select object of wrong type").arg("object", object).arg("type", object.getClass()).arg("in", access);
89                }
90                return type.cast(object);
91        }
92
93        public static int getNumberOfCompositeParamChild(Access access, Object child) {
94                int count = access.getCompositeParamCount();
95                for (int i = 0; i < count; ++i) {
96                        if (access.get(i, Object.class) == child) {
97                                return i;
98                        }
99                }
100                return -1;
101        }
102
103        public static Object[] arguments(Object... args) {
104                return args;
105        }
106
107        public static Param getParam(ParamCollection collection, int i) {
108                return collection.getParam(i);
109        }
110
111        public static Param getParam(ParamCollection collection, String id) {
112                return collection.getParam(id);
113        }
114
115        public static @Nonnull <T extends Param> T castedParam(ParamCollection collection, @Nonnull final Param param, @Nonnull final Class<T> type, Object name) {
116                if (param == null) {
117                        // return null;
118                        throw new FramsticksException().msg("param is missing").arg("name", name).arg("in", collection);
119                }
120                if (!type.isInstance(param)) {
121                        // return null;
122                        throw new FramsticksException().msg("wrong type of param").arg("actual", param.getClass()).arg("requested", type).arg("in", collection);
123                }
124                return type.cast(param);
125        }
126
127        /**
128         * Gets the param entry.
129         *
130         * @param i
131         *            the offset of parameter
132         * @return the param entry
133         */
134        public static @Nonnull <T extends Param> T getParam(ParamCollection collection, final int i, @Nonnull final Class<T> type) {
135                return castedParam(collection, collection.getParam(i), type, i);
136        }
137
138        /**
139         * Gets the param entry.
140         *
141         * @param id
142         *            the getId of parameter
143         * @return the param entry
144         */
145        public static @Nonnull <T extends Param> T getParam(ParamCollection collection, @Nonnull final String id, @Nonnull final Class<T> type) {
146                return castedParam(collection, collection.getParam(id), type, id);
147        }
148
149        public static final String SERIALIZED = "@Serialized:";
150
151        public static class SerializationContext {
152                protected final StringBuilder builder = new StringBuilder();
153                protected final ArrayList<Object> objects = new ArrayList<>();
154
155                protected void appendString(String value) {
156                        builder.append('"').append(value).append('"');
157                }
158
159                protected boolean serializeInternal(Object value) {
160                        if (value == null) {
161                                builder.append("null");
162                                return true;
163                        }
164                        /** indexOf is not used here, because it uses equals() internally, which results in StackOverflowError */
165                        Class<?> type = value.getClass();
166                        if (type.equals(String.class)) {
167                                String stringValue = (String) value;
168                                appendString(stringValue);
169                                return stringValue.startsWith(SERIALIZED);
170                        }
171                        if (type.equals(Boolean.class)) {
172                                builder.append(((Boolean) value) ? "1" : "0");
173                                return false;
174                        }
175                        if (type.equals(Double.class) || type.equals(Integer.class)) {
176                                builder.append(value.toString());
177                                return false;
178                        }
179
180                        for (int i = 0; i < objects.size(); ++i) {
181                                if (objects.get(i) == value) {
182                                        builder.append("^").append(i);
183                                        return true;
184                                }
185                        }
186
187                        if (List.class.isAssignableFrom(type)) {
188                                objects.add(value);
189                                List<?> list = (List<?>) value;
190                                boolean placeComma = false;
191                                builder.append("[");
192                                for (Object element : list) {
193                                        if (placeComma) {
194                                                builder.append(",");
195                                        } else {
196                                                placeComma = true;
197                                        }
198                                        serializeInternal(element);
199                                }
200                                builder.append("]");
201                                return true;
202                        }
203                        if (Map.class.isAssignableFrom(type)) {
204                                objects.add(value);
205                                Map<?, ?> map = (Map<?, ?>) value;
206                                boolean placeComma = false;
207                                builder.append("{");
208                                for (Map.Entry<?, ?> entry : map.entrySet()) {
209                                        if (placeComma) {
210                                                builder.append(",");
211                                        } else {
212                                                placeComma = true;
213                                        }
214                                        if (!(entry.getKey() instanceof String)) {
215                                                throw new FramsticksException().msg("non string keys are not allowed in serialization").arg("key type", entry.getKey().getClass());
216                                        }
217                                        appendString((String) entry.getKey());
218                                        builder.append(":");
219                                        serializeInternal(entry.getValue());
220                                }
221                                builder.append("}");
222                                return true;
223                        }
224                        if (type.equals(OpaqueObject.class)) {
225                                builder.append(value.toString());
226                                return true;
227                        }
228                        throw new FramsticksException().msg("invalid type for serialization").arg("type", type);
229                }
230
231                public String serialize(Object value) {
232                        if (value instanceof String) {
233                                String stringValue = (String) value;
234                                if (!stringValue.startsWith(SERIALIZED)) {
235                                        return stringValue;
236                                }
237                        }
238                        boolean complex = serializeInternal(value);
239                        return (complex ? SERIALIZED : "") + builder.toString();
240                }
241
242        }
243
244
245        public static <T> String serialize(T value) {
246                return new SerializationContext().serialize(value);
247        }
248
249        public static class DeserializationContext {
250
251                public static final Pattern OPAQUE_OBJECT_PATTERN = Pattern.compile("^(\\w+)<0x([a-fA-F0-9]+)>$");
252
253                @SuppressWarnings("serial")
254                public static class Exception extends FramsticksException {
255                }
256
257                protected final ArrayList<Object> objects = new ArrayList<>();
258                protected int cursor = 0;
259                protected final String input;
260
261                /**
262                 * @param input
263                 */
264                public DeserializationContext(String input) {
265                        this.input = input;
266                        cursor = 0;
267                }
268
269                protected boolean isFinished() {
270                        return cursor == input.length();
271                }
272
273                protected boolean is(char value) {
274                        if (isFinished()) {
275                                throw fail().msg("input ended");
276                        }
277                        return input.charAt(cursor) == value;
278                }
279
280                protected boolean isOneOf(String values) {
281                        if (isFinished()) {
282                                throw fail().msg("input ended");
283                        }
284                        return values.indexOf(input.charAt(cursor)) != -1;
285                }
286
287                protected char at() {
288                        return input.charAt(cursor);
289                }
290
291                protected char at(int pos) {
292                        return input.charAt(pos);
293                }
294
295                protected FramsticksException fail() {
296                        return new Exception().arg("at", cursor).arg("input", input);
297                }
298
299                protected void force(char value) {
300                        if (!is(value)) {
301                                throw fail().msg("invalid character").arg("expected", value).arg("found", at());
302                        }
303                        next();
304                }
305
306                protected boolean isAndNext(char value) {
307                        if (!is(value)) {
308                                return false;
309                        }
310                        next();
311                        return true;
312                }
313
314                protected void next() {
315                        ++cursor;
316                        // log.info("at: {}|{}", input.substring(0, cursor), input.substring(cursor));
317                }
318
319                protected void goToNext(char value) {
320                        while (cursor < input.length()) {
321                                if (is(value)) {
322                                        return;
323                                }
324                                next();
325                        }
326                        throw fail().msg("passed end").arg("searching", value);
327                }
328
329
330                protected String forceStringRemaining() {
331                        int start = cursor;
332                        while (true) {
333                                goToNext('"');
334                                if (at(cursor - 1) != '\\') {
335                                        next();
336                                        return input.substring(start, cursor - 1);
337                                }
338                                next();
339                                // it is finishing that loop, because of throwing in goToNext()
340                        }
341                        // throw fail();
342                }
343
344                public Object deserialize() {
345                        if (isAndNext('[')) {
346                                List<Object> list = new ArrayList<>();
347                                objects.add(list);
348                                while (!isAndNext(']')) {
349                                        if (!list.isEmpty()) {
350                                                force(',');
351                                        }
352                                        Object child = deserialize();
353                                        list.add(child);
354                                }
355                                return list;
356                        }
357
358                        if (isAndNext('{')) {
359                                Map<String, Object> map = new TreeMap<>();
360                                objects.add(map);
361                                while (!isAndNext('}')) {
362                                        if (!map.isEmpty()) {
363                                                force(',');
364                                        }
365                                        force('"');
366                                        String key = forceStringRemaining();
367                                        force(':');
368                                        Object value = deserialize();
369                                        map.put(key, value);
370                                }
371                                return map;
372                        }
373
374                        if (isAndNext('"')) {
375                                return forceStringRemaining();
376                        }
377                        int start = cursor;
378                        while (!isFinished() && !isOneOf("]},")) {
379                                next();
380                        }
381                        if (start == cursor) {
382                                throw fail().msg("empty value");
383                        }
384
385                        String value = input.substring(start, cursor);
386                        if (value.equals("null")) {
387                                //TODO: add this to list?
388                                return null;
389                        }
390
391                        Matcher matcher = OPAQUE_OBJECT_PATTERN.matcher(value);
392                        if (matcher.matches()) {
393                                return new OpaqueObject(matcher.group(1), Long.parseLong(matcher.group(2), 16));
394                        }
395
396
397                        Object number = DeserializationContext.tryParseNumber(value);
398                        if (number != null) {
399                                return number;
400                        }
401
402                        if (value.charAt(0) == '^') {
403                                Integer reference = Numbers.parse(value.substring(1), Integer.class);
404                                if (reference == null) {
405                                        throw fail().msg("invalid reference").arg("reference", reference);
406                                }
407                                return objects.get(reference);
408                        }
409                        //TODO: parse ^
410                        //TODO: parse opaque object
411                        throw fail().msg("unknown entity");
412
413                }
414
415                public static Object tryParseNumber(String value) {
416                        Integer i = Numbers.parse(value, Integer.class);
417                        if (i != null) {
418                                return i;
419                        }
420
421                        Double d = Numbers.parse(value, Double.class);
422                        if (d != null) {
423                                return d;
424                        }
425
426                        return null;
427                }
428        }
429
430
431        public static Object deserialize(String value) {
432                Object number = DeserializationContext.tryParseNumber(value);
433                if (number != null) {
434                        return number;
435                }
436
437                if (!value.startsWith(SERIALIZED)) {
438                        return value;
439                }
440                return new DeserializationContext(value.substring(SERIALIZED.length())).deserialize();
441        }
442
443        public static <T> T deserialize(String value, Class<T> type) {
444                Object object = deserialize(value);
445
446                return type.cast(object);
447        }
448
449}
Note: See TracBrowser for help on using the repository browser.