source: trunk/org/expeditee/io/KMSReader.java@ 4

Last change on this file since 4 was 4, checked in by davidb, 16 years ago

Starting source code to Expeditee

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