[brailleblaster] Re: Example of Executing a Command-line program from Java

  • From: Bert Frees <bert.frees@xxxxxxxxxxxxxxxx>
  • To: brailleblaster@xxxxxxxxxxxxx
  • Date: Thu, 16 Dec 2010 15:59:09 +0100

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");

     }
}



Other related posts: