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

Last change on this file since 1242 was 1242, checked in by bln4, 5 years ago

Support for new regime in the form of new fields and conditional setting of all paths fields.

Settings are now able to generate their own representation. This allows for the user to explicitly inspect the default values.

When profiles are created, an optional parameter may now be provided. If not null, the new map parameter can contain default values for settings to apply to this profile. This allows for the creation of profiles to that have (for example), their username set to an explicit value. Multiuser mode uses this functionality for usernames and key values among other things.

Frames can now be asked were they are located on the file system. Furthermore, frame indirection is now a thing. Rather than containing data to display, an exp file can contain a line in the format of "REDIRECT:<path>" to go looking for that data. Frames are able to return both their logical (their exp file) and real (the file actually containing the data) paths.

Frames can now store data.

Further fixes to how edits from other users are loaded in.

File size: 10.7 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.gui.FrameIO;
32import org.expeditee.items.Constraint;
33import org.expeditee.items.Dot;
34import org.expeditee.items.Item;
35import org.expeditee.items.Line;
36import org.expeditee.items.Text;
37import org.expeditee.stats.SessionStats;
38
39/**
40 * Reads in Exp format files and constructs the Frame and Item objects they
41 * contain.
42 *
43 * @author mrww1
44 *
45 */
46public class ExpReader extends DefaultFrameReader {
47
48 public static final String EXTENTION = ".exp";
49
50 private BufferedReader _reader = null;
51
52 private String _frameName;
53
54 /**
55 * Does nothing, location must be set before use
56 */
57 public ExpReader(String frameName) {
58 super();
59
60 _frameName = frameName;
61 }
62
63 /**
64 * Determines whether a string begins with tag.
65 *
66 * @param s
67 * a line of text
68 * @return true if s begins with a tag
69 */
70 protected static boolean isValidLine(String s) {
71 // Previously lines in a .exp file had to start with a letter (A-Z, a-z). This allowed for an efficient check for valid lines.
72 // As we started to run out of spare letters to use for properties, we wished to use the full range of characters. But we did not
73 // wish to loose the efficiency of the Character.isLetter check. In order to maintain as much of this efficiency as possible, but
74 // allow for all characters, we take advantage of how || is evaluated:
75 // if the check for Character.isLetter passes, then the more complex map lookup operation does not take place.
76 return s.length() >= 2 && (Character.isLetter(s.charAt(0)) || _ItemTags.keySet().contains(s.charAt(0)));
77 }
78
79 /**
80 * Reads a file with the given name from disk.
81 *
82 * @param frameName
83 * the name of the Frame to read in from a file.
84 * @return A new Frame object that contains any Items described in the file.
85 * @throws IOException
86 * Any exceptions occured by the BufferedReader.
87 */
88 @Override
89 public Frame readFrame(BufferedReader reader) throws IOException {
90 _reader = reader;
91 String next = "";
92 Frame newFrame = new Frame();
93
94 try {
95 // Framename must be set before setting the frame number
96 newFrame.setName(_frameName);
97
98 final List<DelayedAction> delayedActions = new LinkedList<DelayedAction>();
99
100 // First read all the header lines
101 while (_reader.ready() && !(next = _reader.readLine()).equals("Z")) {
102 if (isValidLine(next)) {
103 processHeaderLine(newFrame, next);
104 }
105 }
106
107 // Now read all the items
108 Item currentItem = null;
109 while (_reader.ready() && !(next = _reader.readLine()).equals("Z")) {
110 // if this is the start of a new item add a new item
111 if (isValidLine(next)) {
112 if (getTag(next) == 'S') {
113 String value = getValue(next);
114 int id = Integer.parseInt(value.substring(2));
115
116 switch (value.charAt(0)) {
117 case 'P': // check if its a point
118 currentItem = new Dot(id);
119 break;
120 default:
121 currentItem = new Text(id);
122 break;
123 }
124 _linePoints.put(currentItem.getID(), currentItem);
125 newFrame.addItem(currentItem);
126 } else if (currentItem != null && actionShouldBeDelayed(getTag(next))) {
127 delayedActions.add(new DelayedAction(currentItem, next));
128 } else if (currentItem != null) {
129 processBodyLine(currentItem, next);
130// final boolean hasSpecifiedPermission = currentItem.getPermission() != null;
131// final boolean hasSpecifiedOwner = currentItem.getOwner() != null;
132// if (hasSpecifiedPermission && hasSpecifiedOwner && currentItem.getPermission().getPermission(currentItem.getOwner()) == UserAppliedPermission.denied) {
133// newFrame.removeItem(currentItem);
134// newFrame.addItemHidden(currentItem);
135// continue;
136// }
137 } else {
138 System.err.println("Error while reading in frame (ExpReader): Found body line but no current item to apply it to.");
139 }
140 }
141 }
142
143 // Read the lines
144 while (_reader.ready() && !(next = _reader.readLine()).equals("Z")) {
145 if (isValidLine(next)) {
146 Point idtype = separateValues(next.substring(2));
147 // The next line must be the endpoints
148 if (!_reader.ready()) {
149 throw new Exception("Unexpected end of file");
150 }
151 next = _reader.readLine();
152 Point startend = separateValues(next.substring(2));
153 int start = startend.getX();
154 int end = startend.getY();
155
156 if (_linePoints.get(start) != null
157 && _linePoints.get(end) != null) {
158 newFrame.addItem(new Line(_linePoints.get(start),
159 _linePoints.get(end), idtype.getX()));
160 } else {
161 System.out
162 .println("Error reading line with unknown end points");
163 }
164 }
165 }
166
167 // Read the constraints
168 while (_reader.ready() && !(next = _reader.readLine()).equals("Z")) {
169 if (isValidLine(next)) {
170 Point idtype = separateValues(next.substring(2));
171 // The next line must be the endpoints
172 if (!_reader.ready()) {
173 throw new Exception("Unexpected end of file");
174 }
175 next = _reader.readLine();
176 Point startend = separateValues(next.substring(2));
177
178 Item a = _linePoints.get(startend.getX());
179 Item b = _linePoints.get(startend.getY());
180
181 new Constraint(a, b, idtype.getX(), idtype.getY());
182 }
183 }
184
185 for(DelayedAction action: delayedActions) {
186 action.exec();
187 }
188
189 // Read the stats
190 while (_reader.ready() && ((next = _reader.readLine()) != null)) {
191 if (next.startsWith(SessionStats.ACTIVE_TIME_ATTRIBUTE)) {
192 try {
193 String value = next.substring(SessionStats.ACTIVE_TIME_ATTRIBUTE.length()).trim();
194 newFrame.setActiveTime(value);
195 } catch (Exception e) {
196 }
197
198 } else if (next.startsWith(SessionStats.DARK_TIME_ATTRIBUTE)) {
199 try {
200 String value = next.substring(SessionStats.DARK_TIME_ATTRIBUTE.length()).trim();
201 newFrame.setDarkTime(value);
202 } catch (Exception e) {
203 }
204
205 }
206 }
207
208 } catch (Exception e) {
209 e.printStackTrace();
210 System.out.println("Error reading frame file line: " + next + " "
211 + e.getMessage());
212 }
213
214 //newFrame.refreshItemPermissions();
215 _reader.close();
216 FrameIO.setSavedProperties(newFrame);
217 newFrame.setChanged(false);
218
219 return newFrame;
220 }
221
222 private class DelayedAction {
223 private Item theItem;
224 private String theLine;
225
226 DelayedAction(final Item theItem, final String theLine) {
227 this.theItem = theItem;
228 this.theLine = theLine;
229 }
230
231 void exec() {
232 processBodyLine(theItem, theLine);
233 }
234 }
235
236 // Stores points used when constructing lines
237 private HashMap<Integer, Item> _linePoints = new HashMap<Integer, Item>();
238
239 /**
240 * Processes the body section of the Exp file, which contains all Items
241 *
242 * @param frame
243 * The Frame to add any created Items to.
244 * @param line
245 * The line of text read in from the file to process.
246 */
247 protected void processBodyLine(Item item, String line) {
248 // separate the tag from the value
249 Character tag = getTag(line);
250 String value = getValue(line);
251
252 Method toRun = _ItemTags.get(tag);
253
254 if (toRun == null) {
255 System.out.println("Error accessing tag method: " + tag);
256 }
257
258 Object[] vals = Conversion.Convert(toRun, value);
259 try {
260 if (vals != null) {
261 toRun.invoke(item, vals);
262 }
263 } catch (Exception e) {
264 System.out.println("Error running tag method: " + tag);
265 e.printStackTrace();
266 }
267 }
268
269 protected static Character getTag(String line) {
270 assert (line.length() > 0);
271 return line.charAt(0);
272 }
273
274 protected static String getValue(String line) {
275 if (line.length() > 2) {
276 return line.substring(2);
277 } else {
278 return "";
279 }
280 }
281
282 protected static boolean actionShouldBeDelayed(Character c) {
283 return _DelayedItemTags.contains(c);
284 }
285
286 /**
287 * Reads the header section of the file, which contains information about
288 * the Frame.
289 *
290 * @param frame
291 * The Frame to assign the read values to.
292 * @param line
293 * The line from the file to process.
294 * @return False if the end of the header has been reached, True otherwise.
295 */
296 private void processHeaderLine(Frame frame, String line) throws IOException {
297 // first separate the tag from the text
298 Character tag = getTag(line);
299 String value = getValue(line);
300 Method toRun = _FrameTags.get(tag);
301
302 if (toRun == null) {
303 if (tag != 'v') {
304 System.out.println("Tag '" + tag + "' in '" + line
305 + "' is not supported.");
306 }
307 return;
308 }
309
310 Object[] vals = Conversion.Convert(toRun, value);
311 try {
312 toRun.invoke(frame, vals);
313 } catch (Exception e) {
314 System.out.println("Error running method: "
315 + toRun.toGenericString());
316 e.printStackTrace();
317 }
318 }
319
320 // Returns a point from a String containing two ints separated by a space
321 protected Point separateValues(String line) {
322 int x = Integer.parseInt(line.substring(0, line.indexOf(" ")));
323 int y = Integer.parseInt(line.substring(line.indexOf(" ") + 1));
324
325 return new Point(x, y);
326 }
327
328 public static int getVersion(String fullpath) {
329 try {
330 BufferedReader reader = new BufferedReader(new FileReader(fullpath));
331 String next = "";
332 // First read the header lines until we get the version number
333 while (reader.ready() && !(next = reader.readLine()).equals("Z")) {
334 if (isValidLine(next)) {
335 Character tag = getTag(next);
336 String value = getValue(next);
337 if (tag.equals('V')) {
338 reader.close();
339 return Integer.parseInt(value);
340 }
341 }
342 }
343 reader.close();
344 } catch (Exception e) {
345 }
346 return -1;
347 }
348
349 public static String redirectTo(String fullPath) {
350 try {
351 BufferedReader reader = new BufferedReader(new FileReader(fullPath));
352 String next = "";
353 while (reader.ready() && !(next = reader.readLine()).equals("Z")) {
354 if (next.startsWith("REDIRECT:")) {
355 String redirectTo = next.replace("REDIRECT:", "");
356 reader.close();
357 return redirectTo;
358 }
359 }
360 reader.close();
361 } catch (Exception e) {
362 }
363 return null;
364 }
365}
Note: See TracBrowser for help on using the repository browser.