1   package nl.dedicon.pipeline.braille.calabash.impl;
2   
3   import com.xmlcalabash.core.XProcException;
4   import com.xmlcalabash.core.XProcRuntime;
5   import com.xmlcalabash.core.XProcStep;
6   import com.xmlcalabash.library.DefaultStep;
7   import com.xmlcalabash.runtime.XAtomicStep;
8   import java.io.File;
9   import java.net.URI;
10  import java.nio.file.Files;
11  import java.nio.file.Path;
12  import net.sf.saxon.s9api.Processor;
13  import net.sf.saxon.s9api.QName;
14  import net.sf.saxon.s9api.SaxonApiException;
15  import nl.dedicon.pipeline.braille.step.BrailleToText;
16  import nl.dedicon.pipeline.braille.step.Utils;
17  import org.daisy.common.xproc.calabash.XProcStepProvider;
18  import org.osgi.service.component.annotations.Component;
19  import org.slf4j.Logger;
20  import org.slf4j.LoggerFactory;
21  import org.w3c.dom.Document;
22  
23  /**
24   * XProc step for modifying the preview HTML
25   * 
26   * The pipeline can generate a preview for the generated PEF,
27   * which is an HTML with a braille view and a text view.
28   * This step modifies the text view, such that digits,
29   * capitals and certain symbols are displayed correctly
30   * according to specifications of Dedicon.
31   * 
32   * If the structure of the generated HTML preview changes,
33   * this step may have to be revised.
34   * 
35   * This step is structured as follows:
36   * 
37   * * The preview HTML is read as a string
38   * * The header (everything before "<html ") is removed
39   *   and is processed as XML
40   * * The processed XML is converted to a string,
41   *   all XML end tags are replaced by HTML end tags,
42   *   and the header is prepended
43   * * The result overwrites the original preview
44   *   
45   * @author Paul Rambags
46   */
47  public class ModifyPreviewStep extends DefaultStep {
48  
49      private static final Logger logger = LoggerFactory.getLogger(ModifyPreviewStep.class);
50  
51      private static final QName _preview_uri = new QName("preview-uri");
52  
53      private ModifyPreviewStep(XProcRuntime runtime, XAtomicStep step) {
54          super(runtime, step);
55      }
56  
57      @Override
58      public void reset() {
59      }
60  
61      @Override
62      public void run() throws SaxonApiException {
63          super.run();
64  
65          try {
66  
67              String previewUri = getOption(_preview_uri, "");
68              
69              Processor processor = runtime.getProcessor();
70  
71              Path previewPath = new File(new URI(previewUri)).toPath();
72              String sourceHtml = new String(Files.readAllBytes(previewPath), "UTF-8");
73              int htmlStartIndex = sourceHtml.indexOf("<html ");
74              String header = sourceHtml.substring(0, htmlStartIndex);
75              String sourceXml = sourceHtml.substring(htmlStartIndex);
76              Document document = Utils.convertToDocument(sourceXml);
77  
78              new BrailleToText().convert(document);
79              
80              String resultXml = Utils.toString(document, processor.newDocumentBuilder());
81              String resultHtml = header.concat(Utils.convertXmlEndtagsToHtmlEndtags(resultXml));
82              Files.write(previewPath, resultHtml.getBytes("UTF-8"));
83              
84          } catch (Exception e) {
85  
86              logger.error("dedicon:modify-preview failed", e);
87              throw new XProcException(step.getNode(), e);
88  
89          }
90      }
91  
92      @Component(
93              name = "dedicon:modify-preview",
94              service = {XProcStepProvider.class},
95              property = {"type:String={http://www.dedicon.nl}modify-preview"}
96      )
97      public static class Provider implements XProcStepProvider {
98  
99          @Override
100         public XProcStep newStep(XProcRuntime runtime, XAtomicStep step) {
101             return new ModifyPreviewStep(runtime, step);
102         }
103     }
104 }