001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/search/tags/sakai_2-4-1/search-impl/impl/src/java/org/sakaiproject/search/component/service/impl/SearchResultResponseImpl.java $
003: * $Id: SearchResultResponseImpl.java 29315 2007-04-20 14:28:12Z ajpoland@iupui.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2003, 2004, 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.search.component.service.impl;
021:
022: import java.io.IOException;
023: import java.io.StringReader;
024: import java.io.UnsupportedEncodingException;
025: import java.util.HashMap;
026: import java.util.Iterator;
027: import java.util.Map;
028:
029: import org.apache.commons.codec.binary.Base64;
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032: import org.apache.lucene.analysis.Analyzer;
033: import org.apache.lucene.analysis.TokenStream;
034: import org.apache.lucene.search.Query;
035: import org.apache.lucene.search.highlight.Highlighter;
036: import org.apache.lucene.search.highlight.QueryScorer;
037: import org.apache.lucene.search.highlight.Scorer;
038: import org.sakaiproject.search.api.EntityContentProducer;
039: import org.sakaiproject.search.api.SearchIndexBuilder;
040: import org.sakaiproject.search.api.SearchResult;
041: import org.sakaiproject.search.api.SearchService;
042: import org.sakaiproject.search.api.TermFrequency;
043: import org.sakaiproject.search.component.Messages;
044: import org.xml.sax.Attributes;
045:
046: /**
047: * @author ieb
048: */
049: public class SearchResultResponseImpl implements SearchResult {
050:
051: private static Log log = LogFactory
052: .getLog(SearchResultResponseImpl.class);
053:
054: String[] fieldNames = null;
055:
056: private Query query = null;
057:
058: private Analyzer analyzer = null;
059:
060: private SearchIndexBuilder searchIndexBuilder;
061:
062: private SearchService searchService;
063:
064: private Map attributes;
065:
066: public SearchResultResponseImpl(Map attributes, Query query,
067: Analyzer analyzer, SearchIndexBuilder searchIndexBuilder,
068: SearchService searchService) throws IOException {
069:
070: this .attributes = attributes;
071: this .query = query;
072: this .analyzer = analyzer;
073: this .searchIndexBuilder = searchIndexBuilder;
074: this .searchService = searchService;
075: }
076:
077: public SearchResultResponseImpl(Attributes atts, Query query,
078: Analyzer analyzer, SearchIndexBuilder searchIndexBuilder,
079: SearchService searchService) throws IOException {
080: Map m = new HashMap();
081: for (int i = 0; i < atts.getLength(); i++) {
082: m.put(atts.getLocalName(i), atts.getValue(i));
083: }
084: try {
085: String title = (String) m.get("title"); //$NON-NLS-1$
086: if (title != null) {
087: m
088: .put(
089: "title", new String(Base64.decodeBase64(title.getBytes("UTF-8")), "UTF-8")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
090: }
091: } catch (UnsupportedEncodingException e) {
092: }
093: this .attributes = m;
094: this .query = query;
095: this .analyzer = analyzer;
096: this .searchIndexBuilder = searchIndexBuilder;
097: this .searchService = searchService;
098: }
099:
100: public float getScore() {
101: return Float.parseFloat((String) attributes.get("score")); //$NON-NLS-1$
102: }
103:
104: public String getId() {
105: return (String) attributes.get("sid"); //$NON-NLS-1$
106: }
107:
108: public String[] getFieldNames() {
109:
110: if (fieldNames != null) {
111: return fieldNames;
112: }
113: fieldNames = new String[attributes.size()];
114: int ii = 0;
115: for (Iterator i = attributes.keySet().iterator(); i.hasNext();) {
116: fieldNames[ii++] = (String) i.next();
117: }
118: return fieldNames;
119: }
120:
121: public String[] getValues(String fieldName) {
122: return new String[] { (String) attributes.get(fieldName) };
123: }
124:
125: /**
126: * {@inheritDoc}
127: */
128: public Map getValueMap() {
129: HashMap hm = new HashMap();
130: String[] fieldNames = getFieldNames();
131: for (int i = 0; i < fieldNames.length; i++) {
132: hm.put(fieldNames[i], new String[] { (String) attributes
133: .get(fieldNames[i]) });
134: }
135: return hm;
136: }
137:
138: public String getUrl() {
139: return (String) attributes.get("url"); //$NON-NLS-1$
140: }
141:
142: public String getTitle() {
143: return StringUtils.escapeHtml(
144: (String) attributes.get("title"), false); //$NON-NLS-1$
145: }
146:
147: public String getTool() {
148: return StringUtils.escapeHtml(
149: (String) attributes.get("tool"), false); //$NON-NLS-1$
150:
151: }
152:
153: public int getIndex() {
154: return Integer.parseInt((String) attributes.get("index")); //$NON-NLS-1$
155: }
156:
157: public String getSearchResult() {
158: try {
159: Scorer scorer = new QueryScorer(query);
160: Highlighter hightlighter = new Highlighter(scorer);
161: StringBuffer sb = new StringBuffer();
162: // contents no longer contains the digested contents, so we need to
163: // fetch it from the EntityContentProducer
164:
165: EntityContentProducer sep = searchIndexBuilder
166: .newEntityContentProducer(getReference());
167: sb.append(sep.getContent(getReference()));
168:
169: String text = StringUtils.escapeHtml(sb.toString(), false);
170: TokenStream tokenStream = analyzer.tokenStream(
171: SearchService.FIELD_CONTENTS,
172: new StringReader(text));
173: return hightlighter.getBestFragments(tokenStream, text, 5,
174: " ... "); //$NON-NLS-1$
175: } catch (IOException e) {
176: return Messages.getString("SearchResultResponseImpl.11") + e.getMessage(); //$NON-NLS-1$
177: }
178: }
179:
180: public String getReference() {
181: return (String) attributes.get("reference"); //$NON-NLS-1$
182: }
183:
184: public TermFrequency getTerms() throws IOException {
185: return null;
186: }
187:
188: public void toXMLString(StringBuffer sb) {
189: sb.append("<result"); //$NON-NLS-1$
190: sb.append(" index=\"").append(getIndex()).append("\" "); //$NON-NLS-1$ //$NON-NLS-2$
191: sb.append(" score=\"").append(getScore()).append("\" "); //$NON-NLS-1$ //$NON-NLS-2$
192: sb
193: .append(" sid=\"").append(StringUtils.xmlEscape(getId())).append("\" "); //$NON-NLS-1$ //$NON-NLS-2$
194: sb
195: .append(" reference=\"").append(StringUtils.xmlEscape(getReference())).append("\" "); //$NON-NLS-1$ //$NON-NLS-2$
196: try {
197: sb.append(" title=\"").append( //$NON-NLS-1$
198: new String(Base64.encodeBase64(getTitle().getBytes(
199: "UTF-8")), "UTF-8")).append("\" "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
200: } catch (UnsupportedEncodingException e) {
201: sb
202: .append(" title=\"").append(StringUtils.xmlEscape(getTitle())).append("\" "); //$NON-NLS-1$ //$NON-NLS-2$
203: }
204: sb
205: .append(" tool=\"").append(StringUtils.xmlEscape(getTool())).append("\" "); //$NON-NLS-1$ //$NON-NLS-2$
206: sb
207: .append(" url=\"").append(StringUtils.xmlEscape(getUrl())).append("\" />"); //$NON-NLS-1$ //$NON-NLS-2$
208: }
209:
210: }
|