/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.xpn.xwiki.plugin.lucene;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.document.Field;
import com.xpn.xwiki.XWikiContext;
import com.xpn.xwiki.doc.XWikiDocument;
import com.xpn.xwiki.objects.BaseObject;
import com.xpn.xwiki.objects.BaseProperty;
import com.xpn.xwiki.objects.PropertyInterface;
import com.xpn.xwiki.objects.classes.BaseClass;
import com.xpn.xwiki.objects.classes.ListItem;
import com.xpn.xwiki.objects.classes.PasswordClass;
import com.xpn.xwiki.objects.classes.StaticListClass;
/**
* Hold the property values of the XWiki.ArticleClass Objects.
*/
public class ObjectData extends IndexData
{
private static final Log LOG = LogFactory.getLog(ObjectData.class);
public ObjectData(final XWikiDocument doc, final XWikiContext context)
{
super(doc, context);
setAuthor(doc.getAuthor());
setCreator(doc.getCreator());
setModificationDate(doc.getDate());
setCreationDate(doc.getCreationDate());
}
/**
* @see com.xpn.xwiki.plugin.lucene.IndexData#getType()
*/
@Override
public String getType()
{
return LucenePlugin.DOCTYPE_OBJECTS;
}
@Override
public String getId()
{
return new StringBuffer(super.getId()).append(".objects").toString();
}
/**
* @return a string containing the result of {@link IndexData#getFullText(XWikiDocument,XWikiContext)}plus the full
* text content (values of title,category,content and extract ) XWiki.ArticleClass Object, as far as it
* could be extracted.
*/
@Override
public String getFullText(XWikiDocument doc, XWikiContext context)
{
StringBuffer retval = new StringBuffer(super.getFullText(doc, context));
String contentText = getContentAsText(doc, context);
if (contentText != null) {
retval.append(" ").append(contentText);
}
return retval.toString();
}
/**
* @return string containing value of title,category,content and extract of XWiki.ArticleClass
*/
private String getContentAsText(XWikiDocument doc, XWikiContext context)
{
StringBuffer contentText = new StringBuffer();
contentText.append(doc.getTitle());
contentText.append(" ");
contentText.append(doc.getContent());
contentText.append(" ");
try {
LOG.info(doc.getFullName());
for (String className : doc.getxWikiObjects().keySet()) {
for (BaseObject obj : doc.getObjects(className)) {
extractContent(contentText, obj, context);
}
}
} catch (Exception e) {
LOG.error("error getting content from XWiki Objects ", e);
e.printStackTrace();
}
return contentText.toString();
}
private void extractContent(StringBuffer contentText, BaseObject baseObject, XWikiContext context)
{
try {
if (baseObject != null) {
Object[] propertyNames = baseObject.getPropertyNames();
for (int i = 0; i < propertyNames.length; i++) {
BaseProperty baseProperty = (BaseProperty) baseObject.getField((String) propertyNames[i]);
if ((baseProperty != null) && (baseProperty.getValue() != null)) {
PropertyInterface prop = baseObject.getxWikiClass(context).getField((String) propertyNames[i]);
if (!(prop instanceof PasswordClass)) {
contentText.append(baseProperty.getValue().toString());
}
}
contentText.append(" ");
}
}
} catch (Exception e) {
LOG.error("error getting content from XWiki Object ", e);
e.printStackTrace();
}
}
@Override
public void addDataToLuceneDocument(org.apache.lucene.document.Document luceneDoc, XWikiDocument doc,
XWikiContext context)
{
super.addDataToLuceneDocument(luceneDoc, doc, context);
for (String className : doc.getxWikiObjects().keySet()) {
for (BaseObject obj : doc.getObjects(className)) {
if (obj != null) {
luceneDoc.add(new Field(IndexFields.OBJECT, obj.getClassName(), Field.Store.YES,
Field.Index.TOKENIZED));
Object[] propertyNames = obj.getPropertyNames();
for (int i = 0; i < propertyNames.length; i++) {
try {
indexProperty(luceneDoc, obj, (String) propertyNames[i], context);
} catch (Exception e) {
LOG.error("error extracting fulltext for document " + this, e);
}
}
}
}
}
}
private void indexProperty(org.apache.lucene.document.Document luceneDoc, BaseObject baseObject,
String propertyName, XWikiContext context)
{
String fieldFullName = baseObject.getClassName() + "." + propertyName;
BaseClass bClass = baseObject.getxWikiClass(context);
PropertyInterface prop = bClass.getField(propertyName);
if (prop instanceof PasswordClass) {
// Do not index passwords
} else if (prop instanceof StaticListClass && ((StaticListClass) prop).isMultiSelect()) {
indexStaticList(luceneDoc, baseObject, (StaticListClass) prop, propertyName, context);
} else {
final String ft = getContentAsText(baseObject, propertyName, context);
if (ft != null) {
luceneDoc.add(new Field(fieldFullName, ft, Field.Store.YES, Field.Index.TOKENIZED));
luceneDoc.add(new Field(fieldFullName + IndexFields.UNTOKENIZED, ft.toUpperCase(), Field.Store.NO, Field.Index.UN_TOKENIZED));
}
}
}
private void indexStaticList(org.apache.lucene.document.Document luceneDoc, BaseObject baseObject,
StaticListClass prop, String propertyName, XWikiContext context)
{
Map possibleValues = prop.getMap(context);
List keys = baseObject.getListValue(propertyName);
String fieldFullName = baseObject.getClassName() + "." + propertyName;
Iterator it = keys.iterator();
while (it.hasNext()) {
String value = (String) it.next();
ListItem item = (ListItem) possibleValues.get(value);
if (item != null) {
// we index the key of the list
String fieldName = fieldFullName + ".key";
luceneDoc.add(new Field(fieldName, item.getId(), Field.Store.YES, Field.Index.TOKENIZED));
luceneDoc.add(new Field(fieldName + IndexFields.UNTOKENIZED, item.getId().toUpperCase(), Field.Store.NO, Field.Index.UN_TOKENIZED));
// we index the value
fieldName = fieldFullName + ".value";
luceneDoc.add(new Field(fieldName, item.getValue(), Field.Store.YES, Field.Index.TOKENIZED));
luceneDoc.add(new Field(fieldName + IndexFields.UNTOKENIZED, item.getValue().toUpperCase(), Field.Store.NO, Field.Index.UN_TOKENIZED));
if (!item.getId().equals(item.getValue())) {
luceneDoc.add(new Field(fieldFullName, item.getValue(), Field.Store.YES, Field.Index.TOKENIZED));
luceneDoc.add(new Field(fieldFullName + IndexFields.UNTOKENIZED, item.getValue().toUpperCase(), Field.Store.NO, Field.Index.UN_TOKENIZED));
}
}
// we index both if value is not equal to the id(key)
luceneDoc.add(new Field(fieldFullName, value, Field.Store.YES, Field.Index.TOKENIZED));
luceneDoc.add(new Field(fieldFullName + IndexFields.UNTOKENIZED, value.toUpperCase(), Field.Store.NO, Field.Index.UN_TOKENIZED));
}
}
public String getFullText(XWikiDocument doc, BaseObject baseObject, String property, XWikiContext context)
{
return getContentAsText(baseObject, property, context);
}
private String getContentAsText(BaseObject baseObject, String property, XWikiContext context)
{
StringBuffer contentText = new StringBuffer();
try {
BaseProperty baseProperty;
baseProperty = (BaseProperty) baseObject.getField(property);
if (baseProperty.getValue() != null) {
PropertyInterface prop = baseObject.getxWikiClass(context).getField(property);
if (!(prop instanceof PasswordClass)) {
contentText.append(baseProperty.getValue().toString());
}
}
} catch (Exception e) {
LOG.error("error getting content from XWiki Objects ", e);
e.printStackTrace();
}
return contentText.toString();
}
}