Package fi.celia.asciimath.xml

Source Code of fi.celia.asciimath.xml.AsciiMathXml

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("&lt;", "<");
        inputAsciiMathText2 = inputAsciiMathText2.replaceAll("&#60;", "<");
        inputAsciiMathText2 = inputAsciiMathText2.replaceAll("&#x3c;", "<");
        // replace all html coded > character into normal > characer
        inputAsciiMathText2 = inputAsciiMathText2.replaceAll("&gt;", ">");
        inputAsciiMathText2 = inputAsciiMathText2.replaceAll("&#62;", ">");       
        inputAsciiMathText2 = inputAsciiMathText2.replaceAll("&#x3e;", ">");
        // replace possible &amp; into & character:
        inputAsciiMathText2 = inputAsciiMathText2.replaceAll("&amp;", "&");
        // 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.subSequenceiPrev, iStart));
            founded = value.substring(iStart, iEnd);
            sb.append(value.replaceAll("&", "&amp;"));
            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("\"", "&quot;");
            title = title.replaceAll("'", "&apos;");
            title = JAsciiMath.getChangeNormalCharactersIntoLTAndGTHtmlCharacters(title);
            title = replaceAmpCharacterIfnotReservedVariables(title);           
          }
         
          return title;
          //+ ret.substring(indTitleStop);
        }
      }
      return null;
    }
   
    public static String
    replaceAmpCharacterIfnotReservedVariables(String title)
    {
      //title = title.replaceAll("&", "&amp;");
      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("&", "&amp;");
      // 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("&", "&amp;"));
        }
        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("&amp;");
          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("&amp;");
              indReadStart = indAmp +1;
            }
            else
            {
              if (!strVarName.contains("&")) // if this then it is not a really & variable ;
              {
                sp.append("&amp;");
                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("&lt;", "<");
          tmp = tmp.replaceAll("&gt;", ">");
          tmp = tmp.replaceAll("&amp;", "&");
          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; }
}
TOP

Related Classes of fi.celia.asciimath.xml.AsciiMathXml

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.