1   package org.daisy.pipeline.asciimathml;
2   
3   import java.io.InputStreamReader;
4   
5   import javax.script.Invocable;
6   import javax.script.ScriptEngine;
7   import javax.script.ScriptEngineManager;
8   import javax.script.ScriptException;
9   import javax.xml.parsers.DocumentBuilderFactory;
10  
11  import org.slf4j.Logger;
12  import org.slf4j.LoggerFactory;
13  
14  import org.w3c.dom.Element;
15  
16  public class ASCIIMathML {
17  	
18  	private static final Logger logger = LoggerFactory.getLogger(ASCIIMathML.class);
19  	
20  	private static final Invocable engine;
21  	static {
22  		try {
23  			ScriptEngine javascriptEngine = new ScriptEngineManager().getEngineByName("javascript");
24  			logger.debug("Using JavaScript engine: " + javascriptEngine);
25  			javascriptEngine.put("document",
26  			                     DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
27  			javascriptEngine.eval(new InputStreamReader(
28  			                      ASCIIMathML.class.getResource("/javascript/ASCIIMathML.js").openStream()));
29  			javascriptEngine.eval(
30  				"initSymbols();                                                                      \n" +
31  				"main = function(ascii) {                                                            \n" +
32  				"    var content = AMparseExpr(ascii, false)[0];                                     \n" +
33  				"    content = content.length == 1 ? content : createMmlNode(\"mrow\", content);     \n" +
34  				"    var semantics = createMmlNode(\"semantics\", content);                          \n" +
35  				"    var annotation = createMmlNode(\"annotation\", document.createTextNode(ascii)); \n" +
36  				"    annotation.setAttribute(\"encoding\", \"ASCIIMath\");                           \n" +
37  				"    semantics.appendChild(annotation);                                              \n" +
38  				"    return createMmlNode(\"math\", semantics);                                      \n" +
39  				"}");
40  			engine = (Invocable)javascriptEngine; }
41  		catch (Exception e) {
42  			logger.error("Failed to load ASCIIMathML.js", e);
43  			throw new RuntimeException(e); }
44  	}
45  	
46  	public static Element convert(String asciimath) {
47  		try {
48  			return (Element)engine.invokeFunction("main", asciimath); }
49  		catch (ScriptException e) {
50  			throw new RuntimeException("JavaScript exception was thrown", e); }
51  		catch (NoSuchMethodException e) {
52  			throw new RuntimeException("coding error", e); }
53  	}
54  }