001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.search; 029 030import org.opencms.monitor.CmsMemoryMonitor; 031import org.opencms.monitor.I_CmsMemoryMonitorable; 032import org.opencms.search.fields.CmsSearchField; 033import org.opencms.util.CmsStringUtil; 034 035import java.text.ParseException; 036import java.util.Date; 037import java.util.HashMap; 038import java.util.Iterator; 039import java.util.Map; 040 041import org.apache.lucene.document.DateTools; 042import org.apache.lucene.document.Document; 043import org.apache.lucene.index.IndexableField; 044 045/** 046 * Contains the data of a single item in a search result.<p> 047 * 048 * @since 6.0.0 049 */ 050public class CmsSearchResult implements I_CmsMemoryMonitorable, Comparable<CmsSearchResult> { 051 052 /** The creation date of this search result. */ 053 protected Date m_dateCreated; 054 055 /** The last modification date of this search result. */ 056 protected Date m_dateLastModified; 057 058 /** The document type of the search result. */ 059 protected String m_documentType; 060 061 /** The excerpt of this search result. */ 062 protected String m_excerpt; 063 064 /** Holds the values of the search result fields. */ 065 protected Map<String, String> m_fields; 066 067 /** The resource path of this search result. */ 068 protected String m_path; 069 070 /** The score of this search result. */ 071 protected int m_score; 072 073 /** Contains the pre-calculated memory size. */ 074 private int m_memorySize; 075 076 /** 077 * Creates a new search result.<p> 078 * 079 * @param score the score of this search result 080 * @param doc the Lucene document to extract fields from such as description, title, key words etc. pp. 081 * @param excerpt the excerpt of the search result's content 082 */ 083 public CmsSearchResult(int score, Document doc, String excerpt) { 084 085 m_score = score; 086 m_excerpt = excerpt; 087 m_fields = new HashMap<String, String>(); 088 089 Iterator<IndexableField> i = doc.getFields().iterator(); 090 while (i.hasNext()) { 091 IndexableField field = i.next(); 092 // content can be displayed only if it has been stored in the field 093 String name = field.name(); 094 String value = field.stringValue(); 095 if (CmsStringUtil.isNotEmpty(value) 096 && !CmsSearchField.FIELD_PATH.equals(name) 097 && !CmsSearchField.FIELD_DATE_CREATED.equals(name) 098 && !CmsSearchField.FIELD_DATE_LASTMODIFIED.equals(name)) { 099 // these "hard coded" fields are treated differently 100 m_fields.put(name, value); 101 } 102 } 103 104 IndexableField f = doc.getField(CmsSearchField.FIELD_PATH); 105 if (f != null) { 106 m_path = f.stringValue(); 107 } else { 108 m_path = null; 109 } 110 111 f = doc.getField(CmsSearchField.FIELD_DATE_CREATED); 112 if (f != null) { 113 try { 114 m_dateCreated = DateTools.stringToDate(f.stringValue()); 115 } catch (ParseException exc) { 116 m_dateCreated = null; 117 } 118 } else { 119 m_dateCreated = null; 120 } 121 122 f = doc.getField(CmsSearchField.FIELD_DATE_LASTMODIFIED); 123 if (f != null) { 124 try { 125 m_dateLastModified = DateTools.stringToDate(f.stringValue()); 126 } catch (ParseException exc) { 127 m_dateLastModified = null; 128 } 129 } else { 130 m_dateLastModified = null; 131 } 132 133 f = doc.getField(CmsSearchField.FIELD_TYPE); 134 if (f != null) { 135 m_documentType = f.stringValue(); 136 } else { 137 m_documentType = null; 138 } 139 } 140 141 /** 142 * Empty constructor to be used for overriding classes. 143 */ 144 protected CmsSearchResult() { 145 146 // noop 147 } 148 149 /** 150 * @see java.lang.Comparable#compareTo(java.lang.Object) 151 */ 152 public int compareTo(CmsSearchResult obj) { 153 154 if (obj == this) { 155 return 0; 156 } 157 return obj.m_score - m_score; 158 } 159 160 /** 161 * @see java.lang.Object#equals(java.lang.Object) 162 */ 163 @Override 164 public boolean equals(Object obj) { 165 166 if (obj == this) { 167 return true; 168 } 169 if (obj instanceof CmsSearchResult) { 170 CmsSearchResult other = (CmsSearchResult)obj; 171 return m_documentType.equals(other.m_documentType) && m_path.equals(other.m_path); 172 } 173 return false; 174 } 175 176 /** 177 * Returns the date created.<p> 178 * 179 * @return the date created 180 */ 181 public Date getDateCreated() { 182 183 if (m_dateCreated != null) { 184 return (Date)m_dateCreated.clone(); 185 } 186 return null; 187 } 188 189 /** 190 * Returns the date last modified.<p> 191 * 192 * @return the date last modified 193 */ 194 public Date getDateLastModified() { 195 196 if (m_dateLastModified != null) { 197 return (Date)m_dateLastModified.clone(); 198 } 199 return null; 200 } 201 202 /** 203 * Returns the description.<p> 204 * 205 * @return the description 206 * 207 * @deprecated use {@link #getField(String)} instead with the name of the field, 208 * for example use {@link org.opencms.search.fields.CmsLuceneField#FIELD_DESCRIPTION} to get the description (if available) 209 */ 210 @Deprecated 211 public String getDescription() { 212 213 return getField(CmsSearchField.FIELD_DESCRIPTION); 214 } 215 216 /** 217 * Returns the document type of the search result document.<p> 218 * 219 * Usually this will be a VFS resource type String that can be used in the 220 * resource type manager with {@link org.opencms.loader.CmsResourceManager#getResourceType(String)}. 221 * However, what is stored in the document type field depends only on the indexer used, and therefore it 222 * may also be some String not referring a VFS resource type but some external type or application. 223 * It may also be <code>null</code> in case it has not been set by a non-standard indexer.<p> 224 * 225 * @return the document type of the search result document 226 * 227 * @see org.opencms.loader.CmsResourceManager#getResourceType(String) 228 */ 229 public String getDocumentType() { 230 231 return m_documentType; 232 } 233 234 /** 235 * Returns the excerpt.<p> 236 * 237 * @return the excerpt 238 */ 239 public String getExcerpt() { 240 241 return m_excerpt; 242 } 243 244 /** 245 * Returns the text stored in the search index field with the given name.<p> 246 * 247 * @param fieldName the name of the field to get the stored text for 248 * 249 * @return the text stored in the search index field with the given name 250 */ 251 public String getField(String fieldName) { 252 253 return m_fields.get(fieldName); 254 } 255 256 /** 257 * Returns the key words.<p> 258 * 259 * @return the key words 260 * 261 * @deprecated use {@link #getField(String)} instead with the name of the field, 262 * for example use {@link org.opencms.search.fields.CmsLuceneField#FIELD_KEYWORDS} to get the keywords (if available) 263 */ 264 @Deprecated 265 public String getKeywords() { 266 267 return getField(CmsSearchField.FIELD_KEYWORDS); 268 } 269 270 /** 271 * @see org.opencms.monitor.I_CmsMemoryMonitorable#getMemorySize() 272 */ 273 public int getMemorySize() { 274 275 if (m_memorySize == 0) { 276 int result = 8; 277 if (m_dateCreated != null) { 278 result += CmsMemoryMonitor.getMemorySize(m_dateCreated); 279 } 280 if (m_dateLastModified != null) { 281 result += CmsMemoryMonitor.getMemorySize(m_dateLastModified); 282 } 283 if (m_path != null) { 284 result += CmsMemoryMonitor.getMemorySize(m_path); 285 } 286 if (m_fields != null) { 287 Iterator<Map.Entry<String, String>> entries = m_fields.entrySet().iterator(); 288 while (entries.hasNext()) { 289 Map.Entry<String, String> entry = entries.next(); 290 result += CmsMemoryMonitor.getMemorySize(entry.getKey()); 291 result += CmsMemoryMonitor.getMemorySize(entry.getValue()); 292 } 293 } 294 if (m_excerpt != null) { 295 result += CmsMemoryMonitor.getMemorySize(m_excerpt); 296 } 297 m_memorySize = result; 298 } 299 return m_memorySize; 300 } 301 302 /** 303 * Returns the path.<p> 304 * 305 * @return the path 306 */ 307 public String getPath() { 308 309 return m_path; 310 } 311 312 /** 313 * Returns the score.<p> 314 * 315 * @return the score 316 */ 317 public int getScore() { 318 319 return m_score; 320 } 321 322 /** 323 * Returns the title.<p> 324 * 325 * @return the title 326 * 327 * @deprecated use {@link #getField(String)} instead with the name of the field, 328 * for example use {@link org.opencms.search.fields.CmsLuceneField#FIELD_TITLE} to get the title (if available) 329 */ 330 @Deprecated 331 public String getTitle() { 332 333 return getField(CmsSearchField.FIELD_TITLE); 334 } 335 336 /** 337 * @see java.lang.Object#hashCode() 338 */ 339 @Override 340 public int hashCode() { 341 342 return (m_documentType.hashCode() * 1109) + m_path.hashCode(); 343 } 344}