/**
* DefaultTreeWriter.java
* Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.expeditee.io;
import java.io.IOException;
import java.util.List;
import java.util.Stack;
import org.expeditee.gui.Frame;
import org.expeditee.gui.FrameIO;
import org.expeditee.gui.MessageBay;
import org.expeditee.io.flowlayout.XGroupItem;
import org.expeditee.items.Item;
import org.expeditee.items.Text;
public abstract class DefaultTreeWriter extends DefaultFrameWriter implements
TreeWriter {
private int _indent = 0;
// the list of frames currently being processed
private Stack _frames = new Stack();
private int _frameCount = 0;
public int getFrameCount() {
return _frameCount;
}
public String writeTree(Frame toWrite) throws IOException {
try {
initialise(toWrite);
outputTree(toWrite);
} catch (IOException ioe) {
_running = false;
throw ioe;
} catch (Exception e) {
e.printStackTrace();
}
_running = false;
return finaliseTree();
}
/**
* This method is used to output any tags before following the Item's link
* when using tree writers.
*
* @param linker
* The linked Item that is about to be followed.
* @throws IOException
*/
protected void writeStartLink(Item linker) throws IOException {
_indent++;
}
/**
* This method is called after the Frame the Item links to has been
* processed. This allows end tags to be written if the format requires it.
*
* @param linker
* The Item whose link was just followed.
* @throws IOException
*/
protected void writeEndLink(Item linker) throws IOException {
_indent--;
}
protected void resumeFrame(Frame resuming) {
}
protected List- getSortedItems(Frame frame)
{
List
- items = frame.getItems();
return items;
}
protected void outputTree(Frame toWrite) throws IOException {
if (toWrite == null) {
return;
}
XGroupItem.doImplicitBoxing = false;
_frames.push(new FrameCounter(toWrite.getName(), -1));
// process the entire tree of frames in depth-first order
while (_frames.size() > 0) {
FrameCounter cur = _frames.pop();
if (_stop)
return;
Frame next = FrameIO.LoadFrame(cur.frame);
if (next == null) {
return;
}
Text title = next.getTitleItem();
// the items on the frame currently being processed.
List
- items = getSortedItems(next);
// write any information relating to the end of the link
if (cur.index > 0) {
this.writeEndLink(items.get(cur.index));
this.resumeFrame(next);
} else {
MessageBay.overwriteMessage("Writing: " + next.getName());
_frameCount++;
writeStartFrame(next);
}
boolean complete = true;
// resume from the next item in the list
for (int i = cur.index + 1; i < items.size(); i++) {
if (_stop)
return;
Item item = items.get(i);
// ignore annotation and framenames
if (item.getID() >= 0) {
// Only follow the links of non annotation text items
boolean followLink = item instanceof Text
&& item.getLink() != null
&& (!item.isAnnotation() /*|| item.getText()
.toLowerCase().equals("@next")*/);
if (followLink) {
cur.index = i;
_frames.push(cur);
// write any information relating to the start of the
// link
this.writeStartLink(item);
Frame linked = FrameIO
.LoadFrame(item.getAbsoluteLink());
// if the linked frame was found, then display it next
if (linked != null) {
FrameCounter fc = new FrameCounter(
linked.getName(), -1);
if (!_frames.contains(fc)) {
// remember what frame we are on before
// processing it
_frames.push(fc);
complete = false;
// process the loaded frame immediately
// (depth-first)
break;
}
}
// Don't write out the title here because it is written
// out earlier
} else if (item != title)
this.writeItem(item);
}
}
if (complete)
writeEndFrame(next);
}
}
protected String finaliseTree() throws IOException {
return "Tree" + finalise();
}
/**
* Inner class used to keep track of what frames have been seen, as well as
* what Item in the Frame the processing was up to. Only Frame names are
* stored to keep memory usage down.
*/
private class FrameCounter {
public int index;
public String frame;
public FrameCounter(String f, int i) {
frame = f.toLowerCase();
index = i;
}
@Override
public boolean equals(Object o) {
if (o instanceof FrameCounter)
return (((FrameCounter) o).frame.equals(frame));// && fc.index
// == index);
return false;
}
}
protected int getIndent() {
return _indent;
}
}