001: /*
002: * Copyright 2001-2006 C:1 Financial Services GmbH
003: *
004: * This software is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License Version 2.1, as published by the Free Software Foundation.
007: *
008: * This software is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011: * Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public
014: * License along with this library; if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
016: */
017:
018: package de.finix.contelligent.search;
019:
020: import java.io.IOException;
021: import java.io.Writer;
022: import java.util.Collection;
023: import java.util.Collections;
024: import java.util.Enumeration;
025: import java.util.Iterator;
026: import java.util.Map;
027: import java.util.StringTokenizer;
028:
029: import org.apache.lucene.document.Field;
030:
031: import de.finix.contelligent.AbstractComponent;
032: import de.finix.contelligent.CallData;
033: import de.finix.contelligent.Component;
034: import de.finix.contelligent.ComponentManager;
035: import de.finix.contelligent.ComponentPath;
036: import de.finix.contelligent.action.ActionResult;
037: import de.finix.contelligent.logging.LoggingService;
038: import de.finix.contelligent.render.ParameterDescription;
039: import de.finix.contelligent.render.Renderable;
040: import de.finix.contelligent.render.Renderer;
041:
042: public class BasicSearchResult2XML extends AbstractComponent implements
043: Renderable, Renderer {
044: final static org.apache.log4j.Logger log = LoggingService
045: .getLogger(BasicSearchResult2XML.class);
046:
047: int MAX_RESULT = 20;
048:
049: String SERVER_CATEGORYNAME = "server";
050:
051: int MAX_CONTENT_LENGTH = 300;
052:
053: ComponentPath searchResult;
054:
055: boolean displayall = false;
056:
057: public void setSearchResult(ComponentPath s) {
058: this .searchResult = s;
059: }
060:
061: public ComponentPath getSearchResult() {
062: return searchResult;
063: }
064:
065: /**
066: * the view component should allow xml based datamining of components
067: * structure the getValue will return the xml String representing this node
068: */
069: public void render(Writer writer, Map parameterMap,
070: CallData callData) throws IOException {
071: StringBuffer buf = new StringBuffer(); // search results for fulltext
072: StringBuffer retbuf = new StringBuffer(); // search results for
073: // fulltext
074:
075: SearchResult res = null;
076: String query = "";
077: retbuf
078: .append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
079:
080: ComponentManager cm = callData.getActualManager();
081: try {
082: ActionResult ar = (ActionResult) cm.getComponent(
083: searchResult, callData);
084: res = (SearchResult) ar.getObject(callData);
085: } catch (Exception e) {
086: log
087: .error(
088: "an exception occured while retrieving the searchresult: ",
089: e);
090: }
091:
092: if (res != null) {
093: retbuf.append("<searchresult count=\"");
094: retbuf.append(res.getTotalLength());
095: retbuf.append("\" displayall=\"");
096: retbuf.append(displayall ? "true" : "false");
097: retbuf.append("\" >");
098:
099: query = res.getQuery();
100: retbuf.append("<query>");
101: retbuf.append(query);
102: retbuf.append("</query>");
103:
104: Iterator results = res.iterator();
105: while (results.hasNext()) {
106: SearchResult.SearchResultItem ri = (SearchResult.SearchResultItem) results
107: .next();
108:
109: ComponentPath cp = null;
110: Component parent = null;
111:
112: try {
113: ComponentPath cpath = new ComponentPath(ri
114: .getPath());
115: buf.append("<searchitem type=\"");
116: buf.append(ri.getType());
117: buf.append("\" path=\"");
118: buf.append(ri.getPath());
119: buf.append("\" dir=\"");
120: buf.append(cpath.getDir());
121: buf.append("\" name=\"");
122: buf.append(cpath.getName());
123: buf.append("\" parentdir=\"");
124: buf.append(cpath.parentPath().getDir());
125: buf.append("\" parentname=\"");
126: buf.append(cpath.parentPath().getName());
127: buf.append("\" score=\"");
128: buf.append(ri.getScore());
129: buf.append("\" >");
130:
131: for (Enumeration e = ri.getDocument().fields(); e
132: .hasMoreElements();) {
133: Field field = (Field) e.nextElement();
134: String fieldName = field.name();
135:
136: if (fieldName.equals("contents")) {
137: String content = ri
138: .getFieldValue(fieldName);
139:
140: content = markQueryInText(query, content);
141:
142: buf.append("<").append(fieldName).append(
143: ">");
144: buf.append("<![CDATA[").append(content)
145: .append("]]>");
146: buf.append("</").append(fieldName).append(
147: ">");
148: } else {
149: buf.append("<").append(fieldName).append(
150: ">");
151: buf.append("<![CDATA[").append(
152: ri.getFieldValue(fieldName))
153: .append("]]>");
154: buf.append("</").append(fieldName).append(
155: ">");
156: }
157: }
158:
159: buf.append("</searchitem>");
160:
161: } catch (Exception ce) {
162: log.warn("Problem with a search result: ", ce);
163: }
164: }
165: retbuf.append(buf.toString());
166: retbuf.append("</searchresult>");
167:
168: } else {
169: retbuf.append("<searchresult/>");
170: }
171:
172: if (log.isDebugEnabled()) {
173: log.debug("will return as value " + retbuf.toString());
174: }
175:
176: writer.write(retbuf.toString());
177: }
178:
179: public String extractQuery(String query) {
180: return query;
181: }
182:
183: public String markQueryInText(String query, String textInPage) {
184: StringBuffer result = new StringBuffer();
185:
186: query = extractQuery(query);
187:
188: query = query.replace('+', ' ');
189: query = query.replace('(', ' ');
190: query = query.replace(')', ' ');
191: query = query.replace('*', ' ');
192:
193: int firstHit = -1;
194:
195: StringTokenizer st = new StringTokenizer(query, " ");
196: while (st.hasMoreTokens()) {
197: String searchString = textInPage.toLowerCase();
198: String queryPart = ((String) st.nextToken()).toLowerCase();
199:
200: int querylen = queryPart.length();
201: int lastpos = 0;
202: int pos = searchString.indexOf(queryPart);
203: if (firstHit == -1)
204: firstHit = pos;
205: else
206: firstHit = (pos > firstHit) ? firstHit : pos;
207: while (pos >= 0) {
208: result.append(textInPage.substring(lastpos, pos))
209: .append(
210: "<b>"
211: + textInPage.substring(pos, pos
212: + querylen) + "</b>");
213: lastpos = pos + querylen;
214: pos = searchString.indexOf(queryPart, pos + querylen);
215: }
216: result.append(textInPage.substring(lastpos));
217: textInPage = result.toString();
218: result = new StringBuffer();
219: }
220:
221: try {
222: int left = firstHit > (MAX_CONTENT_LENGTH / 2) ? MAX_CONTENT_LENGTH / 2
223: : firstHit;
224: int right = firstHit + (MAX_CONTENT_LENGTH - left);
225:
226: int leftPos = firstHit - left;
227: int rightPos = right > textInPage.length() ? textInPage
228: .length() : right;
229:
230: textInPage = textInPage.substring(leftPos, rightPos);
231: } catch (Exception e) {
232: if (textInPage.length() > MAX_CONTENT_LENGTH)
233: textInPage = textInPage
234: .substring(0, MAX_CONTENT_LENGTH);
235: }
236:
237: return textInPage;
238: }
239:
240: private void handleDocument(ComponentPath cpath, StringBuffer buf) {
241:
242: }
243:
244: public Renderer getRenderer() {
245: return this ;
246: }
247:
248: public ParameterDescription[] getParameterDescription() {
249: return null;
250: }
251:
252: public Collection getSensitiveCategories() {
253: return Collections.EMPTY_SET;
254: }
255:
256: }
|