package nota.oxygen.epub.notes;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import nota.oxygen.epub.EpubUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import de.schlichtherle.truezip.file.TArchiveDetector;
import de.schlichtherle.truezip.file.TConfig;
import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.fs.archive.zip.JarDriver;
import de.schlichtherle.truezip.socket.sl.IOPoolLocator;
@SuppressWarnings("serial")
public class NoteRefInserter extends JPanel implements ActionListener, PropertyChangeListener {
private static JFrame frame;
private JButton startButton;
private JTextArea taskOutput;
private Task task;
private static String fileName;
private File[] listOfFiles;
private static FindNoteRefHandler findNoteRefHandler;
public static boolean ERRORS_FOUND;
class Task extends SwingWorker<Void, Void> {
@Override
protected Void doInBackground() throws Exception {
if (!EpubUtils.start(taskOutput))
return null;
if (!EpubUtils.unzip(taskOutput))
return null;
if (!EpubUtils.backup(taskOutput))
return null;
EpubUtils.outputProcess("PREPARING AND PARSING", true, taskOutput);
// get all files where noterefs can be found
listOfFiles = EpubUtils.getFiles(false, false);
findNoteRefHandler = new FindNoteRefHandler();
for (File file : listOfFiles) {
String fileName = file.getName();
if (fileName.endsWith("-footnotes.xhtml") || fileName.endsWith("-rearnotes.xhtml")) {
continue;
}
// prepare source file
if (!EpubUtils.prepareFile(file, taskOutput))
return null;
// set source filename
findNoteRefHandler.setFileName(file.getName());
// parse source file
if (!EpubUtils.parseFile(file, findNoteRefHandler, taskOutput))
return null;
}
if (findNoteRefHandler.getIDMap().size() == 0 || findNoteRefHandler.getFNMap().size() == 0) {
EpubUtils.outputMessage(taskOutput, "Cannot insert noterefs, zero found");
return null;
}
if (findNoteRefHandler.getFNMap().size() != findNoteRefHandler.getFNMap().size()) {
EpubUtils.outputMessage(taskOutput, "Cannot insert noterefs, mismatch between ids and filenames");
return null;
}
EpubUtils.outputProcess("ADDING NOTEREFS TO DOCUMENT", true, taskOutput);
Document doc = EpubUtils.createDocument(new File(EpubUtils.EPUB_FOLDER + File.separator + fileName), taskOutput);
if (doc == null) {
return null;
}
NodeList liNodeList = doc.getDocumentElement().getElementsByTagName("li");
for (int i=0; i<liNodeList.getLength(); i++) {
Element liElement = (Element) liNodeList.item(i);
NodeList pNodeList = liElement.getElementsByTagName("p");
String id = liElement.getAttribute("id");
if (id == null || id.equals("")) {
EpubUtils.outputMessage(taskOutput, "Cannot insert noteref to list element " + liElement.getTextContent() + ", id not found");
ERRORS_FOUND = true;
continue;
}
String epubType = liElement.getAttribute("epub:type");
if (epubType == null || epubType.equals("")) {
EpubUtils.outputMessage(taskOutput, "Cannot insert noteref to list element with id " + id + ", epub:type not found");
ERRORS_FOUND = true;
continue;
}
if (!epubType.equals("footnote") && !epubType.equals("rearnote")) {
EpubUtils.outputMessage(taskOutput, "Cannot insert noteref to list element with id " + id + ", epub:type should be either footnote or rearnote");
ERRORS_FOUND = true;
continue;
}
List<String> idList = findNoteRefHandler.getIDMap().get(id);
List<String> fnList = findNoteRefHandler.getFNMap().get(id);
if (pNodeList.getLength() == 0) {
NodeList aNodeList = liElement.getElementsByTagName("a");
System.out.println("notes: " + aNodeList.getLength());
Set<Node> removeNodes = new HashSet<Node>();
for (int j = 0; j < aNodeList.getLength(); j++) {
removeNodes.add(aNodeList.item(j));
}
for (Node node : removeNodes) {
System.out.println("removing node with href " + ((Element)node).getAttribute("href"));
liElement.removeChild(node);
}
if (aNodeList.getLength() == 0) {
for (int j=0; j<idList.size(); j++) {
Element aElement = doc.createElement("a");
aElement.setAttribute("class", "noteref");
aElement.setAttribute("epub:type", "noteref");
aElement.setAttribute("href", fnList.get(j) + "#" + idList.get(j));
aElement.setTextContent("*");
liElement.appendChild(aElement);
System.out.println("appended note with href " + fnList.get(j) + "#" + idList.get(j));
}
}
} else if (pNodeList.getLength() == 1) {
Element pElement = (Element) pNodeList.item(0);
NodeList aNodeList = pElement.getElementsByTagName("a");
System.out.println("notes: " + aNodeList.getLength());
Set<Node> removeNodes = new HashSet<Node>();
for (int j = 0; j < aNodeList.getLength(); j++) {
removeNodes.add(aNodeList.item(j));
}
for (Node node : removeNodes) {
System.out.println("removing node with href " + ((Element)node).getAttribute("href"));
pElement.removeChild(node);
}
if (aNodeList.getLength() == 0) {
for (int j=0; j<idList.size(); j++) {
Element aElement = doc.createElement("a");
aElement.setAttribute("class", "noteref");
aElement.setAttribute("epub:type", "noteref");
aElement.setAttribute("href", fnList.get(j) + "#" + idList.get(j));
aElement.setTextContent("*");
pElement.appendChild(aElement);
System.out.println("appended note with href " + fnList.get(j) + "#" + idList.get(j));
}
}
} else {
EpubUtils.outputMessage(taskOutput, "Cannot insert noteref to list element, too many paragraphs");
ERRORS_FOUND = true;
continue;
}
}
if (!EpubUtils.saveDocument(doc, new File(EpubUtils.EPUB_FOLDER + File.separator + fileName), taskOutput))
return null;
EpubUtils.outputProcess("MODIFYING EPUB", true, taskOutput);
// obtain the global configuration
TConfig config = TConfig.get();
config.setArchiveDetector(new TArchiveDetector("epub", new JarDriver(IOPoolLocator.SINGLETON)));
// get epub file destination
String epubPath = EpubUtils.EPUB.getPath();
String epubFolder = EpubUtils.EPUB_FOLDER.substring(EpubUtils.EPUB_FOLDER.lastIndexOf(File.separator)).replace(File.separator, "");
TFile destination = new TFile(epubPath + File.separator + epubFolder);
// modify epub file destination
for (File file : listOfFiles) {
if (!EpubUtils.addFileToEpub(new TFile(file), destination, taskOutput))
return null;
}
// commit changes to epub file destination
if (!EpubUtils.commitChanges(taskOutput))
return null;
if (!EpubUtils.finish(taskOutput))
return null;
return null;
}
@Override
public void done() {
Toolkit.getDefaultToolkit().beep();
startButton.setEnabled(true);
setCursor(null);
EpubUtils.outputMessage(taskOutput, "Done");
}
}
public NoteRefInserter() {
super(new BorderLayout());
// Create the demo's UI.
startButton = new JButton("Start");
startButton.setActionCommand("start");
startButton.addActionListener(this);
startButton.setVisible(false);
taskOutput = new JTextArea(30, 130);
taskOutput.setMargin(new Insets(5, 5, 5, 5));
taskOutput.setEditable(false);
JPanel panel = new JPanel();
panel.add(startButton);
add(panel, BorderLayout.PAGE_START);
add(new JScrollPane(taskOutput), BorderLayout.CENTER);
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
startButton.doClick();
}
@Override
public void propertyChange(PropertyChangeEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void actionPerformed(ActionEvent e) {
startButton.setEnabled(false);
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
this.task = new Task();
this.task.addPropertyChangeListener(this);
this.task.execute();
}
private static void createAndShowGUI() {
JComponent newContentPane = new NoteRefInserter();
newContentPane.setOpaque(true);
frame = new JFrame("Inserting noterefs into " + fileName);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
EpubUtils.EPUB = new File(args[0]);
EpubUtils.EPUB_FOLDER = args[1];
EpubUtils.prepare("noterefinserter", "noterefinsert");
fileName = args[2];
// Schedule a job for the event-dispatching thread: creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}