source: trunk/src/org/expeditee/io/DefaultTreeWriter.java@ 80

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

Added some more unit tests
Did a bunch of refactoring
AND added a few new features... @b @v were the most significant

File size: 4.1 KB
Line 
1package org.expeditee.io;
2
3import java.io.IOException;
4import java.util.List;
5import java.util.Stack;
6
7import org.expeditee.gui.Frame;
8import org.expeditee.gui.FrameGraphics;
9import org.expeditee.gui.FrameIO;
10import org.expeditee.items.Item;
11import org.expeditee.items.Text;
12
13public abstract class DefaultTreeWriter extends DefaultFrameWriter implements
14 TreeWriter {
15
16 // the list of frames currently being processed
17 private Stack<FrameCounter> _frames = new Stack<FrameCounter>();
18
19 private int _frameCount = 0;
20
21 public int getFrameCount() {
22 return _frameCount;
23 }
24
25 public String writeTree(Frame toWrite) throws IOException {
26 try {
27 initialise(toWrite);
28 outputTree(toWrite);
29
30 } catch (IOException ioe) {
31 _running = false;
32 throw ioe;
33 } catch (Exception e) {
34 e.printStackTrace();
35 }
36 _running = false;
37 return finaliseTree();
38 }
39
40 /**
41 * This method is used to output any tags before following the Item's link
42 * when using tree writers.
43 *
44 * @param linker
45 * The linked Item that is about to be followed.
46 * @throws IOException
47 */
48 protected void writeStartLink(Item linker) throws IOException {
49
50 }
51
52 /**
53 * This method is called after the Frame the Item links to has been
54 * processed. This allows end tags to be written if the format requires it.
55 *
56 * @param linker
57 * The Item whose link was just followed.
58 * @throws IOException
59 */
60 protected void writeEndLink(Item linker) throws IOException {
61
62 }
63
64 protected void resumeFrame(Frame resuming) {
65 }
66
67 protected void outputTree(Frame toWrite) throws IOException {
68 if (toWrite == null)
69 return;
70
71 _frames.push(new FrameCounter(toWrite.getName(), -1));
72
73 // process the entire tree of frames in depth-first order
74 while (_frames.size() > 0) {
75 FrameCounter cur = _frames.pop();
76
77 if (_stop)
78 return;
79
80 Frame next = FrameIO.LoadFrame(cur.frame);
81 if (next == null) {
82 return;
83 }
84
85 // the items on the frame currently being processed.
86 List<Item> items = next.getItems();
87
88 // write any information relating to the end of the link
89 if (cur.index > 0) {
90 this.writeEndLink(items.get(cur.index));
91 this.resumeFrame(next);
92 } else {
93 FrameGraphics.OverwriteMessage("Writing: " + next.getName());
94 _frameCount++;
95 writeStartFrame(next);
96 }
97
98 boolean complete = true;
99
100 // resume from the next item in the list
101 for (int i = cur.index + 1; i < items.size(); i++) {
102 if (_stop)
103 return;
104
105 Item item = items.get(i);
106
107 // ignore annotation and framenames
108 if (item.getID() >= 0) {
109 //Only follow the links of text items
110 if (item instanceof Text && item.getLink() != null
111 && !item.isAnnotation()) {
112 cur.index = i;
113 _frames.push(cur);
114
115 // write any information relating to the start of the
116 // link
117 this.writeStartLink(item);
118
119 Frame linked = FrameIO
120 .LoadFrame(item.getAbsoluteLink());
121
122 // if the linked frame was found, then display it next
123 if (linked != null) {
124 FrameCounter fc = new FrameCounter(
125 linked.getName(), -1);
126 if (!_frames.contains(fc)) {
127 // remember what frame we are on before
128 // processing it
129 _frames.push(fc);
130
131 complete = false;
132 // process the loaded frame immediately
133 // (depth-first)
134 break;
135 }
136 }
137 // Dont write out the title here because it is written
138 // out earlier
139 } else if (item != next.getTitleItem())
140 this.writeItem(item);
141 }
142 }
143
144 if (complete)
145 writeEndFrame(next);
146 }
147 }
148
149 protected String finaliseTree() throws IOException {
150 return "Tree" + finalise();
151 }
152
153 /**
154 * Inner class used to keep track of what frames have been seen, as well as
155 * what Item in the Frame the processing was up to. Only Frame names are
156 * stored to keep memory usage down.
157 */
158 private class FrameCounter {
159 public int index;
160
161 public String frame;
162
163 public FrameCounter(String f, int i) {
164 frame = f.toLowerCase();
165 index = i;
166 }
167
168 @Override
169 public boolean equals(Object o) {
170 if (o instanceof FrameCounter)
171 return (((FrameCounter) o).frame.equals(frame));// && fc.index
172 // == index);
173
174 return false;
175 }
176 }
177}
Note: See TracBrowser for help on using the repository browser.