package fi.celia.asciimath;
import java.io.File;
import java.io.BufferedReader;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.util.regex.*;
import java.util.Properties;
import java.util.Set;
import java.util.HashMap;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serializable;
import fi.celia.asciimath.xml.AsciiMathXml;
/**
* This class is for to modify asciimath sentences after 3 rules. These 3 rules says,
* how an asciimath sentence contains words, aka reserved words or or special
* characters must be replaced into another word or character, or add or remove space,
* how to show numbers etc. These rules values are readed from a config file (.properties).
* <p>
* Above changes are done by with regular expressions, and by calling method:
* string.replaceAll(...,...). Before changing searched expressions, the class is replacing
* "not-replace words" (cnstNOTThiswords) with special (cnstDontModify) word before
* an until actual replace process is starting. An example: search word: int, with also has a
* do-not-change value: int_, then a word "int_" will be replaced
* "x__JAsciiMath_DontModifyconst__x" (cnstDontModify) untill int words has been changed.
* And then actual replace int value will be done, at last x__JAsciiMath_DontModifyconst__x
* strings are replaced back into int_ etc. By using this kind of special mark strings,
* all ready replaced or changed words are marked: "do-not-change-this-any-more" or
* "do-not-change-this-on-this-time". After all changes these kind of special marked
* strings are removed from modified text. Only actual modified characters and strings will
* be remained and a text will returned.
* <p>
* (c) Copyright 2010 Celia, wwww.celia.fi
* published as open source, license xxx
* <p>
* @author tkassila, Tuomas Kassila
*
*/
/*
* - Modifications: 25.6.10 SpaceAfterButNotBeforeToken-regular string bug fixed
* (now: strReplace = "%s "). And test application corrected also.
* - Modifications: 18.9.10 Fixed none sorted replace-hash-key, which lead to a bug
* when replaced iff = omm and if = om. Added sorting into
* all arrays. Modified also rules after: "do not modify a
* searched word if it contains " strikes at the start and
* end of the word.
* - Modifications: 20.9.10 Fixed used wrong variable bug.
*/
public class JAsciiMath
{
private AsciiMathBlockValue [] m_arrblok = null;
/**
* This class is used when sorting hasmap keys and array after searched
* values. There is best to search/replace or modify at first most length
* values and after at last a shortest value. Also notice, that a searched
* value may contains (not: xxx) which are not calculated into the length
* of an value. See below:
*
* @author tuomas kassila
*
*/
private static class StringLengthComparator implements Comparator<String>,
Serializable {
public int compare(String o1, String o2)
{
String strO1 = getCompareStringWhichContainsCnstNOTThiswords(o1);
String strO2 = getCompareStringWhichContainsCnstNOTThiswords(o2);
if (strO1.length() < strO2.length()) {
return 1;
} else if (strO1.length() > strO2.length()) {
return 0;
} else {
return -1;
}
}
/**
* Also notice, that a searched
* value may contains (not: xxx) which are not calculated into the length
* of an value. See below:
* @param value
* @return
*/
private String
getCompareStringWhichContainsCnstNOTThiswords(String value)
{
int ind = value.indexOf(cnstNOTThiswords);
if (ind > -1)
return value.substring(0, ind).trim();
return value;
}
}
private static String m_static_strInputFileName = null;
private static String m_static_strOutputFileName = null;
private boolean bConvertHtmlChars = true;
private boolean m_bWarningsOn = false;
private boolean m_bPrintAsciMaths = false;
private StringBuffer m_sbPrintData = null;
private boolean m_bCorrectStrikeErrors = false;
private HashMap<String, List<AsciiMathBlockValue>> m_hm_asciimath_values = null;
// tka added 16.6.2011: from local variable
// private boolean bRegexTokenWithPossibleLiteral = true;
private boolean m_bAddBrowserStrikes = false;
/**
* When replacing a word with another, with this constant, you
* say, replace longer words temporally with x__JAsciiMath_DontModifyconst__x
* string. And after actual changing word has been replaced, change back
* x__JAsciiMath_DontModifyconst__x into earlier value back again. An example:
* int (not: int_) means: 1. replace all int_ into x__JAsciiMath_DontModifyconst__x,
* 2. then replace all int words into another reserved, like in english word,
* let's say: decimalnumber, 3. replace x__JAsciiMath_DontModifyconst__x into
* back int_ again, etc. Where x means a sequence number starting from 1 to up.
*/
private static final String cnstNOTThiswords = "(not: ";
/**
* Which xml-block is starting an asciimath sentence. This value is
* only a part from original search value: <span class="Asciimath" >
*/
public static final String cnstAsciiMathBlockStart = "<span";
/**
* Which xml-block is stopping an asciimath sentence
*/
public static final String cnstAsciiMathBlockEnds = "</span>";
/**
* This class do not modify word this kind of const.
*/
private static final String cnstDontModify = "x__JAsciiMath_DontModifyconst__x";
/**
* With this string is starting a block: do not modify words under this work.
*/
public static final String cnstDontModifyBegin =
"x_JAsciiMath_DontModifyconst__begin";
/**
* The same kind of literal as upper variable.
*/
public static final String cnstDontModifyEnd =
"end_JAsciiMath_DontModifyconst__x";
private static final String cnstPropertyFileDoesNotFound =
"Property file %s does not found!";
/**
* configuration property value:
*/
private static final String cnstSpace_on_both_sides_name = "space_on_both_sides_section_name";
/**
* configuration property variable:
*/
private String m_space_on_both_sides_name;
/**
* configuration property value:
*/
private static final String cnstSpace_on_neigther_sides_name = "space_on_neigther_sides_section_name";
/**
* configuration property variable:
*/
private String m_space_on_neigther_sides_name;
/**
* configuration property value:
*/
private static final String cnstSpace_before_but_not_after_name = "space_before_but_not_after_section_name";
/**
* configuration property variable:
*/
private String m_space_before_but_not_after_name;
/**
* configuration property value:
*/
private static final String cnstSpace_after_but_not_before_name = "space_after_but_not_before_section_name";
/**
* configuration property variable:
*/
private String m_space_after_but_not_before_name;
/**
* configuration property value:
*/
private static final String cnstReplace_reserved_words_section_name = "replace_reserved_words_section_name";
/**
* configuration property variable:
*/
private String m_replace_reserved_words_section_name;
/**
* configuration property value:
*/
private static final String cnstRegex_special_meaning_characters = "regex_special_meaning_characters";
private String m_regex_special_meaning_characters;
private String m_strInputFileName = null;
private String m_strOutputFileName = null;
//private File m_FileInput = null;
//private File m_FileOutput = null;
private String m_strInputData = null;
private int m_iInputDataLen = 0;
//private String m_strOutputData = null;
/**
* a data output variable
*/
private StringBuffer m_sb = null;
/**
* an error "string" variable
*/
private StringBuffer m_sbError = null;
/*
* contains read/foundef asciimath block as object array
*/
private AsciiMathBlockValue [] m_arrErrorAsciiMathBlockValue = null;
/*
* an application property file name:
*/
public final String cnstReplacePropertiesFileName = "dtbookasciimath.properties";
private String m_strReplacePropertiesFileName = cnstReplacePropertiesFileName;
private File m_FileReplaceProperty = null;
/**
* Config property variable for this class
*/
private Properties m_propertyReplace = null;
/**
* Properties for replacing reserved words
*/
private Properties m_propertyReplaceReservedWords = null;
private List<String> m_sortedReplaceReservedWords = null;
//private List<String> m_listCurrentToken = null;
private RuleConfig m_srcBothSidesSpaceToken = null;
private RuleConfig m_srcSpaceBeforeButNotAfter = null;
private RuleConfig m_srcNoSpaciesIntoBohSideToken = null;
private RuleConfig m_srcSpaceAfterButNotBeforeToken = null;
private RuleConfig m_listReplace_reserved_wordToken = null;
private RuleConfig m_listCurrentToken = null;
/**
* boolean variables for each rules:
*/
private boolean bConvertAsciiMathDataSpaceRule = false;
private boolean bConvertAsciiMathDataCommaRule = false;
private boolean bConvertAsciiMathDataNumberRule = false;
private boolean bConvertAsciiMathDataReplaceAllReservedWords = false;
private boolean bCheckStrikeErrors = true;
/**
* const and string variables for the comma rule:
*/
private static final String cnstReplaceAllComma = "replaceAllComma";
private String m_replaceAllComma = ",";
private static final String cnstReplaceAllWithSemiColon = "replaceAllWithSemiColon";
private String m_replaceAllWithSemiColon = ";";
private static final String cnstReplaceAllNumberPoint = "replaceAllNumberPoint";
private static String m_replaceAllNumberPoint = ".";
private static final String cnstReplaceAllNumberComma = "replaceAllNumberComma";
private static String m_replaceAllNumberComma = ",";
private HashMap<String, String> hmDontModifyData = null;
public boolean getConvertHtmlChars() { return bConvertHtmlChars; }
public void setConvertHtmlChars(boolean value) { bConvertHtmlChars = value; }
public StringBuffer getPrintData() { return m_sbPrintData; }
final HashMap<String, List<AsciiMathBlockValue>> getAsciimatHashMapValues ()
{ return m_hm_asciimath_values; }
/**
* This class stores rule configuration for one rule
*
* @author tkassila
*
*/
private static class RuleConfig
{
private List<String> m_list;
private String [] m_array;
public RuleConfig()
{
m_list = new ArrayList<String>();
}
public final List<String> getList() { return m_list; }
public String[] getArray()
{
if (m_array == null)
createArray();
return m_array;
}
public void addToken(String line)
{
m_list.add(line);
}
public void createArray()
{
int max = m_list.size();
m_array = new String[max];
String value;
for(int i = 0; i < max; i++)
{
value = m_list.get(i);
if (value == null)
continue;
m_array[i] = value;
}
}
public int size()
{
if (m_list == null)
return 0;
return m_list.size();
}
} // end of private class
/**
* This method is returning "will this rule executed under conversion"
*
* @return See above
*/
public boolean getConvertAsciiMathDatSpaceRule()
{ return bConvertAsciiMathDataSpaceRule; }
/**
* This method sets "will this rule executed under conversion"
*/
public void setConvertAsciiMathDataWithSpaceRules(boolean value)
{
bConvertAsciiMathDataSpaceRule = value;
}
/**
* This method is returning "will this rule executed under conversion"
*
* @return See above
*/
public boolean getConvertAsciiMathDataCommaRule()
{ return bConvertAsciiMathDataCommaRule; }
/**
* This method sets "will this rule executed under conversion"
*/
public void setConvertAsciiMathDataCommaRule(boolean value)
{
bConvertAsciiMathDataCommaRule = value;
}
/**
* This method is returning "will this rule executed under conversion"
*
* @return See above
*/
public boolean getConvertAsciiMathDataNumberRule()
{ return bConvertAsciiMathDataNumberRule; }
/**
* This method sets "will this rule executed under conversion"
*/
public void setConvertAsciiMathDataThousndNumberRule(boolean value)
{
bConvertAsciiMathDataNumberRule = value;
}
/**
* This method is returning "will this rule executed under conversion"
*
* @return See above
*/
public boolean getConvertAsciiMathDataReplaceAllReservedWords()
{ return bConvertAsciiMathDataReplaceAllReservedWords; }
/**
* This method sets "will this rule executed under conversion"
*/
public void setConvertAsciiMathDataReplaceAllReservedWords(boolean value)
{
bConvertAsciiMathDataReplaceAllReservedWords = value;
}
/**
*
* These values will be used when adding space on both sides
* of an string
*/
private String [] m_arrBothSidesSpaceToken;
/*
= { ">", "<", "<=", ">=", "sin", "cos", "tan",
"cot", "sec", "int (not: int_)", "ln",
"test_substring", "test_substr"
};
*/
/**
*
* These values will be used when adding space on before of an string
*/
private String [] m_arrSpaceBeforeButNotAfter;
/*
= { "-", "+", "=", "!=", "~~", "*"
};
*/
/**
* Näiden edessä ja takana ei välilyöntejä
* These values will be used when removing spacies from both sides
* of an string
*/
private String [] m_arrNoSpaciesIntoBothSideToken;
/*
= { "#"
};
*/
/**
* Näiden takana ei välilyöntejä
* These values will be used when adding space after but
* not before of an searched string
*/
private String [] m_arrSpaceAfterButNotBefore
= { "("
};
/**
* regex special characters which must make into literal
* charachters by adding \ character before character.
*/
private String [] arrRegexToken
= { "?", ".", "[", "]", "(", ")", "*", "+", "{", "}", "|", "^" };
/**
* The constructor of the class.
* @param p_strReplacePropertiesFileName An absolute path value of the configuration file
* @throws DtbookAsciiMathException
* @throws FileNotFoundException
* @throws IOException
*/
public JAsciiMath(String p_strReplacePropertiesFileName,
boolean p_bCheckStrikeErrors, boolean p_bCorrectStrikeErrors,
boolean bAddBrowserStrikes)
throws DtbookAsciiMathException, FileNotFoundException, IOException
{
m_strReplacePropertiesFileName = p_strReplacePropertiesFileName;
m_bCorrectStrikeErrors = p_bCorrectStrikeErrors;
bCheckStrikeErrors = p_bCheckStrikeErrors;
if (m_FileReplaceProperty == null)
m_FileReplaceProperty = new File(m_strReplacePropertiesFileName);
m_bAddBrowserStrikes = bAddBrowserStrikes;
readSectionNamesAndSectionData();
}
public boolean isPrintAsciimathValues() { return m_bPrintAsciMaths; }
public void setPrintAsciimathValues(boolean value)
{
m_bPrintAsciMaths = value;
}
public String getInputFileName()
{
return m_strInputFileName;
}
public void setInputFileName(String p_strInputFileName)
{
m_strInputFileName = p_strInputFileName;
}
public String getOutputFileName()
{
return m_strOutputFileName;
}
public void setOutputFileName(String p_strOutputFileName)
{
m_strOutputFileName = p_strOutputFileName;
}
public String getInputData()
{
return m_strInputData;
}
public void setInputData(String p_strInputData)
{
m_strInputData = p_strInputData;
setInputDataLen();
}
private void setInputDataLen()
{
if (m_strInputData == null)
m_iInputDataLen = 0;
else
m_iInputDataLen = m_strInputData.length();
}
public String getOutputData()
{
if (m_sb == null)
return null;
return m_sb.toString();
}
public String toStringError()
{
if (m_sbError == null)
return null;
return m_sbError.toString();
}
public AsciiMathBlockValue [] getErrorAsciiMathBlockValueArray()
{
if (m_arrErrorAsciiMathBlockValue == null)
return null;
return m_arrErrorAsciiMathBlockValue;
}
/*
private void setOutputData(String p_strOutputData)
{
m_strOutputData = p_strOutputData;
}
*/
/**
* The method which is starting convertion process after boolean rule attribute
* and input data has been set
*/
public int
replaceAsciiMathBlocks()
throws NullPointerException, Exception
{
if (m_strInputData == null)
throw new Exception("m_strInputData is null!");
if (m_strInputData.trim().length() == 0)
throw new Exception("m_strInputData is empty!");
//System.err.println("1 m_strInputData.length()=" +m_strInputData.length());
// is there an asciimath xml block:
int ind = m_strInputData.indexOf(cnstAsciiMathBlockStart);
if (ind == -1) // does not have ascii-xml start block
{
ind = m_strInputData.indexOf(cnstAsciiMathBlockStart.toUpperCase());
if (ind == -1) // does not have ascii-xml start block
{
m_sb = new StringBuffer(m_strInputData);
return 0;
}
}
//System.err.println("2 m_strInputData.length()=" +m_strInputData.length());
// collect asciimath blocks
CollectAsciiMathBlocks pamb = new CollectAsciiMathBlocks(this,
bCheckStrikeErrors, m_bCorrectStrikeErrors);
//pamb.setInputData(m_strInputData);
AsciiMathBlockValue [] arrblok = pamb.getAllAsciiMathBlocks(m_bAddBrowserStrikes);
if (arrblok == null || arrblok.length == 0)
{ // no ascimmath blocks has been founded, return unmodified data
m_sb = new StringBuffer(m_strInputData);
return -1;
}
m_arrblok = arrblok;
//System.err.println("3 m_strInputData.length()=" +m_strInputData.length());
int max = arrblok.length;
String strAsciiMathValue, strEndAsciiMathBlock;
String modifiedMathValue, strStart;
final int cnstError = 1;
int ret = cnstError, indNextMathBlockStart;
int start = 0, end = -1, indInput = 0, indAsciiMathBlockEnds;
AsciiMathBlockValue prevAsciiMathBlockValue = null, currAMValue = null;
// new output buffer
m_sb = new StringBuffer ();
// new error buffer
m_sbError = new StringBuffer ();
List<AsciiMathBlockValue> listErrorValues = new ArrayList<AsciiMathBlockValue>();
// m_sbError = null; AsciiMathBlockValue [] m_arrErrorAsciiMathBlockValue = null;
int i = 0, iPrevAsciiMathBlockValue_BlockEnds, iIndEndofStartBlock;
String msgError;
// read config file data
fullFillArraysWithConfigList();
HashMap<String, List<AsciiMathBlockValue>> hm_value = new HashMap<String, List<AsciiMathBlockValue>>();
List<AsciiMathBlockValue> list = null;
String key = null;
// loop readed asciimath instancies and do checkings,
// are there some error or warnings, convert asciimath
// values
for(i = 0; i < max; i++)
{
currAMValue = arrblok[i];
if (currAMValue == null)
continue;
strAsciiMathValue = currAMValue.getAsciiMathValue();
if (strAsciiMathValue == null)
continue;
key = "" + currAMValue.getRow();
if (key.trim().length() > 0)
{
list = (List<AsciiMathBlockValue>) hm_value.get(key);
if (list == null)
{
list = new ArrayList<AsciiMathBlockValue>();
hm_value.put(key, list);
}
list.add(currAMValue);
}
if (m_bWarningsOn && strAsciiMathValue.trim().length() == 0)
{
listErrorValues.add(currAMValue);
msgError = "Warning:\nEmpty asciimath: " +strAsciiMathValue +"\n"
+ "row = " +currAMValue.getRow() +"\n"
+ "column = " +currAMValue.getColumn() +"\n"
+"--------------------------------------\n\n";
m_sbError.append(msgError);
currAMValue.setErrorString(msgError);
}
modifiedMathValue = getConvertAsciiMatchValue(strAsciiMathValue);
//if (modifiedMathValue != null)
//modifiedMathValue = modifiedMathValue.replaceAll("\"", "");
currAMValue.setModifiedValue(modifiedMathValue);
if (strAsciiMathValue.trim().length() != 0
&& modifiedMathValue.trim().length() == 0)
{
listErrorValues.add(currAMValue);
msgError = "Error:\nEmpty asciimath after convet!!!! Before convert: "
+strAsciiMathValue +"\n"
+ "row = " +currAMValue.getRow() +"\n"
+ "column = " +currAMValue.getColumn() +"\n"
+"--------------------------------------\n\n";
m_sbError.append(msgError);
currAMValue.setErrorString(msgError);
}
else
if (m_bWarningsOn && modifiedMathValue.equals(strAsciiMathValue))
{
listErrorValues.add(currAMValue);
msgError = "Warning:\nUnchanged asciimath value after convet!!!!\nBefore convert:\n"
+strAsciiMathValue +"\n"
+ "row = " +currAMValue.getRow() +"\n"
+ "column = " +currAMValue.getColumn() +"\n"
+"--------------------------------------\n\n";
m_sbError.append(msgError);
currAMValue.setErrorString(msgError);
}
start = currAMValue.getIndEndofStartBlock();
end = currAMValue.getIndFoundEnd();
if (end <= start)
{
listErrorValues.add(currAMValue);
msgError = "Error:\nEnd is smaller than or equal Start!!!!\n"
+strAsciiMathValue +"\n"
+ "row = " +currAMValue.getRow() +"\n"
+ "column = " +currAMValue.getColumn() +"\n"
+ "start = " + start +"\n"
+ "end = " + end +"\n========= data ===========\n"
+ m_strInputData.substring(end, start)
+"\n========= data ===========\n"
+"\n--------------------------------------\n\n";
m_sbError.append(msgError);
currAMValue.setErrorString(msgError);
}
iPrevAsciiMathBlockValue_BlockEnds = currAMValue.getPrevAsciiMathBlockValue_BlockEnds();
iIndEndofStartBlock = currAMValue.getIndEndofStartBlock();
/*
System.out.println("1 m_strInputData.len=" +m_strInputData.length());
System.out.println("iPrevAsciiMathBlockValue_BlockEnds=" +iPrevAsciiMathBlockValue_BlockEnds);
System.out.println("iIndEndofStartBlock=" +iIndEndofStartBlock);
System.out.println();
*/
if (prevAsciiMathBlockValue == null)
iPrevAsciiMathBlockValue_BlockEnds = 0;
/*
else
iPrevAsciiMathBlockValue_BlockEnds = prevAsciiMathBlockValue.getIndFoundEnd();
*/
iIndEndofStartBlock = start;
/*
System.err.println("m_strInputData.len=" +m_strInputData.length());
System.err.println("iPrevAsciiMathBlockValue_BlockEnds=" +iPrevAsciiMathBlockValue_BlockEnds);
System.err.println("iIndEndofStartBlock=" +iIndEndofStartBlock);
System.err.println();
*/
if (iIndEndofStartBlock <= iPrevAsciiMathBlockValue_BlockEnds)
{
listErrorValues.add(currAMValue);
int indSubStart = prevAsciiMathBlockValue.getIndFound();
int indSubEnd ;
indSubEnd = currAMValue.getNextAsciiMathBlockValue_EndofStartBlock();
if (indSubEnd == -1)
indSubEnd = currAMValue.getIndFoundEnd();
msgError = "Error:\nIndex value for starting asciimath xml-block is smaller than where a previous ascimatch index value ended!!!!\n"
+strAsciiMathValue +"\nThis means usually that asmiimath blocks are not correct!!!\n"
+ "row = " +currAMValue.getRow() +"\n"
+ "column = " +currAMValue.getColumn() +"\n"
+ "iIndEndofStartBlock = " +iIndEndofStartBlock +"\n"
+ "iPrevAsciiMathBlockValue_BlockEnds = " +iPrevAsciiMathBlockValue_BlockEnds +"\n"
+"\n========= data ===========\n"
+ m_strInputData.substring(indSubStart, indSubEnd)
+"\n========= data ===========\n"
+"\n--------------------------------------\n\n";
m_sbError.append(msgError);
currAMValue.setErrorString(msgError);
}
// all done, returning ok
if (currAMValue == null)
return 0; // ok
// start substring before current asciimath block and after allready
// handled text position end
strStart = m_strInputData.substring(iPrevAsciiMathBlockValue_BlockEnds,
iIndEndofStartBlock);
m_sb.append(strStart);
// when convert html chars has been set, then convert html chars
if (bConvertHtmlChars)
m_sb.append(getChangeNormalCharactersIntoLTAndGTHtmlCharacters(modifiedMathValue));
else // do not convert html chars
m_sb.append(modifiedMathValue);
if (m_bPrintAsciMaths) // "print" current asciimath block values (gui uses)
m_sbPrintData = pamb.printAllAsciiMathBloks(arrblok);
/*
indAsciiMathBlockEnds = currAMValue.getIndAsciiMathBlockEnds();
indNextMathBlockStart = currAMValue.getNextAsciiMathBlockValue_EndofStartBlock();
if (indNextMathBlockStart == -1)
strEndAsciiMathBlock = m_strInputData.substring(indAsciiMathBlockEnds);
else
strEndAsciiMathBlock = m_strInputData.substring(indAsciiMathBlockEnds, indNextMathBlockStart);
if (strEndAsciiMathBlock == null)
System.err.println("!!");
else
m_sb.append(strEndAsciiMathBlock);
*/
prevAsciiMathBlockValue = currAMValue;
indInput = end;
} // end of for
m_hm_asciimath_values = hm_value;
indAsciiMathBlockEnds = m_strInputData.length();
indNextMathBlockStart = currAMValue.getIndFoundEnd();
/*
if (indNextMathBlockStart == -1)
strEndAsciiMathBlock = m_strInputData.substring(indAsciiMathBlockEnds);
else
*/
// add possible last text into data buffer
strEndAsciiMathBlock = m_strInputData.substring(indNextMathBlockStart);
if (strEndAsciiMathBlock == null)
System.err.println("!!");
else
m_sb.append(strEndAsciiMathBlock);
// check and convert possible errors
if (m_sbError != null && m_sbError.length() == 0 && listErrorValues.size() == 0)
{
m_sbError = null;
m_arrErrorAsciiMathBlockValue = null;
}
else
{
Object arrObj [] = listErrorValues.toArray();
int size = arrObj.length;
m_arrErrorAsciiMathBlockValue = new AsciiMathBlockValue[size];
for(int j = 0; j < size; j++)
{
m_arrErrorAsciiMathBlockValue[j] = (AsciiMathBlockValue)arrObj[j];
}
}
// if there is no asciimath blocks, then return unmodified text
if (m_sb.length() == 0)
{
m_sb = new StringBuffer(m_strInputData);
return -1;
}
ret = 0; // ok
/*
if (m_sb.length() != end)
{
strStart = m_strInputData.substring(end);
m_sb.append(strStart);
}
*/
/*
// if data is unmodified:
m_sb = new StringBuffer(m_strInputData);
// start convertion (ind is an index value on
// next search postion, until -1 reached
while((ind = seekAndConvertAsciiMathData(ind)) > -1)
;
int ret = 0; // ok
*/
return ret;
}
/*
private int
seekAndConvertAsciiMathData(int indFound)
throws NullPointerException, Exception
{
final int cnstStop = -1;
// a paraemter check:
if (indFound < 0)
return cnstStop;
int len = m_sb.length()-1;
if (indFound > len)
return cnstStop;
// searching possible asciimath block:
int indAsciiMathBlockStart = m_sb.indexOf(
cnstAsciiMathBlockStart, indFound);
if (indAsciiMathBlockStart == -1)
{
// with different charachter size:
indAsciiMathBlockStart = m_sb.indexOf(
cnstAsciiMathBlockStart.toUpperCase(), indFound);
if (indAsciiMathBlockStart == -1)
return cnstStop;
}
// seaching ending character > for start asciimath block:
int indEndofStartBlock = m_sb.indexOf(">", indAsciiMathBlockStart);
if (indEndofStartBlock == -1)
return indAsciiMathBlockStart+1;
if (len < (indEndofStartBlock+1) )
return cnstStop;
int indAsciiMathBlockEnds = m_sb.indexOf(
cnstAsciiMathBlockEnds, indEndofStartBlock+1);
if (indAsciiMathBlockEnds == -1)
{
// with different charachter size:
indAsciiMathBlockEnds = m_sb.indexOf(
cnstAsciiMathBlockEnds.toUpperCase(), indEndofStartBlock);
if (indAsciiMathBlockEnds == -1)
return cnstStop;
}
//String tmp_test = m_sb.substring(indEndofStartBlock+1);
//tmp_test = m_sb.substring(indEndofStartBlock+1, indAsciiMathBlockEnds);
// is there is an another started asciimath block allready...
int iAnotherSpanHasStarted = anotherSpanHasStarted(indAsciiMathBlockStart,
indAsciiMathBlockEnds);
if (iAnotherSpanHasStarted > -1)
{
// TODO: virheenkäsittely koodi, kerää tiedot, mutta jatkaa silti?!!
return iAnotherSpanHasStarted;
}
// is not an ascimath block:
if (isNotAsciiMathBlock(indAsciiMathBlockStart, indEndofStartBlock))
return indAsciiMathBlockEnds;
// a founded asciimath block:
int indMatchDataStart = indEndofStartBlock +1;
int indMatchDataEnd = indAsciiMathBlockEnds;
String strAsciiMath = m_sb.substring(
indMatchDataStart, indMatchDataEnd);
if (strAsciiMath == null)
return cnstStop;
String strNewAsciiMath = getConvertAsciiMatchValue(strAsciiMath);
?*
String strNewAsciiMath = getChangeLTAndGTHtmlCharactersIntoNormalCharacters(strAsciiMath);
//String strNewAsciiMath = strAsciiMath; //
// read lists and array from configuration file:
fullFillArraysWithConfigList();
// rule handling:
if (bConvertAsciiMathDataReplaceAllReservedWords)
{
strNewAsciiMath = replaceAllReservedWords(strNewAsciiMath);
}
if (bConvertAsciiMathDataCommaRule)
{
strNewAsciiMath = convertAsciiMathDataCommaRule(strNewAsciiMath);
}
if (bConvertAsciiMathDataNumberRule)
{
strNewAsciiMath = convertAsciiMathDataNumberRule(strNewAsciiMath);
}
if (bConvertAsciiMathDataSpaceRule)
{
//String markedDoNotModifySomeWords = getDontModifyData(strNewAsciiMath);
strNewAsciiMath = convertAsciiMathDataWithSpaceRule(strNewAsciiMath);
}
*?
if (strNewAsciiMath == null)
return cnstStop;
// construct a new modified start string and end string between
// modified ascimath block:
String strStart = m_sb.substring(0, indMatchDataStart);
int lenNewAsciiMath = strNewAsciiMath.length();
// m_sb.replace(start, end, str)
//m_sb.replace((indMatchDataStart), (indMatchDataStart+strStart.length()),
// strNewAsciiMath);
String strEnd = m_sb.substring(indMatchDataEnd);
//StringBuffer tmp_m_sb =
m_sb = new StringBuffer(strStart + strNewAsciiMath + strEnd);
//System.out.println("tmp_m_sb='" +tmp_m_sb.toString() +"'");
//System.out.println("m_sb='" +m_sb.toString() +"'");
setInputDataLen();
// calculate a new searching postion for an asciimath block:
return getNewIndMatchDataEnd(indMatchDataStart,
strNewAsciiMath.length());
}
*/
/**
* This method returns a modified String after replaced all reserved words
* in the paraemeter value. Replaced words and new values for them are located in
* the .properties file of this class.
* @param strAsciiMath
* @return See above
*/
private String
replaceAllReservedWords(String strAsciiMath)
throws DtbookAsciiMathException
{
if (strAsciiMath == null || strAsciiMath.trim().length() == 0)
return strAsciiMath;
int max = m_sortedReplaceReservedWords.size();
if (max == 0)
return strAsciiMath;
/*
while (stepper.hasNext()) {
current = (String)stepper.next();
System.out.println(current);
}
//listvalues
*
*/
String strSearch, strValue;
// use sorted list, because longest search value will be handled at first etc
Iterator<String> ite = m_sortedReplaceReservedWords.iterator();
int ind ;
for(; ite.hasNext(); )
{
strSearch = (String)ite.next();
if (strSearch == null || strSearch.trim().length() == 0)
continue;
// get replace value by search value
strValue = (String)this.m_propertyReplaceReservedWords.get(strSearch);
if (strValue == null)
strValue = "";
ind = strAsciiMath.indexOf(strSearch);
if (ind > -1 /* strAsciiMath.contains(strSearch) */)
{
String start, end = "", replacedValue = strValue;
int len = strSearch.length();
StringBuffer sb = new StringBuffer();
int pos;
while(ind != -1)
{
start = strAsciiMath.substring(0, ind);
if (start == null)
start = "";
pos = (ind + len);
end = strAsciiMath.substring(pos);
if (end == null)
end = "";
sb.append(start + replacedValue);
strAsciiMath = end;
ind = strAsciiMath.indexOf(strSearch);
}
sb.append(end);
strAsciiMath = sb.toString();
}
}
return strAsciiMath;
}
/**
* This method is converting an ascimath block value after rules
* @param strAsciiMath an ascimath block value
* @return Converted asciimath text
* @throws DtbookAsciiMathException an error occurred
* @throws NullPointerException an null pointer error occurred
* @throws Exception common error occurred
*/
public String getConvertAsciiMatchValue(String strAsciiMath)
throws DtbookAsciiMathException, NullPointerException, Exception
{
String strNewAsciiMath = getChangeLTAndGTHtmlCharactersIntoNormalCharacters(strAsciiMath);
//String strNewAsciiMath = strAsciiMath; //
// read lists and array from configuration file:
//fullFillArraysWithConfigList();
// rule handling:
// converting is done after boolean flags
int indDupleStrike = strNewAsciiMath.indexOf('"');
String strStikeValue = strNewAsciiMath;
String [] arrStrikeValues = null;
int len = 0;
if (indDupleStrike != -1)
{
arrStrikeValues = strNewAsciiMath.split("\"");
len = arrStrikeValues.length;
if (arrStrikeValues.length % 2 != 0 && (arrStrikeValues.length-1) % 2 != 0)
//indDupleStrike = len -1; // ERROR: NONE PAIR STRIKE!!!
throw new DtbookAsciiMathException("None Pair\" characters: " +strAsciiMath);
}
int i = 0;
StringBuffer sb = new StringBuffer();
boolean bNoneStrikes = true;
// System.err.println("len=" +len);
while((indDupleStrike == -1 && i == 0) || (indDupleStrike != -1 && i < len))
{
if (indDupleStrike > -1)
{
strStikeValue = arrStrikeValues[i];
}
if (bNoneStrikes)
{
if (bConvertAsciiMathDataReplaceAllReservedWords)
{
strStikeValue = replaceAllReservedWords(strStikeValue);
}
if (bConvertAsciiMathDataCommaRule)
{
strStikeValue = convertAsciiMathDataCommaRule(strStikeValue);
}
if (bConvertAsciiMathDataNumberRule)
{
strStikeValue = convertAsciiMathDataNumberRule(strStikeValue);
}
if (bConvertAsciiMathDataSpaceRule)
{
//String markedDoNotModifySomeWords = getDontModifyData(strNewAsciiMath);
strStikeValue = convertAsciiMathDataWithSpaceRule(strStikeValue);
}
sb.append(strStikeValue);
}
else
sb.append("\"" + strStikeValue + "\"");
i++;
bNoneStrikes = ! bNoneStrikes;
}
return sb.toString();
}
/**
* This method is converting some html characters into normal characters
* @param value A value contains possible html characters
* @return Converted normal text
*/
public static String
getChangeLTAndGTHtmlCharactersIntoNormalCharacters(String value)
{
if (value != null)
{
// replace these html coded < character into normal < characer
value = value.replaceAll("<", "<");
value = value.replaceAll("<", "<");
value = value.replaceAll("<", "<");
// replace all html coded > character into normal > characer
value = value.replaceAll(">", ">");
value = value.replaceAll(">", ">");
value = value.replaceAll(">", ">");
// replace all html coded & character into normal & characer
value = value.replaceAll("&", "&");
value = value.replaceAll("&", "&");
value = value.replaceAll("&", "&");
}
return value;
}
/**
* This method is converting some normal characters into some html characters
* @param value Normal text
* @return Converted text, which may contain some html characcters
*/
public static String
getChangeNormalCharactersIntoLTAndGTHtmlCharacters(String value)
{
if (value != null)
{
// & replace must done before another replacing, because they contains also & character!!:
//value = value.replaceAll("&", "&");
value = value.replaceAll("&", "&");
// replace all earlier html coded < character back into html coded < characer
value = value.replaceAll("<", "<");
// replace all earlier html coded > character back into html coded > characer
value = value.replaceAll(">", ">");
}
return value;
}
/*
private int
getNewIndMatchDataEnd(int indMatchDataStart, int iNewAsciiMathLength)
{
return indMatchDataStart + iNewAsciiMathLength
+cnstAsciiMathBlockEnds.length(); // ok, continue
}
*/
/*
private int
anotherSpanHasStarted(int indAsciiMathBlockStart, int indAsciiMathBlockEnds)
{
int ind2 = indAsciiMathBlockStart + cnstAsciiMathBlockStart.length();
if (ind2 > (m_sb.length()-1) )
return -1;
int ind = m_sb.indexOf(cnstAsciiMathBlockStart, ind2);
if (ind == -1)
{
// eri kirjainkoolla:
ind = m_sb.indexOf(
cnstAsciiMathBlockStart.toUpperCase(), ind2);
}
if (ind > -1 && ind < indAsciiMathBlockEnds)
return ind;
return -1; // all is ok, has not started an another span block before ending the first one
}
*/
/*
private boolean
isNotAsciiMathBlock(int indAsciiMathBlockStart, int indEndofStartBlock)
{
// class="asciimath">
int ind = m_sb.indexOf("class", indAsciiMathBlockStart);
if (ind == -1 || ind >= indEndofStartBlock)
{
ind = m_sb.indexOf("CLASS", indAsciiMathBlockStart);
if (ind == -1 || ind >= indEndofStartBlock)
return true;
}
int ind2 = m_sb .indexOf("=", ind);
if (ind2 == -1 || ind2 >= indEndofStartBlock)
return true;
char chDelim = '"';
int ind3 = m_sb.indexOf(""+chDelim, ind2);
if (ind3 == -1 || ind3 >= indEndofStartBlock)
{
chDelim = '\'';
ind3 = m_sb.indexOf(""+chDelim, ind2);
if (ind3 == -1 || ind3 >= indEndofStartBlock)
return true;
}
if ((ind3+1) >= indEndofStartBlock || (ind3+1) > m_sb.length())
return true;
int ind4 = m_sb.indexOf(""+chDelim, ind3+1);
if (ind4 == -1 || ind4 >= indEndofStartBlock)
return true;
String strAttrib = m_sb.substring(ind3+1, ind4);
if (strAttrib == null)
return true;
if (!strAttrib.toLowerCase().equals("asciimath"))
return true;
return false; // span is an ASCIIMATH span
}
*/
/**
* This method is converting asciimath block data after comma rule
* for numbers. The rule is says that all point characters inside
* numbers must converted into , characters. It is using regexp for that.
* @param strMathData
* @return
* @throws NullPointerException
* @throws Exception
*/
private String
convertAsciiMathDataCommaRule(String strMathData)
throws PatternSyntaxException, IllegalArgumentException,
NullPointerException, Exception
{
// replace all comma character into "new" comma characters
String strModifiedMathData = strMathData.replace(m_replaceAllComma, m_replaceAllWithSemiColon);
String strRegex = "(\\d{1,})\\" + m_replaceAllNumberPoint +"(\\d{1,})";
String strReplace = "$1" + m_replaceAllNumberComma +"$2";
strModifiedMathData = strModifiedMathData.replaceAll(strRegex, strReplace);
return strModifiedMathData;
}
/**
* This method is converting asciimath block data after that numbers must
* have point characters every 3th charachter and have possible comma
* character at last within a number before decimal fragment numbers.
* It is using regexp and java code for that.
*
* @param strMathData
* @return
* @throws PatternSyntaxException
* @throws IllegalArgumentException
* @throws NullPointerException
* @throws Exception
*/
private String
convertAsciiMathDataNumberRule(String strMathData)
throws PatternSyntaxException, IllegalArgumentException,
NullPointerException, Exception
{
// search number in the form: 999,222:
try {
//1.version: Pattern regex = Pattern.compile("(\\d{1,}),(\\d{1,})");
//2.version: Pattern regex = Pattern.compile("(\\d{1,})((\\,(\\d{1,})){0,1})");
// search all numbers wich may have , or . characters inside a number
Pattern regex = Pattern.compile("((\\d{1,})([\\,\\.]{0,1})){1,}");
Matcher regexMatcher = regex.matcher(strMathData);
//MatchResult matchResult;
try {
int iStart, iEnd, istartPartOfNumberLen;
String number;
String endPartOfNumber, startPartOfNumber, modiedData;
StringBuffer sb = new StringBuffer();
boolean founded = false;
// find numbers and add . or , characters between 3th number characters
// The , character is set only at last inside of a number
while(regexMatcher.find())
{
founded = true;
//matchResult = regexMatcher.toMatchResult();
iStart = regexMatcher.start();
iEnd = regexMatcher.end();
number = strMathData.substring(iStart, iEnd);
if (number == null)
continue;
// is there , charchter
int indComma = number.indexOf(',');
endPartOfNumber = null;
startPartOfNumber = null;
startPartOfNumber = number;
if (indComma != -1)
{
endPartOfNumber = number.substring(indComma);
startPartOfNumber = number.substring(0, indComma);
}
if (startPartOfNumber == null)
continue;
istartPartOfNumberLen = startPartOfNumber.length();
modiedData = startPartOfNumber;
if (istartPartOfNumberLen > 0) // if there exists number characters before , or .
modiedData = getNumberAddedWithPointChar(startPartOfNumber);
if (endPartOfNumber != null)
modiedData = modiedData + endPartOfNumber;
// replace current value with modied data
regexMatcher.appendReplacement(sb, modiedData);
} // end of while
String modifiedValue = strMathData;
if (founded) // at last one number has been founded
{ // append tail text into regex variable and return
// modified value
regexMatcher.appendTail(sb);
modifiedValue = sb.toString();
}
// 2. searh: mixed search strings; partly right, partly wrong words:
/* not working:
founded = false;
regex = Pattern.compile("((\\d{1,}\\.\\d{0,}\\,\\d{1,}))");
regexMatcher = regex.matcher(modifiedValue);
sb = new StringBuffer();
while(regexMatcher.find())
{
founded = true;
matchResult = regexMatcher.toMatchResult();
iStart = regexMatcher.start();
iEnd = regexMatcher.end();
number = strMathData.substring(iStart, iEnd);
if (number == null)
continue;
int indComma = number.indexOf(',');
endPartOfNumber = null;
startPartOfNumber = null;
startPartOfNumber = number;
if (indComma != -1)
{
endPartOfNumber = number.substring(indComma);
startPartOfNumber = number.substring(0, indComma);
}
if (startPartOfNumber == null)
continue;
istartPartOfNumberLen = startPartOfNumber.length();
modiedData = startPartOfNumber;
if (istartPartOfNumberLen > 0)
modiedData = getNumberAddedWithPointChar(startPartOfNumber);
if (endPartOfNumber != null)
modiedData = modiedData + endPartOfNumber;
regexMatcher.appendReplacement(sb, modiedData);
}
if (founded)
{
regexMatcher.appendTail(sb);
modifiedValue = sb.toString();
}
*/
return modifiedValue;
} catch (IllegalArgumentException ex) {
// Syntax error in the replacement text (unescaped $ signs?)
throw ex;
} catch (IndexOutOfBoundsException ex2) {
// Non-existent backreference used the replacement text
throw ex2;
}
} catch (PatternSyntaxException ex3) {
// Syntax error in the regular expression
throw ex3;
}
}
/**
* This method returns a number string added . character every 3th number
* character if needed. A parameter number must <b>not</b> have decimal
* numbers after an , character!
* @param value
* @return
*/
private String
getNumberAddedWithPointChar(String value)
{
if (value != null)
{
int len = value.length();
if (len < 4)
return value;
String tmp = value.replaceAll("\\.", "");
len = tmp.length();
StringBuffer sp = new StringBuffer();
int iStartNumberChars = (len % 3);
//int iRemain = (len > (3*iStartNumberChars)) ? (len - (3*iStartNumberChars)) : ((3*iStartNumberChars) - len);
int iCounter = (len / 3);
int iStartPart = (iStartNumberChars > 0) ? iStartNumberChars : 0;
String substr = null;
if (iStartNumberChars > 0)
{
substr = tmp.substring(0, iStartNumberChars);
if (substr != null)
{
sp.append(substr);
}
}
int pos = iStartPart;
boolean bFirsTime = true;
for(int i = 0; i < iCounter ; i++)
{
if (bFirsTime)
{
if (iStartPart > 0)
sp.append("." + tmp.substring(pos, (pos+3)));
else
sp.append(tmp.substring(pos, (pos+3)));
}
else
sp.append("." + tmp.substring(pos, (pos+3)));
pos = pos +3;
bFirsTime = false;
}
return sp.toString();
}
return value;
}
/**
* This method is converting asciimath block data after what
* space character rules says. These space rules added, removed
* space character before or/and after specific words or text.
* It is using regexp and java code for that.
*
* @param strMathData
* @return
* @throws NullPointerException
* @throws Exception
*/
private String
convertAsciiMathDataWithSpaceRule(String strMathData)
throws NullPointerException, Exception
{
String strModifiedMathData = new String(strMathData);
//fullFillArraysWithConfigList();
//strModifiedMathData = replaceAllReservedWords(strModifiedMathData);
String [] arrUsedTokens;
// sort used array after logest words,
// without 'not:' values:
arrUsedTokens = getArrBothSidesSpaceToken();
String strRegex = "(\\s*)%s(\\s*)";
String strReplace = " %s ";
strModifiedMathData = getModifyData(strRegex, strReplace,
arrUsedTokens, strModifiedMathData);
arrUsedTokens = getArrSpaceBeforeButNotAfter();
strRegex = "(\\s*)%s(\\s*)";
strReplace = " %s";
strModifiedMathData = getModifyData(strRegex, strReplace,
arrUsedTokens, strModifiedMathData);
arrUsedTokens = getArrNoSpaciesIntoBothSideToken();
strRegex = "(\\s*)%s(\\s*)";
strReplace = "%s";
strModifiedMathData = getModifyData(strRegex, strReplace,
arrUsedTokens, strModifiedMathData);
arrUsedTokens = getArrSpaceAfterButNotBeforeToken();
//strRegex = "%s(\\s*)";
strRegex = "(\\s*)%s(\\s*)";
strReplace = "%s ";
strModifiedMathData = getModifyData(strRegex, strReplace,
arrUsedTokens, strModifiedMathData);
// ota pois mahdolliset muutettujen kohtien merkkausliteraalit sen jälkeen,
// kun kaikki muutokset on tehty
int ind = strModifiedMathData.indexOf(cnstDontModifyBegin);
if (ind > -1)
strModifiedMathData = strModifiedMathData.replaceAll(
cnstDontModifyBegin, "");
ind = strModifiedMathData.indexOf(cnstDontModifyEnd);
if (ind > -1)
strModifiedMathData = strModifiedMathData.replaceAll(
cnstDontModifyEnd, "");
return strModifiedMathData;
}
/**
* This method is fullfilling config value arrays from corresponding
* list variable, which are readed from config file. All config values
* are sorted after the longest value comes at first, etc.
*
* @throws NullPointerException
* @throws Exception
*/
private void
fullFillArraysWithConfigList()
throws NullPointerException, Exception
{
int max = m_srcBothSidesSpaceToken.size();
m_arrBothSidesSpaceToken = getOrderedArr(m_srcBothSidesSpaceToken.getArray(), -1);
max = m_srcSpaceBeforeButNotAfter.size();
m_arrSpaceBeforeButNotAfter = getOrderedArr(m_srcSpaceBeforeButNotAfter.getArray(), -1);
max = m_srcSpaceAfterButNotBeforeToken.size();
m_arrSpaceAfterButNotBefore = getOrderedArr(m_srcSpaceAfterButNotBeforeToken.getArray(), -1);
max = m_srcNoSpaciesIntoBohSideToken.size();
m_arrNoSpaciesIntoBothSideToken = getOrderedArr(m_srcNoSpaciesIntoBohSideToken.getArray(), -1);
String rowArray [] = m_listReplace_reserved_wordToken.getArray();
m_propertyReplaceReservedWords = new Properties();
if (rowArray != null)
{
max = rowArray.length;
String row, key, value, msgError;
int ind;
HashMap<String, String> listvalues = new HashMap<String, String> ();
List <String> stuff = new ArrayList<String>();
for(int i = 0; i < max; i++)
{
row = rowArray[i];
if (row == null || row.trim().length() == 0)
continue;
ind = row.indexOf('=');
if (ind == -1)
continue;
key = row.substring(0, ind).trim();
if (key.trim().length() == 0)
{
msgError = "Warning:\nEmpty property-key: row '" + row +"'\n"
+"--------------------------------------\n\n";
m_sbError.append(msgError);
continue;
}
value = row.substring(ind+1).trim();
listvalues.put(key, value);
stuff.add(key);
}
m_propertyReplaceReservedWords.putAll(listvalues);
//System.out.println("---------- Sort by line length");
Collections.sort(stuff, new StringLengthComparator());
m_sortedReplaceReservedWords = stuff;
}
}
/**
* This method is returning modified data after space rules.
* @param strRegex conversion regex value, like:
* @param strReplace replace regex value, like:
* @param arrTokens text values which must added/removed space before or after it
* @param strModifiedMathData a data must be modified after a space rule
* @return Modified data
* @throws NullPointerException Error exception
* @throws Exception Error exception
*/
private String
getModifyData(String strRegex,
String strReplace,
String [] arrTokens,
String strModifiedMathData)
throws NullPointerException, Exception
{
int max = arrTokens.length;
String strToken;
String strDontModifyToken;
boolean bRegexTokenWithPossibleLiteral = true;
// at first mark those search text, which will not changed during convertion,
// but which too same kind of searched value. By example: change int, but not
// int_ . See config file: int (not: int_)
// Text values which must not changed are marked with "not-replace words"
// (cnstNOTThiswords) with special (cnstDontModify) word before an actual
// replace will start. An example, search word: int, with also has a
// do-not-change value: int_, then a word "int_" will be replaced
// "x__JAsciiMath_DontModifyconst__x" (cnstDontModify). And then actual
// replace int value will be done. At last x__JAsciiMath_DontModifyconst__x
// strings are replaced back into int_ etc.
// By using this kind of special mark strings, all ready replaced
// or changed words are marked: "do-not-change-this-any-more" or
// "do-not-change-this-on-this-time". After all changes these kind of
// special marked strings are removed from modified text. Only actual
// modified characters and strings will be remained and a text will returned.
// it is important that all array values are sorted after longest value
// at first! So that allready modified value will be marked
// "do-not-chnage-this-any-more-it-has-been-allready-changed" mark text.
// at last all special mark text are removed
for(int i = 0; i < max; i++)
{
// if this search value has dont modify this value
// if no, then it returs null
// TODO: if don't modify value has more than just one value, is that working!!
strDontModifyToken = getDontModifyToken(arrTokens[i]);
// get serached token, possible change what regexp says about special meta regex characters
strToken = getNormalToken(arrTokens[i], bRegexTokenWithPossibleLiteral);
if (strToken == null)
continue;
// jos älä muuta dataa, muuta varoiksi mahdollinen merkkijono
// vakioksi, jota ei ole tekstissä, ja se sitten normaalin muutoksen
// jälkeen takaisin vakio siksi merkkijonoksi, jota ei saa muuttaa!
// Tämä merkkijono, jota halutaan muuttaa, on osamerkkijono siitä merkkijonosta, jota ei saa
// muuttaa. Sellainen ilmoitetaan (not: xxx, xxx2) merkkijonolla. Esim: int saa välilyönnit,
// paitsi ei int_ merkkjono.
// if there is do-not-modify-this, replace word with strDontModifyToken
// before actual change
if (strDontModifyToken != null)
strModifiedMathData = getDontModifyMarketedData(strDontModifyToken,
strModifiedMathData);
/*
* strModifiedMathData.replaceAll(
strDontModifyToken, cnstDontModify);
*/
// do actual modification with regexp and java code
strModifiedMathData = getModifiedMathData(strModifiedMathData,
strToken, strRegex, // "(\\s*)" +strToken +"(\\s*)",
strReplace); // " " + strToken +" ");
// if there has been used do-not-modify-this, unmodify mark word
// back into earlier text value within strModifiedMathData
if (strDontModifyToken != null)
strModifiedMathData = getUnMarkDontModifyMarketedData(
strDontModifyToken,
strModifiedMathData
);
/* strModifiedMathData.replaceAll(
cnstDontModify,
cnstDontModifyBegin + strDontModifyToken
+cnstDontModifyEnd);
*/
}
return strModifiedMathData;
}
/**
* This method marks one do-not-modify-this-text before actual modification
* (change text) (after workds it is converted back again.). It is supposing
* that dont-modify parameter may contains words (splitted after space!)!!!
* @param strDontModifyToken
* @param strModifiedMathData Data string
* @return
*/
private String
getDontModifyMarketedData(String strDontModifyToken,
String strModifiedMathData)
{
// TODO: is this supposing right: splitted array after space!!! See method comment also!
String dontModifyData [] = strDontModifyToken.split(" ");
if (dontModifyData == null || dontModifyData.length == 0)
return null;
if (dontModifyData.length == 1)
return strModifiedMathData.replaceAll( // tka: added getRegexTokenWithPossibleLiteral( 16.6.2011
getRegexTokenWithPossibleLiteral(strDontModifyToken), cnstDontModify);
String data;
int max = dontModifyData.length;
String dontModifyGeneratedValue;
hmDontModifyData = new HashMap<String, String>();
for(int i = 0; i < max; i++)
{
data = dontModifyData[i];
if (data == null || data.trim().length() == 0)
continue;
dontModifyGeneratedValue = cnstDontModify +i;
hmDontModifyData.put(data, dontModifyGeneratedValue);
strModifiedMathData = strModifiedMathData.replaceAll(data, dontModifyGeneratedValue);
}
return strModifiedMathData;
}
/**
* This method unmarks speciall words (not: xxx, xxx) after marked words and
* after replacing a changed word.
* @param strDontModifyToken
* @param strModifiedMathData
* @return
*/
private String
getUnMarkDontModifyMarketedData(String strDontModifyToken,
String strModifiedMathData)
{
String dontModifyData [] = strDontModifyToken.split(" ");
if (dontModifyData == null || dontModifyData.length == 0)
return null;
if (dontModifyData.length == 1)
return strModifiedMathData.replaceAll(
cnstDontModify,
cnstDontModifyBegin + strDontModifyToken
+cnstDontModifyEnd);
String data;
int max = hmDontModifyData.size();
String dontModifyGeneratedValue;
Set<String> keys = hmDontModifyData.keySet();
Iterator<String> ite = keys.iterator();
while(ite.hasNext())
{
data = ite.next();
dontModifyGeneratedValue = hmDontModifyData.get(data);
strModifiedMathData = strModifiedMathData.replaceAll(dontModifyGeneratedValue, data);
}
return strModifiedMathData;
}
/**
* This method reorderer array after max words first, shorter after it etc.
* parameter from arrUnOrdered array.
*
* @param arrUnOrdered
* @param iBelowValue
* @return
* @throws NullPointerException
* @throws Exception
*/
private String []
getOrderedArr(String [] arrUnOrdered, int iBelowValue)
throws NullPointerException, Exception
{
if (arrUnOrdered == null)
return arrUnOrdered;
int maxValueLen = 0;
List<String> list = new ArrayList<String>();
maxValueLen = seekMaxLenghtOfIndexValue(arrUnOrdered, iBelowValue);
while(maxValueLen != 0 && (iBelowValue == -1 || maxValueLen < iBelowValue))
{
list.addAll(getMaxLenghtOfIndexValue(arrUnOrdered, maxValueLen));
maxValueLen = seekMaxLenghtOfIndexValue(arrUnOrdered, maxValueLen);
}
Collections.sort(list, new StringLengthComparator());
Object [] arrObj = list.toArray();
int max2 = arrObj.length;
String [] arrRet = new String [max2];
for(int j = 0; j < max2; j++)
{
arrRet[j] = arrObj[j].toString();
}
return arrRet;
}
/**
* @param arrUnOrdered
* @param iAllValuesOfLen
* @return
* @throws NullPointerException
* @throws Exception
*/
private Collection<String>
getMaxLenghtOfIndexValue(String [] arrUnOrdered, int iAllValuesOfLen)
throws NullPointerException, Exception
{
Collection<String> col = new ArrayList<String>();
int max = arrUnOrdered.length;
String strValue;
int iValueLen, maxValueLen = 0;
boolean bRegexTokenWithPossibleLiteral = false;
for(int i = 0; i < max; i++)
{
strValue = getNormalToken(arrUnOrdered[i], bRegexTokenWithPossibleLiteral);
if (strValue == null)
continue;
iValueLen = strValue.length();
if (iAllValuesOfLen == iValueLen)
// palauta alkup. arvo, koska se voi sisältää (paisi: xxx):n, eli mitä arvoa ei muuuteta
col.add(arrUnOrdered[i]);
}
return col;
}
/**
* This method seeks index value of max length below iBelowValue
* parameter from arrUnOrdered array.
* @param arrUnOrdered
* @param iBelowValue
* @return
* @throws NullPointerException
* @throws Exception
*/
private int
seekMaxLenghtOfIndexValue(String [] arrUnOrdered, int iBelowValue)
throws NullPointerException, Exception
{
if (arrUnOrdered == null)
return 0;
if (iBelowValue == 1)
return 0;
int iValueLen, maxValueLen = 0;
int max = arrUnOrdered.length;
String strValue;
boolean bRegexTokenWithPossibleLiteral = false;
for(int i = 0; i < max; i++)
{
strValue = getNormalToken(arrUnOrdered[i], bRegexTokenWithPossibleLiteral);
if (strValue == null)
continue;
iValueLen = strValue.length();
if (iValueLen > maxValueLen &&
(iBelowValue == -1 || iValueLen < iBelowValue))
maxValueLen = iValueLen;
}
return maxValueLen;
}
/**
* See the name of method.
* @return
*/
private String []
getArrBothSidesSpaceToken()
{
return m_arrBothSidesSpaceToken;
}
/*
* See the name of method.
* @return
*/
private String []
getArrSpaceBeforeButNotAfter()
{
return m_arrSpaceBeforeButNotAfter;
}
/**
* See the name of method.
* @return
*/
private String []
getArrNoSpaciesIntoBothSideToken()
{
return m_arrNoSpaciesIntoBothSideToken;
}
/**
* See the name of method.
* @return
*/
private String []
getArrSpaceAfterButNotBeforeToken()
{
return m_arrSpaceAfterButNotBefore;
}
/* ok for 14.9.2010, regex search method:
*
*/
/**
* This method converts data after the parameters with regexp and java code.
* @param strModifiedMathData Data or part of it
* @param strToken A text to changed
* @param strRegex Used regular expression
* @param strReplace Replace value (like: " %s", " %s " etc)
* @return Modified data
* @throws NullPointerException An error
*/
private String
getModifiedMathData(String strModifiedMathData,
String strToken,
String strRegex,
String strReplace)
throws NullPointerException
{
// parameter checking
if (strModifiedMathData == null)
return strModifiedMathData;
if (strToken == null)
throw new NullPointerException("strToken == null");
if (strRegex == null)
throw new NullPointerException("strRegex == null");
if (strReplace == null)
throw new NullPointerException("strReplace == null");
String resultString = null, strValue;
String regexString = null;
String replaceString = null;
try {
// Replace regex %s value (like: "regexp1%sregexp1", where %s will be strToken value)
regexString = String.format(strRegex, strToken);
// Replace value (like: " %s", " %s " etc where %s has strToken value)
replaceString = String.format(strReplace, strToken);
Pattern regex = Pattern.compile(regexString);
Matcher regexMatcher = regex.matcher(strModifiedMathData);
int iStart, iEnd;
boolean bPossibleModificationOfMarkStartWord = false;
boolean bPossibleModificationOfMarkEndWord = false;
// check token has don-modify this xxx
int indPossibleModificationOfMarkStartWord = cnstDontModifyBegin.indexOf(strToken);
if (indPossibleModificationOfMarkStartWord > -1)
bPossibleModificationOfMarkStartWord = true;
int indPossibleModificationOfMarkEndWord = cnstDontModifyEnd.indexOf(strToken);
if (indPossibleModificationOfMarkEndWord > -1)
bPossibleModificationOfMarkEndWord = true;
boolean ret = false;
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)
// check if there is don-modify-begin word before it
if (bPossibleModificationOfMarkStartWord)
{
ret = getPossibleModificationOfMarkWord(cnstDontModifyBegin,
strToken, strModifiedMathData, iStart, iEnd);
if (ret)
continue;
}
// check if there is don-modify-end word after it
if (bPossibleModificationOfMarkEndWord)
{
ret = getPossibleModificationOfMarkWord(cnstDontModifyEnd,
strToken, strModifiedMathData, iStart, iEnd);
if (ret)
continue;
}
// if this foundedf value has not modified-allready-value, then
// convert it
if (isNotModifiedToken(strToken, strModifiedMathData, iStart, iEnd,
bPossibleModificationOfMarkStartWord,
bPossibleModificationOfMarkEndWord))
{
strValue = strModifiedMathData.substring(iStart, iEnd);
// some data checking
if (strValue == null)
throw new NullPointerException("strValue == null");
resultString = strValue.replaceAll(regexString, replaceString);
if (resultString == null)
throw new NullPointerException("resultString == null");
String strStart = strModifiedMathData.substring(0, iStart);
String strEnd = "";
if (iEnd < (strModifiedMathData.length()))
strEnd = strModifiedMathData.substring(iEnd);
// that this token is handled allready:
if (strEnd == null || strEnd.trim().length() == 0)
{
return strStart + cnstDontModifyBegin +
resultString + cnstDontModifyEnd
+ "" ;
}
else
{
/* if founded value contains " chars at the end and
* start of it, then do not change anything, but
* mark this founded: do not chnage any more,
* at last call recursive this method to the rest of
* data
*/
if (strStart != null && strEnd != null
&& strStart.endsWith("\"")
&& strEnd.startsWith("\"") )
{
return strStart + cnstDontModifyBegin +
strValue + cnstDontModifyEnd +
getModifiedMathData(strEnd, strToken, strRegex, strReplace);
}
else
{
// normal change without " strikes
// at last call recursive this method to the rest of data
return strStart + cnstDontModifyBegin +
resultString + cnstDontModifyEnd +
getModifiedMathData(strEnd, strToken, strRegex, strReplace);
}
}
}
}
return strModifiedMathData;
} 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;
}
//return strModifiedMathData.replaceAll(strRegex, strReplace);
}
/*
* for testing of an another opportunity to code this function:
* because there has been problem with regex special characters,
* are they literated all ways right!
*/
private String
getModifiedMathData2(String strModifiedMathData,
String strToken,
String strRegex,
String strReplace)
throws NullPointerException
{
if (strModifiedMathData == null)
return strModifiedMathData;
if (strToken == null)
throw new NullPointerException("strToken == null");
if (strRegex == null)
throw new NullPointerException("strRegex == null");
if (strReplace == null)
throw new NullPointerException("strReplace == null");
String resultString = null, strValue;
String regexString = null;
String replaceString = null;
try {
int ind = strModifiedMathData.indexOf(strToken);
if (ind == -1)
return strModifiedMathData;
int iStart, iEnd, indSearch;
boolean bPossibleModificationOfMarkStartWord = false;
boolean bPossibleModificationOfMarkEndWord = false;
int indPossibleModificationOfMarkStartWord = cnstDontModifyBegin.indexOf(strToken);
if (indPossibleModificationOfMarkStartWord > -1)
bPossibleModificationOfMarkStartWord = true;
int indPossibleModificationOfMarkEndWord = cnstDontModifyEnd.indexOf(strToken);
if (indPossibleModificationOfMarkEndWord > -1)
bPossibleModificationOfMarkEndWord = true;
boolean ret = false;
int iStrLen = strToken.length();
try {
resultString = String.format(strReplace, strToken);
ind = -2;
while(ind != -1)
{
if (ind == -2)
ind = -1;
ind = strModifiedMathData.indexOf(strToken, ++ind);
if (ind == -1)
break;
iStart = ind;
iEnd = ind + iStrLen;
if (bPossibleModificationOfMarkStartWord)
{
ret = getPossibleModificationOfMarkWord(cnstDontModifyBegin,
strToken, strModifiedMathData, iStart, iEnd);
if (ret)
continue;
}
if (bPossibleModificationOfMarkEndWord)
{
ret = getPossibleModificationOfMarkWord(cnstDontModifyEnd,
strToken, strModifiedMathData, iStart, iEnd);
if (ret)
continue;
}
if (isNotModifiedToken(strToken, strModifiedMathData, iStart, iEnd,
bPossibleModificationOfMarkStartWord,
bPossibleModificationOfMarkEndWord))
{
strValue = strModifiedMathData.substring(iStart, iEnd);
if (strValue == null)
throw new NullPointerException("strValue == null");
//resultString = strValue.replaceAll(regexString, replaceString);
if (resultString == null)
throw new NullPointerException("resultString == null");
String strStart = strModifiedMathData.substring(0, iStart);
String strEnd = "";
if (iEnd < (strModifiedMathData.length()))
strEnd = strModifiedMathData.substring(iEnd);
// that this token is handled allready:
if (strEnd == null || strEnd.trim().length() == 0)
{
return strStart + cnstDontModifyBegin +
resultString + cnstDontModifyEnd
+ "";
}
else
{
/* if founded value contains " chars in the end and
* start of it, then do not change anything, but
* mark this founded: do not chnage any more:
*/
if (strStart != null && strEnd != null
&& strStart.endsWith("\"")
&& strEnd.startsWith("\"") )
return strStart + cnstDontModifyBegin +
strValue + cnstDontModifyEnd +
getModifiedMathData(strEnd, strToken, strRegex, strReplace);
else // normal change without " strikes:
{
/* resultString.startsWith(" ")
&& */
/*
if (/strStart.endsWith(" "))
strStart = strStart.substring(0, strStart.length()-1);
if (strEnd.startsWith(" "))
strEnd = strEnd.substring(1);
*/
/* resultString.endsWith(" ")
&& */
return strStart + cnstDontModifyBegin +
resultString + cnstDontModifyEnd +
getModifiedMathData(strEnd, strToken, strRegex, strReplace);
}
}
}
}
return strModifiedMathData;
} 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;
}
//return strModifiedMathData.replaceAll(strRegex, strReplace);
}
/**
* This method is returng a boolean value is this token all ready modified.
*
* @param strToken
* @param strModifiedMathData
* @param iStart
* @param iEnd
* @param bPossibleModificationOfMarkStartWord
* @param bPossibleModificationOfMarkEndWord
* @return
*/
private boolean
isNotModifiedToken(String strToken, String strModifiedMathData, int iStart, int iEnd,
boolean bPossibleModificationOfMarkStartWord,
boolean bPossibleModificationOfMarkEndWord)
{
if (strModifiedMathData == null)
return false;
if (iStart < 0)
return false;
int len = strModifiedMathData.length() ;
if (iEnd > (len))
return false;
String strValue = strModifiedMathData.substring(iStart, iEnd);
if (strValue == null)
return true;
boolean bStartOk = false;
boolean bEndOk = false;
String strStart = strModifiedMathData.substring(0, iStart);
if (strStart == null || strStart.trim().length() == 0)
bStartOk = true;
else
bStartOk = getStartNotModified(strStart);
String strEnd = strModifiedMathData.substring(iEnd);
if (strEnd == null || strEnd.trim().length() == 0)
bEndOk = true;
else
bEndOk = getEndNotModified(strEnd);
boolean ret = false;
//if (!bStartOk && !bEndOk)
if (bStartOk && bEndOk)
return true;
return ret;
}
/**
* @param markValue
* @param strToken
* @param strModifiedMathData
* @param start
* @param end
* @return boolean
*/
public boolean
getPossibleModificationOfMarkWord(String markValue,
String strToken, String strModifiedMathData, int start, int end)
{// cnstDontModifyEnd,
if (start == end)
return false;
int lenData = strModifiedMathData.length();
if (lenData == 0 || lenData == start) // error!?: lenData == start !!
return false;
String strFounded = strModifiedMathData.substring(start, end);
if (strFounded == null)
return false;
String strValue = strFounded.trim();
int len = strValue.length();
if (len == 0)
return false;
int ind = getMarkValueIndexNearOfFoundToken(strModifiedMathData, markValue, start, end);
if (ind == -1)
return false;
int indEnd = ind + markValue.length();
if (ind <= start && start <= indEnd && ind <= end && end <= indEnd )
return true;
return false;
}
/**
* @param strModifiedMathData
* @param markValue
* @param start
* @param end
* @return int
*/
public int
getMarkValueIndexNearOfFoundToken(String strModifiedMathData,
String markValue,
int start,
int end)
{
if (strModifiedMathData == null || markValue == null | start < 0 || end < 0)
return -1; // = false
int len = strModifiedMathData.length();
if (len < 1)
return -1; // = false
if (start > len)
return -1; // = false
if (end > len)
return -1; // = false
int markLength = markValue.length();
if (markLength < 1)
return -1; // = false
int indStartMark = start - markLength;
if (indStartMark < 0)
indStartMark = 0;
int indEndMark = end + markLength;
if (indEndMark > len)
indEndMark = len;
String strPossibleMarkValue = strModifiedMathData.substring(indStartMark, indEndMark);
if (strPossibleMarkValue == null || strPossibleMarkValue.trim().length() == 0)
return -1;
int lenFoundMarkValue = strPossibleMarkValue.length();
if (lenFoundMarkValue < markLength)
return -1;
int indFoundMarkValue = strPossibleMarkValue.indexOf(markValue);
if (indFoundMarkValue == -1)
return -1;
int indMarkValue = (indStartMark +indFoundMarkValue);
return indMarkValue;
}
/**
* This method returns a boolean value "has a token a dont-modify value"
* before it.
* @param strValue text before founded token
* @return See above.
*/
private boolean
getStartNotModified(String strValue)
{
if (strValue != null && strValue.trim().length() != 0)
{
int indStart = strValue.lastIndexOf(cnstDontModifyBegin);
int len = strValue.length();
if (indStart == -1)
return true;
int iPlace = len - cnstDontModifyBegin.length();
if (indStart == iPlace)
return false;
int indEnd = strValue.lastIndexOf(cnstDontModifyEnd);
// jos ei end-constia, löytynyt begin-consti tämän oma begin-consti:
if (indEnd == -1)
return false;
// jos ei end-constia löytynyt begin-consti jälkeen,
// ei ole tämän oma begin-consti:
if (indEnd > indStart )
return true;
return false;
}
return true;
}
/**
* This method returns a boolean value "has a token a dont-modify value"
* after it.
* @param strValue text after founded token
* @return See above.
*/
private boolean
getEndNotModified(String strValue)
{
if (strValue != null && strValue.trim().length() != 0)
{
int indEnd = strValue.indexOf(cnstDontModifyEnd);
// jos ei end-constia, ei ole tämän oma begin-consti:
if (indEnd == -1 )
return true;
if (indEnd == 0)
return false;
int len = strValue.length();
//int iPlace = len - cnstDontModifyEnd.length();
int indStart = strValue.indexOf(cnstDontModifyBegin);
// jos ei begin-constia, on tämän end-consti
if (indStart == -1)
return false;
// jos ei end-constia löytynyt begin-consti jälkeen,
// ei ole tämän oma end-consti:
if (indStart < indEnd )
return true;
return false;
}
// kun hakee substring:ia, voi vastaus olla väärä, mutta getStartNotModified(...) on tarkka
return true;
}
private String
getDontModifyToken(String strToken)
throws NullPointerException, Exception
{
if (strToken == null)
throw new NullPointerException("strToken is null!");
int ind = strToken.indexOf(cnstNOTThiswords);
if (ind == -1)
return null;
int ind2 = strToken.lastIndexOf(")");
if (ind2 == -1)
return null;
String strNOTThiswords = strToken.substring(
ind +cnstNOTThiswords.length(), ind2);
if (strNOTThiswords == null)
throw new NullPointerException("strNOTThiswords == null!");
if (strNOTThiswords.trim().length() == 0)
throw new Exception("strNOTThiswords.trim().length() == 0");
return strNOTThiswords.trim(); // foundedd cnstNOTThiswords and ')', do not change this
// word
}
/**
* This method returns normal token value after regex meta character rules
* @param strToken
* @param bRegexTokenWithPossibleLiteral
* @return
* @throws NullPointerException
* @throws Exception
*/
private String
getNormalToken(String strToken, boolean bRegexTokenWithPossibleLiteral)
throws NullPointerException, Exception
{
String tmp = getDontModifyToken(strToken);
if (tmp == null) // no strNOTThiswords: value
{
if (bRegexTokenWithPossibleLiteral)
return getRegexTokenWithPossibleLiteral(strToken);
else
return strToken;
}
String [] arrValues = strToken.split(" ");
if (arrValues[0] == null)
throw new NullPointerException("arrValues[0] is null!");
if (bRegexTokenWithPossibleLiteral)
return getRegexTokenWithPossibleLiteral(arrValues[0]);
else
return arrValues[0];
}
/**
* This method returns token replaced with \ characters if it contains some
* meta characters
* @param strToken
* @return
*/
private String
getRegexTokenWithPossibleLiteral(String strToken)
{
int max = arrRegexToken.length;
String regexToken;
for(int i = 0; i < max; i++)
{
regexToken = arrRegexToken[i];
if (regexToken == null)
continue;
// TODO: check this rule, when thinking morphys rule;
// there migth be some missmachts!: indirect modified after below if,
// and coming here and match on the next if!!:
if (regexToken.equals(strToken))
return "\\" +strToken;
if(strToken.contains(regexToken) && ! regexToken.equals("\\") )
strToken = strToken.replaceAll("\\"+regexToken, "\\\\"+regexToken);
}
return strToken;
}
/**
* The main application, for testing purposes
* @param args
*/
public static void main(String[] args)
{
System.out.println("The application has been started.");
int program_exit = 0;
try {
JAsciiMath jAsciiMath = getJAsciiMath(args);
if (jAsciiMath != null)
{
program_exit = jAsciiMath.replaceAsciiMathBlocks();
}
System.out.println("The end of the application");
} catch(Exception e){
e.printStackTrace();
program_exit = 1;
System.out.println("An application error has been occurred!");
}
System.exit(program_exit);
}
/**
* @param args
* @return
* @throws Exception
*/
private static JAsciiMath
getJAsciiMath(String[] args)
throws Exception
{
m_static_strInputFileName = null;
m_static_strOutputFileName = null;
checkCommandLineParameters(args);
boolean bCorrectStrikeErrors = false;
boolean bCheckStrikeErrors = true;
JAsciiMath jAsciiMath = new JAsciiMath("", bCheckStrikeErrors,
bCorrectStrikeErrors, false);
jAsciiMath.setInputFileName(m_static_strInputFileName);
jAsciiMath.setOutputFileName(m_static_strOutputFileName);
//jAsciiMath.setConvertAsciiMathDataWithSpaceRules(true);
return jAsciiMath;
}
/**
* Un implemented method.
* @param args
* @throws Exception
*/
private static void
checkCommandLineParameters(String[] args)
throws Exception
{
}
/**
* This method returns a modified String after replaced all reserved words
* in the paraemeter value. Replaced words and new values for them are located in
* the .properties file of this class.
* @param strAsciiMath
* @return See above
*/
private String
replaceAllReservedWords_new(String strAsciiMath)
throws DtbookAsciiMathException
{
if (strAsciiMath == null || strAsciiMath.trim().length() == 0)
return strAsciiMath;
int dataLen = strAsciiMath.length();
int max = m_sortedReplaceReservedWords.size();
if (max == 0)
return strAsciiMath;
int [][] arrIntstrikepairStartStopValues = getPossibleStrikePairs(strAsciiMath);
/*
while (stepper.hasNext()) {
current = (String)stepper.next();
System.out.println(current);
}
//listvalues
*
*/
String strSearch, strValue;
// use sorted list, because longest search value will be handled at first etc
Iterator<String> ite = m_sortedReplaceReservedWords.iterator();
int ind ;
String old_value = new String(strAsciiMath);
for(; ite.hasNext(); )
{
strSearch = (String)ite.next();
dataLen = strAsciiMath.length();
if (strSearch == null || strSearch.trim().length() == 0)
continue;
// get replace value by search value
strValue = (String)this.m_propertyReplaceReservedWords.get(strSearch);
if (strValue == null)
strValue = "";
if (!old_value.equals(strAsciiMath))
{
arrIntstrikepairStartStopValues = getPossibleStrikePairs(strAsciiMath);
old_value = new String(strAsciiMath);
}
ind = strAsciiMath.indexOf(strSearch);
if (ind > -1 /* strAsciiMath.contains(strSearch) */)
{
String start, end = "", replacedValue = strValue;
int len = strSearch.length();
StringBuffer sb = new StringBuffer();
int pos, iArrIndex = 0, indArr = 0, iCurrent = 0;
while(ind != -1)
{
start = strAsciiMath.substring(iCurrent, ind);
if (start == null)
start = "";
pos = (ind + len);
end = strAsciiMath.substring(pos);
if (end == null)
end = "";
if (arrIntstrikepairStartStopValues == null
|| arrIntstrikepairStartStopValues.length == 0
|| indArr == -1)
{
System.err.println("start='" + start +"'");
System.err.println("start.len='" + start.length() +"'");
sb.append(start);
System.err.println("sb.len='" + sb.length() +"'");
System.err.println("replacedValue.len='" + replacedValue.length() +"'");
System.err.println("replacedValue='" + replacedValue +"'");
sb.append(replacedValue);
System.err.println("sb.len='" + sb.length() +"'");
iCurrent = ind + len;
}
else
{
String strAppend = strAsciiMath.substring(iCurrent, arrIntstrikepairStartStopValues[indArr][1]);
sb.append(strAppend);
iCurrent = arrIntstrikepairStartStopValues[indArr][1];
end = strAsciiMath.substring(iCurrent);
}
if (iCurrent >= dataLen)
break;
// strAsciiMath = end;
ind = strAsciiMath.indexOf(strSearch, iCurrent);
}
sb.append(end);
strAsciiMath = sb.toString();
if (!old_value.equals(strAsciiMath))
{
arrIntstrikepairStartStopValues = getPossibleStrikePairs(strAsciiMath);
old_value = new String(strAsciiMath);
}
}
}
return strAsciiMath;
}
private int
getInSideOfStrikes(int ind, int [][] arrIntstrikepairStartStopValues)
{
if (arrIntstrikepairStartStopValues == null)
return -1;
if (arrIntstrikepairStartStopValues.length == 0)
return -1;
if (ind == -1)
return -1;
int max = arrIntstrikepairStartStopValues.length;
for(int i = 0; i < max; i++)
{
if (arrIntstrikepairStartStopValues[i][0] <= ind
&& arrIntstrikepairStartStopValues[i][1] >= ind)
return i;
}
return -1;
}
private int [][] getPossibleStrikePairs(String strAsciiMath)
{
if (strAsciiMath == null)
return null;
if (strAsciiMath.indexOf('"') == -1)
return null;
try {
// search all " " pairs
Pattern regex = Pattern.compile("\" *([\\w+ ])+ *\"");
Matcher regexMatcher = regex.matcher(strAsciiMath);
//MatchResult matchResult;
try {
int iCounter = 0;
boolean founded = false;
StringBuffer sp = new StringBuffer();
int start, end;
while(regexMatcher.find())
{
founded = true;
iCounter++;
start = regexMatcher.start();
end = regexMatcher.end();
sp.append("" + start +" " +end +"\n");
} // end of while
if (founded)
{
int [][] arrIntstrikepairStartStopValues = new int[iCounter][2];
String [] startStops = sp.toString().split("\n");
int max = startStops.length;
String strikepairStartStopValue, strOneValue, strSecondValue;
String [] arrStrikepairStartStopValue;
for(int i = 0; i < max; i++)
{
strikepairStartStopValue = startStops[i];
if (strikepairStartStopValue == null)
continue;
arrStrikepairStartStopValue = strikepairStartStopValue.split(" ");
strOneValue = arrStrikepairStartStopValue[0];
if (strOneValue == null)
continue;
strSecondValue = arrStrikepairStartStopValue[1];
if (strSecondValue == null)
continue;
arrIntstrikepairStartStopValues[i][0] = new Integer(strOneValue).intValue();
arrIntstrikepairStartStopValues[i][1] = new Integer(strSecondValue).intValue();
}
/*
int [][] arrIntstrikepairStartStopValues = getPossibleStrikePairs(strAsciiMath);
String [] strikepairStartStopValues =
int max = strikepairStartStopValues.length;
String strikepairStartStopValue;
String [] strikepairStartStop;
int [][] arrIntstrikepairStartStopValues = new int [max][2];
for(int i = 0; i < max; i++)
{
strikepairStartStopValue = strikepairStartStopValues[i];
if (strikepairStartStopValue == null)
continue;
strikepairStartStop = strikepairStartStopValue.split(" ");
}
*/
return arrIntstrikepairStartStopValues;
}
return null;
} catch (IllegalArgumentException ex) {
// Syntax error in the replacement text (unescaped $ signs?)
throw ex;
} catch (IndexOutOfBoundsException ex2) {
// Non-existent backreference used the replacement text
throw ex2;
}
} catch (PatternSyntaxException ex3) {
// Syntax error in the regular expression
throw ex3;
}
}
/**
* This method returns a marked asciimath string. When some changed word
* (reserved or not) is a substring of an another replaced or modified string,
* these words must marked with: _do_not_modify<number> = <replacedword>,
* with _do_not_modify<number+1> = <replacedword2> etc.
* @param strAsciiMath
* @return
*/
private String
getDontModifyData(String strAsciiMath)
{
return strAsciiMath;
}
/**
* This method reads property file of the class. If exceptions occurs it is
* an error.
* @throws DtbookAsciiMathException
* @throws FileNotFoundException
* @throws IOException
*/
private void
readSectionNamesAndSectionData()
throws DtbookAsciiMathException, FileNotFoundException, IOException
{
if (!m_FileReplaceProperty.exists())
throw new DtbookAsciiMathException(
String.format(cnstPropertyFileDoesNotFound,
m_FileReplaceProperty.getAbsolutePath()));
m_propertyReplace = new Properties();
FileReader fr = new FileReader(m_FileReplaceProperty);
m_propertyReplace.load(fr);
fr.close();
m_space_on_both_sides_name = (String)
m_propertyReplace.get(cnstSpace_on_both_sides_name);
m_space_on_neigther_sides_name = (String)
m_propertyReplace.get(cnstSpace_on_neigther_sides_name);
m_space_before_but_not_after_name = (String)
m_propertyReplace.get(cnstSpace_before_but_not_after_name);
m_space_after_but_not_before_name = (String)
m_propertyReplace.get(cnstSpace_after_but_not_before_name);
m_replace_reserved_words_section_name = (String)
m_propertyReplace.get(cnstReplace_reserved_words_section_name);
m_replaceAllComma = (String)m_propertyReplace.get(cnstReplaceAllComma);
m_replaceAllWithSemiColon = (String)m_propertyReplace.get(cnstReplaceAllWithSemiColon);
m_replaceAllNumberPoint = (String)m_propertyReplace.get(cnstReplaceAllNumberPoint);
m_replaceAllNumberComma = (String)m_propertyReplace.get(cnstReplaceAllNumberComma);
m_regex_special_meaning_characters = (String)m_propertyReplace.get(cnstRegex_special_meaning_characters);
if (m_regex_special_meaning_characters != null)
{
String [] arrRegex = m_regex_special_meaning_characters.trim().split(" ");
if (arrRegex != null)
{
arrRegexToken = arrRegex;
}
}
fr = new FileReader(m_FileReplaceProperty);
BufferedReader br = new BufferedReader(fr);
String line;
//StringBuffer sb = new StringBuffer();
List<String> listPropertyLines = new ArrayList<String>();
while ( (line = br.readLine()) != null )
{
listPropertyLines.add(line);
}
br.close();
if (listPropertyLines.size() == 0)
throw new DtbookAsciiMathException("Property "
+ m_FileReplaceProperty.getAbsolutePath() + " file is etmpty!");
fr.close();
readSections(listPropertyLines);
}
/**
* This method collects special sections data for a properties (=config) file
* @param listPropertyLines Data is the form of list
*/
private void
readSections(List<String> listPropertyLines)
{
String line = null,
currentSectionName = null,
newSectionName = null;
int max = listPropertyLines.size();
boolean bInsideSection = false;
for(int i = 0; i < max; i++)
{
line = listPropertyLines.get(i);
if (line == null // Skip null, emptys line and comment lines
|| line.trim().length() == 0
|| (!bInsideSection && line.trim().startsWith("#"))
)
continue;
//line = line.trim();
// if line is not section name and has not finded a first section name:
newSectionName = getSectionName(line);
if (! bInsideSection && newSectionName == null)
continue;
// if an first section or an old section has finished
// and a new has been started
if (!bInsideSection || (currentSectionName != null
&& newSectionName != null
&& ! currentSectionName.equals(newSectionName)) )
{
createNewSection(newSectionName, currentSectionName);
currentSectionName = newSectionName;
bInsideSection = true;
continue;
}
addIntoSection(currentSectionName, line);
}
}
/**
* This method creates new variable instancies when collectino config
* data.
* @param newSectionName
* @param currentSectionName
*/
private void
createNewSection(String newSectionName, String currentSectionName)
{
/*
j = arrBothSidesSpaceToken
arrBeforeSpaceToken
j = arrNoSpaciesIntoBothSideToken
j = arrNoSpaceAfterToken
space_on_both_sides_name=molemmin_puolin
space_on_neigther_sides_name=ei_kummallakaan_puolella
space_before_but_not_after_name=ennen_mutta_ei_jalkeen
space_after_but_not_before_name=jalkeen_mutta_ei_ennen
*/
//if (m_listCurrentToken != null)
///createTokenArray(currentSectionName);
if (newSectionName.equals(m_space_on_both_sides_name))
{
m_arrBothSidesSpaceToken = null;
m_listCurrentToken = new RuleConfig();
m_srcBothSidesSpaceToken = m_listCurrentToken;
}
else
if (newSectionName.equals(m_space_after_but_not_before_name))
{
m_arrSpaceAfterButNotBefore = null;
m_listCurrentToken = new RuleConfig();
m_srcSpaceAfterButNotBeforeToken = m_listCurrentToken;
}
else
if (newSectionName.equals(m_space_on_neigther_sides_name))
{
m_arrNoSpaciesIntoBothSideToken = null;
m_listCurrentToken = new RuleConfig();
m_srcNoSpaciesIntoBohSideToken = m_listCurrentToken;
}
else
if (newSectionName.equals(m_space_before_but_not_after_name))
{
m_arrSpaceBeforeButNotAfter = null;
m_listCurrentToken = new RuleConfig();
m_srcSpaceBeforeButNotAfter = m_listCurrentToken;
}
else
if (newSectionName.equals(m_replace_reserved_words_section_name))
{
m_listCurrentToken = new RuleConfig();
m_listReplace_reserved_wordToken = m_listCurrentToken;
}
}
/*
private void
createTokenArray(String listCurrentToken)
{
// m_listCurrentToken
}
*/
/**
* This method adds a line data into current token list
* @param currentSectionName
* @param line
*/
private void
addIntoSection(String currentSectionName, String line)
{
m_listCurrentToken.addToken(line);
}
/**
* This method is returning a name of section.
* @param line A readed line from properties file, spec. versio of properties file
* @return Returns a string value if has been founded a section name,otherwise it
* returns a null
*/
private String
getSectionName(String line)
{
if (line == null)
return null;
if ( ! (line.contains(this.m_space_after_but_not_before_name +":")
|| line.contains(this.m_space_before_but_not_after_name +":")
|| line.contains(this.m_space_on_both_sides_name +":")
|| line.contains(this.m_space_on_neigther_sides_name +":")
|| line.contains(this.m_replace_reserved_words_section_name +":"))
)
return null;
int ind = line.indexOf(':');
if (ind < 0)
return null;
String ret = line.substring(0, ind);
if (ret == null)
return null;
ret = ret.trim();
if (ret.length() == 0)
return null;
return ret;
}
/**
* This method sets warning on or off.
* @param value
*/
public void setWarningsOn(boolean value)
{
m_bWarningsOn = value;
}
/**
* This method gets warning boolean value.
* @return boolean
*/
public boolean getWarningsOn() { return m_bWarningsOn; }
/**
* This method is converting asciimath xml blocks within firefox browser
* into ascimath daisy xml entities.
*
* @param templatefilename
* @param dtbookFileName Dtbook-asciimath file name
* @param dtbookCharacterSet Used characterset
* @param jasciiMathPropertyFileName Used asciimath property file name
* @param asciiMathWWWBrowserApplication
* @param targetDtbookFileName Target file name
* @param targetCharacterSet Used target character set
* @param bPrintXmlStatements
* @throws DtbookAsciiMathException An error occurred
* @throws FileNotFoundException File not found error occurred
* @throws InterruptedException An error occurred,
* @throws IOException An io error occurred
* @throws NullPointerException An null pointer error occurred
* @throws Exception An error occurred
*/
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
{
AsciiMathXml asciimathxml = new AsciiMathXml();
Properties prop = new Properties();
File fileProp = new File(jasciiMathPropertyFileName);
FileReader freader = new FileReader(fileProp);
prop.load(freader);
String strSleepCounter = prop.getProperty("sleepconter");
if (strSleepCounter != null && strSleepCounter.trim().length() > 0)
{
try {
int iSleepCounter = Integer.valueOf(strSleepCounter);
asciimathxml.setSleepConter(iSleepCounter);
} catch(Exception inte){
}
}
freader.close();
int result = -1;
try {
result = asciimathxml.modifyDtbookIntoAsciiMathXml(templatefilename,
dtbookFileName, dtbookCharacterSet, jasciiMathPropertyFileName,
asciiMathWWWBrowserApplication, targetDtbookFileName,
targetCharacterSet, bPrintXmlStatements,
bCheckStrikeErrors, p_bCorrectStrikeErrors);
} catch(Exception e) {
m_sbError = new StringBuffer(e.getMessage());
throw e;
}
//asciimathxml.
String printdata = asciimathxml.getPrintData();
m_sbPrintData = new StringBuffer((printdata == null ? "" : printdata));
String data = asciimathxml.getOutputData();
m_sb = new StringBuffer((data == null ? "" : data));
String error = asciimathxml.getErrorData();
m_sbError = new StringBuffer((error == null ? "" : error));
if (asciimathxml.getJAsciiMath() != null)
m_hm_asciimath_values = asciimathxml.getJAsciiMath().getAsciimatHashMapValues();
// ???
return result;
/*
} catch(Exception e) {
m_sbError = new StringBuffer(e.getMessage());
throw e;
}
*/
}
public AsciiMathBlockValue [] getArrayOfAsciiMathBlocks()
{
return m_arrblok;
}
}