*) this should fix a bug in snippet creation (also cleaned up a little bit)

git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@7972 6c8d7289-2bf4-0310-a012-ef5d649a1542
pull/1/head
low012 14 years ago
parent 277b454a62
commit 42b5f09f68

@ -27,11 +27,10 @@ package de.anomic.search;
import java.io.ByteArrayInputStream;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.yacy.cora.document.ASCII;
@ -57,34 +56,34 @@ import de.anomic.yacy.yacySearch;
public class TextSnippet implements Comparable<TextSnippet>, Comparator<TextSnippet> {
private static final int maxCache = 1000;
private static final int MAX_CACHE = 1000;
/**
* <code>\\A[^\\p{L}\\p{N}].+</code>
*/
private final static Pattern p1 = Pattern.compile("\\A[^\\p{L}\\p{N}].+");
private static final Pattern p1 =
Pattern.compile("\\A[^\\p{L}\\p{N}].+");
/**
* <code>.+[^\\p{L}\\p{N}]\\Z</code>
*/
private final static Pattern p2 = Pattern.compile(".+[^\\p{L}\\p{N}]\\Z");
private static final Pattern p2 =
Pattern.compile(".+[^\\p{L}\\p{N}]\\Z");
/**
* <code>\\A[\\p{L}\\p{N}]+[^\\p{L}\\p{N}].+\\Z</code>
*/
private final static Pattern p3 = Pattern.compile("\\A[\\p{L}\\p{N}]+[^\\p{L}\\p{N}].+\\Z");
private static final Pattern p3 =
Pattern.compile("\\A[\\p{L}\\p{N}]+[^\\p{L}\\p{N}].+\\Z");
/**
* <code>[^\\p{L}\\p{N}]</code>
*/
private final static Pattern p4 = Pattern.compile("[^\\p{L}\\p{N}]");
/**
* <code>(.*?)(\\&lt;b\\&gt;.+?\\&lt;/b\\&gt;)(.*)</code>
*/
private final static Pattern p01 = Pattern.compile("(.*?)(\\<b\\>.+?\\</b\\>)(.*)"); // marked words are in <b>-tags
private static final Pattern p4 =
Pattern.compile("[^\\p{L}\\p{N}]");
public static class Cache {
private final ARC<String, String> cache;
public Cache() {
this.cache = new ConcurrentARC<String, String>(maxCache, Math.max(32, 4 * Runtime.getRuntime().availableProcessors()));
this.cache = new ConcurrentARC<String, String>(MAX_CACHE, Math.max(32, 4 * Runtime.getRuntime().availableProcessors()));
}
public void put(final String wordhashes, final String urlhash, final String snippet) {
// generate key
@ -310,7 +309,11 @@ public class TextSnippet implements Comparable<TextSnippet>, Comparator<TextSnip
return document;
}
private void init(final byte[] urlhash, final String line, final ResultClass errorCode, final String errortext) {
private void init(
final byte[] urlhash,
final String line,
final ResultClass errorCode,
final String errortext) {
this.urlhash = urlhash;
this.line = line;
this.resultStatus = errorCode;
@ -333,29 +336,39 @@ public class TextSnippet implements Comparable<TextSnippet>, Comparator<TextSnip
return this.resultStatus;
}
private final static Pattern splitPattern = Pattern.compile(" |-");
private static final Pattern SPLIT_PATTERN = Pattern.compile(" |-");
/**
* Marks all words in current line which have the same
* hash values as the ones contained in argument.
* @param queryHashes hashes of search words
* @return line with marked words
*/
public String getLineMarked(final HandleSet queryHashes) {
if (this.line == null) return "";
if (queryHashes == null || queryHashes.isEmpty()) return this.line.trim();
if (this.line.endsWith(".")) this.line = this.line.substring(0, this.line.length() - 1);
final Iterator<byte[]> i = queryHashes.iterator();
byte[] h;
final String[] words = splitPattern.split(this.line);
while (i.hasNext()) {
h = i.next();
for (int j = 0; j < words.length; j++) {
final List<String> al = markedWordArrayList(words[j]); // mark special character separated words correctly if more than 1 word has to be marked
words[j] = "";
for (int k = 0; k < al.size(); k++) {
if(k % 2 == 0){ // word has not been marked
words[j] += getWordMarked(al.get(k), h);
} else { // word has been marked, do not encode again
words[j] += al.get(k);
}
}
}
}
final StringBuilder l = new StringBuilder(this.line.length() + queryHashes.size() * 8);
if (this.line == null) {
return "";
}
if (queryHashes == null || queryHashes.isEmpty()) {
return this.line.trim();
}
if (this.line.endsWith(".")) {
this.line = this.line.substring(0, this.line.length() - 1);
}
final String[] words = SPLIT_PATTERN.split(this.line);
final Iterator<byte[]> iterator = queryHashes.iterator();
final Set<byte[]> queryHashesSet = new HashSet<byte[]>();
while (iterator.hasNext()) {
queryHashesSet.add(iterator.next());
}
for (int i = 0; i < words.length; i++) {
words[i] = getWordMarked(words[i], queryHashesSet);
}
final StringBuilder l =
new StringBuilder(this.line.length() + queryHashes.size() * 8);
for (final String word : words) {
l.append(word);
l.append(' ');
@ -382,99 +395,97 @@ public class TextSnippet implements Comparable<TextSnippet>, Comparator<TextSnip
}
/**
* mark words with &lt;b&gt;-tags
* Marks words with &lt;b&gt;-tags. <b>Beware</b>: Method
* has side effects! Certain characters in words will be
* escaped to HTML encoding. Using this method a second
* time with already escaped characters might lead to
* undesired results.
* @param word the word to mark
* @param h the hash of the word to mark
* @return the marked word if hash matches, else the unmarked word
* @param queryHashes hashes of the words to mark
* @return the marked word if one of the hashes matches,
* else the unmarked word
* @see #getLineMarked(Set)
*/
private static String getWordMarked(final String word, final byte[] h){
//ignore punctuation marks (contrib [MN])
//note to myself:
private static String getWordMarked(
final String word, final Set<byte[]> queryHashes) {
//note to myself [MN]:
//For details on regex see "Mastering regular expressions" by J.E.F. Friedl
//especially p. 123 and p. 390/391 (in the German version of the 2nd edition)
StringBuilder theWord = new StringBuilder(word);
final StringBuilder theWord = new StringBuilder(word);
final StringBuilder prefix = new StringBuilder(40);
final StringBuilder postfix = new StringBuilder(40);
int len = 0;
// cut off prefix if it contains of non-characters or non-numbers
while(p1.matcher(theWord).find()) {
prefix.append(theWord.substring(0,1));
theWord = theWord.delete(0, 1);
while (p1.matcher(theWord).find()) {
prefix.append(theWord.substring(0, 1));
theWord.delete(0, 1);
}
// cut off postfix if it contains of non-characters or non-numbers
while(p2.matcher(theWord).find()) {
while (p2.matcher(theWord).find()) {
len = theWord.length();
postfix.insert(0, theWord.substring(len-1,len));
theWord = theWord.delete(len - 1, len);
postfix.insert(0, theWord.substring(len - 1, len));
theWord.delete(len - 1, len);
}
//special treatment if there is a special character in the word
if(p3.matcher(theWord).find()) {
if (p3.matcher(theWord).find()) {
StringBuilder out = null;
String temp = "";
for(int k=0; k < theWord.length(); k++) {
for (int k = 0; k < theWord.length(); k++) {
out = new StringBuilder(80);
//is character a special character?
if(p4.matcher(theWord.substring(k,k+1)).find()) {
if (ByteBuffer.equals(Word.word2hash(temp), h)) temp = "<b>" + CharacterCoding.unicode2html(temp, false) + "</b>";
if (p4.matcher(theWord.substring(k, k + 1)).find()) {
if (ByteBuffer.contains(queryHashes, Word.word2hash(temp))) {
temp = "<b>" + CharacterCoding.unicode2html(temp, false) + "</b>";
}
out.append(temp);
out.append(CharacterCoding.unicode2html(theWord.substring(k,k+1), false));
out.append(CharacterCoding.unicode2html(theWord.substring(k, k +1), false));
temp = "";
}
//last character
else if(k == (theWord.length()-1)) {
temp = temp + theWord.substring(k,k+1);
if (ByteBuffer.equals(Word.word2hash(temp), h)) temp = "<b>" + CharacterCoding.unicode2html(temp, false) + "</b>";
else if (k == (theWord.length() - 1)) {
temp = temp + theWord.substring(k, k + 1);
if (ByteBuffer.contains(queryHashes, Word.word2hash(temp))) {
temp = "<b>" + CharacterCoding.unicode2html(temp, false) + "</b>";
}
out.append(temp);
temp = "";
}
else {
temp = temp + theWord.substring(k,k+1);
}
temp = temp + theWord.substring(k, k + 1);
}
theWord = out;
}
theWord.delete(0, theWord.length());
theWord.append(out);
//end contrib [MN]
else if (ByteBuffer.equals(Word.word2hash(theWord), h)) {
theWord.replace(0, theWord.length(), CharacterCoding.unicode2html(theWord.toString(), false));
} else if (ByteBuffer.contains(queryHashes, Word.word2hash(theWord))) {
theWord.replace(
0,
theWord.length(),
CharacterCoding.unicode2html(theWord.toString(), false));
theWord.insert(0, "<b>");
theWord.append("</b>");
}
theWord.insert(0, CharacterCoding.unicode2html(prefix.toString(), false));
theWord.insert(
0,
CharacterCoding.unicode2html(prefix.toString(), false));
theWord.append(CharacterCoding.unicode2html(postfix.toString(), false));
return theWord.toString();
}
/**
* words that already has been marked has index <code>(i % 2 == 1)</code>
* words that has not yet been marked has index <code>(i % 2 == 0)</code>
* @param string the String to be processed
* @return words that already has and has not yet been marked
* @author [DW], 08.11.2008
*/
private static List<String> markedWordArrayList(String string){
final List<String> al = new java.util.ArrayList<String>(1);
Matcher m = p01.matcher(string);
while (m.find()) {
al.add(m.group(1));
al.add(m.group(2));
string = m.group(3); // the postfix
m = p01.matcher(string);
}
al.add(string);
return al;
}
private static boolean containsAllHashes(final String sentence, final HandleSet queryhashes) {
final SortedMap<byte[], Integer> m = WordTokenizer.hashSentence(sentence, null);
for (final byte[] b: queryhashes) {
if (!(m.containsKey(b))) return false;
private static boolean containsAllHashes(
final String sentence, final HandleSet queryhashes) {
final SortedMap<byte[], Integer> m =
WordTokenizer.hashSentence(sentence, null);
for (final byte[] b : queryhashes) {
if (!(m.containsKey(b))) {
return false;
}
}
return true;
}

Loading…
Cancel
Save