The method for calling xml2brl is now in LiblouisXML.java: https://odt2braille.svn.sourceforge.net/svnroot/odt2braille/Odt2Braille/src/be/docarch/odt2braille/LiblouisXML.java
It works for both Windows and Mac OS. Bert On 16/12/2010 15:51, John J. Boyer wrote:
First, my server is back up. We're tying up the loose ends. Below is the Odt2Braille.java class from the odt2braille plugin for OpenOffi e. It calls xml2brl with RunTime.exec We could easily modify it to call file2brl Because of the server problems I haven't yet read the tutorial that Susan suggested. What do you think of the following? Search for the word execute to find the method that does the actual work. ---------------------- /** * odt2braille - Braille authoring in OpenOffice.org. * * Copyright (c) 2010 by DocArch<http://www.docarch.be>. * * 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<http://www.gnu.org/licenses/>. */ package be.docarch.odt2braille; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.BufferedWriter; import java.io.Writer; import java.io.FileWriter; import java.util.logging.Logger; import java.util.logging.Level; import java.io.File; import java.util.ArrayList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.Element; import org.w3c.dom.DOMImplementation; import org.w3c.dom.ProcessingInstruction; import java.io.FileInputStream; import org.apache.commons.io.IOUtils; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.Locale; import java.util.ResourceBundle; import javax.xml.namespace.NamespaceContext; import net.sf.saxon.TransformerFactoryImpl; import javax.xml.transform.Transformer; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.OutputKeys; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import org.xml.sax.SAXException; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import com.versusoft.packages.jodl.OdtUtils; import org_pef_text.AbstractTable; import org_pef_text.TableFactory; import org_pef_text.TableFactory.TableType; /** * This class provides a way to convert a flat .odt file to a *<a href="http://www.daisy.org/projects/braille/braille_workarea/pef.html";>.pef (portable embosser format)</a> file. * The conversion is done according to previously defined braille {@link Settings}. *<code>liblouisxml</code> is used for the actual transcription to braille. * A {@link Checker} checks the resulting braille document for possible accessibility issues. * * @see<a href="http://code.google.com/p/liblouisxml/";><code>liblouisxml</code></a> * @author Bert Frees */ public class Odt2Braille { private final static Logger logger = Logger.getLogger("be.docarch.odt2braille.addone"); private static NamespaceContext namespace = new Odt2BrailleNamespaceContext(); private final static boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("windows"); private static final String LIBLOUIS_EXEC_NAME = "xml2brl"; private final static String LIBLOUIS_EXEC_EXT = IS_WINDOWS?".exe":""; private static final String TMP_NAME = "odt2braille"; private final static String DAISY_EXT = ".xml"; private final static String BRAILLE_EXT = ".txt"; private final static String CONFIG_EXT = ".cfg"; public enum TranscribersNote { IMAGES_NOT_REPRODUCED }; public enum VolumeType { NORMAL, PRELIMINARY, SUPPLEMENTARY, NONE }; private static String L10N_statusIndicatorStep = null; private String liblouisDirUrl = null; private String brailleUrl = null; private String daisyUrl = null; private File brailleFile = null; private File daisyFile = null; private File stylesFile = null; private File chardefsFile = null; private File tempChardefsFile = null; private Odt2Daisy odt2daisy; private Settings settings = null; private StatusIndicator statusIndicator = null; private Checker checker = null; private ArrayList configurationList = new ArrayList(); AbstractTable liblouisTable = new TableFactory().newTable(TableType.LIBLOUIS); /** * Creates a new<code>Odt2Braille</code> instance. * The {@link Locale} for the user interface is set to the default value. * * @param flatOdtFile The "flat XML" .odt file. * This single file is the concatenation of all XML files in a normal .odt file. * @param liblouisDirUrl The URL of the<code>liblouis</code> executable. * @param settings The<code>Settings</code> that determine how the conversion is done. * @param statusIndicator The<code>StatusIndicator</code> that will be used. * @param checker The<code>Checker</code> that will check the braille document for possible accessibility issues. * @param odtLocale The<code>Locale</code> for the document. */ public Odt2Braille(File flatOdtFile, String liblouisDirUrl, Settings settings, StatusIndicator statusIndicator, Checker checker, Locale odtLocale) throws IOException, ParserConfigurationException, SAXException, TransformerConfigurationException, TransformerException{ this(flatOdtFile, liblouisDirUrl, settings, statusIndicator, checker, odtLocale, Locale.getDefault()); } /** * Creates a new<code>Odt2Braille</code> instance. * * @param flatOdtFile The "flat XML" .odt file. * This single file is the concatenation of all XML files in a normal .odt file. * @param liblouisDirUrl The URL of the liblouis executable. liblouis is used for the actual transcription to braille. * @param statusIndicator The<code>StatusIndicator</code> that will be used. * @param settings The<code>Settings</code> that determine how the conversion is done. * @param checker The<code>Checker</code> that will check the braille document for possible accessibility issues. * @param odtLocale The<code>Locale</code> for the document. * @param oooLocale The<code>Locale</code> for the user interface. */ public Odt2Braille(File flatOdtFile, String liblouisDirUrl, Settings settings, StatusIndicator statusIndicator, Checker checker, Locale odtLocale, Locale oooLocale) throws IOException, ParserConfigurationException, SAXException, TransformerConfigurationException, TransformerException { logger.entering("Odt2Braille", "<init>"); this.settings = settings; this.liblouisDirUrl = liblouisDirUrl; this.statusIndicator = statusIndicator; this.checker = checker; L10N_statusIndicatorStep = ResourceBundle.getBundle("be/docarch/odt2braille/l10n/Bundle", oooLocale).getString("statusIndicatorStep"); // Request temporary liblouisxml braille file brailleFile = File.createTempFile(TMP_NAME,BRAILLE_EXT); brailleFile.deleteOnExit(); brailleUrl = brailleFile.getAbsolutePath(); // Request temporary daisy xml file daisyFile = File.createTempFile(TMP_NAME,DAISY_EXT); daisyFile.deleteOnExit(); daisyUrl = daisyFile.getAbsolutePath(); // Create odt2daisy odt2daisy = new Odt2Daisy(flatOdtFile, settings, this.statusIndicator, odtLocale, oooLocale); odt2daisy.preProcessing(); chardefsFile = new File(liblouisDirUrl + "share" + System.getProperty("file.separator") + "liblouis" + System.getProperty("file.separator") + "tables" + System.getProperty("file.separator") + "_chardefs.cti"); tempChardefsFile = File.createTempFile(TMP_NAME, ".xml"); tempChardefsFile.deleteOnExit(); stylesFile = File.createTempFile(TMP_NAME,CONFIG_EXT); stylesFile.deleteOnExit(); createStylesFile(); } private void createStylesFile() throws IOException { logger.entering("Odt2Braille", "createStylesFile"); // Create temporary styles file Writer bufferedWriter = new BufferedWriter(new FileWriter(stylesFile)); String sep = System.getProperty("line.separator"); String s = null; // Paragraphs s = "firstLineIndent " + (settings.getFirstLineMargin("paragraph") - settings.getRunoversMargin("paragraph")) + sep + "leftMargin " + settings.getRunoversMargin("paragraph") + sep + "linesBefore " + settings.getLinesAbove("paragraph") + sep + "linesAfter " + settings.getLinesBelow("paragraph") + sep + "format " + (settings.getCentered("paragraph")?"centered":"leftJustified") + sep; bufferedWriter.write("style para" + sep + s); // Headings for (int i=1;i<=4;i++) { s = "firstLineIndent " + (settings.getFirstLineMargin("heading" + i) - settings.getRunoversMargin("heading" + i)) + sep + "leftMargin " + settings.getRunoversMargin("heading" + i) + sep + "linesBefore " + 0 + sep + "linesAfter " + 0 + sep + "format " + (settings.getCentered("heading" + i)?"centered":"leftJustified") + sep; bufferedWriter.write("style heading" + i + sep + s); bufferedWriter.write("style dummyheading" + i + sep + s); s = "linesBefore " + settings.getLinesAbove("heading" + i) + sep + "linesAfter " + settings.getLinesBelow("heading" + i) + sep; bufferedWriter.write("style heading" + i + "container" + sep + s); } // Lists for (int i=1;i<=10;i++) { s = "linesBefore " + settings.getLinesAbove("list" + i) + sep + "linesAfter " + settings.getLinesBelow("list" + i) + sep; bufferedWriter.write("style list" + i + sep + s); s = "linesAfter " + settings.getLinesBetween("list" + i) + sep; bufferedWriter.write("style li" + i + sep + s); s = "firstLineIndent " + (settings.getFirstLineMargin("list" + i) - settings.getRunoversMargin("list" + i)) + sep + "leftMargin " + settings.getRunoversMargin("list" + i) + sep + "format " + (settings.getCentered("list" + i)?"centered":"leftJustified") + sep; bufferedWriter.write("style listitem" + i + sep + s); } for (int i=2;i<=10;i++) { s = "linesBefore " + settings.getLinesAbove("list" + i) + sep; bufferedWriter.write("style lastlist" + i + sep + s); } // Tables s = "linesBefore " + settings.getLinesAbove("table") + sep + "linesAfter " + settings.getLinesBelow("table") + sep; bufferedWriter.write("style tablenoborder" + sep + s); bufferedWriter.write("style lasttablerow" + sep); if (settings.stairstepTableIsEnabled()) { for (int i=1;i<=10;i++) { s = "firstLineIndent " + (settings.getFirstLineMargin("table" + i) - settings.getRunoversMargin("table" + i)) + sep + "leftMargin " + settings.getRunoversMargin("table" + i) + sep + "format " + (settings.getCentered("table" + i)?"centered":"leftJustified") + sep; bufferedWriter.write("style tablecolumn" + i + sep + s); } s = ""; } else { s = "firstLineIndent " + (settings.getFirstLineMargin("table") - settings.getRunoversMargin("table")) + sep + "leftMargin " + settings.getRunoversMargin("table") + sep + "format " + (settings.getCentered("table")?"centered":"leftJustified") + sep; bufferedWriter.write(s); } s += "linesAfter " + settings.getLinesBetween("table") + sep; bufferedWriter.write("style tablerow" + sep + s); // Pagenumbers bufferedWriter.write("style document" + sep + "braillePageNumberFormat " + (settings.getBraillePageNumbers()?"normal": "blank") + sep); bufferedWriter.write("style preliminary" + sep + "braillePageNumberFormat " + (settings.getBraillePageNumbers()?settings.getPreliminaryPageFormat():"blank") + sep); // Table of contents s = "firstLineIndent " + (settings.getFirstLineMargin("heading1") - settings.getRunoversMargin("heading1")) + sep + "leftMargin " + settings.getRunoversMargin("heading1") + sep + "linesBefore " + settings.getLinesAbove("heading1") + sep + "linesAfter " + settings.getLinesBelow("heading1") + sep + "format " + (settings.getCentered("heading1")?"centered":"leftJustified") + sep; bufferedWriter.write("style contentsheader" + sep + s); for (int i=1;i<=4;i++) { s = "firstLineIndent " + (settings.getFirstLineMargin("toc" + i) - settings.getRunoversMargin("toc" + i)) + sep + "leftMargin " + settings.getRunoversMargin("toc" + i) + sep /* + "linesAfter " + settings.getLinesBetween("toc") + sep */ + "format " + "contents" + sep; bufferedWriter.write("style contents" + i + sep + s); } bufferedWriter.close(); logger.exiting("Odt2Braille", "createStylesFile"); } private void createChardefsFile(File daisyFile) throws IOException, TransformerConfigurationException, TransformerException { logger.entering("Odt2Braille", "createChardefsFile"); File newChardefsFile = File.createTempFile(TMP_NAME, ".cti"); TransformerFactoryImpl tFactory = new net.sf.saxon.TransformerFactoryImpl(); Transformer unicodeBlocksTransformer = tFactory.newTransformer(new StreamSource(getClass().getResource("/be/docarch/odt2braille/unicodeblocks.xsl").toString())); Writer bufferedWriter = new BufferedWriter(new FileWriter(newChardefsFile)); unicodeBlocksTransformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); unicodeBlocksTransformer.setOutputProperty(OutputKeys.METHOD, "xml"); unicodeBlocksTransformer.setOutputProperty(OutputKeys.INDENT, "yes"); unicodeBlocksTransformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount";, "3"); unicodeBlocksTransformer.transform(new StreamSource(daisyFile), new StreamResult(tempChardefsFile)); bufferedWriter.write("include _chardefs_unicode_BRAILLE_PATTERNS.cti" + System.getProperty("line.separator") // First table should be BRAILLE_PATTERNS + "include _chardefs_unicode_BASIC_LATIN.cti" + System.getProperty("line.separator") + "include _chardefs_unicode_LATIN_1_SUPPLEMENT.cti" + System.getProperty("line.separator") + "include _chardefs_unicode_PRIVATE_USE_AREA.cti" + System.getProperty("line.separator")); String s = null; for (int i=1; i<=XPathUtils.evaluateNumber(tempChardefsFile.toURL().openStream(), "count(/unicodeblocks/block)"); i++) { s = XPathUtils.evaluateString(tempChardefsFile.toURL().openStream(), "/unicodeblocks/block[" + i + "]/@name"); if (s != null) { s = "include _chardefs_unicode_" + s + ".cti"; bufferedWriter.write(s + System.getProperty("line.separator")); logger.log(Level.INFO, s); } } bufferedWriter.close(); if (chardefsFile.exists()) { chardefsFile.delete(); } newChardefsFile.renameTo(chardefsFile); logger.exiting("Odt2Braille", "createChardefsFile"); } /** * Converts the flat .odt filt to a .pef file according to the braille settings. * * This function *<ul> *<li>makes calls to {@link Odt2Daisy}.<code>convertAsDTBook</code> to convert the .odt file to multiple DAISY-like xml files,</li> *<li>uses<code>liblouisxml</code> to translate these files into braille, and</li> *<li>recombines these braille files into one single .pef file.</li> *</ul> * * First, the document<i>body</i> is processed and split in volumes, then the<i>page ranges</i> are calculated * and finally the<i>preliminary pages</i> of each volume are processed and inserted at the right places. * The checker checks the DAISY-like files and the volume lengths. * * When a multi-volume feature is added to liblouisxml, this procedure of pef-creation might be simplified a lot. * * @param pefUrl The URL of the .pef file. */ public boolean makePEF(String pefUrl) throws IOException, ParserConfigurationException, TransformerConfigurationException, TransformerException, InterruptedException, LiblouisException { logger.entering("Odt2Braille", "makePEF"); VolumeType[] volumeTypes = new VolumeType[(settings.preliminaryVolumeEnabled?1:0) + Math.max(1,settings.NUMBER_OF_VOLUMES) + settings.NUMBER_OF_SUPPLEMENTS]; ArrayList<SpecialSymbol> specialSymbolsList = settings.getSpecialSymbolsList(); DocumentBuilderFactory docFactory; DocumentBuilder docBuilder; Document document; Element headElement; Element dcElement; Element bodyElement; Element[] volumeElements = new Element[volumeTypes.length]; Element sectionElement; Element pageElement; Element rowElement; Node node; ProcessingInstruction pi; BufferedReader bufferedReader = null; FileInputStream fileInputStream = null; InputStreamReader inputStreamReader = null; String brfInput = null; String line = null; int lineCount; int pageCount; int volumeCount; boolean cont; Matcher matcher; char ch; int volumeNr; boolean extractpprangemode; boolean allVolumes; boolean body; boolean front; int beginPage; int endPage; int prelPages; int[] bodyPageCount = new int[volumeTypes.length]; int[] preliminaryPageCount = new int[volumeTypes.length]; String[] beginPrintPages = new String[volumeTypes.length]; String[] endPrintPages = new String[volumeTypes.length]; boolean[][] specialSymbolsPresent = new boolean[volumeTypes.length][specialSymbolsList.size()]; boolean[][] transcribersNotesEnabled = new boolean[volumeTypes.length][TranscribersNote.values().length]; // Initialization for (int i=1;i<=volumeTypes.length;i++) { if (i-(settings.preliminaryVolumeEnabled?1:0)==0) { volumeTypes[i-1] = VolumeType.PRELIMINARY; } else if (i-(settings.preliminaryVolumeEnabled?1:0)> Math.max(1,settings.NUMBER_OF_VOLUMES)) { volumeTypes[i-1] = VolumeType.SUPPLEMENTARY; } else { volumeTypes[i-1] = VolumeType.NORMAL; } bodyPageCount[i-1] = 0; preliminaryPageCount[i-1] = 0; for (int j=1;j<=specialSymbolsPresent[0].length;j++) { specialSymbolsPresent[i-1][j-1] = false; } for (int j=1;j<=TranscribersNote.values().length;j++) { transcribersNotesEnabled[i-1][j-1] = false; } } try { docFactory = DocumentBuilderFactory.newInstance(); docFactory.setValidating(false); docBuilder = docFactory.newDocumentBuilder(); DOMImplementation impl = docBuilder.getDOMImplementation(); document = impl.createDocument("http://www.daisy.org/ns/2008/pef";, "pef", null); Element root = document.getDocumentElement(); root.setAttributeNS(null,"version","2008-1"); headElement = document.createElementNS("http://www.daisy.org/ns/2008/pef","head";); headElement.setAttributeNS("http://www.w3.org/2000/xmlns/";, "xmlns:dc", "http://purl.org/dc/elements/1.1/";); dcElement = document.createElementNS("http://purl.org/dc/elements/1.1/","dc:identifier";); node = document.createTextNode("00001"); dcElement.appendChild(node); headElement.appendChild(dcElement); dcElement = document.createElementNS("http://purl.org/dc/elements/1.1/","dc:format";); node = document.createTextNode("application/x-pef+xml"); dcElement.appendChild(node); headElement.appendChild(dcElement); root.appendChild(headElement); // BODY: Split into volumes and extract page ranges allVolumes = true; // all volumes body = true; // only body front = false; // no front beginPage = 1; endPage = 0; // not relevant prelPages = 0; // not relevant volumeNr = 0; // not relevant extractpprangemode = false; if (!odt2daisy.convertAsDTBook(daisyUrl, allVolumes, volumeNr, VolumeType.NONE, body, front, beginPage, endPage, prelPages, null, null, null, null)) { return false; } checker.checkDaisyFile(daisyFile); configureLiblouisxml(extractpprangemode, beginPage); runLiblouisxml(); fileInputStream = new FileInputStream(brailleFile); inputStreamReader = new InputStreamReader(fileInputStream,"UTF-8"); bufferedReader = new BufferedReader(inputStreamReader); statusIndicator.setSteps(1 + (settings.PRELIMINARY_PAGES_PRESENT?volumeElements.length:0)); statusIndicator.reset(); statusIndicator.setStatus(L10N_statusIndicatorStep); for (volumeCount = 1;volumeCount<= volumeElements.length;volumeCount++) { logger.log(Level.INFO,"Processing body of volume " + volumeCount + "/" + volumeElements.length); volumeElements[volumeCount-1] = document.createElementNS("http://www.daisy.org/ns/2008/pef","volume";); volumeElements[volumeCount-1].setAttributeNS(null,"cols",String.valueOf(settings.getNumberOfCellsPerLine())); volumeElements[volumeCount-1].setAttributeNS(null,"rows",String.valueOf(settings.getNumberOfLinesPerPage())); volumeElements[volumeCount-1].setAttributeNS(null,"rowgap","0"); volumeElements[volumeCount-1].setAttributeNS(null,"duplex",settings.isDuplex()?"true":"false"); if (volumeTypes[volumeCount-1] == VolumeType.PRELIMINARY) { bodyPageCount[volumeCount-1] = 0; } else { sectionElement = document.createElementNS("http://www.daisy.org/ns/2008/pef","section";); cont = true; pageCount = 1; while (cont) { pageElement = document.createElementNS("http://www.daisy.org/ns/2008/pef","page";); lineCount = 1; while (lineCount<= settings.getNumberOfLinesPerPage()) { line = bufferedReader.readLine(); /* WINDOWS */ bufferedReader.readLine(); if (line.contains("\uE000")) { line = line.replaceAll("\uE000"," "); cont = false; bodyPageCount[volumeCount-1] = pageCount; } line = line.replaceAll("\u00a0", " "); rowElement = document.createElementNS("http://www.daisy.org/ns/2008/pef","row";); node = document.createTextNode(liblouisTable.toBraille(line)); rowElement.appendChild(node); pageElement.appendChild(rowElement); lineCount++; } sectionElement.appendChild(pageElement); bufferedReader.skip(1); // skip '\f' pageCount++; } volumeElements[volumeCount-1].appendChild(sectionElement); } } statusIndicator.increment(); if (bufferedReader != null) { bufferedReader.close(); inputStreamReader.close(); fileInputStream.close(); } // Print page ranges String s; volumeNr = 0; for (volumeCount = 1;volumeCount<= specialSymbolsPresent.length;volumeCount++) { if (volumeTypes[volumeCount-1]!=VolumeType.PRELIMINARY) { volumeNr++; if (XPathUtils.evaluateBoolean(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeNr + "]/dtb:div[@class='not-in-volume']" + "/following::*[not(self::dtb:pagebreak)][1][self::dtb:pagenum]", namespace)) { s = XPathUtils.evaluateString(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeNr + "]/dtb:div[@class='not-in-volume']" + "/following::*[not(self::dtb:pagebreak)][1][self::dtb:pagenum]", namespace); } else { s = XPathUtils.evaluateString(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeNr + "]/dtb:div[@class='not-in-volume']" + "/following::*[1]/preceding::dtb:pagenum[1]", namespace); } if (s.equals("")){ if (settings.mergeUnnumberedPages) { s = XPathUtils.evaluateString(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeNr + "]/dtb:div[@class='not-in-volume']" + "/following::*[1]/preceding::dtb:pagenum[text()][1]", namespace); } else { s = XPathUtils.evaluateString(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeNr + "]" + "//dtb:pagenum[text() and not(ancestor::dtb:div[@class='not-in-volume'])][1]", namespace); } } if (!s.equals("")){ beginPrintPages[volumeCount-1] = s; s = XPathUtils.evaluateString(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeNr + "]" + "//dtb:pagenum[text() and not(ancestor::dtb:div[@class='not-in-volume'])][last()]", namespace); if (!(s.equals("") || s.equals(beginPrintPages[volumeCount-1]))) { endPrintPages[volumeCount-1] = s; } } } } // LIST OF SPECIAL SYMBOLS: Determine which symbols to display if (settings.specialSymbolsListEnabled) { volumeNr = 0; for (volumeCount = 1;volumeCount<= specialSymbolsPresent.length;volumeCount++) { if (volumeTypes[volumeCount-1]!=VolumeType.PRELIMINARY) { volumeNr++; } for (int i=0;i<specialSymbolsPresent[volumeCount-1].length;i++) { switch (specialSymbolsList.get(i).getMode()) { case NEVER: break; case ALWAYS: specialSymbolsPresent[volumeCount-1][i] = true; break; case FIRST_VOLUME: if (volumeCount == 1) { specialSymbolsPresent[volumeCount-1][i] = true; } break; case IF_PRESENT_IN_VOLUME: if (volumeTypes[volumeCount-1]!=VolumeType.PRELIMINARY) { switch (specialSymbolsList.get(i).getType()) { case NOTE_REFERENCE_INDICATOR: specialSymbolsPresent[volumeCount-1][i] = XPathUtils.evaluateBoolean(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeNr + "]//dtb:note[@class='footnote' or @class='endnote']",namespace); break; case TRANSCRIBERS_NOTE_INDICATOR: specialSymbolsPresent[volumeCount-1][i] = XPathUtils.evaluateBoolean(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeNr + "]//dtb:div[@class='tn']/dtb:note",namespace); break; case ITALIC_INDICATOR: specialSymbolsPresent[volumeCount-1][i] = XPathUtils.evaluateBoolean(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeNr + "]//dtb:em[not(@class='reset')]",namespace); break; case BOLDFACE_INDICATOR: specialSymbolsPresent[volumeCount-1][i] = XPathUtils.evaluateBoolean(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeNr + "]//dtb:strong[not(@class='reset')]",namespace); break; case ELLIPSIS: specialSymbolsPresent[volumeCount-1][i] = XPathUtils.evaluateBoolean(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeNr + "]//dtb:flag[@class='ellipsis']",namespace); break; case DOUBLE_DASH: specialSymbolsPresent[volumeCount-1][i] = XPathUtils.evaluateBoolean(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeNr + "]//dtb:flag[@class='double-dash']",namespace); break; default: } } break; } } } } // TRANSCRIBER'S NOTE PAGES: Determine which notes to display if (settings.transcribersNotesPageEnabled) { for (volumeCount = 1;volumeCount<= transcribersNotesEnabled.length;volumeCount++) { TranscribersNote[] transcribersNoteValues = TranscribersNote.values(); if (volumeTypes[volumeCount-1]!=VolumeType.PRELIMINARY) { for (int i=0;i<transcribersNoteValues.length;i++) { switch (transcribersNoteValues[i]) { case IMAGES_NOT_REPRODUCED: transcribersNotesEnabled[volumeCount-1][i] = XPathUtils.evaluateBoolean(daisyFile.toURL().openStream(), "//dtb:div[@class='volume'][" + volumeCount + "]//dtb:div[@class='image']",namespace); break; default: transcribersNotesEnabled[volumeCount-1][i] = false; } } } } } // PRELIMINARY PAGES: Insert PP sections before body of volumes 1,2,3,... if (settings.PRELIMINARY_PAGES_PRESENT) { beginPage = 0; endPage = 0; for (volumeCount = 1;volumeCount<= volumeElements.length;volumeCount++) { logger.log(Level.INFO,"Processing preliminary pages of volume " + volumeCount + "/" + volumeElements.length); sectionElement = document.createElementNS("http://www.daisy.org/ns/2008/pef","section";); if (volumeCount> 1&& volumeTypes[volumeCount-1]==volumeTypes[volumeCount-2]) { volumeNr ++; } else { volumeNr = 1; } allVolumes = false; front = true; body = (settings.tableOfContentEnabled&& volumeTypes[volumeCount-1]!=VolumeType.SUPPLEMENTARY); beginPage = endPage+1; endPage = endPage + bodyPageCount[volumeCount-1]; // Determine page range extractpprangemode = true; prelPages = 0; // not relevant if (!odt2daisy.convertAsDTBook(daisyUrl, allVolumes, volumeNr, volumeTypes[volumeCount-1], body, front, beginPage, endPage, prelPages, beginPrintPages[volumeCount-1], endPrintPages[volumeCount-1], specialSymbolsPresent[volumeCount-1],transcribersNotesEnabled[volumeCount-1])) { return false; } configureLiblouisxml(extractpprangemode, body?beginPage:1); runLiblouisxml(); fileInputStream = new FileInputStream(brailleFile); inputStreamReader = new InputStreamReader(fileInputStream,"UTF-8"); brfInput = IOUtils.toString(inputStreamReader); matcher = Pattern.compile("(\f|\uE000)").matcher(brfInput); pageCount = 1; while (matcher.find()) { ch = brfInput.charAt(matcher.start()); if (ch=='\f') { pageCount ++; } else { if (settings.tableOfContentEnabled&& volumeTypes[volumeCount-1]!=VolumeType.SUPPLEMENTARY) { pageCount --; } break; } } if (inputStreamReader != null) { inputStreamReader.close(); fileInputStream.close(); } // Extract preliminary pages extractpprangemode = false; prelPages = pageCount; preliminaryPageCount[volumeCount-1] = prelPages; if (!odt2daisy.convertAsDTBook(daisyUrl, allVolumes, volumeNr, volumeTypes[volumeCount-1], body, front, beginPage, endPage, prelPages, beginPrintPages[volumeCount-1], endPrintPages[volumeCount-1], specialSymbolsPresent[volumeCount-1],transcribersNotesEnabled[volumeCount-1])) { return false; } checker.checkDaisyFile(daisyFile); configureLiblouisxml(extractpprangemode, body?beginPage:1); runLiblouisxml(); fileInputStream = new FileInputStream(brailleFile); inputStreamReader = new InputStreamReader(fileInputStream,"UTF-8"); bufferedReader = new BufferedReader(inputStreamReader); pageCount = 1; while (pageCount<= prelPages) { pageElement = document.createElementNS("http://www.daisy.org/ns/2008/pef","page";); lineCount = 1; while (lineCount<= settings.getNumberOfLinesPerPage()) { line = bufferedReader.readLine(); /* WINDOWS */ bufferedReader.readLine(); line = line.replaceAll("\u00a0", " "); rowElement = document.createElementNS("http://www.daisy.org/ns/2008/pef","row";); node = document.createTextNode(liblouisTable.toBraille(line)); rowElement.appendChild(node); pageElement.appendChild(rowElement); lineCount++; } sectionElement.appendChild(pageElement); bufferedReader.skip(1); pageCount ++; } volumeElements[volumeCount-1].insertBefore(sectionElement, volumeElements[volumeCount-1].getFirstChild()); if ((!settings.tableOfContentEnabled || volumeTypes[volumeCount-1]==VolumeType.SUPPLEMENTARY)&& !settings.volumeInfoEnabled&& volumeCount>1) { for (volumeCount=volumeCount+1;volumeCount<=volumeElements.length;volumeCount++) { volumeElements[volumeCount-1].insertBefore(sectionElement.cloneNode(true), volumeElements[volumeCount-1].getFirstChild()); } break; } statusIndicator.increment(); if (bufferedReader != null) { bufferedReader.close(); inputStreamReader.close(); fileInputStream.close(); } } statusIndicator.finish(true); } checker.checkVolumeLengths(bodyPageCount, preliminaryPageCount, volumeTypes); bodyElement = document.createElementNS("http://www.daisy.org/ns/2008/pef","body";); for (volumeCount = 1;volumeCount<=volumeElements.length;volumeCount++) { bodyElement.appendChild(volumeElements[volumeCount-1]); } root.appendChild(bodyElement); pi = (ProcessingInstruction)document.createProcessingInstruction( "xml-stylesheet","type='text/css' href='pef.css'"); document.insertBefore(pi, document.getFirstChild()); OdtUtils.saveDOM(document, pefUrl); logger.exiting("Odt2Braille","makePEF"); return true; } finally { statusIndicator.finish(false); if (bufferedReader != null) { bufferedReader.close(); inputStreamReader.close(); fileInputStream.close(); } } } /** * Execute the<code>xml2brl</code> program. * An xml-file is translated to a braille file. * Before executing,<code>liblouisxml</code> has to be configured. * * @see<a href="http://code.google.com/p/liblouisxml/";><code>liblouisxml</code></a> */ private void runLiblouisxml() throws IOException, InterruptedException, LiblouisException { logger.entering("Odt2Braille","runLiblouisxml"); Process process; Runtime runtime = Runtime.getRuntime(); String exec_cmd[] = new String[configurationList.size()]; configurationList.toArray(exec_cmd); int i; String message = null; String line = null; String errors = ""; message = "liblouis: "; for (i=0;i<exec_cmd.length;i++) { message += "\n " + exec_cmd[i]; } logger.log(Level.INFO,message); process = runtime.exec(exec_cmd); if (process.waitFor() != 0) { throw new LiblouisException("liblouisxml did not terminate correctly"); } InputStream stderr = process.getErrorStream(); InputStreamReader isr = new InputStreamReader(stderr); BufferedReader br = new BufferedReader(isr); while ((line = br.readLine()) != null) { errors += line + "\n"; } if (isr != null) { isr.close(); stderr.close(); } logger.exiting("Odt2Braille","runLiblouisxml"); if (!errors.equals("")) { throw new LiblouisException("liblouisxml error: " + errors); } } /** * Configure the<code>xml2brl</code> program. * @see<a href="http://code.google.com/p/liblouisxml/";><code>liblouisxml</code></a> *<ul> *<li><code>literaryTextTable</code>,<code>printPages</code>,<code>cellsPerLine</code> and<code>linesPerPage</code> * are set according to the braille settings.</li> *<li>Depending on<code>extractpprangemode</code>, an additional semantic-action file is added to<code>semanticFiles</code>.</li> *<li><code>beginningPageNumber</code> is set to<code>beginPage</code>.</li> *</ul> * * @param extractpprangemode<code>true</code> if the braille output will be used to extract the page range of the preliminary section. * @param beginPage The first braille page number after this table of contents. * If no table of contents is rendered,<code>beginPage</code> is just the first braille page number. */ private void configureLiblouisxml(boolean extractpprangemode, int beginPage) throws TransformerConfigurationException, TransformerException, IOException { logger.entering("Odt2Braille","configureLiblouisxml"); configurationList.clear(); String math = settings.getMath().name().toLowerCase(); String translationTable = "__" + settings.getTranslationTable(settings.getMainLanguage()) + "-g" + settings.getGrade(settings.getMainLanguage()) + ".ctb"; String configFiles = stylesFile.getAbsolutePath() + "," + "_config.cfg," + "_styles.cfg"; String semanticFiles = "_main.sem," + (extractpprangemode?"_extractpprangemode.sem,":"") + (settings.stairstepTableIsEnabled()?"_stairsteptable.sem,":"") + "_" + math + ".sem"; String mathTable = "__" + math + ".ctb"; String editTables = "_edit_" + math + ".ctb"; configurationList.add("\"" + liblouisDirUrl + "bin" + System.getProperty("file.separator") + LIBLOUIS_EXEC_NAME + LIBLOUIS_EXEC_EXT + "\""); configurationList.add("-f"); configurationList.add(configFiles); configurationList.add("-C" + "literaryTextTable=" + translationTable); configurationList.add("-C" + "semanticFiles=" + semanticFiles); configurationList.add("-C" + "mathtextTable=" + translationTable); configurationList.add("-C" + "mathexprTable=" + mathTable); configurationList.add("-C" + "editTable=" + editTables); configurationList.add("-C" + "lineFill=" + liblouisTable.toText(settings.getLineFillSymbol())); configurationList.add("-C" + "beginningPageNumber=" + beginPage); configurationList.add("-C" + "cellsPerLine=" + Integer.toString(settings.getNumberOfCellsPerLine())); configurationList.add("-C" + "linesPerPage=" + Integer.toString(settings.getNumberOfLinesPerPage())); configurationList.add("-C" + "hyphenate=" + (settings.getHyphenate()?"yes":"no")); configurationList.add("-C" + "printPages=" + (settings.getPrintPageNumbers()?"yes":"no")); configurationList.add("-C" + "pageSeparator=" + (settings.getPageSeparator()?"yes":"no")); configurationList.add("-C" + "pageSeparatorNumber=" + (settings.getPageSeparatorNumber()?"yes":"no")); configurationList.add("-C" + "ignoreEmptyPages=" + (settings.getIgnoreEmptyPages()?"yes":"no")); configurationList.add("-C" + "continuePages=" + (settings.getContinuePages()?"yes":"no")); configurationList.add("-C" + "mergeUnnumberedPages=" + (settings.getMergeUnnumberedPages()?"yes":"no")); configurationList.add("-C" + "pageNumberTopSeparateLine=" + (settings.getPageNumberAtTopOnSeparateLine()?"yes":"no")); configurationList.add("-C" + "pageNumberBottomSeparateLine=" + (settings.getPageNumberAtBottomOnSeparateLine()?"yes":"no")); configurationList.add("-C" + "printPageNumberRange=" + (settings.getPrintPageNumberRange()?"yes":"no")); configurationList.add("-C" + "printPageNumberAt=" + settings.getPrintPageNumberAt()); configurationList.add("-C" + "braillePageNumberAt=" + settings.getBraillePageNumberAt()); configurationList.add("\"" + daisyUrl + "\""); configurationList.add("\"" + brailleUrl + "\""); createChardefsFile(daisyFile); logger.exiting("Odt2Braille","configureLiblouisxml"); } }