source: trunk/src/org/expeditee/io/KMSReader.java@ 67

Last change on this file since 67 was 67, checked in by ra33, 16 years ago

Fixed a bunch of problems with rectangles and resizing the window, as well as adding some more unit tests etc.

File size: 15.0 KB
Line 
1package org.expeditee.io;
2
3import java.io.BufferedReader;
4import java.io.FileReader;
5import java.io.IOException;
6import java.lang.reflect.Constructor;
7import java.lang.reflect.InvocationTargetException;
8import java.lang.reflect.Method;
9import java.util.HashMap;
10import java.util.Iterator;
11import java.util.LinkedHashMap;
12
13import org.expeditee.gui.Frame;
14import org.expeditee.gui.FrameGraphics;
15import org.expeditee.items.Constraint;
16import org.expeditee.items.Dot;
17import org.expeditee.items.Item;
18import org.expeditee.items.Line;
19import org.expeditee.items.Text;
20
21/**
22 * Reads in KMS format files and constructs the Frame and Item objects they
23 * contain.
24 *
25 * @author jdm18
26 *
27 */
28public class KMSReader extends FrameReader {
29
30 private BufferedReader _reader = null;
31
32 private static LinkedHashMap<String, Method> _ItemTags = null;
33
34 private static LinkedHashMap<String, Method> _FrameTags = null;
35
36 /**
37 * Does nothing, location must be set before use
38 */
39 public KMSReader() {
40 if (_ItemTags != null && _FrameTags != null)
41 return;
42
43 _ItemTags = new LinkedHashMap<String, Method>();
44 _FrameTags = new LinkedHashMap<String, Method>();
45
46 try {
47 _FrameTags.put("A", Frame.class.getMethod("setFrameName", pString));
48 _FrameTags.put("V", Frame.class.getMethod("setVersion", pInt));
49 _FrameTags
50 .put("p", Frame.class.getMethod("setProtection", pString));
51 _FrameTags.put("U", Frame.class.getMethod("setOwner", pString));
52 _FrameTags.put("D", Frame.class
53 .getMethod("setDateCreated", pString));
54 _FrameTags.put("M", Frame.class.getMethod("setLastModifyUser",
55 pString));
56 _FrameTags.put("d", Frame.class.getMethod("setLastModifyDate",
57 pString));
58 _FrameTags
59 .put("F", Frame.class.getMethod("setFrozenDate", pString));
60
61 _FrameTags.put("O", Frame.class.getMethod("setForegroundColor",
62 pColor));
63 _FrameTags.put("B", Frame.class.getMethod("setBackgroundColor",
64 pColor));
65
66 _ItemTags.put("S", Item.class.getMethod("setID", pInt));
67 _ItemTags.put("s", Item.class.getMethod("setDateCreated", pString));
68 _ItemTags.put("d", Item.class.getMethod("setColor", pColor));
69 _ItemTags.put("G", Item.class.getMethod("setBackgroundColor",
70 pColor));
71 _ItemTags.put("P", Item.class.getMethod("setPosition", pPoint));
72 _ItemTags.put("F", Item.class.getMethod("setLink", pString));
73 _ItemTags.put("X", Item.class.getMethod("setAction", pList));
74 _ItemTags.put("x", Item.class.getMethod("setActionMark", pBool));
75 _ItemTags.put("U", Item.class.getMethod("setActionCursorEnter",
76 pList));
77 _ItemTags.put("V", Item.class.getMethod("setActionCursorLeave",
78 pList));
79 _ItemTags.put("W", Item.class.getMethod("setActionEnterFrame",
80 pList));
81 _ItemTags.put("Y", Item.class.getMethod("setActionLeaveFrame",
82 pList));
83 _ItemTags.put("D", Item.class.getMethod("setData", pString));
84 _ItemTags.put("u", Item.class.getMethod("setHighlight", pBool));
85 _ItemTags.put("e", Item.class.getMethod("setFillColor", pColor));
86 _ItemTags.put("i", Item.class.getMethod("setFillPattern", pString));
87 _ItemTags.put("o", Item.class.getMethod("setOwner", pString));
88 _ItemTags.put("n", Item.class.getMethod("setLinkMark", pBool));
89 _ItemTags
90 .put("q", Item.class.getMethod("setLinkFrameset", pString));
91 _ItemTags
92 .put("y", Item.class.getMethod("setLinkTemplate", pString));
93 _ItemTags.put("g", Item.class
94 .getMethod("setLinePattern", pIntArray));
95
96 _ItemTags.put("j", Item.class.getMethod("setArrow", pArrow));
97
98 _ItemTags.put("f", Text.class.getMethod("setFont", pFont));
99 _ItemTags.put("t", Text.class.getMethod("setSpacing", pInt));
100 _ItemTags.put("T", Text.class.getMethod("setText", pString));
101
102 _ItemTags.put("a", Text.class.getMethod("setWordSpacing", pInt));
103 _ItemTags.put("b", Text.class.getMethod("setLetterSpacing", pInt));
104 _ItemTags.put("m", Text.class.getMethod("setInitialSpacing", pInt));
105 _ItemTags.put("w", Text.class.getMethod("setWidth", pInt));
106 _ItemTags.put("k", Text.class.getMethod("setJustification", pInt));
107
108 _ItemTags.put("h", Dot.class.getMethod("setThickness", pFloat));
109 _ItemTags.put("l", Item.class.getMethod("setLineIDs", pString));
110 _ItemTags
111 .put("c", Dot.class.getMethod("setConstraintIDs", pString));
112
113 // Lines and constraints are created differently
114 _ItemTags.put("L", Line.class.getMethod("setStartItem", pItem));
115 // _ItemTags.put("g", null);
116
117 _ItemTags.put("C", Constraint.class.getMethod("getID",
118 (Class[]) null));
119 // _ItemTags.put("s2", null);
120 } catch (SecurityException e) {
121 // TODO Auto-generated catch block
122 e.printStackTrace();
123 } catch (NoSuchMethodException e) {
124 // TODO Auto-generated catch block
125 e.printStackTrace();
126 }
127 }
128
129 /**
130 * Determines whether a string begins with a KMS tag.
131 *
132 * @param s
133 * a line of text
134 * @return true if s begins with a KMS tag
135 */
136 private static boolean isValidLine(String s) {
137 return s.length() >= 3 && s.charAt(0) == '+' && s.charAt(2) == '+'
138 && Character.isLetter(s.charAt(1));
139 }
140
141 /**
142 * Reads a KMS file with the given name from disk.
143 *
144 * @param frameName
145 * the name of the Frame to read in from a file.
146 * @return A new Frame object that contains any Items described in the file.
147 * @throws IOException
148 * Any exceptions occured by the BufferedReader.
149 */
150 public Frame readFrame(String fullPath) throws IOException {
151 _reader = new BufferedReader(new FileReader(fullPath));
152 Frame newFrame = null;
153 String next = "";
154 boolean header = true;
155 // clear hashmap and line list
156 _data.clear();
157 _linePoints.clear();
158 // First read the header
159 try {
160 while (_reader.ready()) {
161 next = _reader.readLine();
162 if (isValidLine(next)) {
163 if (header) {
164 // Create the frame when the first +S+ is reached
165 // And set the flag to indicate the end of the header
166 if (getTag(next).equals("S")) {
167 newFrame = readFrameClass();
168 header = false;
169 _data.clear();
170 processBodyLine(newFrame, next);
171 } else
172 processHeaderLine(next);
173 } else
174 processBodyLine(newFrame, next);
175 }
176 }
177 } catch (Exception e) {
178 System.out.println("Error reading bodyLine: " + next + " "
179 + e.getMessage());
180 }
181
182 // TODO add in stuff required to process stats
183 // included after the +Z+ etc..
184
185 // if the frame contains no items (Default.0 does this)
186 if (newFrame == null)
187 newFrame = readFrameClass();
188
189 _reader.close();
190
191 if (newFrame != null)
192 newFrame.setChanged(false);
193
194 return newFrame;
195 }
196
197 // stores the data of the Item to be created next
198 private LinkedHashMap<String, String> _data = new LinkedHashMap<String, String>(
199 20);
200
201 // creates an item from the last batch of data read from the file
202 private Item createItem() {
203 // creates an item based on the information in the hashmap
204 try {
205 return readItemClass();
206 } catch (IOException e) {
207 // TODO Auto-generated catch block
208 e.printStackTrace();
209 }
210
211 return null;
212 }
213
214 // Stores points used when constructing lines
215 private HashMap<Integer, Item> _linePoints = new HashMap<Integer, Item>();
216
217 /**
218 * Adds any lines stored in _lineStarts and _lineEnds to the given Frame.
219 *
220 * @param frame
221 * The Frame to add the newly created Line objects to.
222 */
223 private Line createLine() {
224 String s = _data.get("L");
225 _data.remove("L");
226
227 // get the line ID and type
228 java.awt.Point idtype = separateValues(s);
229
230 // get the end points
231 s = _data.get("s");
232 _data.remove("s");
233
234 java.awt.Point startend = separateValues(s);
235
236 int start = startend.x;
237 int end = startend.y;
238
239 if (_linePoints.get(start) != null && _linePoints.get(end) != null) {
240 Line line = new Line(_linePoints.get(start), _linePoints.get(end),
241 idtype.x);
242 return line;
243 }
244
245 System.out.println(_linePoints.size());
246 for (int i : _linePoints.keySet())
247 System.out.println(i + " - "
248 + _linePoints.get(i).getClass().getSimpleName());
249
250 System.out.println("Error: Line " + idtype.x
251 + " has missing end point(s) + (Looking for: " + start + " , "
252 + end + ")");
253 return null;
254 }
255
256 /*
257 * Creates a constraint from the data containted in _data
258 */
259 private void createConstraint() {
260 java.awt.Point idtype = separateValues(_data.get("C"));
261 java.awt.Point startend = separateValues(_data.get("s"));
262
263 Dot a = (Dot) _linePoints.get(startend.x);
264 Dot b = (Dot) _linePoints.get(startend.y);
265
266 new Constraint(a, b, idtype.x, idtype.y);
267 }
268
269 /**
270 * Processes the body section of the KMS file, which contains all Items
271 *
272 * @param frame
273 * The Frame to add any created Items to.
274 * @param line
275 * The line of text read in from the file to process.
276 */
277 private void processBodyLine(Frame frame, String line) {
278 // separate the tag from the value
279 String tag = getTag(line);
280 line = getValue(line);
281
282 // if this is the start of a new item, a line, or a constraint
283 // then add the last item to the frame
284 if (tag.charAt(0) == 'S' || tag.charAt(0) == 'L'
285 || tag.charAt(0) == 'C') {
286 frame.addItem(createItem());
287
288 _data.clear();
289 _data.put(tag, line);
290 return;
291 }
292
293 // if this is the end of the file, then add the last item to the frame
294 if (tag.charAt(0) == 'Z') {
295 frame.addItem(createItem());
296 _data.clear();
297
298 return;
299 }
300
301 // check for duplicate tags (multiple lines of text)
302 String newtag = tag;
303 int i = 0;
304
305 // only executes if there are duplicate tags for this Item
306 while (_data.containsKey(newtag)) {
307 newtag = tag + i;
308 i++;
309 }
310
311 // All values are stored in a HashMap until the end of the Item is
312 // found.
313 _data.put(newtag, line);
314 }
315
316 private static String getTag(String line) {
317 assert (line.charAt(0) == '+');
318 assert (line.length() > 2);
319 return line.substring(1, 2);
320 }
321
322 private static String getValue(String line) {
323 assert (line.charAt(0) == '+');
324 if (line.length() > 4)
325 return line.substring(4);
326 else
327 return "";
328 }
329
330 /**
331 * Reads the header section of the file, which contains information about
332 * the Frame.
333 *
334 * @param frame
335 * The Frame to assign the read values to.
336 * @param line
337 * The line from the file to process.
338 * @return False if the end of the header has been reached, True otherwise.
339 */
340 private void processHeaderLine(String line) throws IOException {
341 // first separate the tag from the text
342 String tag = getTag(line);
343 String value = getValue(line);
344
345 if (tag.equals("Z"))
346 return;
347
348 if (_FrameTags.get(tag) == null) {
349 if (!tag.equals("t") && !tag.equals("v") )
350 FrameGraphics.ErrorMessage("Tag '" + tag + "' in '" + line
351 + "' is not supported.");
352 return;
353 }
354
355 _data.put(tag, value);
356 }
357
358 // returns two ints separated by a space from the given String
359 private java.awt.Point separateValues(String line) {
360 int x = Integer.parseInt(line.substring(0, line.indexOf(" ")));
361 int y = Integer.parseInt(line.substring(line.indexOf(" ") + 1));
362
363 return new java.awt.Point(x, y);
364 }
365
366 private Frame readFrameClass() throws IOException {
367 if (_data.size() == 0) {
368 FrameGraphics.ErrorMessage("IO Error: File contains no valid KMS lines.");
369 return null;
370 }
371
372 Frame toMake = new Frame();
373 Iterator<String> it = _data.keySet().iterator();
374
375 while (it.hasNext()) {
376 String datatag = it.next();
377
378 Method toRun = _FrameTags.get(datatag);
379 Object[] vals = Conversion.Convert(toRun, _data.get(datatag));
380 try {
381 toRun.invoke(toMake, vals);
382 } catch (IllegalArgumentException e) {
383 // TODO Auto-generated catch block
384 e.printStackTrace();
385 } catch (IllegalAccessException e) {
386 // TODO Auto-generated catch block
387 e.printStackTrace();
388 } catch (InvocationTargetException e) {
389 // TODO Auto-generated catch block
390 e.printStackTrace();
391 }
392 }
393
394 return toMake;
395 }
396
397 @SuppressWarnings("unchecked")
398 private Item readItemClass() throws IOException {
399 Iterator<String> tags = _data.keySet().iterator();
400 Class toCreate = null;
401
402 // loop through all attributes read in for this item
403 while (tags.hasNext()) {
404 String next = tags.next();
405 Method m = _ItemTags.get(next);
406 if (m != null && _ItemTags.get(next + "2") == null) {
407 if (!m.getDeclaringClass().getSimpleName().equals("Item")) {
408 toCreate = m.getDeclaringClass();
409 break;
410 }
411 }
412 }
413
414 if (toCreate == null) {
415 if (_data.size() > 0)
416 toCreate = Dot.class;
417 else
418 return null;
419 }
420
421 Item toMake = null;
422
423 try {
424 if (toCreate == Line.class)
425 toMake = createLine();
426 else if (toCreate == Constraint.class) {
427 createConstraint();
428 return null;
429 } else if (toCreate == Item.class && _data.size() == 2) {
430 toCreate = Dot.class;
431 } else if (toCreate == Item.class) {
432 for (String s : _data.keySet())
433 System.out.println(s + " -> " + _data.get(s));
434 return null;
435 } else {
436 Object[] params = { -1 };
437 Constructor con = toCreate.getConstructor(int.class);
438 toMake = (Item) con.newInstance(params);
439 }
440 } catch (InstantiationException e) {
441 // TODO Auto-generated catch block
442 e.printStackTrace();
443 } catch (IllegalAccessException e) {
444 // TODO Auto-generated catch block
445 e.printStackTrace();
446 } catch (IllegalArgumentException e) {
447 // TODO Auto-generated catch block
448 e.printStackTrace();
449 } catch (InvocationTargetException e) {
450 // TODO Auto-generated catch block
451 e.printStackTrace();
452 } catch (SecurityException e) {
453 // TODO Auto-generated catch block
454 e.printStackTrace();
455 } catch (NoSuchMethodException e) {
456 // TODO Auto-generated catch block
457 e.printStackTrace();
458 }
459
460 if (toMake == null)
461 return null;
462
463 Iterator<String> it = _data.keySet().iterator();
464 String last = "";
465
466 int count = 0;
467
468 while (it.hasNext()) {
469 String tag = it.next();
470 if (_data.containsKey("" + tag.charAt(0) + count)) {
471 if (last.length() == 0)
472 last = _data.get(tag);
473 else
474 last += "\n" + _data.get(tag);
475
476 count++;
477 } else {
478 Method toRun = _ItemTags.get("" + tag.charAt(0));
479 if (toRun == null)
480 System.out.println("Error accessing tag method: "
481 + tag.charAt(0));
482 Object[] vals;
483 if (last.length() > 0)
484 vals = Conversion.Convert(toRun, last + "\n"
485 + _data.get(tag));
486 else
487 vals = Conversion.Convert(toRun, _data.get(tag));
488
489 try {
490 if (vals != null)
491 toRun.invoke(toMake, vals);
492 } catch (IllegalArgumentException e) {
493 // TODO Auto-generated catch block
494 e.printStackTrace();
495 } catch (IllegalAccessException e) {
496 // TODO Auto-generated catch block
497 e.printStackTrace();
498 } catch (InvocationTargetException e) {
499 // TODO Auto-generated catch block
500 e.printStackTrace();
501 }
502
503 count = 0;
504 last = "";
505 }
506
507 }
508
509 if (!(toMake instanceof Line))
510 _linePoints.put(toMake.getID(), toMake);
511
512 return toMake;
513 }
514
515 public static int getVersion(String fullpath) {
516 try {
517 BufferedReader reader = new BufferedReader(new FileReader(fullpath));
518 String next = "";
519 // First read the header lines until we get the version number
520 while (reader.ready() && (next = reader.readLine())!= null) {
521 if (isValidLine(next)) {
522 char tag = getTag(next).charAt(0);
523 String value = getValue(next);
524 if (tag == 'V')
525 return Integer.parseInt(value);
526 else if(tag == 'Z')
527 return 0;
528 }
529 }
530 } catch (Exception e) {
531 }
532 return 0;
533 }
534}
Note: See TracBrowser for help on using the repository browser.