package mj.ocraptor.console;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import mj.ocraptor.configuration.Config;
import mj.ocraptor.console.Platform.Os;
import mj.ocraptor.database.DBFileStatus;
import mj.ocraptor.tools.St;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.highlight.Formatter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.search.highlight.SimpleSpanFragmenter;
import org.fusesource.jansi.AnsiConsole;
public class COF {
private static final int timeDifference = 200, MAX_LINE_WIDTH = 74;
private static String mainDelimiter, startDelimiter, endDelimiter, progressProcentIndicator,
progressFileIndicator;
private static Long startTime = 0L;
private static boolean quiet;
private static String seperator, scriptName;
public static final AnsiColor[] ERROR_CLR = { AnsiColor.RED_BACKGROUND, AnsiColor.WHITE };
private static final String ID_COLOR = AnsiColor.RED.toString() + AnsiColor.BOLD.toString();
// *INDENT-OFF*
private static final String //
MORE_INFO
= "* Show more information with "
+ ID_COLOR
+ "s[id]"
+ AnsiColor.DEFAULT
+ ".\n (e.g. '"
+ ID_COLOR
+ AnsiColor.BOLD.toString()
+ "s1"
+ AnsiColor.DEFAULT
+ "' for file with id=1)\n ",
OPEN_FILE
= "* Type only the "
+ ID_COLOR
+ "id"
+ AnsiColor.DEFAULT
+ " to open one specific file.\n ",
OPEN_DIR
= "* Show directory with "
+ ID_COLOR
+ "d[id]"
+ AnsiColor.DEFAULT
+ ".\n (e.g. '"
+ ID_COLOR
+ "d1"
+ AnsiColor.DEFAULT
+ "' for file with id=1)\n ",
OPEN_FULLTEXT
= "* Open fulltext in your browser with "
+ ID_COLOR
+ "b[id]"
+ AnsiColor.DEFAULT
+ ".\n (e.g. '"
+ ID_COLOR
+ "b1"
+ AnsiColor.DEFAULT
+ "' for file with id=1)\n ",
QUIT
= "* Type "
+ ID_COLOR
+ "q"
+ AnsiColor.DEFAULT
+" to quit application.";
// *INDENT-ON*
/**
*
*
*/
static {
if (startTime == 0) {
// don't install if running on an eclipse with 'Ansi Console'-Plugin
if (!Config.devMode()) {
AnsiConsole.systemInstall();
}
showedDots = 0;
if (startTime == null)
startTime = System.currentTimeMillis();
if (Platform.getSystem() == Os.LINUX || Platform.getSystem() == Os.OSX) {
// 220, 177, 176, 219, 218
mainDelimiter = AnsiColor.BLUE_BACKGROUND.toString() + AnsiColor.WHITE.toString() + " "
+ AnsiColor.DEFAULT;
startDelimiter = ExtendedAscii.getAsciiAsString(174);
endDelimiter = ExtendedAscii.getAsciiAsString(173);
progressProcentIndicator = AnsiColor.GREEN + ExtendedAscii.getAsciiAsString(253)
+ AnsiColor.DEFAULT;
progressFileIndicator = AnsiColor.GREEN + ExtendedAscii.getAsciiAsString(253)
+ AnsiColor.DEFAULT;
scriptName = Config.APP_NAME_LOWER + "-cl";
} else {
mainDelimiter = AnsiColor.BLUE_BACKGROUND.toString() + AnsiColor.WHITE.toString() + "*"
+ AnsiColor.DEFAULT;
startDelimiter = Config.SEARCH_DELIMITER_END_SINGLE;
endDelimiter = Config.SEARCH_DELIMITER_START_SINGLE;
progressProcentIndicator = "|";
progressFileIndicator = "|";
scriptName = Config.APP_NAME + "CL";
}
// seperator = StringUtils.repeat(mainDelimiter, MAX_LINE_WIDTH);
seperator = AnsiColor.GREEN + StringUtils.repeat("*", MAX_LINE_WIDTH) + AnsiColor.DEFAULT;
}
}
// ------------------------------------------------ //
// --
// ------------------------------------------------ //
/**
*
*
* @param line
*/
public static void printLine(final String line) {
printLine(line, false);
}
/**
*
*
* @param line
*/
public static void printLineStretched(final String line) {
printLine(line, false, AnsiColor.getColorIndex(line), true);
}
/**
*
*
* @param line
* @param end
*/
public static void printLine(String line, boolean end) {
printLine(line, end, AnsiColor.getColorIndex(line), false);
}
/**
*
*
* @param line
* @param end
*/
public static void printLineStretched(String line, boolean end) {
printLine(line, end, AnsiColor.getColorIndex(line), true);
}
/**
*
*
* @param line
* @param end
* @param colors
*/
private static synchronized void printLine(final String line, boolean end,
final SortedMap<Integer, AnsiColor[]> colors, boolean stretched) {
if (quiet)
return;
final boolean lineIsEmpty = line.trim().isEmpty();
if (!blockEmptySeparator || !lineIsEmpty) {
System.out.println(printLine(line, MAX_LINE_WIDTH, end, colors, stretched));
}
blockEmptySeparator = lineIsEmpty ? true : false;
blockSeparator = false;
}
/**
*
*
* @param line
* @param maxLineWidth
* @param end
*/
private static String printLine(String line, int maxLineWidth, boolean end,
final SortedMap<Integer, AnsiColor[]> colors, boolean stretched) {
// colors = AnsiColor.getColorIndexAsSet(line);
line = AnsiColor.removeAnsiColors(line);
line = line.replaceAll("\\s", " ");
line = St.trimToLengthIndicatorRight(line, maxLineWidth - 4);
boolean endsWithIndicator = line.endsWith(St.TRIMMED_INDICATOR);
int lineLength = line.length();
String mainColor = AnsiColor.DEFAULT.toString();
if (colors != null) {
for (Entry<Integer, AnsiColor[]> colorEntry : colors.entrySet()) {
int index = colorEntry.getKey();
AnsiColor[] entryColors = colorEntry.getValue();
for (int i = entryColors.length - 1; i >= 0; i--) {
AnsiColor cl = entryColors[i];
if (!stretched) {
if (endsWithIndicator && index + 5 > lineLength) {
line = St.insertStringAtIndex(line, AnsiColor.DEFAULT.toString(), lineLength - 5);
} else {
if (line.length() > index) {
line = St.insertStringAtIndex(line, cl.toString(), index);
}
}
} else {
mainColor += cl.toString();
}
}
}
}
// AnsiColor.printColorIndex(colors);
// *INDENT-OFF*
if (end) {
return (
mainDelimiter
+
mainColor
+
StringUtils.repeat(" ", maxLineWidth - lineLength - 3) + line
+
" "
+
AnsiColor.DEFAULT
+
mainDelimiter);
} else {
return (
mainDelimiter
+
mainColor
+
" "
+
line + StringUtils.repeat(" ", maxLineWidth - lineLength - 4)
+
mainColor
+
" "
+
AnsiColor.DEFAULT
+
mainDelimiter
);
}
// *INDENT-ON*
}
// ------------------------------------------------ //
// --
// ------------------------------------------------ //
/**
*
*
*/
public static void printCLIHelp() {
printCLIHelp(null);
}
/**
* Prints Help for Commandline-Interpreter.
*
* @param options
* possible options
*/
public static void printCLIHelp(String errorMessage) {
HelpFormatter helpFormater = new HelpFormatter();
helpFormater.setOptionComparator(new OptionComparator());
System.out.println(seperator);
if (errorMessage != null) {
try {
Thread.sleep(100);
System.out.println("ERROR: " + errorMessage);
Thread.sleep(50);
System.out.println(seperator);
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// System.out.println(CommandLineInterpreter.instance().getOptions());
helpFormater.printHelp(scriptName, "\noptions:", CommandLineInterpreter.instance().getOptions(),
"\n", true);
System.out.println(seperator);
System.exit(0);
}
/**
* Prints Help for Commandline-Interpreter.
*
* @param options
* possible options
*/
public static void printCLIExtendedHelp() {
StringBuffer extendedHelp = new StringBuffer();
// extendedHelp.append("( TEXT=[<String>] AND FILETYPE=[<String>] ) OR
// FILENAME=[<String>]\n");
// extendedHelp.append("( TEXT=[account] AND FILETYPE=[xslx] ) OR
// FILENAME=[march]\n");
// extendedHelp.append("( TEXT=[fax] OR TEXT=[turnover] ) AND
// FILENAME=[scan]\n");
System.out.println(seperator);
HelpFormatter helpFormater = new HelpFormatter();
helpFormater.setOptionComparator(new OptionComparator());
helpFormater.printHelp(scriptName, "\noptions:", CommandLineInterpreter.instance().getOptions(),
"\n" + extendedHelp + "\n" + "\n", true);
System.out.println(seperator);
System.exit(0);
}
/**
*
*
*/
public static void loadIcon(int timeInMs) {
String[] icons = new String[] { "|", "/", "-", "\\" };
AnsiConsole.out.print("\033[s");
for (int i = 0; i < Math.round((double) timeInMs / (double) 100); i++) {
String lineToRepeat = "LOADING: " + StringUtils.repeat(icons[i % icons.length], 4);
lineToRepeat = AnsiColor.CYAN_BACKGROUND + lineToRepeat + AnsiColor.DEFAULT;
lineToRepeat = printLine(lineToRepeat, MAX_LINE_WIDTH, false, null, false);
String ansiColor = "30";
String line = "\033[u\033[" + lineToRepeat.length() + "D" + "\033[" + ansiColor + "m"
+ lineToRepeat + "\033[s\033[0;0f";
AnsiConsole.out.print(line);
AnsiConsole.out.flush();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
AnsiConsole.out.print("\033[u");
}
/**
*
*
* @param timeInMs
*/
public static void loadIconInOwnThread(int timeInMs) {
LoadIcon icon = new LoadIcon(timeInMs);
new Thread(icon).start();
}
/**
*
*/
private static class LoadIcon implements Runnable {
private int timeInMs;
/**
*
*/
public LoadIcon(int timeInMs) {
this.timeInMs = timeInMs;
}
@Override
public void run() {
Thread.currentThread().setName(Config.APP_NAME + "Loading icon");
COF.loadIcon(this.timeInMs);
}
}
/**
*
*/
private static class OptionComparator implements Comparator<Option> {
public int compare(Option opt1, Option opt2) {
boolean hasArg1 = opt1.hasArg();
boolean hasArg2 = opt2.hasArg();
boolean required1 = opt1.isRequired();
boolean required2 = opt2.isRequired();
if (required1 && required2) {
if (hasArg1 && hasArg2)
return 0;
if (hasArg1)
return -1;
if (hasArg2)
return 1;
}
if (hasArg1 && hasArg2) {
if (required1 && required2)
return 0;
if (required1)
return -1;
if (required2)
return 1;
}
if (hasArg1 && !hasArg2)
return -1;
if (required1 && !required2)
return -1;
return 0;
}
}
/**
*
*
* @return
*/
private static boolean checkTimeRestriction() {
if (System.currentTimeMillis() - startTime > timeDifference) {
startTime = System.currentTimeMillis();
return true;
}
return false;
}
/**
*
*
* @param fileCount
*/
private static void initProgressBar(long fileCount) {
if (progressBarWidth == null) {
if (fileCount <= 100) {
progressBarWidth = 20;
progressBarHeight = 5;
} else if (fileCount > 100 && fileCount <= 500) {
progressBarWidth = 50;
progressBarHeight = 10;
} else if (fileCount > 500 && fileCount <= 1000) {
progressBarWidth = 50;
progressBarHeight = 20;
} else if (fileCount > 1000 && fileCount <= 2500) {
progressBarWidth = 50;
progressBarHeight = 50;
} else if (fileCount > 2500) {
progressBarWidth = 50;
progressBarHeight = 100;
}
}
}
private static double lastPercent = 0;
/**
*
*
* @param fileCount
* @param currentPosition
*/
public static void printFile(Long fileCount, Long currentPosition, File file,
DBFileStatus status) {
boolean progressIndicator = fileCount != null && currentPosition != null;
double percent = 0;
// ------------------------------------------------ //
if (file != null && status != null) {
String message = "";
String color = null;
if (status == DBFileStatus.NOT_FOUND) {
message = "Status: Inserted into database";
color = AnsiColor.GREEN.toString() + AnsiColor.BOLD.toString();
} else if (status == DBFileStatus.UP_TO_DATE) {
message = "Status: File has not changed.";
color = AnsiColor.BOLD.toString();
} else {
message = "Status: File modified. Database entry updated.";
color = AnsiColor.MAGENTA + AnsiColor.BOLD.toString();
}
COF.printEmptySeparator();
printLine(color + "File: " + file.getName());
printLine(color + "Dir: " + file.getParent());
printLine(color + message);
COF.printEmptySeparator();
}
// ------------------------------------------------ //
if (progressIndicator) {
if (fileCount == 0 && currentPosition == 0) {
percent = 100;
} else {
percent = ((double) currentPosition / (double) fileCount * 100);
}
if (percent == 100) {
percent = 99.99d;
}
if (percent > lastPercent) {
COF.printEmptySeparator();
printLine(AnsiColor.BOLD + "Progress: " + St.formatDouble(percent, 2) + "%");
COF.printEmptySeparator();
lastPercent = percent;
}
}
// ------------------------------------------------ //
}
private static int showedDots;
private static Integer progressBarWidth, progressBarHeight;
/**
*
*
* @param fileCount
* @param currentPosition
*/
public static synchronized void printProcess(long fileCount, long currentPosition) {
if (quiet)
return;
blockEmptySeparator = false;
blockSeparator = false;
if (!checkTimeRestriction() && (fileCount - currentPosition) > 20)
return;
initProgressBar(fileCount);
double pr = 0;
if (fileCount == 0 && currentPosition == 0)
pr = 1;
else
pr = (double) currentPosition / (double) fileCount;
int newDotsCount = (int) Math.round(pr / ((double) 1 / ((double) progressBarHeight
* (double) progressBarWidth)));
int newDotsToShow = newDotsCount - showedDots;
int percent = 0;
if (currentPosition == 0 && fileCount != 0) {
printEmptySeparator();
}
for (int i = 0; i < newDotsToShow; i++) {
int currentProgress = (showedDots % progressBarWidth);
showedDots++;
int resolution = (100 / progressBarHeight);
percent = (showedDots / progressBarWidth) * resolution;
if (showedDots % progressBarWidth == 1) {
System.out.print(mainDelimiter + StringUtils.repeat(" ", 4) + St.zeroPadSpaces(percent, 2)
+ "% " + startDelimiter + " ");
}
if ((currentProgress == (percent / (100 / progressBarWidth)) - 1) && percent != 100
- resolution) {
System.out.print(progressProcentIndicator);
} else {
System.out.print(progressFileIndicator);
}
if (showedDots % progressBarWidth == 0) {
System.out.print(" " + endDelimiter);
int surroundingChars = MAX_LINE_WIDTH - progressBarWidth - 20;
System.out.print(" " + St.zeroPadSpaces(percent, 3) + "% " + StringUtils.repeat(" ",
surroundingChars) + mainDelimiter + "\n");
}
}
if (percent == 100) {
printEmptySeparator();
}
}
/**
*
*
*/
public static void printScannerInfo() {
printSeparator();
printEmptySeparator();
printText(MORE_INFO);
printText(OPEN_DIR);
printText(OPEN_FULLTEXT);
printText(OPEN_FILE);
printText(QUIT);
printEmptySeparator();
printSeparator();
System.out.print("\n" + AnsiColor.BLUE.toString() + AnsiColor.BOLD.toString()
+ " -> Your input: ");
System.out.print(AnsiColor.RED.toString());
}
private static long lastFileCount;
/**
*
*
* @return
*/
public static void printFileCount(long count, boolean lastOutput) {
if (quiet)
return;
if (!checkTimeRestriction() && !lastOutput)
return;
if (count > 0 && lastFileCount != count) {
printLine("File count: " + St.zeroPadSpaces((int) count, 5) + " ");
lastFileCount = count;
}
}
/**
*
*
*/
public static void printExit() {
COF.printFilledLine("Exiting " + Config.APP_NAME + " and cleaning up", true);
}
private static boolean blockEmptySeparator, blockSeparator;
/**
*
*
*/
public static void printSeparator() {
if (quiet)
return;
if (!blockSeparator) {
System.out.println(StringUtils.repeat(mainDelimiter, MAX_LINE_WIDTH));
blockEmptySeparator = false;
}
}
/**
*
*
* @param maxLineWidth
*/
public static String printSeparator(int maxLineWidth) {
return StringUtils.repeat(mainDelimiter, maxLineWidth);
}
/**
*
*
*/
public static void printEmptySeparator() {
printLine("", false);
}
/**
*
*
* @param lines
*/
public static void printLines(final String lines) {
printLines(lines, false);
}
/**
*
*
* @param lines
*/
public static void printLinesStretched(final String lines) {
printLines(lines, true);
}
/**
*
*
* @param lines
* @param stretched
*/
private static void printLines(final String lines, final boolean stretched) {
SortedMap<Integer, AnsiColor[]> colors = AnsiColor.getColorIndex(lines);
final String[] partialTextStrings = St.splitToLines(lines);
for (String singleLine : partialTextStrings) {
// aa
printLine(singleLine, false, colors, stretched);
colors = AnsiColor.shiftColorIndex(colors, singleLine.length());
}
}
/**
*
*
* @param text
*/
public static void printText(String text) {
printText(text, false, true);
}
/**
*
*
* @param text
*/
public static void printTextStretched(String text) {
printText(text, true, true);
}
/**
*
*
* @param text
*/
public static void printText(String text, boolean stretched, boolean showEmptyLines) {
SortedMap<Integer, AnsiColor[]> cls = AnsiColor.getColorIndex(text);
text = AnsiColor.removeAnsiColors(text);
final String[] partialTextStrings = St.splitToLines(text);
for (int i = 0; i < partialTextStrings.length; i++) {
final String partialText = partialTextStrings[i];
printPartialText(partialText, cls, stretched, showEmptyLines);
cls = AnsiColor.shiftColorIndex(cls, partialText.length() + 1);
}
}
/**
*
*
* @param text
* @param colors
* @param stretched
*/
private static void printPartialText(final String text, SortedMap<Integer, AnsiColor[]> colors,
boolean stretched, boolean showEmptyLines) {
List<String> strings = new ArrayList<String>();
int index = 0;
int lineWidth = MAX_LINE_WIDTH - 4;
while (index < text.length()) {
strings.add(text.substring(index, Math.min(index + lineWidth, text.length())));
index += lineWidth;
}
for (String str : strings) {
if (!str.trim().isEmpty() || showEmptyLines) {
printLine(str, false, colors, stretched);
colors = AnsiColor.shiftColorIndex(colors, str.length());
}
}
}
/**
*
*
* @param line
*/
public static void printFilledLine(String line) {
printFilledLine(line, false);
}
/**
*
*
* @param line
* @param end
*/
public static void printFilledLine(String line, boolean end) {
if (quiet)
return;
line = St.trimToLengthIndicatorRight(line, MAX_LINE_WIDTH - 4);
String colorString = AnsiColor.BLUE_BACKGROUND.toString() + AnsiColor.WHITE.toString();
if (end) {
System.out.println(StringUtils.repeat(mainDelimiter, MAX_LINE_WIDTH - line.length() - 3)
+ colorString + " " + line + " " + mainDelimiter + AnsiColor.DEFAULT);
} else {
System.out.println(mainDelimiter + " " + line + " " + StringUtils.repeat(mainDelimiter,
MAX_LINE_WIDTH - line.length() - 3));
}
blockSeparator = true;
}
/**
*
*
* @param results
* @param searchString
*/
public static void printDetails(List<String[]> results, String[] searchStringParts, int id) {
}
/**
*
*
* @param id
*/
public static void printWrongIDMessage(int id) {
System.out.println("ERROR: given id \"" + id + "\" does not exist!\n");
}
/**
* @param quiet
* the quiet to set
*/
public static void setQuiet(boolean quiet) {
COF.quiet = quiet;
}
// ------------------------------------------------ //
// --
// ------------------------------------------------ //
/**
*
*
* @param text
* @param startString
* @param query
* @param analyzer
* @param maxSnippetLength
* @param maxWidthForOneLine
* @return
*/
public static String prepareHighlight(String text, String startString, Query query,
Analyzer analyzer, int maxSnippetLength, int maxWidthForOneLine, int offset,
int maxHighlights) {
StringBuffer output = new StringBuffer();
try {
String modifiedString = getHighlightedField(query, analyzer, "", text);
HashMap<Integer, String> tags = getTagValues(modifiedString);
List<Integer> keys = new ArrayList<Integer>(tags.keySet());
class FullTextSorter implements Comparator<Integer> {
@Override
public int compare(Integer a, Integer b) {
return a.compareTo(b);
}
}
Collections.sort(keys, new FullTextSorter());
int lastPrintedIndex = 0;
int i = 0;
for (Integer ind : keys) {
if (i >= maxHighlights)
break;
String firstHighlightString = tags.get(ind);
if (ind + firstHighlightString.length() < lastPrintedIndex)
continue;
String snippetIndicator = AnsiColor.DEFAULT + "" + AnsiColor.GREEN + "[...]"
+ AnsiColor.DEFAULT;
String[] temp = St.findSn(modifiedString, firstHighlightString, snippetIndicator, ind,
maxSnippetLength);
String snippet = temp[0] + firstHighlightString + temp[1];
if (temp != null) {
String tab = AnsiColor.GREEN + " |" + StringUtils.repeat(" ", 6) + AnsiColor.DEFAULT;
if (i == 0)
output.append(startString);
output.append(((i > 0) ? (output.length() > 0 ? "\n" : "") + tab : "") + St.breakToSpace(
snippet, tab + " ", maxWidthForOneLine - ((i > 0) ? 0 : offset), maxWidthForOneLine));
if (maxHighlights > 0) {
output.append("\n");
}
lastPrintedIndex = ind + firstHighlightString.length() + temp[1].length();
}
i++;
}
} catch (Exception e) {
// TODO: logging
e.printStackTrace();
}
return output.toString();
}
private static final Pattern TAG_REGEX = Pattern.compile(Config.SEARCH_DELIMITER_START.replace(
"[", "\\[") + "(.+?)" + Config.SEARCH_DELIMITER_END.replace("[", "\\["));
/**
*
*
* @param str
* @return
*/
public static HashMap<Integer, String> getTagValues(final String str) {
final HashMap<Integer, String> tagValues = new HashMap<Integer, String>();
if (str != null) {
final Matcher matcher = TAG_REGEX.matcher(str);
while (matcher.find()) {
tagValues.put(matcher.start(), Config.SEARCH_DELIMITER_START + matcher.group(1)
+ Config.SEARCH_DELIMITER_END);
}
}
return tagValues;
}
/**
*
*
* @param query
* @param analyzer
* @param fieldName
* @param fieldValue
* @return
*
* @throws IOException
* @throws InvalidTokenOffsetsException
*/
public static String getHighlightedField(Query query, Analyzer analyzer, String fieldName,
String fieldValue) throws IOException, InvalidTokenOffsetsException {
return getHighlightedField(query, analyzer, fieldName, fieldValue,
Config.SEARCH_DELIMITER_START, Config.SEARCH_DELIMITER_END);
}
/**
*
*
* @param query
* @param analyzer
* @param fieldName
* @param fulltext
* @param startDelimiter
* @param stopDelimiter
* @return
*
* @throws IOException
* @throws InvalidTokenOffsetsException
*/
public static String getHighlightedField(Query query, Analyzer analyzer, String fieldName,
String fulltext, final String startDelimiter, final String stopDelimiter) throws IOException,
InvalidTokenOffsetsException {
Formatter formatter = new SimpleHTMLFormatter(startDelimiter, stopDelimiter);
QueryScorer queryScorer = new QueryScorer(query);
Highlighter highlighter = new Highlighter(formatter, queryScorer);
highlighter.setTextFragmenter(new SimpleSpanFragmenter(queryScorer, Integer.MAX_VALUE));
highlighter.setMaxDocCharsToAnalyze(Integer.MAX_VALUE);
return highlighter.getBestFragment(analyzer, fieldName, fulltext);
}
}