blob: 4ac528f1b6703012dfd8fe1927a4c2f883de2702 [file] [log] [blame]
package org.eclipse.help.internal.server;
/*
* Licensed Materials - Property of IBM,
* WebSphere Studio Workbench
* (c) Copyright IBM Corp 2000
*/
import java.util.*;
import java.net.URLDecoder;
import org.eclipse.help.internal.navigation.HelpNavigationManager;
import org.eclipse.help.internal.HelpSystem;
/**
* This class should perhaps be changed a bit, and so
* should the SearchURL. Factor out some search utility
* and have it return the correct processed stream.
*/
class HighlightProcessor implements OutputProcessor {
private HelpURL url;
private static final byte[] headTagBegin = "<head".getBytes();
private static final byte[] headTagBeginCaps = "<HEAD".getBytes();
private static final char headTagEnd = '>';
private static final String scriptPart1 =
"\n<script language=\"JavaScript\">\n<!--\nvar keywords = new Array (";
private static final String scriptPart3 =
");\nonload=highlight;\nfunction highlight()\n{\nvar newText = document.body.createTextRange();\nfor (var i = 0; i < keywords.length; i++) {\nwhile (newText.findText(keywords[i]) )\n{\nvar replacement = newText.text\nnewText.pasteHTML(\"<span class=highlight style='background-color:lightgrey'>\" + replacement + \"</span>\");\n}\nnewText = document.body.createTextRange();\n}\n}\n// -->\n</script>\n";
//private int docNumber;
private String query;
/**
* HighlightProcessor constructor.
*/
public HighlightProcessor() {
super();
}
public HighlightProcessor(HelpURL url) {
this.url = url;
//docNumber = Integer.parseInt(url.getValue("hitOrder"));
query = url.getValue("resultof");
}
/**
* Crates Java Script that does hightlighting
*/
private byte[] createJScript(Collection keywords) {
StringBuffer buf = new StringBuffer(scriptPart1);
Iterator it = keywords.iterator();
if (!it.hasNext())
return null;
String keyword = (String) it.next();
buf.append("\"").append(keyword).append("\"");
while (it.hasNext()) {
keyword = (String) it.next();
buf.append(", \"").append(keyword).append("\"");
}
buf.append(scriptPart3);
return buf.toString().getBytes();
}
/**
* Extract keywords from query in the GTR format
* @return Collection of String
*/
private Collection getKeywords() {
Collection tokens = new ArrayList();
//Divide along quotation marks and brackets
StringTokenizer qTokenizer = new StringTokenizer(query.trim(), "\"()", true);
boolean withinQuotation = false;
String quotedString = "";
while (qTokenizer.hasMoreTokens()) {
String curToken = qTokenizer.nextToken();
if (curToken.equals("\"")) {
if (!withinQuotation) {
//beginning of quoted string
quotedString = "";
} else {
//end of quoted string
tokens.add(quotedString);
}
withinQuotation = !withinQuotation;
continue;
}
if (withinQuotation) {
quotedString += (curToken);
} else {
//divide not quoted strings along white space
StringTokenizer parser = new StringTokenizer(curToken.trim());
while (parser.hasMoreTokens()) {
tokens.add(parser.nextToken());
}
}
}
Collection keywords = new HashSet(); // to eliminate duplicate words
for (Iterator it = tokens.iterator(); it.hasNext();) {
String token = (String) it.next();
String tokenLowerCase = token.toLowerCase();
if (!tokenLowerCase.equals("\"")
&& !tokenLowerCase.equals("(")
&& !tokenLowerCase.equals(")")
&& !tokenLowerCase.equals("and")
&& !tokenLowerCase.equals("or")
&& !tokenLowerCase.equals("not"))
keywords.add(token);
}
return keywords;
}
/**
* Encodes strings inside collection for embedding in HTML source
* @return Collection of String
*/
private Collection JavaScriptEncode(Collection col) {
if (col == null)
return col;
Collection result = new ArrayList();
for (Iterator it = col.iterator(); it.hasNext();) {
String keyword = (String) it.next();
int l = keyword.length();
if (l < 1)
continue;
char[] keywordChars = new char[l];
keyword.getChars(0, l, keywordChars, 0);
StringBuffer jsEncoded = new StringBuffer();
for (int j = 0; j < keywordChars.length; j++) {
String charInHex = Integer.toString((int) keywordChars[j], 16).toUpperCase();
switch (charInHex.length()) {
case 1 :
jsEncoded.append("\\u000").append(charInHex);
break;
case 2 :
jsEncoded.append("\\u00").append(charInHex);
break;
case 3 :
jsEncoded.append("\\u0").append(charInHex);
break;
default :
jsEncoded.append("\\u").append(charInHex);
break;
}
}
result.add(jsEncoded.toString());
}
return result;
}
public byte[] processOutput(byte[] input) {
if (query == null)
return input;
Collection keywords = getKeywords();
keywords = removeWildCards(keywords);
keywords = JavaScriptEncode(keywords);
byte[] script = createJScript(keywords);
if (script == null)
return input;
// Create new buffer
byte[] buffer = new byte[input.length + script.length];
int bufPointer = 0;
int inputPointer = 0;
boolean foundHeadTagBegin = false;
boolean foundHeadTagEnd = false;
while (inputPointer < input.length) {
// copy character
buffer[bufPointer++] = input[inputPointer++];
// look for head tag copied
if (!foundHeadTagEnd
&& !foundHeadTagBegin
&& (bufPointer >= headTagBegin.length)) {
for (int i = 0; i < headTagBegin.length; i++) {
if ((buffer[bufPointer - headTagBegin.length + i] != headTagBegin[i])
&& (buffer[bufPointer - headTagBegin.length + i] != headTagBeginCaps[i])) {
break;
}
if (i == headTagBegin.length - 1)
foundHeadTagBegin = true;
}
}
if (!foundHeadTagEnd && foundHeadTagBegin && buffer[bufPointer - 1] == '>') {
foundHeadTagEnd = true;
//embed Script
System.arraycopy(script, 0, buffer, bufPointer, script.length);
bufPointer += script.length;
// copy rest
System.arraycopy(
input,
inputPointer,
buffer,
bufPointer,
input.length - inputPointer);
return buffer;
}
}
return buffer;
}
/**
* Removes wildcard characters from keywords, by splitting keywords around wild cards
* @return Collection of String
*/
private Collection removeWildCards(Collection col) {
if (col == null)
return col;
// Split keywords into parts: before "*" and after "*"
Collection resultPass1 = new ArrayList();
for (Iterator it = col.iterator(); it.hasNext();) {
String keyword = (String) it.next();
int index;
while((index=keyword.indexOf("*"))>=0){
if(index>0)
resultPass1.add(keyword.substring(0, index));
if(keyword.length()>index)
keyword=keyword.substring(index+1);
}
if(keyword.length()>0)
resultPass1.add(keyword);
}
// Split keywords into parts: before "?" and after "?"
Collection resultPass2 = new ArrayList();
for (Iterator it = resultPass1.iterator(); it.hasNext();) {
String keyword = (String) it.next();
int index;
while((index=keyword.indexOf("?"))>=0){
if(index>0)
resultPass2.add(keyword.substring(0, index));
if(keyword.length()>index)
keyword=keyword.substring(index+1);
}
if(keyword.length()>0)
resultPass2.add(keyword);
}
return resultPass2;
}
}