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

Last change on this file since 919 was 919, checked in by jts21, 10 years ago

Added license headers to all files, added full GPL3 license file, moved license header generator script to dev/bin/scripts

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