/** * ExpWriter.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.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.lang.reflect.Method; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import org.expeditee.agents.DefaultAgent; import org.expeditee.gui.Frame; import org.expeditee.items.Constraint; import org.expeditee.items.Item; import org.expeditee.items.Line; import org.expeditee.items.widgets.WidgetEdge; import org.expeditee.stats.SessionStats; /** * Writes a Frame out to a Expeditee format file. * * @author jdm18 * */ public class ExpWriter extends DefaultFrameWriter { protected ProxyWriter _writer = null; protected StringBuilder _stringWriter = null; protected String _framename; protected static final char TERMINATOR = 'Z'; public ExpWriter() { super(); } @Override public void initialise(Frame start, Writer writer) throws IOException { _framename = start.getName(); String name = start.getFramesetName().toLowerCase(); if (_filename == null) _filename = start.getPath() + name + File.separator + start.getNumber() + ExpReader.EXTENTION; _stringWriter = new StringBuilder(); if (writer != null) { _writer = new ProxyWriter(writer); _output = writer.toString(); } else if (_filename.equalsIgnoreCase(DefaultAgent.CLIPBOARD)) { _writer = new ProxyWriter(true); _filename = DefaultAgent.CLIPBOARD; } else { // Open an Output Stream Writer to set encoding OutputStream fout = new FileOutputStream(_filename); OutputStream bout = new BufferedOutputStream(fout); Writer out = new OutputStreamWriter(bout, "UTF-8"); _writer = new ProxyWriter(out); } try { _FrameTags.remove('A'); getItemCharTags().put('S', Item.class.getMethod("getTypeAndID", new Class[] {})); } catch (Exception e) { } } /** * Writes the given Frame (and all items it contains) to a Expeditee file. * Note: File path and location must be set before calling this or it will * do nothing. * * @param frame * The Frame to write out to the file. * @throws IOException * Any exceptions occured by the BufferedWriter. */ public void outputFrame(Frame frame) throws IOException { if (_writer == null) return; preOutputFrame(); writeHeader(frame); // write each item in the frame for (Item i : frame.getItemsToSave()) { assert (!(i instanceof Line)); writeItem(i); } for (final Item i: frame.getBodyItemsWithInsufficientPermissions()) { assert (!(i instanceof Line)); writeItem(i); } // write any lines or constraints writeTerminator(); writeLineData(); writeTerminator(); writeConstraintData(); writeTerminator(); writeLine(SessionStats.getFrameEventList(frame)); } protected void preOutputFrame() { } protected void writeHeader(Frame toWrite) throws IOException { Iterator it = _FrameTags.keySet().iterator(); Object[] param = {}; while (it.hasNext()) { Character tag = it.next(); try { Object o = _FrameTags.get(tag).invoke(toWrite, param); o = Conversion.ConvertToExpeditee(_FrameTags.get(tag), o); if (o != null) { if (o instanceof List) { for (Object line: (List) o) { writeLine(tag.toString(), line.toString()); } } else { writeLine(tag.toString(), o.toString()); } } } catch (Exception e) { e.printStackTrace(); } } writeTerminator(); } // while (it.hasNext()) { // Character tag = it.next(); // Method toRun = _ItemTags.get(tag); // Class declarer = toRun.getDeclaringClass(); // if (declarer.isAssignableFrom(toWrite.getClass())) { // try { // Object o = toRun.invoke(toWrite, param); // o = Conversion.ConvertToExpeditee(toRun, o); // if (o != null) { // if (o instanceof List) { // for (Object line : (List) o) { // writeLine(tag.toString(), line.toString()); // } // } else // writeLine(tag.toString(), o.toString()); // } // } catch (Exception e) { // e.printStackTrace(); // } // } // } protected void writeLine(String tag, String line) throws IOException { writeLine(tag + " " + line); } protected void writeTerminator() throws IOException { writeLine(TERMINATOR + "\n"); } // writes the given line out to the file protected void writeLine(String line) throws IOException { // do not write empty lines if (line == null) return; String toWrite = line + "\n"; _writer.write(toWrite); _stringWriter.append(toWrite); } // writes the given Item out to the file // This method is not used to write out LINE items public void writeItem(Item item) throws IOException { if (_writer == null) return; writeItemAlways(item); } protected void writeItemAlways(Item item) throws IOException { if (item.isLineEnd()) writeLineEnd(item); else if (!(item instanceof Line)) writeClass(item); // lines are saved at the end of the file // So dont worry about them in here // else // System.out.println("Unknown Item: " + item.getID() + " (" + item.getClass().getName() + ")"); writeLine(""); } protected List _lineEnds = new LinkedList(); // Writes out a LineEnd to the file protected void writeLineEnd(Item point) throws IOException { _lineEnds.add(point); writeClass(point); } // writes out all lines to the file protected void writeLineData() throws IOException { List seen = new LinkedList(); // loop through all points stored for (int i = 0; i < _lineEnds.size(); i++) { List lines = _lineEnds.get(i).getLines(); // if this point is part of one or more lines if (lines != null && lines.size() > 0) { for (Line line : lines) { // Brook: widget edges are not saved if (line instanceof WidgetEdge) { seen.add(line); continue; } // only output new lines that have not yet been output if (!seen.contains(line)) { writeLine("L", line.getID() + " " + line.getLineType()); writeLine("s", line.getLineEnds()); writeLine(""); // add this line to the list of lines that have been // seen seen.add(line); } } } } } // writes out any constraints to the file protected void writeConstraintData() throws IOException { // outputs any constraints the points have // loop through all the points while (_lineEnds.size() > 0) { Item i = _lineEnds.get(0); // if there are any constraints to write if (i.getConstraints() != null) { List constraints = i.getConstraints(); // do not write constraints that have already been // written for (Constraint c : constraints) { if (_lineEnds.contains(c.getStart()) && _lineEnds.contains(c.getEnd())) { writeLine("C", c.getID() + " " + c.getType()); writeLine("s", c.getLineEnds()); writeLine(""); } } } // remove the point from the list _lineEnds.remove(0); } } @Override protected String finaliseFrame() throws IOException { _writer.flush(); _writer.close(); _writer = null; return "Frame successfully written to " + _filename; } protected void writeClass(Item toWrite) throws IOException { writeTags(toWrite, new Object[] {}, getItemCharTags()); writeTags(toWrite, new Object[] {}, getItemStrTags()); } protected void writeTags(Item toWrite, Object[] param, LinkedHashMap tags) { Iterator it = tags.keySet().iterator(); while (it.hasNext()) { T tag = it.next(); writeTag(toWrite, param, tags, tag); } } protected void writeTag(Item toWrite, Object[] param, LinkedHashMap tags, T tag) { Method toRun = tags.get(tag); Class declarer = toRun.getDeclaringClass(); if (declarer.isAssignableFrom(toWrite.getClass())) { try { Object o = toRun.invoke(toWrite, param); o = Conversion.ConvertToExpeditee(toRun, o); if (o != null) { if (o instanceof List) { for (Object line : (List) o) { writeLine(tag.toString(), line.toString()); } } else writeLine(tag.toString(), o.toString()); } } catch (Exception e) { e.printStackTrace(); } } } /** * Gets a string representation of the frame file contents. */ public String getFileContents() { return _stringWriter.toString(); } }