source: java/main/src/main/java/com/framsticks/parsers/MultiParamLoader.java @ 77

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

Add new java codebase.

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