package fi.celia.asciimath.xml;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader ;
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
//import fi.celia.groovy.util.XmlReader;
//import fi.celia.asciimath.PrintAsciiMathBlocks;
import fi.celia.asciimath.CollectAsciiMathBlocks;
import fi.celia.asciimath.AsciiMathBlockValue;
import fi.celia.asciimath.CollectAsciiMathBlocks;
import fi.celia.asciimath.JAsciiMath;
import fi.celia.asciimath.DtbookAsciiMathException;
import fi.celia.asciimath.GuiDtbook2AsciiMath;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* This class is for converting a dtbook file ascimath data into html page
* after a template file. The html page is then executed within firefox browser,
* which contains asciimath plug-in. The asciimath stateemtns are converted into
* asciimath daisy xml enties. After execution and user stored html page back into
* a disk, modified asciimath statements puts into target dtook-document.
*
* @author tuomas kassila
*
*/
public class AsciiMathXml {
private final static String cnstMarkBegin = "input2AM_b_x";
private final static String cnstMarkEnd = "input2AM_e_x";
private final static int cnstMarkBegin_len = cnstMarkBegin.length();
private final static int cnstMarkEnd_len = cnstMarkEnd.length();
private String m_strDtbookData;
private String m_PrintData = null;
private String m_ErrorData = null;
private JAsciiMath m_jAsciiMath = null;
private static int m_sleepConter = 10;
public AsciiMathXml() {
}
private String
readFileData(File templatefile, String characterSet)
throws DtbookAsciiMathException,
FileNotFoundException,
InterruptedException,
IOException
{
StringBuffer sb = new StringBuffer();
FileInputStream fis = new FileInputStream(templatefile);
InputStreamReader isr = new InputStreamReader(fis, characterSet);
BufferedReader br = new BufferedReader(isr);
String it;
while((it = br.readLine()) != null)
{
sb.append(it+"\n");
}
br.close();
String strTemplate = sb.toString();
return strTemplate;
}
private int run (String [] args)
throws DtbookAsciiMathException,
FileNotFoundException,
InterruptedException,
IOException,
NullPointerException,
Exception
{
System.out.println ("Command line paramets: " );
int maxj = args.length;
for(int j = 0; j < maxj; j++)
System.out.print(args[j]);
System.out.println();
if (args.length < 2)
{
System.out.println("usage: templatefilename dtbookfilename");
System.exit(1);
}
String firefox_install_dir = "C:\\Program Files\\Mozilla Firefox" +File.separator;
String templatefilename = args[0];
String dtbookFileName = args[1];
System.out.println( "template: " +templatefilename);
System.out.println( "dtbook: " +dtbookFileName);
//String inputAsciimathFileName = "C:\\java\\project\\dtbook2aschiimath\\tuomas\\test1.xml";
String asciiMathWWWBrowserApplication = firefox_install_dir;
final String cnstAsciiMathPropertyFileName = "dtbookasciimath.properties";
String jasciiMathPropertyFileName = "./" + cnstAsciiMathPropertyFileName;
if (jasciiMathPropertyFileName == null || jasciiMathPropertyFileName.trim().length() == 0)
jasciiMathPropertyFileName = "dtbookasciimath.properties";
boolean p_bCorrectStrikeErrors = true;
boolean bCheckStrikeErrors = true;
int run_result = modifyDtbookIntoAsciiMathXml(templatefilename,
"UTF-8",
dtbookFileName, jasciiMathPropertyFileName,
asciiMathWWWBrowserApplication, "koe.xml",
"ISO-8859-1", false, bCheckStrikeErrors, p_bCorrectStrikeErrors);
return run_result ;
}
/**
* This method will copy a path from a path into another path. (Here: Used to copy javascript
* files into user home direcotry.)
*
* @param copyPath
* @param dirName
* @param intoDir
* @throws DtbookAsciiMathException
* @throws FileNotFoundException
* @throws IOException
*/
private void
copyDirIntoTargetHome(String copyPath, String dirName, String intoDir)
throws DtbookAsciiMathException, FileNotFoundException, IOException
{
if (copyPath == null)
throw new DtbookAsciiMathException("copyPath is null!");
if (dirName == null)
throw new DtbookAsciiMathException("dirName is null!");
if (intoDir == null)
throw new DtbookAsciiMathException("intoDir is null!");
File fromDirFile = new File(copyPath +File.separator + dirName);
if (!fromDirFile.exists())
throw new DtbookAsciiMathException(fromDirFile.getAbsolutePath() +" does not exist!");
if (!fromDirFile.isDirectory())
throw new DtbookAsciiMathException(fromDirFile.getAbsolutePath() +" is not a directory!");
File intoDirFile = new File(intoDir);
if (!intoDirFile.exists())
throw new DtbookAsciiMathException(intoDirFile.getAbsolutePath() +" does not exist!");
if (!intoDirFile.isDirectory())
throw new DtbookAsciiMathException(intoDirFile.getAbsolutePath() +" is not a directory!");
File targetFile = new File(intoDir +File.separator +dirName);
if (!targetFile.exists())
{
if (!targetFile.mkdir())
throw new DtbookAsciiMathException(targetFile.getAbsolutePath() +" cannot create a new directory!");
}
File [] arrFiles = fromDirFile.listFiles();
int max = arrFiles.length;
if(max == 0)
throw new DtbookAsciiMathException(fromDirFile.getAbsolutePath() +" nothing to copy!");
for(int i = 0; i < max; i++)
{
copyFile(arrFiles[i], targetFile.getAbsolutePath() +File.separator +arrFiles[i].getName());
}
}
/**
* This method will copy a file from one location into another location (path).
*
* @param fromFile
* @param intoFileName
* @throws DtbookAsciiMathException
* @throws IOException
*/
private void copyFile(File fromFile, String intoFileName)
throws DtbookAsciiMathException, IOException
{
FileInputStream fis = new FileInputStream(fromFile);
//BufferedInputStream bis = new BufferedInputStream(fis);
int available = fis.available();
byte [] bytes = new byte[available];
int read = fis.read(bytes);
fis.close();
if (available != read)
throw new DtbookAsciiMathException("All data (" +available
+") has not read (" +read +")!");
FileOutputStream fos = new FileOutputStream(intoFileName);
fos.write(bytes);
fos.close();
}
/**
* This method is calling a firefox browser to open generated html
* file with template file after xml data (parameter file name)
* has been parsed into asciimath statements. These founded asciimath
* values are marked with special uniques words and puts inside generated
* html file. This html file will be opend with firefox browser itself.
* The browser has asciimath-plug-in, which is capable to parse asciimath
* statements between ' characters.
*
* A user of this Gui dtbook-asciimath application must store generated
* asciimath file into the same name and directory, which has been used
* (normally user-home directory). After user has been stored browser handled
* html file, this application (and this method) will be continued execution!
*
* After browser has been executed statements into asciimath xml entities
* and user stored html page, these new asciimath xml values are parsed again
* and replaced into the same position, where original asciimath text statement
* was. All needed html-xml < and > etc characters are converted into htlm
* form.
*
* As a result, target dtbook-file has different asciimath data, but also
* different dtbook format, which is suitable for dtbook with ascimmath xml
* entities.
*
* @param templatefilename A template file name
* @param dtbookFileName Dtbook-asciimath file name
* @param dtbookCharacterSet Used character set of the dtbook
* @param jasciiMathPropertyFileName used ascriimath property file name
* @param asciiMathWWWBrowserApplication Called www-browser, usually a firefox with asccmath plug-in
* @param targetDtbookFileName Target dtbook file name
* @param targetCharacterSet Target character set
* @param bPrintXmlStatements a flag of priont xml statements into special buffer
* @throws DtbookAsciiMathException An Asciimaht error occurred
* @throws FileNotFoundException file not found error occurred
* @throws InterruptedException Browser interrupted, regular expression execution interrupted
* @throws IOException IO eror occurred
* @throws NullPointerException An null pointer error occurred
* @throws Exception An common error occurred
*/
/**
* @param templatefilename
* @param dtbookFileName
* @param dtbookCharacterSet
* @param jasciiMathPropertyFileName
* @param asciiMathWWWBrowserApplication
* @param targetDtbookFileName
* @param targetCharacterSet
* @param bPrintXmlStatements
* @throws DtbookAsciiMathException
* @throws FileNotFoundException
* @throws InterruptedException
* @throws IOException
* @throws NullPointerException
* @throws Exception
*/
public int
modifyDtbookIntoAsciiMathXml(String templatefilename,
String dtbookFileName,
String dtbookCharacterSet,
String jasciiMathPropertyFileName,
String asciiMathWWWBrowserApplication,
String targetDtbookFileName,
String targetCharacterSet,
boolean bPrintXmlStatements,
boolean bCheckStrikeErrors,
boolean p_bCorrectStrikeErrors)
throws DtbookAsciiMathException,
FileNotFoundException,
InterruptedException,
IOException,
NullPointerException,
Exception
{
int result = 0;
// read template file data
// String charsetName = "ISO-8859-1";
String charsetName = dtbookCharacterSet;
File templatefile = new File(templatefilename);
if (!templatefile.exists())
throw new FileNotFoundException("File not found: Titemplatefilename=" +templatefilename);
// read a template data and replace template variables with text values:
String strTemplate = readFileData(templatefile, charsetName);
// set template output file name and file:
//String strTemplate = new String(templatefile.readBytes());
String tmp_filePath = templatefile.getParentFile().getAbsolutePath();
if (tmp_filePath.endsWith("."))
tmp_filePath = tmp_filePath.substring(0, tmp_filePath.length()-2);
String strUserHome = System.getProperty("user.home");
if (strUserHome != null)
{ // copy javascript files below user home directory
copyDirIntoTargetHome(tmp_filePath, "exe_asciimath_files", strUserHome);
tmp_filePath = strUserHome;
}
// an output file for template file content
File outputFile = new File(tmp_filePath +File.separator
+ "exe_asciimath.html");
String exeXmlFileName = outputFile.getAbsolutePath();
// to be sure, that browser execution will be successfulll:
// " xxx " / " sddd " => will be changed into (" xxx ") / (" sddd ")
// " xxx " => (" xxx ") etc
boolean bAddBrowserStrikes = true;
// create asciimath variable
JAsciiMath jAsciiMath = new JAsciiMath(jasciiMathPropertyFileName,
bCheckStrikeErrors, p_bCorrectStrikeErrors, bAddBrowserStrikes);
//CollectAsciiMathBlocks asciimathBlocks = new CollectAsciiMathBlocks(jAsciiMath);
// dtbook = acutual input file
File file = new File(dtbookFileName);
String inputText = readFileData(file, charsetName);
// skip possible error data of beginning of the input file (binary characters), like: ?>>
int ind = inputText.indexOf("<?xml");
if (ind > -1) // fix a possible bug: ï»Â¿<?xml ....
inputText = inputText.substring(ind);
// tell which is input data
m_strDtbookData = inputText;
jAsciiMath.setInputData(inputText);
jAsciiMath.replaceAsciiMathBlocks();
// create collector of asciimath data blocks (calculus etc)
CollectAsciiMathBlocks pamb = new CollectAsciiMathBlocks(jAsciiMath,
bCheckStrikeErrors,
p_bCorrectStrikeErrors);
//pamb.printAllAsciiMathBloks sb.toString();
try {
// collect asciimath data with the collector
//AsciiMathBlockValue [] arrAMBlock = pamb.getAllAsciiMathBlocks();
AsciiMathBlockValue [] arrAMBlock = jAsciiMath.getArrayOfAsciiMathBlocks();
if (arrAMBlock == null)
throw new DtbookAsciiMathException("Not founded any asciimath-blocks!");
String inputAsciiMathText;
StringBuffer sb = new StringBuffer();
int iCount = 0, max = arrAMBlock.length;
AsciiMathBlockValue amValue;
// collect all asciimath calculus data into one stringbuffer
// and mark every asciimath blocks with special mark string,
// that is possible to find these special labeled asciimath
// positions later. At later time, generated asciimath-xml
// blocks will replaced <asciimath> and </asciimath> blocks.
for(int i = 0; i < max; i++)
{
amValue = arrAMBlock[i];
// to much strings: class="asciimath">
inputAsciiMathText = amValue.getAsciiMathValue();
//inputAsciiMathText = inputAsciiMathText.substring("class=\"asciimath\">".length());
sb.append("x_" + iCount + cnstMarkBegin + inputAsciiMathText + "x_" + iCount +cnstMarkEnd +"\n");
iCount++;
}
inputAsciiMathText = sb.toString();
// replace inputText_here with template data
// (template data is just little modifyed ascimath editor data)
String strChanged = strTemplate.replace("inputText_here",
new String(inputAsciiMathText.getBytes(charsetName)));
//System.out.println( "strMuutettu");
//System.out.println( strMuutettu);
//System.out.println();
// write modified template data into a file and run it later within
// the asciimath browser:
FileWriter fw = new FileWriter(outputFile);
fw.write(strChanged.toCharArray());
fw.close();
// take timestamp just writen file:
File tmp_file = outputFile ;
//outputFile = null;
outputFile = new File(tmp_file.getAbsolutePath());
tmp_file = null;
long outputFile_lastModified = outputFile.lastModified();
long outputFile_size = outputFile.length();
File exe_asciimath = outputFile.getAbsoluteFile();
// A string can be executed in the standard java way:
// Create the String
outputFile = null;
outputFile = new File(exeXmlFileName);
if (outputFile == null)
throw new DtbookAsciiMathException("outputFile is null: " + exeXmlFileName +"!");
long outputFileSize = exe_asciimath.length();
exe_asciimath = null;
String command = "\"" + asciiMathWWWBrowserApplication +"\""; // -chrome
// see if this application is executed under unix
boolean bExecutingUnderUnix = (File.separatorChar == '/' ? true : false);
if (bExecutingUnderUnix)
command = asciiMathWWWBrowserApplication; // -chrome
// prepare to start application
ProcessBuilder pb = new ProcessBuilder(command, "-silent", exeXmlFileName);
// tell current directory to pb
pb.directory(new File("."));
System.out.println(("Save html-file after ascimmath editor has been executed this file: " + exeXmlFileName));
// start the browser
Process proc = pb.start(); // Call *execute* on the string
// NOTICE! (case 1) if the browser (firefox) has not executed under the start time,
// a exitvalue will returned after user has been saved generated xhtml file
// and *closed* the browser!
// (case 2) but if the browser is executing under at start time, a exitvalue will
// returned when starting process will noticed that the browser is running
// allready. And exit value is 1. And a length of proc.getErrorStream() is empty.
// In this case, the applcation will go into a loop, which will sleep 10 seconds
// afteer configurad times. After a sleep time, application will check: has a user
// saved a generated html-file. If not and the loop has been stopped, a user will
// noticde about an error or like that.
// if the user has been saved the file, it is readed and converted into target file.
// This file contains all asciimath xml blocks from browser generated file.
// (case 3) Another wise returned value will tell that an error has occured.
int exitvalue = proc.waitFor(); // Wait for the command to finish
//long waitMSec = 10000L;
//proc.waitFor();
//int exitvalue = proc.exitValue();
boolean bStillBrowserExecutionOK = false;
if (exitvalue != 0)
{ // possible errors (case 1,2,3)
result = exitvalue;
// Obtain status and output
System.err.println( "return code: " +exitvalue);
InputStream erroStream = proc.getErrorStream();
int availbable = erroStream.available();
byte [] bytes = new byte[availbable];
long luettu = erroStream.read(bytes);
String strError = "";
// if there is proble to read all characers
if (luettu != availbable)
System.err.println("Process error stream read error: read: " +luettu +" available: " +availbable);
else
{ // get error stream value
strError = new String (bytes);
System.err.println( "stderr: " + strError);
}
if (exitvalue == 1 && strError != null && strError.equals(""))
{ // (case 2):
int iCounter = 0;
// wait for the user and for saved file:
while(iCounter < m_sleepConter)
{
iCounter++;
Thread.sleep(10000);
File modifiedFile = new File(exeXmlFileName);
System.out.println( iCounter + " outputFile_lastModified " + outputFile_lastModified);
System.out.println( "outputFile_size=" + outputFileSize);
System.out.println( "modifiedfile.lastModified()=" + modifiedFile.lastModified());
System.out.println( "modifiedfile.size()=" + modifiedFile.length());
if (outputFileSize != modifiedFile.length()
|| outputFile_lastModified != modifiedFile.lastModified())
{ // the user has changed the input file for the browser
bStillBrowserExecutionOK = true;
break;
}
}
}
if (!bStillBrowserExecutionOK)
{ // (case 2): the user has not saved the file
this.m_ErrorData = GuiDtbook2AsciiMath.m_afterbrowsercall +": " +exitvalue
+ " stderr: " +strError +"\n" + GuiDtbook2AsciiMath.m_possible_reasons_are
+"(~" + m_sleepConter+"x10sec)?!\n"
+ GuiDtbook2AsciiMath.m_browser_exec_problem_reason_2;
return result ;
}
}
if (bStillBrowserExecutionOK || exitvalue == 0)
{
result = 0;
exitvalue = 0;
System.out.println( "Successfull execution of the Browser!");
File modifiedFile = new File(exeXmlFileName);
System.out.println( "outputFile_lastModified " + outputFile_lastModified);
System.out.println( "outputFile_size=" + outputFileSize);
System.out.println( "modifiedfile.lastModified()=" + modifiedFile.lastModified());
System.out.println( "modifiedfile.size()=" + modifiedFile.length());
/*
while(modifiedFile.lastModified() == outputFile_lastModified ?*
&& muutettuFile.size() == outputFileSize*? )
{
System.out.println("Save " + outputFile.getAbsolutePath() +"\n"
+ " - and after it the programs continues...");
modifiedFile = null;
//outputFile = null;
Thread.sleep(10000);
modifiedFile = new File(outputFile.getAbsolutePath());
System.out.println( "outputFile_lastModified=" + outputFile_lastModified);
System.out.println( "modifiedFile.lastModified()=" + modifiedFile.lastModified());
}
*/
replaceAsciimathBlocksWithXmlAsciimathBlocks(arrAMBlock,
exeXmlFileName, bPrintXmlStatements, charsetName,
outputFileSize, strUserHome, targetDtbookFileName,
pamb);
m_jAsciiMath = jAsciiMath;
}
} catch(DtbookAsciiMathException dame){
this.m_ErrorData = dame.getMessage();
throw dame;
} catch(Exception e){
this.m_ErrorData = e.getMessage();
throw e;
}
System.out.println( " -- end of modification --");
return result ;
}
private void
replaceAsciimathBlocksWithXmlAsciimathBlocks(AsciiMathBlockValue [] arrAMBlock,
String exeXmlFileName, boolean bPrintXmlStatements, String charsetName,
long outputFileSize, String strUserHome, String targetDtbookFileName,
CollectAsciiMathBlocks pamb)
throws DtbookAsciiMathException,
FileNotFoundException,
InterruptedException,
IOException,
NullPointerException,
Exception
{
File modifiedFile = null;
modifiedFile = new File(exeXmlFileName);
AsciiMathBlockValue amValue;
//String strMuutettuFileData = new String(muutettuFile.readBytes());
System.out.println( "modifiedFile.lastModified()=" + modifiedFile.lastModified());
System.out.println( "modifiedFile.size()=" + modifiedFile.length());
//System.out.println( "strMuutettuFileData");
//System.out.println( strMuutettuFileData);
System.out.println();
long modifiedFile_length = modifiedFile.length();
if (modifiedFile_length == outputFileSize)
throw new DtbookAsciiMathException("Unmodified file! The size of file is same: " +outputFileSize
+"\nUser has not saved a generated asciimath editor file by the browser!");
System.out.println( "Reading and handling just saved file....");
String strMuutettuFileData = readFileData(modifiedFile, charsetName);
//strMuutettuFileData = korjaaPuuttuvaMetaTag(strMuutettuFileData);
String strMathMlData = null; // getMathMlData(strMuutettuFileData);
//stMarkBegin cnstMarkEnd
int iCount = 0, max = arrAMBlock.length;
StringBuffer sb = new StringBuffer();
String inputAsciiMathText2;
String search_start;
String search_end;
String strFound;
int indBegin, indBegin_end, indEnd;
// selecting/searching read modified data and collection every value
// into back asciimath data block:
for(int i = 0; i < max; i++)
{
amValue = arrAMBlock[i];
// liika mjonoa: class="asciimath">
// inputAsciiMathText2 = getXmlAsciiMathValue(iCount, strMuutettuFileData)
search_start = "x_" + iCount + cnstMarkBegin;
search_end = "x_" + iCount + cnstMarkEnd;
indBegin = strMuutettuFileData.indexOf(search_start);
if (indBegin == -1)
continue;
indBegin_end = indBegin + search_start.length();
strFound = strMuutettuFileData.substring(indBegin);
indBegin = strMuutettuFileData.indexOf(search_start, indBegin_end);
if (indBegin == -1)
continue;
indBegin_end = indBegin + search_start.length();
indBegin = strMuutettuFileData.indexOf(search_start, indBegin_end);
if (indBegin == -1)
continue;
indBegin_end = indBegin + search_start.length();
indEnd = strMuutettuFileData.indexOf(search_end, indBegin);
if (indBegin == -1)
continue;
if (indEnd == -1)
continue;
inputAsciiMathText2 = strMuutettuFileData.substring(indBegin_end, indEnd);
// replace html asciimath characters and words into normal characters:
inputAsciiMathText2 = inputAsciiMathText2.replaceAll("<", "<");
inputAsciiMathText2 = inputAsciiMathText2.replaceAll("<", "<");
inputAsciiMathText2 = inputAsciiMathText2.replaceAll("<", "<");
// replace all html coded > character into normal > characer
inputAsciiMathText2 = inputAsciiMathText2.replaceAll(">", ">");
inputAsciiMathText2 = inputAsciiMathText2.replaceAll(">", ">");
inputAsciiMathText2 = inputAsciiMathText2.replaceAll(">", ">");
// replace possible & into & character:
inputAsciiMathText2 = inputAsciiMathText2.replaceAll("&", "&");
// take away unneede and unxml attribute: <m:mtd -moz-math-columnalign="left">
inputAsciiMathText2 = inputAsciiMathText2.replaceAll("-moz-math-columnalign=\"left\"", "");
inputAsciiMathText2 = inputAsciiMathText2.replaceAll("<m:mtd >", "<m:mtd>");
inputAsciiMathText2 = inputAsciiMathText2.replaceAll("<m:mspace>\\s*</m:mspace>", "<m:mspace/>");
inputAsciiMathText2 = inputAsciiMathText2.replaceAll(
"<(\\s*)mspace((\\s+\\S+\\s*=\\s*\\S+\\s*)+)>\\s*<(\\s*)/(\\s*)mspace(\\s*)>",
"<mspace$2/>");
/** TODO: Handle: & character in:
<m:math xmlns:dtbook="http://www.daisy.org/z3986/2005/dtbook/" altimg="" alttext="& lt lt A lt rArr lt B lt">
inputAsciiMathText2 = replaceETCharsInAsciiMath(inputAsciiMathText2);
*/
amValue.setXmlValue(inputAsciiMathText2);
amValue.setModifiedXmlValue(getModifiedXmlValue(inputAsciiMathText2));
// collect textual data into a caller buffer:
sb.append("" + iCount + ":\n Row: " + amValue.getRow() +" Column: " + amValue.getColumn() + "\n\n");
sb.append("" + ":\n"+ amValue.getModifiedXmlValue() + "\n\n");
iCount++;
}
// sb.append strMuutettuFileData
strMathMlData = sb.toString();
System.out.println( "Saving asciimat asciimath.blocks.log for execution of dtbook-file....");
String outputMathMlFileName = targetDtbookFileName; // modifiedFile.getParent() +File.separator +"mathml.html";
File outputMathMlFile = new File( (strUserHome == null ? "." : strUserHome)
+ File.separatorChar + "asciimath.blocks.log");
//outputMathMlFile.text = strMathMlData;
FileWriter fwMathMlData = new FileWriter(outputMathMlFile);
fwMathMlData.write(strMathMlData.toCharArray());
fwMathMlData.close();
System.out.println( "Saving asciimat asciimath dtbook-file....");
// modify dtbook file data
String strMathXmlData = getMathDtBook(arrAMBlock);
outputMathMlFileName = targetDtbookFileName; // modifiedFile.getParent() +File.separator +"mathmlxml.html";
// store target dtbook asciimath file
outputMathMlFile = new File(outputMathMlFileName);
//outputMathMlFile.text = strMathMlData;
//fwMathMlData = new FileWriter(outputMathMlFile);
FileOutputStream os = new FileOutputStream(outputMathMlFile);
OutputStreamWriter osw = new OutputStreamWriter(os, charsetName);
osw.write(strMathXmlData.toCharArray());
osw.close();
m_strDtbookData = strMathXmlData;
System.out.println( "Saved file: " + outputMathMlFile.getAbsolutePath()) ;
if (bPrintXmlStatements)
{
StringBuffer sbPrintData = pamb.printAllAsciiMathBloks(arrAMBlock);
if (sbPrintData != null)
m_PrintData = sbPrintData.toString();
}
}
/**
* this method is not finished!
* @param value
* @return
*/
private String
replaceETCharsInAsciiMath(String value)
{
String resultString = null, strValue;
String regexString = null;
String founded = null;
try {
// Replace regex %s value (like: "regexp1%sregexp1", where %s will be strToken value)
regexString = "alttext=\"(&+)(.+)|(.+)(&+)\">";
// Replace value (like: " %s", " %s " etc where %s has strToken value)
Pattern regex = Pattern.compile(regexString);
Matcher regexMatcher = regex.matcher(value);
int iStart, iEnd = 0, iPrev = 0;
String ret = value;
StringBuffer sb = new StringBuffer();
try {
// find a searched value
while(regexMatcher.find())
{
// get position values of founded value
iStart = regexMatcher.start();
iEnd = regexMatcher.end();
// check if there is don-modify-this text value and if it exists
// then continue (no chnage)
sb.append(value.subSequence( iPrev, iStart));
founded = value.substring(iStart, iEnd);
sb.append(value.replaceAll("&", "&"));
iPrev = iEnd;
}
sb.append(value.substring(iEnd));
return sb.toString();
} catch (IllegalArgumentException ex) {
// Syntax error in the replacement text (unescaped $ signs?)
throw ex;
} catch (IndexOutOfBoundsException ex) {
// Non-existent backreference used the replacement text
throw ex;
}
} catch (PatternSyntaxException ex) {
// Syntax error in the regular expression
throw ex;
}
}
private String
getMathDtBook(AsciiMathBlockValue [] arrAMBlock)
{
if (m_strDtbookData == null)
return null;
if (arrAMBlock == null)
return null;
if (arrAMBlock.length == 0)
return m_strDtbookData;
int iCount = 0;
AsciiMathBlockValue amValue;
int max = arrAMBlock.length, start,
end, previousEnd = 0,
spanEndLen = "</span>".length(),
indSearchSpan;
StringBuffer sb = new StringBuffer();
String strStart, strEnd, strEnd2, strEnd3;
for(int i = 0; i < max; i++)
{
amValue = arrAMBlock[i];
if (amValue == null)
continue;
start = amValue.getIndFound();
end = amValue.getIndFoundEnd();
strStart = m_strDtbookData.substring(previousEnd, start);
sb.append(strStart);
sb.append(amValue.getModifiedXmlValue());
indSearchSpan = m_strDtbookData.indexOf("</span>", end);
previousEnd = (end +spanEndLen);
if (indSearchSpan != -1 && previousEnd != indSearchSpan)
previousEnd = (indSearchSpan +spanEndLen) ;
strEnd = m_strDtbookData.substring(end);
strEnd2 = m_strDtbookData.substring(indSearchSpan);
strEnd3 = m_strDtbookData.substring(previousEnd);
iCount++;
}
sb.append(m_strDtbookData.substring(previousEnd));
String strXmlDtbook = sb.toString();
sb = new StringBuffer();
int ind1 = strXmlDtbook.indexOf('>');
if (ind1 > -1)
{
int ind2 = strXmlDtbook.indexOf('>', (ind1+1));
if (ind2 > -1)
{
String startDeclaration = strXmlDtbook.substring(0, ind2);
String mdDecl = getMathDtbookDeclaration();
sb.append(startDeclaration + mdDecl + ">\n");
}
}
int ind = strXmlDtbook.indexOf("<dtbook");
String dtbookElement;
if (ind > -1)
{
String search = "</dtbook>";
int indEnd = strXmlDtbook.indexOf(search);
if (indEnd > -1)
{
dtbookElement = strXmlDtbook.substring(ind, indEnd+search.length());
String modifiedDtbookElement = dtbookElement ;
int indStartElementEnd = dtbookElement.indexOf('>');
String dtbookStartElement;
if (indStartElementEnd > -1)
{
dtbookStartElement = dtbookElement.substring(0, (indStartElementEnd));
//int indLastStrike = dtbookStartElement.lastIndexOf('"');
modifiedDtbookElement = dtbookStartElement +' '
+ getAsciiMathNameSpace().replace("xmlns=", "xmlns:m=")
//+">\n"
+ dtbookElement.substring(indStartElementEnd);
search = "<head>";
int indHeader = modifiedDtbookElement.indexOf(search);
if (indHeader > -1)
{
modifiedDtbookElement = modifiedDtbookElement.substring(0, indHeader+search.length())
+ getMathMetaData()
+ modifiedDtbookElement.substring(indHeader+search.length());
}
}
sb.append(modifiedDtbookElement);
}
}
return sb.toString();
}
private String
getModifiedXmlValue(String inputAsciiMathText)
throws Exception
{
String title = getCorrectTitle(inputAsciiMathText);
if (title == null)
return inputAsciiMathText; // return null;
String value = null;
if (title != null)
{
if (title.contains("\""))
value = getMathTemplateWithDupleStrikesInAlttextAttribute().replace("$title", title);
else
value = getMathTemplate().replace("$title", title);
}
if (value == null)
return inputAsciiMathText; // return null;
String childtext = getXmlChildEntities(inputAsciiMathText);
if (childtext != null)
{
value = value.replace("$childtext", childtext);
}
if (value == null)
return inputAsciiMathText;
return value;
}
private String
getMathTemplate()
{
return "<m:math " + getDtBookNameSpace()
+ " altimg=\"\" alttext=\"$title\">$childtext</m:math>";
}
private String
getMathTemplateWithDupleStrikesInAlttextAttribute()
{
return "<m:math " + getDtBookNameSpace()
+ " altimg='' alttext='$title'>$childtext</m:math>";
}
private String
getCorrectTitle(String inputAsciiMathText)
{
String ret = inputAsciiMathText; // new String(inputAsciiMathText);
final String search = "title=\"";
int ind = ret.indexOf(search);
if (ind > -1)
{
String titleStart = ret.substring(ind+search.length());
int indXlns = titleStart.indexOf("xmlns=");
int indTitleStop = -1;
if (indXlns == -1) // if not found (error?!) xmlns= , then try to find first " character
indTitleStop = titleStart.indexOf("\"");
else
{
String titleEndind = titleStart.substring(0, indXlns);
indTitleStop = titleEndind.lastIndexOf("\"");
if (indTitleStop > -1)
titleStart = titleEndind;
}
if (indTitleStop > -1)
{
String title = titleStart.substring(0, indTitleStop);
//ret = ret.substring(0, ind)
if (title != null)
{
title = title.replaceAll("\"", """);
title = title.replaceAll("'", "'");
title = JAsciiMath.getChangeNormalCharactersIntoLTAndGTHtmlCharacters(title);
title = replaceAmpCharacterIfnotReservedVariables(title);
}
return title;
//+ ret.substring(indTitleStop);
}
}
return null;
}
public static String
replaceAmpCharacterIfnotReservedVariables(String title)
{
//title = title.replaceAll("&", "&");
int indAmp = title.indexOf('&');
if (indAmp == -1) // if no & characters
return title;
int indSemiColon = title.indexOf(';');
if (indSemiColon == -1) // if no ; characters
return title.replaceAll("&", "&");
// there is & and ; characters, check &var; strings
String ret = new String(title);
int len = ret.length();
indAmp = ret.indexOf('&');
String strVarName;
int indReadStart = 0, ind2Amp = 0, indReadEnd = 0;
StringBuffer sp = new StringBuffer();
boolean founded = false;
indReadEnd = indReadStart;
while(indAmp != -1 && indReadStart < len)
{
founded = true;
//if (indReadStart == 0) // append the start or previous string before & character
sp.append(ret.substring(indReadStart, indAmp));
//else
//if (indReadStart != indAmp)
//sp.append(ret.substring(indReadStart, indAmp));
// seek ; character
indSemiColon = ret.indexOf(';', indAmp);
if (indSemiColon == -1 || indAmp == indSemiColon) // is allmost ready, there are any ; character
{
return (sp.toString() + ret.substring(indAmp).replaceAll("&", "&"));
}
ind2Amp = -1;
if (indReadStart < len) // can seek 2. & char
ind2Amp = ret.indexOf('&', indAmp+1);
if (ind2Amp != -1 && ind2Amp < indSemiColon)
{ // there is a second & char before founded ; character
sp.append("&");
indReadStart = indAmp +1;
}
else
{ // there is & and ; chars
strVarName = ret.substring(indAmp+1, indSemiColon);
if (strVarName == null || strVarName.trim().length() == 0
|| strVarName.contains(" ") || strVarName.contains("\t")
|| strVarName.contains("&"))
{ // if possible variable name contains any of space, it'snt a really
// reference variable, then replace 1 & character
if (strVarName == null)
{
sp.append("&");
indReadStart = indAmp +1;
}
else
{
if (!strVarName.contains("&")) // if this then it is not a really & variable ;
{
sp.append("&");
sp.append(strVarName);
indReadStart = indAmp + strVarName.length() +1;
}
else
{
int indSubAmp = strVarName.indexOf('&');
if (indSubAmp > -1)
sp.append(strVarName.subSequence(0, indSubAmp));
if (indSubAmp == 0)
indReadStart = indAmp +(indSubAmp);
else
indReadStart = indAmp +(indSubAmp-1);
}
}
}
else
{
// skip this &xxx; xml reference variable
indReadStart = indSemiColon;
}
}
indAmp = ret.indexOf('&', indReadStart);
if (indAmp > -1)
indReadEnd = indReadStart;
}
if (!founded)
return ret;
else
{
if (indReadEnd < len)
sp.append(ret.substring(indReadEnd+1));
return sp.toString() ;
}
}
private String
getAsciiMathNameSpace()
{
return "xmlns=\"http://www.w3.org/1998/Math/MathML\"";
}
private String
getDtBookNameSpace()
{
return "xmlns:dtbook=\"" +getDtbookURL() +"\"";
}
private String
getDtbookURL()
{;
String search = "http://";
int ind = m_strDtbookData.indexOf(search);
if (ind > -1)
{
String dtbookURL = null;
search = "\"";
int ind2 = m_strDtbookData.indexOf(search, ind);
if (ind2 > -1)
{
dtbookURL = m_strDtbookData.substring(ind, ind2);
int ind3 = dtbookURL.lastIndexOf('/');
if (ind3 > -1)
{
search = "PUBLIC";
int ind4 = m_strDtbookData.indexOf(search);
if (ind4 > -1)
{
String [] arrWords = m_strDtbookData.substring(
(ind4+search.length()), ind).replaceAll("\"", "").split(" ");
dtbookURL = dtbookURL.substring(0, ind3) +"/"
+ arrWords[2] +"/" ;
}
}
return dtbookURL;
}
}
//return "http://www.daisy.org/z3986/2005/dtbook/";
return null;
}
private String
getMathDtbookDeclaration()
{
String dtbookURL = getDtbookURL();
/* String search = "xmlns:dtbook=\"";
int ind = dtbookURL.indexOf(search);
if (ind > -1)
{
dtbookURL = dtbookURL.substring(ind+search.length());
search = "\"";
int ind2 = dtbookURL.indexOf(search);
if (ind2 > -1)
{
dtbookURL = dtbookURL.substring(0, ind2);
}
}
*/
return getMathDtbookDeclarationTemplate().replaceAll("\\$dtbooknamespace",
dtbookURL);
}
private String
getMathMetaData()
{
return "<meta name=\"z39-86-extension-version\"\n"
+"scheme=\"http://www.w3.org/1998/Math/MathML\"\n"
+"content=\"1.0\" />\n"
+"<meta name=\"DTBook-XSLTFallback\"\n"
+"scheme=\"http://www.w3.org/1998/Math/MathML\"\n"
+"content=\"xslt-file-name\" />";
}
private String
getMathDtbookDeclarationTemplate()
{
return "\n[\n"
+"\t<!ENTITY % MATHML.prefixed \"INCLUDE\" >\n"
+"\t<!ENTITY % MATHML.prefix \"m\">\n"
+"\t<!ENTITY % MATHML.Common.attrib\n"
+"\t\"xlink:href CDATA #IMPLIED\n"
+"\txlink:type CDATA #IMPLIED\n"
+"\tclass CDATA #IMPLIED\n"
+"\tstyle CDATA #IMPLIED\n"
+"\tid ID #IMPLIED\n"
+"\txref IDREF #IMPLIED\n"
+"\tother CDATA #IMPLIED\n"
+"\txmlns:dtbook CDATA #FIXED '$dtbooknamespace'\n"
+"\tdtbook:smilref CDATA #IMPLIED\"\n"
+"\t>\n"
+"\t<!ENTITY % mathML2 PUBLIC \"-//W3C//DTD MathML 2.0//EN\"\n"
+"\t\"http://www.w3.org/Math/DTD/mathml2/mathml2.dtd\"\n"
+"\t>\n"
+"\t%mathML2;\n"
+"\t<!ENTITY % externalFlow \"| m:math\">\n"
+"\t<!ENTITY % externalNamespaces \"xmlns:m CDATA #FIXED\n"
+"\t'http://www.w3.org/1998/Math/MathML'\">\n"
+"]\n";
}
private String
getCorrectNameSpace(String inputAsciiMathText)
{
String ret = inputAsciiMathText ; // new String(inputAsciiMathText);
int ind = ret.indexOf(getAsciiMathNameSpace());
if (ind > -1)
{
String titleStart = ret.substring(ind);
int indTitleStop = titleStart.indexOf("\"");
if (indTitleStop > -1)
{
String title = titleStart.substring(0, indTitleStop);
ret = ret.substring(0, ind)
+ JAsciiMath.getChangeNormalCharactersIntoLTAndGTHtmlCharacters(title)
+ ret.substring(indTitleStop);
}
}
return ret;
}
private String
getXmlChildEntities(String inputAsciiMathText)
throws Exception
{
String ret = inputAsciiMathText;
String search = getAsciiMathNameSpace();
int ind = inputAsciiMathText.indexOf(search);
if (ind > -1)
{
String value = inputAsciiMathText.substring(ind+search.length());
if (value != null)
{
int indStart = value.indexOf('>');
if (indStart > -1)
{
int indEnd = value.indexOf("</math>");
if (indEnd > -1)
{
String childtext = getCorrectEntityNames(value.substring((indStart+1), indEnd));
return childtext ;
}
}
}
}
return ret;
}
private String
getCorrectEntityNames(String asciiMathText)
throws Exception
{
//String ret = asciiMathText.replaceAll("<", "<m:");
StringBuffer sb = new StringBuffer();
String start, end, ret = asciiMathText, str;
int ind = 0, prev_ind = 0, len = asciiMathText.length();
char nextCh;
boolean founded = false;
while( (ind = asciiMathText.indexOf('<', ind)) != -1)
{
//String ret = asciiMathText.replaceAll("<", "<m:");
str = asciiMathText.substring(ind);
start = asciiMathText.substring(prev_ind, ind);
founded = true;
sb.append(start);
nextCh = 0;
if (len >= (ind+1))
{
nextCh = asciiMathText.charAt(ind+1);
if (nextCh == '/')
{
if (len >= (ind+3))
if (notM_NameSpaceAdded(str.substring(0, 3)))
{
sb.append("</m:");
ind = ind +1;
}
}
else
{
if (len >= (ind+3))
if (notM_NameSpaceAdded(str.substring(0, 3)))
{
sb.append("<m:");
}
}
ind = ind +1;
prev_ind = ind;
}
}
if (founded && len > (ind+1))
{
end = asciiMathText.substring(prev_ind, (len-1));
sb.append( end );
}
ret = sb.toString();
return ret;
}
private boolean
notM_NameSpaceAdded(String m_namespace2Chars)
throws NullPointerException, Exception
{
if (m_namespace2Chars == null)
throw new NullPointerException("m_namespace2Chars == null");
if (m_namespace2Chars.length() != 3)
throw new Exception("m_namespace2Chars.trim().length() != 2");
char ch1 = m_namespace2Chars.charAt(1);
char ch2 = m_namespace2Chars.charAt(2);
if (ch1 == 'm' && ch2 == ':')
return false;
return true;
}
private String getXmlAsciiMathValue(Integer iCount, String strMathMlData)
{
//sb.append "x_" + iCount + cnstMarkBegin + inputAsciiMathText + "x_" + iCount +cnstMarkEnd
String ret = strMathMlData;
/*
def search_start = "x_" + iCount + cnstMarkBegin
def search_end = "x_" + iCount + cnstMarkEnd
int indBegin, indBegin_end, indEnd
indBegin = strMathMlData.indexOf(search_start)
indBegin_end = indBegin + cnstMarkBegin_len
indEnd = strMathMlData.indexOf(search_end)
if (indBegin == -1)
return null
if (indEnd == -1)
return null
String ret = strMathMlData.substring(indBegin_end, indEnd)
*/
return ret;
}
private String korjaaPuuttuvaMetaTag(String strHtmlMathMlData)
{
int ind = strHtmlMathMlData.indexOf("<meta");
if (ind > -1)
{
int ind2 = strHtmlMathMlData.indexOf(">", ind);
if (ind2 > -1)
{
String ret = strHtmlMathMlData.substring(0, ind2+1) +"</meta>" + strHtmlMathMlData.substring(ind2+2);
return ret;
}
}
return strHtmlMathMlData;
}
/*
private String
getMathMlData(String strHtmlMathMlData)
throws Exception
{
if (strHtmlMathMlData == null)
return null;
String strSearch = "id=\"outputNode\"";
int ind = strHtmlMathMlData.indexOf(strSearch);
if (ind > -1)
{
int ind2 = strHtmlMathMlData.indexOf(">", ind);
if (ind2 > -1)
{
int ind3 = strHtmlMathMlData.indexOf("</textarea>", ind2);
if (ind3 > -1)
{
String tmp = strHtmlMathMlData.substring(
ind2 +1,
ind3);
// hae ja korvaa html-koodit:
tmp = tmp.replaceAll("<", "<");
tmp = tmp.replaceAll(">", ">");
tmp = tmp.replaceAll("&", "&");
String ret = tmp;
System.out.println( "outputNode löydetty");
?*
System.out.println( "strOutput"
System.out.println( ret
System.out.println();
*?
return ret;
}
}
}
?*
XmlReader xr = new XmlReader()
//def readCharacterSet = "UTF-8"
def htmldocument = xr.readXmlStringWithXmlSlurper(strHtmlMathMlData)
if (!htmldocument) // on: dorisdocument == null
return
// ? merkki tarkoittaa groovyssä, että jos publishing on null,
// niin silti ei tule nullpointer-exceptionia, vaan palautetaan null tässä
// publishing muuttujaan:
def body = htmldocument.body
def table = body.table
def outputtextarea = table.find { it['@id'] == 'outputNode' }
def strOutput = outputtextarea.text()
*?
throw new Exception("outputNode: does not found!");
}
*/
public static void main(String [] args) {
try {
AsciiMathXml gam = new AsciiMathXml();
gam.run (args);
} catch(Exception e){
e.printStackTrace();
}
}
public String getOutputData()
{
return m_strDtbookData;
}
public String getPrintData()
{
return m_PrintData;
}
public String getErrorData()
{
return m_ErrorData;
}
public JAsciiMath getJAsciiMath() { return m_jAsciiMath; }
public static int getSleepConter() { return m_sleepConter; }
public static void setSleepConter(int sleepConter) { m_sleepConter = sleepConter; }
}