/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/
package org.olat.core.commons.services.search;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.lucene.document.DateTools;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.olat.core.util.StringHelper;
/**
* Lucene document mapper.
* @author Christian Guretzki
*/
public class OlatDocument implements Serializable {
// Field names
public static final String TITLE_FIELD_NAME = "title";
public static final String DESCRIPTION_FIELD_NAME = "description";
public static final String CONTENT_FIELD_NAME = "content";
public static final String DOCUMENTTYPE_FIELD_NAME = "documenttype";
public static final String FILETYPE_FIELD_NAME = "filetype";
public static final String RESOURCEURL_FIELD_NAME = "resourceurl";
public static final String AUTHOR_FIELD_NAME = "author";
public static final String CREATED_FIELD_NAME = "created";
public static final String CHANGED_FIELD_NAME = "changed";
public static final String TIME_STAMP_NAME = "timestamp";
public static final String PARENT_CONTEXT_TYPE_FIELD_NAME = "parentcontexttype";
public static final String PARENT_CONTEXT_NAME_FIELD_NAME = "parentcontextname";
public static final String CSS_ICON = "cssicon";
// Lucene Attributes
private String title = "";
protected String description = "";
private String content = "";
/** E.g. 'Group','ForumMessage'. */
private String documentType = "";
private String fileType = "";
/** JumpInUrl to E.g. 'Group:123456:Forum:342556:Message:223344'. */
private String resourceUrl = "";
private String author = "";
private Date createdDate = null;
private Date lastChange = null;
private Date timestamp = null;
/** Various metadata, most likely doublin core **/
private Map<String, List<String>> metadata = null;
/* e.g. Course */
private String parentContextType = "";
/* e.g. Course-name */
private String parentContextName = "";
private String cssIcon;
public OlatDocument() {
timestamp = new Date();
}
public OlatDocument(Document document) {
title = document.get(TITLE_FIELD_NAME);
description = document.get(DESCRIPTION_FIELD_NAME);
content = document.get(CONTENT_FIELD_NAME);
documentType = document.get(DOCUMENTTYPE_FIELD_NAME);
fileType = document.get(FILETYPE_FIELD_NAME);
resourceUrl = document.get(RESOURCEURL_FIELD_NAME);
author = document.get(AUTHOR_FIELD_NAME);
try {
String f = document.get(CREATED_FIELD_NAME);
if(StringHelper.containsNonWhitespace(f)) {
createdDate = DateTools.stringToDate(f);
}
} catch (Exception e) {
//can happen
}
try {
String f = document.get(CHANGED_FIELD_NAME);
if(StringHelper.containsNonWhitespace(f)) {
lastChange = DateTools.stringToDate(f);
}
} catch (Exception e) {
//can happen
}
try {
String f = document.get(TIME_STAMP_NAME);
if(StringHelper.containsNonWhitespace(f)) {
timestamp = DateTools.stringToDate(f);
}
} catch (Exception e) {
//can happen
}
parentContextType = document.get(PARENT_CONTEXT_TYPE_FIELD_NAME);
parentContextName = document.get(PARENT_CONTEXT_NAME_FIELD_NAME);
cssIcon = document.get(CSS_ICON);
}
/**
* @return Returns the author.
*/
public String getAuthor() {
if (author == null) {
return ""; // Do not return null
}
return author;
}
/**
* @param author The author to set.
*/
public void setAuthor(String author) {
this.author = author;
}
/**
* @return Returns the content.
*/
public String getContent() {
if (content == null) {
return ""; // Do not return null
}
return content;
}
/**
* @param content The content to set.
*/
public void setContent(String content) {
this.content = content;
}
/**
* @return Returns the description.
*/
public String getDescription() {
if (description == null) {
return ""; // Do not return null
}
return description;
}
/**
* @param description The description to set.
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @return Returns the documentType.
*/
public String getDocumentType() {
if (documentType == null) {
return ""; // Do not return null
}
return documentType;
}
/**
* @param documentType The documentType to set.
*/
public void setDocumentType(String documentType) {
this.documentType = documentType;
}
/**
* @return Returns the fileType.
*/
public String getFileType() {
return fileType;
}
/**
* @param fileType The fileType to set.
*/
public void setFileType(String fileType) {
this.fileType = fileType;
}
/**
* @return Returns the lastChange.
*/
public Date getLastChange() {
return lastChange;
}
/**
* @param lastChange The lastChange to set.
*/
public void setLastChange(Date lastChange) {
this.lastChange = lastChange;
}
/**
* @return Returns the resourceUrl.
*/
public String getResourceUrl() {
if (resourceUrl == null) {
return ""; // Do not return null
}
return resourceUrl;
}
/**
* @param resourceUrl The resourceUrl to set.
*/
public void setResourceUrl(String resourceUrl) {
this.resourceUrl = resourceUrl;
}
/**
* @return Returns the title.
*/
public String getTitle() {
if (title == null) {
return ""; // Do not return null
}
return title;
}
/**
* @param title The title to set.
*/
public void setTitle(String title) {
this.title = title;
}
/**
* Add generic metadata. It is strongly recommended not to use anything else
* than the doublin core metadata namespace here. See {@link http
* ://en.wikipedia.org/wiki/Dublin_Core} for more information.
* <p>
* A metadata element consists of a key-value pair. It is possible to have
* more than one value for a key. In this case use the method multiple times
* with the same key.
* <p>
* Example:<br>
* DC.subject OLAT - the best Open Source LMS<br>
* DC.creator Florian GnÔøΩgi
*
* @param key The metadata key
* @param value The metadata value
*/
public synchronized void addMetadata(String key, String value) {
if (key == null || ! StringHelper.containsNonWhitespace(value)) return;
// initialize metadata map if never done before
if (metadata == null) metadata = new HashMap<String, List<String>>();
// get list of already added values for this key
List<String> values = metadata.get(key);
if (values == null) {
// this meta key has never been added so far
values = new ArrayList<String>();
metadata.put(key, values);
}
values.add(value);
}
/**
* Get the list of metadata values for the given key. This might return NULL
* if no such metadata is linked to this document.
*
* @param key The metadata key, e.g. DC.subject
* @return The list of values or NULL if not found
*/
public List<String> getMetadataValues(String key) {
List<String> values = null;
if (metadata != null) {
values = metadata.get(key);
}
return values;
}
/**
* Generate a lucene document from the data stored in this document
* @return
*/
public Document getLuceneDocument() {
Document document = new Document();
document.add( createField(TITLE_FIELD_NAME,getTitle(), Field.Index.ANALYZED,4) );
document.add( createField(DESCRIPTION_FIELD_NAME,getDescription(), Field.Index.ANALYZED,2) );
document.add( createField(CONTENT_FIELD_NAME,getContent(), Field.Index.ANALYZED, 0.5f ) );
document.add(new Field(RESOURCEURL_FIELD_NAME,getResourceUrl(), Field.Store.YES, Field.Index.NOT_ANALYZED) );//SET to ANALYZED
document.add(new Field(DOCUMENTTYPE_FIELD_NAME,getDocumentType(), Field.Store.YES, Field.Index.NOT_ANALYZED) );
if(getCssIcon() != null)
document.add(new Field(CSS_ICON,getCssIcon(), Field.Store.YES, Field.Index.NOT_ANALYZED) );
document.add(new Field(FILETYPE_FIELD_NAME,getFileType(), Field.Store.YES, Field.Index.NOT_ANALYZED) );
document.add( createField(AUTHOR_FIELD_NAME,getAuthor(), Field.Index.ANALYZED, 2) );
try {
if(getCreatedDate() != null) {
document.add(new Field(CREATED_FIELD_NAME,DateTools.dateToString(getCreatedDate(), DateTools.Resolution.DAY), Field.Store.YES, Field.Index.ANALYZED) );
}
}catch (Exception ex) {
// No createdDate set => does not add field
}
try {
if(getLastChange() != null) {
document.add(new Field(CHANGED_FIELD_NAME,DateTools.dateToString(getLastChange(), DateTools.Resolution.DAY), Field.Store.YES, Field.Index.ANALYZED) );
}
}catch (Exception ex) {
// No changedDate set => does not add field
}
try {
if(getTimestamp() != null) {
document.add(new Field(TIME_STAMP_NAME,DateTools.dateToString(getTimestamp(), DateTools.Resolution.MILLISECOND), Field.Store.YES, Field.Index.NO) );
}
}catch (Exception ex) {
// No changedDate set => does not add field
}
// Add various metadata
if (metadata != null) {
for (Entry<String, List<String>> metaDataEntry : metadata.entrySet()) {
String key = metaDataEntry.getKey();
List<String> values = metaDataEntry.getValue();
for (String value : values) {
//FIXME:FG: tokenized or not? which priority
document.add( createField(key, value, Field.Index.ANALYZED, 2) );
}
}
}
document.add(new Field(PARENT_CONTEXT_TYPE_FIELD_NAME,getParentContextType(), Field.Store.YES, Field.Index.ANALYZED) );
document.add(new Field(PARENT_CONTEXT_NAME_FIELD_NAME,getParentContextName(), Field.Store.YES, Field.Index.ANALYZED) );
return document;
}
private Field createField(String fieldName, String content, Field.Index fieldIndex, float wight) {
Field field = new Field(fieldName,content, Field.Store.YES, fieldIndex);
field.setBoost(wight);
return field;
}
public String getParentContextType() {
if (parentContextType == null) {
return ""; // Do not return null
}
return parentContextType;
}
public void setParentContextType(String parentContextType) {
this.parentContextType = parentContextType;
}
public String getParentContextName() {
if (parentContextName == null) {
return ""; // Do not return null
}
return parentContextName;
}
public void setParentContextName(String parentContextName) {
this.parentContextName = parentContextName;
}
public String getCssIcon() {
return cssIcon;
}
public void setCssIcon(String cssIcon) {
this.cssIcon = cssIcon;
}
public Date getTimestamp() {
return timestamp;
}
/**
* @return Returns the createdDate.
*/
public Date getCreatedDate() {
return createdDate;
}
/**
* @param createdDate The createdDate to set.
*/
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(this.getDocumentType());
buf.append("|");
buf.append(getTitle());
buf.append("|");
if (getDescription() != null) buf.append(getDescription());
buf.append("|");
buf.append(getResourceUrl());
return buf.toString();
}
}