source: java/main/src/main/java/com/framsticks/parsers/F0Parser.java @ 84

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

HIGHLIGHTS:

  • simplification of entities management model
  • cleanup around params (improve hierarchy)
  • migrate from JUnit to TestNG
  • introduce FEST to automatically test GUI
  • improve slider control
  • loosen synchronization between gui tree and backend representation
  • and many other bug fixes

NOTICE:

  • a great many of lines is changed only because of substituting spaces with tabs

CHANGELOG (oldest changes at the bottom):

Some cleaning after fix found.

Fix bug with tree.

More changes with TreeNodes?.

Finally fix issue with tree.

Improve gui tree management.

Decouple update of values from fetch request in gui.

Minor changes.

Minor changes.

Minor change.

Change Path construction wording.

More fixes to SliderControl?.

Fix SliderControl?.

Fix SliderControl?.

Minor improvement.

Several changes.

Make NumberParam? a generic class.

Add robot to the gui test.

Setup common testing logging configuration.

Remove Parameters class.

Remove entityOwner from Parameters.

Move name out from Parameters class.

Move configuration to after the construction.

Simplify observers and endpoints.

Remove superfluous configureEntity overrides.

Add dependency on fest-swing-testng.

Use FEST for final print test.

Use FEST for more concise and readable assertions.

Divide test of F0Parser into multiple methods.

Migrate to TestNG

Minor change.

Change convention from LOGGER to log.

Fix reporting of errors during controls filling.

Bound maximal height of SliderControl?.

Minor improvements.

Improve tooltips for controls.

Also use Delimeted in more places.

Move static control utilities to Gui.

Rename package gui.components to controls.

Some cleaning in controls.

Improve Param classes placing.

Move ValueParam?, PrimitiveParam? and CompositeParam? one package up.

Improve ParamBuilder?.

Move getDef to ValueParam? and PrimitiveParam?.

Move getMax and getDef to ValueParam?.

Move getMin to ValueParam?.

Upgrade to laters apache commons versions.

Use filterInstanceof extensively.

Add instanceof filters.

Make ValueParam? in many places of Param.

Place assertions about ValueParam?.

Add ValueParam?

Rename ValueParam? to PrimitiveParam?

Minor changes.

Several improvements to params types.

Add NumberParam?.

Add TextControl? component.

Add .swp files to .gitignore

Greatly improved slider component.

Some improvements.

Make Param.reassign return also a state.

Add IterableIterator?.

Several changes.

  • Move util classes to better packages.
  • Remove warnings from eclim.

Several improvements.

Fix bug with BooleanParam?.

Some experiments with visualization.

Another fix to panel management.

Improve panel management.

Some refactorization around panels.

Add root class for panel.

File size: 7.9 KB
Line 
1package com.framsticks.parsers;
2
3import java.io.BufferedReader;
4import java.io.IOException;
5import java.io.InputStream;
6import java.io.InputStreamReader;
7import java.text.ParseException;
8import java.util.ArrayList;
9import java.util.Collection;
10import java.util.List;
11
12import com.framsticks.model.Model;
13import static com.framsticks.params.SimpleAbstractAccess.*;
14
15import com.framsticks.params.Flags;
16import com.framsticks.params.Param;
17import com.framsticks.params.PrimitiveParam;
18import com.framsticks.util.lang.Containers;
19import com.framsticks.util.lang.Exceptions;
20import com.framsticks.util.lang.Pair;
21import com.framsticks.util.lang.Strings;
22import org.apache.log4j.Logger;
23
24import com.framsticks.params.FramsClass;
25import com.framsticks.params.AccessInterface;
26
27/**
28 * The class Parser is used to parse genotype encoded in f0 representation.
29 */
30public class F0Parser {
31
32        private final static Logger log = Logger.getLogger(F0Parser.class);
33
34        /** The schema proper for f0 representation. */
35        protected final Schema schema;
36        protected final InputStream is;
37        protected final List<AccessInterface> result = new ArrayList<AccessInterface>();
38        int lineNumber = 0;
39
40        public F0Parser(Schema schema, InputStream is) {
41                assert schema != null;
42                assert is != null;
43                this.schema = schema;
44                this.is = is;
45        }
46
47        protected AccessInterface processLine(String line) {
48                try {
49
50                        Pair<String, String> p = Strings.splitIntoPair(line, ':', "");
51                        String classId = p.first.trim();
52                        FramsClass framsClass = schema.getRegistry().getInfoFromCache(classId);
53                        if (framsClass == null) {
54                                throw new Exception("unknown class id: " + classId);
55                        }
56                        AccessInterface access = schema.getRegistry().createAccess(classId, framsClass);
57                        access.select(access.createAccessee());
58                        for (Exception e : loadFromLine(access, p.second)) {
59                                warn(lineNumber, "however entry was added", e);
60                        }
61                        return access;
62                } catch (Exception e) {
63                        warn(lineNumber, "entry was not added", e);
64                }
65                return null;
66        }
67
68        /**
69         * Parses the stream with genotype in f0 representation. The correctness of
70         * genotype is checked. IO and syntax exceptions interrupts parsing and no
71         * result is returned. Other exceptions, connected with schema validation
72         * cause that certain object or it's parameter is ignored (appropriate
73         * communicate informs user about it). Inappropriate values in numeric
74         * fields (bigger than maximum or smaller than minimum values) are
75         * communicated by warnings and set to minimum / maximum value.
76         *
77         * @return the list
78         * @throws IOException
79         *             Signals that an I/O exception has occurred.
80         * @throws ParseException
81         *             the parse exception
82         */
83        public List<AccessInterface> parse() throws IOException,
84                        ParseException {
85
86                InputStreamReader reader = null;
87                try {
88                        reader = new InputStreamReader(is, "UTF-8");
89                        BufferedReader br = new BufferedReader(reader);
90                        while (br.ready()) {
91                                ++lineNumber;
92                                String line = br.readLine();
93                                line = (line == null ? "" : line.trim());
94                                if (lineNumber == 1) {
95                                        if (!"//0".equals(line)) {
96                                                log.warn("stream should begin with \"//0\" in the first line");
97                                        } else {
98                                                continue;
99                                        }
100                                }
101                                if (line.equals("")) {
102                                        continue;
103                                }
104                                if (line.startsWith("#")) {
105                                        continue;
106                                }
107                                AccessInterface access = processLine(line);
108                                if (access != null) {
109                                        result.add(access);
110                                }
111                        }
112
113                        /** If no 'm' (Model) line was found, than simulate it on the beginning of the result.*/
114                        if (result.isEmpty() || !(result.get(0) instanceof Model)) {
115                                result.add(0, processLine("m:"));
116                        }
117                } finally {
118                        if (reader != null) {
119                                reader.close();
120                        }
121                }
122
123                return result;
124        }
125
126        private static void warn(int lineNumber, String message, Exception e) {
127                log.warn("in line " + lineNumber + " the following error occurred (" + message + "): " + e + "\n" + Exceptions.printStackTrace(e));
128        }
129
130        /** Breaks string into entries.*/
131        public List<Entry> breakIntoEntries(String parameters) throws Exception {
132                // tokenize
133                boolean inQuotes = false;
134                char previousChar = ',';
135                List<Entry> result = new ArrayList<Entry>();
136                StringBuilder stringBuilder = new StringBuilder();
137                String key = null;
138                if (parameters.trim().length() > 0) {
139                        for (char currentChar : parameters.toCharArray()) {
140                                if (!inQuotes && (currentChar == '=') && (key == null)) {
141                                        key = stringBuilder.toString().trim();
142                                        stringBuilder = new StringBuilder();
143                                } else if (!inQuotes && currentChar == ',') {
144                                        if (previousChar == ',') {
145                                                result.add(new Entry(key, null));
146                                        } else {
147                                                result.add(new Entry(key, stringBuilder.toString().trim()));
148                                        }
149                                        stringBuilder = new StringBuilder();
150                                        key = null;
151                                } else if (currentChar == '"') {
152                                        if (previousChar == '\\') {
153                                                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
154                                                stringBuilder.append(currentChar);
155                                        } else {
156                                                inQuotes = !inQuotes;
157                                        }
158                                } else {
159                                        stringBuilder.append(currentChar);
160                                }
161
162                                previousChar = currentChar;
163                        }
164
165                        result.add(new Entry(key, stringBuilder.toString().trim()));
166
167                        if (inQuotes) {
168                                throw new Exception("Double quotes expected while end of line met");
169                        }
170                }
171                return result;
172        }
173
174        public List<Exception> loadFromLine(AccessInterface access, String parameters) throws Exception {
175
176                List<Entry> entries = breakIntoEntries(parameters);
177
178                List<Exception> exceptions = new ArrayList<Exception>();
179
180                Collection<Param> paramsC = access.getParams();
181                Param[] params = paramsC.toArray(new Param[] {null});
182                if (params.length == 0) {
183                        return exceptions;
184                }
185                for (PrimitiveParam p : Containers.filterInstanceof(paramsC, PrimitiveParam.class)) {
186                        Object def = p.getDef(Object.class);
187                        if (def != null) {
188                                access.set(p, def);
189                        }
190                }
191
192                int number = -1;
193                Integer nextParamNumber = 0;
194                for (Entry pair : entries) {
195                        ++number;
196                        try {
197                                Param currentParam;
198                                if (pair.key != null) {
199                                        currentParam = access.getParam(pair.key);
200                                        if (currentParam == null) {
201                                                nextParamNumber = null;
202                                                throw new Exception("no parameter with such id: " + pair.key);
203                                        }
204                                } else {
205                                        if (nextParamNumber == null || ((params[nextParamNumber].getFlags() & Flags.CANOMITNAME) == 0)) {
206                                                nextParamNumber = null;
207                                                throw new Exception(
208                                                                "parameter with offset: "
209                                                                                + number
210                                                                                + " is not set, "
211                                                                                + "because it's definition or definition of the previous param "
212                                                                                + "does not contain flag, which allows to skip the name (flag 1024)");
213                                        }
214                                        currentParam = params[nextParamNumber];
215                                }
216                                if (currentParam != null) {
217                                        if (pair.value != null) {
218                                                PrimitiveParam vp = (PrimitiveParam) currentParam;
219                                                int setFlag = access.set(vp, pair.value);
220                                                if ((setFlag & Flags.PSET_HITMIN) != 0) {
221                                                        exceptions.add(createBoundaryHitException(access, vp, pair.value, Flags.PSET_HITMIN));
222                                                }
223
224                                                if ((setFlag & Flags.PSET_HITMAX) != 0) {
225                                                        exceptions.add(createBoundaryHitException(access, vp, pair.value, Flags.PSET_HITMAX));
226                                                }
227
228                                                if ((setFlag & Flags.PSET_RONLY) != 0) {
229                                                        throw (new Exception("tried to set a read-only attribute \""
230                                                                + currentParam.getId()
231                                                                + "\" in class \"" + access.getId() + "\""));
232                                                }
233                                        }
234                                        nextParamNumber = null;
235                                        for (int j = params.length - 1; j > 0; --j) {
236                                                if (params[j - 1] == currentParam) {
237                                                        nextParamNumber = j;
238                                                }
239                                        }
240                                }
241
242                        } catch (Exception e) {
243                                exceptions.add(e);
244                        }
245                }
246                return exceptions;
247        }
248
249        private static Exception createBoundaryHitException(AccessInterface access, PrimitiveParam param, String value, int flag) {
250                boolean minimum = (flag & Flags.PSET_HITMIN) != 0;
251                String boundary = (minimum ? param.getMin(Object.class) : param.getMax(Object.class)).toString();
252                String name =  (minimum ? "minimum" : "maximum");
253                return new Exception("Tried to set attribute \""
254                                + param.getId()
255                                + "\" in class \""
256                                + access.getId()
257                                + "\" to value which exceeds " + name + " ("
258                                + value
259                                + "), truncated to: "
260                                + boundary);
261        }
262}
Note: See TracBrowser for help on using the repository browser.