source: java/main/src/main/java/com/framsticks/parsers/MultiParamLoader.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: 9.2 KB
Line 
1package com.framsticks.parsers;
2
3import com.framsticks.params.*;
4import org.apache.log4j.Logger;
5
6import java.io.FileNotFoundException;
7import java.io.IOException;
8import java.util.*;
9
10public class MultiParamLoader {
11        private final static Logger log = Logger.getLogger(MultiParamLoader.class);
12
13        /**
14         * The class which name was recently found in the file, to which execution
15         * should be passed.
16         */
17        public AccessInterface getLastAccessInterface() {
18                return lastAccessInterface;
19        }
20
21        /** TODO does it support multilines? */
22        /**
23         * Specifies the condition to break execution.
24         */
25        public enum Status {
26                None, Finished, BeforeObject, AfterObject, BeforeUnknown, OnComment, OnError, Loading
27        }
28
29        /**
30         * Specifies the action that should be taken inside loops.
31         */
32        private enum LoopAction {
33                Nothing, Break, Continue
34        }
35
36        protected AccessInterface lastAccessInterface;
37
38        /**
39         * Empty Param representing unknown classes - used to omit unknown
40         * objects in the file.
41         */
42        protected AccessInterface emptyParam = new PropertiesAccess(new FramsClass());
43
44        /**
45         * Last comment found in the file.
46         */
47        protected String lastComment;
48
49        /**
50         * Set of break conditions.
51         */
52        private EnumSet<Status> breakConditions = EnumSet.of(Status.None);
53
54        /**
55         * Status of current execution.
56         */
57        private Status status = Status.None;
58
59        private void setStatus(Status status) {
60                log.trace("changing status: " + this.status.toString() + " -> " + status.toString());
61                this.status = status;
62        }
63
64        /**
65         * File from which data should be read.
66         */
67        private SourceInterface currentSource;
68
69        protected String currentLine;
70
71
72        /**
73         * All the files read by the loader (there could be many of them because of
74         * '#|include').
75         */
76        private Stack<String> fileStack = new Stack<String>();
77
78        /**
79         * A map that specifies connection between the getName of the file and the
80         * actual reader.
81         */
82        private Map<String, SourceInterface> fileMap = new HashMap<String, SourceInterface>();
83
84        /**
85         * List of known classes.
86         */
87        private Map<String, AccessInterface> knownParamInterfaces = new HashMap<String, AccessInterface>();
88
89        /**
90         * Last unknown object found in the file.
91         */
92        private String lastUnknownObjectName;
93
94        /**
95         * @return the currentLine
96         */
97        public String getCurrentLine() {
98                return currentLine;
99        }
100
101        public MultiParamLoader() {
102
103        }
104
105        /**
106         * Starts reading the file.
107         */
108        public Status go() throws Exception {
109                log.trace("go");
110
111                while (!isFinished()) {
112                        // check if we are before some known or unknown object
113                        LoopAction loopAction = tryReadObject();
114                        if (loopAction == LoopAction.Break) {
115                                break;
116                        } else if (loopAction == LoopAction.Continue) {
117                                continue;
118                        }
119
120                        // read data
121                        currentLine = currentSource.readLine();
122
123                        // end of file
124                        if (currentLine == null) {
125                                if (!returnFromIncluded()) {
126                                        finish();
127                                        break;
128                                } else {
129                                        continue;
130                                }
131                        }
132                        log.trace("read line: " + currentLine);
133
134                        // empty line
135                        if (currentLine.length() == 0) {
136                                continue;
137                        }
138
139                        // check if some file should be included
140                        if (isIncludeLine(currentLine) == LoopAction.Continue) {
141                                continue;
142                        }
143
144                        // check if should break on comment
145                        if (isCommentLine(currentLine) == LoopAction.Break) {
146                                break;
147                        }
148
149                        // get class getName
150                        LoopAction action = changeCurrentParamInterface(currentLine);
151                        if (action == LoopAction.Break) {
152                                break;
153                        }
154                        if (action == LoopAction.Continue) {
155                                continue;
156                        }
157                        log.warn("unknown line: " + currentLine);
158                }
159
160                return status;
161        }
162
163        /**
164         * Checks whether the reader found a known or unknown object and execution
165         * should be passed to it.
166         * @throws Exception
167         */
168        private LoopAction tryReadObject() throws Exception {
169                if (status == Status.BeforeObject
170                                || (status == Status.BeforeUnknown && lastAccessInterface != null)) {
171                        // found object - let it load data
172                        if (lastAccessInterface.getSelected() == null) {
173                                lastAccessInterface.select(lastAccessInterface.createAccessee());
174                        }
175                        log.trace("loading into " + lastAccessInterface);
176                        lastAccessInterface.load(currentSource);
177
178                        if (isBreakCondition(Status.AfterObject)) {
179                                // break after object creation
180                                return LoopAction.Break;
181                        }
182
183                        return LoopAction.Continue;
184                } else if (status == Status.BeforeUnknown) {
185                        log.warn("omitting unknown object: " + lastUnknownObjectName);
186
187                        // found unknown object
188                        emptyParam.load(currentSource);
189                        setStatus(Status.AfterObject);
190
191                        return LoopAction.Continue;
192                }
193
194                return LoopAction.Nothing;
195        }
196
197        /**
198         * Checks whether some additional file shouldn't be included.
199         */
200        private LoopAction isIncludeLine(String line) throws FileNotFoundException {
201                try {
202                        // found comment
203                        if (line.charAt(0) == '#') {
204                                // maybe we should include something
205                                if (line.substring(1, 8).equals("include")) {
206                                        int beg = line.indexOf('\"');
207                                        if (beg == -1) {
208                                                log.info("Wanted to include some file, but the format is incorrect");
209                                                return LoopAction.Continue;
210                                        }
211
212                                        String includeFileName = line.substring(beg + 1);
213                                        int end = includeFileName.indexOf('\"');
214                                        if (end == -1) {
215                                                log.info("Wanted to include some file, but the format is incorrect");
216                                                return LoopAction.Continue;
217                                        }
218
219                                        includeFileName = includeFileName.substring(0, end);
220
221                                        include(includeFileName);
222
223                                        return LoopAction.Continue;
224                                }
225                        }
226                } catch (IndexOutOfBoundsException ex) {
227                        // value after # sign is shorter than expected 7 characters - do
228                        // nothing
229                }
230
231                return LoopAction.Nothing;
232        }
233
234        /**
235         * Checks whether execution shouldn't break on comment.
236         */
237        private LoopAction isCommentLine(String line) {
238                if (line.charAt(0) == '#' && isBreakCondition(Status.OnComment)) {
239                        // it's a simple comment - maybe we should break?
240                        lastComment = line;
241                        return LoopAction.Break;
242                }
243
244                return LoopAction.Nothing;
245        }
246
247        /**
248         * Gets the getName of the class from line read from file.
249         */
250        private LoopAction changeCurrentParamInterface(String line) {
251                // found key - value line
252                if (line.charAt(line.length() - 1) == ':') {
253                        String typeName = line.substring(0, line.length() - 1);
254                        lastAccessInterface = knownParamInterfaces.get(typeName);
255
256                        if (lastAccessInterface != null) {
257                                if (isBreakCondition(Status.BeforeObject)) {
258                                        log.debug("breaking before object");
259                                        return LoopAction.Break;
260                                } else {
261                                        return LoopAction.Continue;
262                                }
263                        } else {
264                                lastUnknownObjectName = typeName;
265                                if (isBreakCondition(Status.BeforeUnknown)) {
266                                        log.debug("breaking before unknown");
267                                        return LoopAction.Break;
268                                } else {
269                                        return LoopAction.Continue;
270                                }
271                        }
272                }
273                return LoopAction.Nothing;
274        }
275
276        /**
277         * Adds another break condition.
278         */
279        public void addBreakCondition(Status condition) {
280                breakConditions.add(condition);
281        }
282
283        /**
284         * Removes break condition.
285         */
286        public void removeBreakCondition(Status condition) {
287                breakConditions.remove(condition);
288        }
289
290        /**
291         * Adds another class.
292         */
293        public void addAccessInterface(AccessInterface accessInterface) {
294                /**TODO: by id or by name? rather by id, because from file is always lowercase*/
295                knownParamInterfaces.put(accessInterface.getId(), accessInterface);
296        }
297
298        /**
299         * Checks whether execution is finished.
300         */
301        private boolean isFinished() {
302                return (status == Status.Finished);
303        }
304
305        private void finish() {
306                log.trace("finishing");
307                if (currentSource != null) {
308                        currentSource.close();
309                }
310
311                setStatus(Status.Finished);
312        }
313
314        /**
315         * Opens selected file.
316         */
317
318        public boolean setNewSource(SourceInterface source) {
319                log.debug("switching current source to " + source.getFilename() + "...");
320
321                currentSource = source;
322                setStatus(Status.Loading);
323
324                return true;
325        }
326
327        /**
328         * Includes specified file.
329         */
330        private void include(String includeFilename) {
331
332                includeFilename = currentSource.demangleInclude(includeFilename);
333
334                if (includeFilename == null) {
335                        return;
336                }
337                // check if it is already included and break if it is
338                if (isAlreadyIncluded(includeFilename)) {
339                        log.debug("circular reference ignored (" + includeFilename
340                                        + ")");
341                        return;
342                }
343
344                log.info("including file " + includeFilename + "...");
345
346                SourceInterface newSource = currentSource.openInclude(includeFilename);
347                if (newSource == null) {
348                        return;
349                }
350
351                fileStack.add(currentSource.getFilename());
352                fileMap.put(currentSource.getFilename(), currentSource);
353                setNewSource(newSource);
354
355        }
356
357        /**
358         * Checks whether selected file was already included.
359         */
360        private boolean isAlreadyIncluded(String filename) {
361                for (String file : fileStack) {
362                        if (filename.equals(file)) {
363                                log.warn("file " + filename + " was already included");
364                                return true;
365                        }
366                }
367
368                return false;
369        }
370
371        /**
372         * Returns from included file.
373         */
374        private boolean returnFromIncluded() throws IOException {
375                if (fileStack.size() == 0) {
376                        return false;
377                }
378
379                if (currentSource != null) {
380                        currentSource.close();
381                }
382
383                String filename = fileStack.pop();
384                currentSource = fileMap.get(filename);
385                fileMap.remove(filename);
386
387                return true;
388        }
389
390        /**
391         * Checks whether execution should break on selected condition.
392         */
393        private boolean isBreakCondition(Status condition) {
394                setStatus(condition);
395                return breakConditions.contains(condition);
396        }
397
398        public Object returnObject() {
399                assert lastAccessInterface != null;
400                Object result = lastAccessInterface.getSelected();
401                if (result == null) {
402                        return null;
403                }
404                lastAccessInterface.select(null);
405                return result;
406        }
407}
Note: See TracBrowser for help on using the repository browser.