source: trunk/src/org/expeditee/io/ExpReader.java@ 1102

Last change on this file since 1102 was 1102, checked in by davidb, 6 years ago

Reworking of the code-base to separate logic from graphics. This version of Expeditee now supports a JFX graphics as an alternative to SWING

File size: 9.1 KB
Line 
1/**
2 * ExpReader.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.io;
20
21import java.io.BufferedReader;
22import java.io.FileReader;
23import java.io.IOException;
24import java.lang.reflect.Method;
25import java.util.HashMap;
26import java.util.LinkedList;
27import java.util.List;
28
29import org.expeditee.core.Point;
30import org.expeditee.gui.Frame;
31import org.expeditee.items.Constraint;
32import org.expeditee.items.Dot;
33import org.expeditee.items.Item;
34import org.expeditee.items.Line;
35import org.expeditee.items.Text;
36import org.expeditee.stats.SessionStats;
37
38/**
39 * Reads in Exp format files and constructs the Frame and Item objects they
40 * contain.
41 *
42 * @author mrww1
43 *
44 */
45public class ExpReader extends DefaultFrameReader {
46
47 public static final String EXTENTION = ".exp";
48
49 private BufferedReader _reader = null;
50
51 private String _frameName;
52
53 /**
54 * Does nothing, location must be set before use
55 */
56 public ExpReader(String frameName) {
57 super();
58
59 _frameName = frameName;
60 }
61
62 /**
63 * Determines whether a string begins with tag.
64 *
65 * @param s
66 * a line of text
67 * @return true if s begins with a tag
68 */
69 protected static boolean isValidLine(String s) {
70 return s.length() >= 2 && s.charAt(1) == ' '
71 && (Character.isLetter(s.charAt(0)) || s.charAt(0) == '[' || s.charAt(0) == ']' || s.charAt(0) == '^' || s.charAt(0) == '_');
72 }
73
74 /**
75 * Reads a file with the given name from disk.
76 *
77 * @param frameName
78 * the name of the Frame to read in from a file.
79 * @return A new Frame object that contains any Items described in the file.
80 * @throws IOException
81 * Any exceptions occured by the BufferedReader.
82 */
83 public Frame readFrame(BufferedReader reader) throws IOException {
84 _reader = reader;
85 String next = "";
86 Frame newFrame = new Frame();
87
88 try {
89 // Framename must be set before setting the frame number
90 newFrame.setName(_frameName);
91
92 final List<DelayedAction> delayedActions = new LinkedList<DelayedAction>();
93
94 // First read all the header lines
95 while (_reader.ready() && !(next = _reader.readLine()).equals("Z")) {
96 if (isValidLine(next)) {
97 processHeaderLine(newFrame, next);
98 }
99 }
100
101 // Now read all the items
102 Item currentItem = null;
103 while (_reader.ready() && !(next = _reader.readLine()).equals("Z")) {
104 // if this is the start of a new item add a new item
105 if (isValidLine(next)) {
106 if (getTag(next) == 'S') {
107 String value = getValue(next);
108 int id = Integer.parseInt(value.substring(2));
109
110 switch (value.charAt(0)) {
111 case 'P': // check if its a point
112 currentItem = new Dot(id);
113 break;
114 default:
115 currentItem = new Text(id);
116 break;
117 }
118 _linePoints.put(currentItem.getID(), currentItem);
119 newFrame.addItem(currentItem);
120 } else if (currentItem != null && actionShouldBeDelayed(getTag(next))) {
121 delayedActions.add(new DelayedAction(currentItem, next));
122 } else if (currentItem != null) {
123 processBodyLine(currentItem, next);
124 } else {
125 System.err.println("Error while reading in frame (ExpReader): Found body line but no current item to apply it to.");
126 }
127 }
128 }
129
130 // Read the lines
131 while (_reader.ready() && !(next = _reader.readLine()).equals("Z")) {
132 if (isValidLine(next)) {
133 Point idtype = separateValues(next.substring(2));
134 // The next line must be the endpoints
135 if (!_reader.ready())
136 throw new Exception("Unexpected end of file");
137 next = _reader.readLine();
138 Point startend = separateValues(next.substring(2));
139 int start = startend.x;
140 int end = startend.y;
141
142 if (_linePoints.get(start) != null
143 && _linePoints.get(end) != null) {
144 newFrame.addItem(new Line(_linePoints.get(start),
145 _linePoints.get(end), idtype.x));
146 } else {
147 System.out
148 .println("Error reading line with unknown end points");
149 }
150 }
151 }
152
153 // Read the constraints
154 while (_reader.ready() && !(next = _reader.readLine()).equals("Z")) {
155 if (isValidLine(next)) {
156 Point idtype = separateValues(next.substring(2));
157 // The next line must be the endpoints
158 if (!_reader.ready())
159 throw new Exception("Unexpected end of file");
160 next = _reader.readLine();
161 Point startend = separateValues(next.substring(2));
162
163 Item a = _linePoints.get(startend.x);
164 Item b = _linePoints.get(startend.y);
165
166 new Constraint(a, b, idtype.x, idtype.y);
167 }
168 }
169
170 for(DelayedAction action: delayedActions)
171 action.exec();
172
173 // Read the stats
174 while (_reader.ready() && ((next = _reader.readLine()) != null)) {
175 if (next.startsWith(SessionStats.ACTIVE_TIME_ATTRIBUTE)) {
176 try {
177 String value = next.substring(SessionStats.ACTIVE_TIME_ATTRIBUTE.length()).trim();
178 newFrame.setActiveTime(value);
179 } catch (Exception e) {
180 }
181
182 } else if (next.startsWith(SessionStats.DARK_TIME_ATTRIBUTE)) {
183 try {
184 String value = next.substring(SessionStats.DARK_TIME_ATTRIBUTE.length()).trim();
185 newFrame.setDarkTime(value);
186 } catch (Exception e) {
187 }
188
189 }
190 }
191
192 } catch (Exception e) {
193 e.printStackTrace();
194 System.out.println("Error reading frame file line: " + next + " "
195 + e.getMessage());
196 }
197
198 //newFrame.refreshItemPermissions();
199 _reader.close();
200 newFrame.setChanged(false);
201
202 return newFrame;
203 }
204
205 private class DelayedAction {
206 private Item theItem;
207 private String theLine;
208
209 DelayedAction(final Item theItem, final String theLine) {
210 this.theItem = theItem;
211 this.theLine = theLine;
212 }
213
214 void exec() {
215 processBodyLine(theItem, theLine);
216 }
217 }
218
219 // Stores points used when constructing lines
220 private HashMap<Integer, Item> _linePoints = new HashMap<Integer, Item>();
221
222 /**
223 * Processes the body section of the Exp file, which contains all Items
224 *
225 * @param frame
226 * The Frame to add any created Items to.
227 * @param line
228 * The line of text read in from the file to process.
229 */
230 protected void processBodyLine(Item item, String line) {
231 // separate the tag from the value
232 Character tag = getTag(line);
233 String value = getValue(line);
234
235 Method toRun = _ItemTags.get(tag);
236 if (toRun == null) System.out.println("Error accessing tag method: " + tag);
237 Object[] vals = Conversion.Convert(toRun, value);
238
239 try {
240 if (vals != null) toRun.invoke(item, vals);
241 } catch (Exception e) {
242 System.out.println("Error running tag method: " + tag);
243 e.printStackTrace();
244 }
245 }
246
247 protected static Character getTag(String line) {
248 assert (line.length() > 0);
249 return line.charAt(0);
250 }
251
252 protected static String getValue(String line) {
253 if (line.length() > 2)
254 return line.substring(2);
255 else
256 return "";
257 }
258
259 protected static boolean actionShouldBeDelayed(Character c) {
260 return _DelayedItemTags.contains(c);
261 }
262
263 /**
264 * Reads the header section of the file, which contains information about
265 * the Frame.
266 *
267 * @param frame
268 * The Frame to assign the read values to.
269 * @param line
270 * The line from the file to process.
271 * @return False if the end of the header has been reached, True otherwise.
272 */
273 private void processHeaderLine(Frame frame, String line) throws IOException {
274 // first separate the tag from the text
275 Character tag = getTag(line);
276 String value = getValue(line);
277 Method toRun = _FrameTags.get(tag);
278
279 if (toRun == null) {
280 if (tag != 'v') {
281 System.out.println("Tag '" + tag + "' in '" + line
282 + "' is not supported.");
283 }
284 return;
285 }
286
287 Object[] vals = Conversion.Convert(toRun, value);
288 try {
289 toRun.invoke(frame, vals);
290 } catch (Exception e) {
291 System.out.println("Error running method: "
292 + toRun.toGenericString());
293 e.printStackTrace();
294 }
295 }
296
297 // Returns a point from a String containing two ints separated by a space
298 protected Point separateValues(String line) {
299 int x = Integer.parseInt(line.substring(0, line.indexOf(" ")));
300 int y = Integer.parseInt(line.substring(line.indexOf(" ") + 1));
301
302 return new Point(x, y);
303 }
304
305 public static int getVersion(String fullpath) {
306 try {
307 BufferedReader reader = new BufferedReader(new FileReader(fullpath));
308 String next = "";
309 // First read the header lines until we get the version number
310 while (reader.ready() && !(next = reader.readLine()).equals("Z")) {
311 if (isValidLine(next)) {
312 Character tag = getTag(next);
313 String value = getValue(next);
314 if (tag.equals('V'))
315 return Integer.parseInt(value);
316 }
317 }
318 } catch (Exception e) {
319 }
320 return -1;
321 }
322}
Note: See TracBrowser for help on using the repository browser.