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

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

HIGHLIGHTS:

for Joinables running

CHANGELOG:
Add WorkPackageLogic? and classes representing prime experiment state.

Add classes for PrimeExperiment? state.

Extract single netload routine in Simulator.

Working netload with dummy content in PrimeExperiment?.

More development with NetLoadSaveLogic? and PrimeExperiment?.

Improvement around prime.

Improve BufferedDispatcher?.isActive logic.

Add prime-all.xml configuration.

Manual connecting to existing simulators from GUI.

Guard in SimulatorConnector? against expdef mismatch.

Guard against empty target dispatcher in BufferedDispatcher?.

Make BufferedDispatcher? a Dispatcher (and Joinable).

Minor improvements.

Done StackedJoinable?, improve Experiment.

Develop StackedJoinable?.

Add StackedJoinable? utility joinables controller.

Add dependency on apache-commons-lang.

Add ready ListChange? on Simulators.

Improve hints in ListChange?.

Several improvements.

Found bug with dispatching in Experiment.

Minor improvements.

Fix bug with early finishing Server.

Many changes in Dispatching.

Fix bug with connection.

Do not obfuscate log with socket related exceptions.

Add SocketClosedException?.

Add SimulatorConnector?.

Work out conception of experiment composing of logics building blocks.

Rename SinkInterface? to Sink.

Move saving of Accesses into AccessOperations?.

Some improvements to Experiment.

Improve joinables.

Fix issue with joinables closing.

Add direct and managed consoles to popup menu.

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