1   package org.daisy.pipeline.asciimathml.calabash.impl;
2   
3   import java.io.StringReader;
4   import java.io.StringWriter;
5   import java.util.Map;
6   
7   import javax.xml.transform.dom.DOMSource;
8   import javax.xml.transform.OutputKeys;
9   import javax.xml.transform.stream.StreamResult;
10  import javax.xml.transform.stream.StreamSource;
11  import javax.xml.transform.Transformer;
12  import javax.xml.transform.TransformerFactory;
13  
14  import com.xmlcalabash.core.XProcRuntime;
15  import com.xmlcalabash.io.WritablePipe;
16  import com.xmlcalabash.library.DefaultStep;
17  import com.xmlcalabash.runtime.XAtomicStep;
18  
19  import net.sf.saxon.s9api.QName;
20  import net.sf.saxon.s9api.SaxonApiException;
21  
22  import org.daisy.common.xproc.calabash.XProcStep;
23  import org.daisy.common.xproc.calabash.XProcStepProvider;
24  import org.daisy.common.xproc.XProcMonitor;
25  import org.daisy.pipeline.asciimathml.ASCIIMathML;
26  
27  import org.osgi.service.component.annotations.Component;
28  
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  import org.w3c.dom.Element;
33  
34  @Component(
35  	name = "px:asciimathml",
36  	service = { XProcStepProvider.class },
37  	property = { "type:String={http://www.daisy.org/ns/pipeline/xproc}asciimathml" }
38  )
39  public class ASCIIMathMLProvider implements XProcStepProvider {
40  	
41  	@Override
42  	public XProcStep newStep(XProcRuntime runtime, XAtomicStep step, XProcMonitor monitor, Map<String,String> properties) {
43  		return new ASCIIMathMLStep(runtime, step);
44  	}
45  	
46  	private static class ASCIIMathMLStep extends DefaultStep implements XProcStep {
47  		
48  		private static final Logger logger = LoggerFactory.getLogger(ASCIIMathMLStep.class);
49  		
50  		private static final QName _asciimath = new QName("asciimath");
51  	
52  		private WritablePipe result;
53  		
54  		private ASCIIMathMLStep(XProcRuntime runtime, XAtomicStep step) {
55  			super(runtime, step);
56  		}
57  		
58  		@Override
59  		public void setOutput(String port, WritablePipe pipe) {
60  			result = pipe;
61  		}
62  		
63  		@Override
64  		public void reset() {
65  			result.resetWriter();
66  		}
67  	
68  		@Override
69  		public void run() throws SaxonApiException {
70  			super.run();
71  			try {
72  				String ascii = getOption(_asciimath).getString().replaceAll("^`", "").replaceAll("`$", "");
73  				logger.info("Translating `" + ascii + "` to MathML ...");
74  				result.write(runtime.getProcessor().newDocumentBuilder().build(
75  					new StreamSource(new StringReader(Serializer.serialize(ASCIIMathML.convert(ascii)))))); }
76  			catch (Throwable e) {
77  				throw XProcStep.raiseError(e, step); }
78  		}
79  	}
80  	
81  	private static class Serializer {
82  		private static Transformer transformer;
83  		private static String serialize(Element element) {
84  			try {
85  				if (transformer == null) {
86  					transformer = TransformerFactory.newInstance().newTransformer();
87  					transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); }
88  				StringWriter writer = new StringWriter();
89  				transformer.transform(new DOMSource(element), new StreamResult(writer));
90  				return writer.toString(); }
91  			catch (Exception e) {
92  				throw new RuntimeException(e); }
93  		}
94  	}
95  }