blob: c54c6d6767b4903fbe75ae06f3ab76cffe2d5bc7 [file] [log] [blame]
/**
*
*/
package org.eclipse.smila.solr.update;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.solr.common.SolrInputDocument;
import org.eclipse.smila.datamodel.Any;
import org.eclipse.smila.datamodel.AnyMap;
import org.eclipse.smila.datamodel.Record;
import org.eclipse.smila.datamodel.util.AnyUtil;
import org.eclipse.smila.solr.params.SolrParams;
import org.eclipse.smila.solr.params.UpdateParams;
/**
* @author pwissel
*
*/
public class SolrDocumentConverter {
public static final String FIELD_NAME = "fieldName";
public static final String FIELD_BOOST = "fieldBoost";
public static final String TYPE = "type";
private final Log _log = LogFactory.getLog(getClass());
public enum Type {
ATTACHMENT, ATTRIBUTE;
public static Type get(final String label) {
return valueOf(label.toUpperCase());
}
}
public SolrInputDocument toSolrDocument(final Record record) throws UnsupportedEncodingException {
return toSolrDocument(record, false);
}
public SolrInputDocument toSolrDocument(final Record record, final List<Record> children)
throws UnsupportedEncodingException {
return toSolrDocument(record, false, children);
}
public List<SolrInputDocument> toSolrDocuments(final List<Record> records) throws UnsupportedEncodingException {
return toSolrDocuments(records, false);
}
public SolrInputDocument toSolrDocument(final Record record, final boolean attachments)
throws UnsupportedEncodingException {
final SolrInputDocument document = prepareSolrDocument(record);
// add all metadata fields if name is not a system key (begins with underscore)
for (final Entry<String, Any> entry : record.getMetadata().entrySet()) {
final String name = entry.getKey();
if (isSystemKey(name)) {
continue;
}
final Any any = entry.getValue();
if (any.isValue() || any.isSeq()) {
final Object value = AnyUtil.anyToNative(any);
document.addField(name, value);
}
}
// add all attachments if name is not a system key (begins with underscore)
if (attachments && record.hasAttachments()) {
final Iterator<String> attachmentNames = record.getAttachmentNames();
while (attachmentNames.hasNext()) {
final String name = attachmentNames.next();
if (isSystemKey(name)) {
continue;
}
final byte[] bytes = record.getAttachmentAsBytes(name);
document.addField(name, new String(bytes, "UTF-8"));
}
}
return document;
}
public SolrInputDocument toSolrDocument(final Record record, final boolean attachments,
final List<Record> children) throws UnsupportedEncodingException {
final SolrInputDocument document = toSolrDocument(record, attachments);
for (final Record child : children) {
final SolrInputDocument childDocument = toSolrDocument(child, attachments);
document.addChildDocument(childDocument);
}
return document;
}
public List<SolrInputDocument> toSolrDocuments(final List<Record> records, final boolean attachments)
throws UnsupportedEncodingException {
final List<SolrInputDocument> documents = new ArrayList<SolrInputDocument>(records.size());
for (final Record record : records) {
final SolrInputDocument document = toSolrDocument(record, attachments);
documents.add(document);
}
return documents;
}
public SolrInputDocument toSolrDocument(final Record record, final AnyMap mapping)
throws UnsupportedEncodingException {
final SolrInputDocument document = prepareSolrDocument(record);
final String id = record.getId();
final AnyMap metadata = record.getMetadata();
// add mapping fields
for (final Entry<String, Any> entry : mapping.entrySet()) {
String name = entry.getKey();
final Any any = entry.getValue();
// read mapping from value
if (any.isValue()) {
String fieldName = any.asValue().asString();
if (StringUtils.isEmpty(fieldName)) {
fieldName = name;
}
addObjectToDocument(id, metadata, name, document, fieldName);
} else if (any.isSeq()) {
final String[] fieldNames = any.asSeq().asStrings().toArray(new String[any.asSeq().size()]);
addObjectToDocument(id, metadata, name, document, fieldNames);
} else if (any.isMap()) {
// read mapping from map
final AnyMap map = any.asMap();
final String fieldName = map.containsKey(FIELD_NAME) ? map.getStringValue(FIELD_NAME) : name;
float fieldBoost = 0;
boolean boost = false;
if (map.containsKey(FIELD_BOOST)) {
fieldBoost = map.getDoubleValue(FIELD_BOOST).floatValue();
boost = true;
}
final Type type = map.containsKey(TYPE) ? Type.get(map.getStringValue(TYPE)) : Type.ATTRIBUTE;
Object value = null;
switch (type) {
case ATTRIBUTE:
addObjectToDocument(id, metadata, name, document, fieldName);
break;
case ATTACHMENT:
// check if attachment is available
if (record.hasAttachment(name)) {
final byte[] bytes = record.getAttachmentAsBytes(name);
value = new String(bytes, "UTF-8");
} else {
if (_log.isWarnEnabled()) {
final String message =
String.format("Record does not contain attachment for given key. _recordid=%s, key=%s", id, name);
_log.warn(message);
}
}
break;
}
// add field to document
if (boost) {
document.addField(fieldName, value, fieldBoost);
} else {
document.addField(fieldName, value);
}
}
}
return document;
}
public SolrInputDocument toSolrDocument(final Record record, final AnyMap mapping, final List<Record> children)
throws UnsupportedEncodingException {
final SolrInputDocument document = toSolrDocument(record, mapping);
for (final Record child : children) {
final SolrInputDocument childDocument = toSolrDocument(child, mapping);
document.addChildDocument(childDocument);
}
return document;
}
private void addObjectToDocument(final String id, final AnyMap metadata, final String name,
final SolrInputDocument document, final String... fieldNames) {
if (metadata.containsKey(name)) {
Any val;
// check if attribute is not a map and get value
if (!(val = metadata.get(name)).isMap()) {
final Object value = AnyUtil.anyToNative(val);
for (final String fieldName : fieldNames) {
document.addField(fieldName, value);
}
} else {
if (_log.isWarnEnabled()) {
final String message =
String.format("Can not convert AnyMap to SolrDocument field. _recordid=%s, key=%s", id, name);
_log.warn(message);
}
}
} else {
if (_log.isDebugEnabled()) {
final String message =
String.format("Record does not contain mapping for given key. _recordid=%s, key=%s", id, name);
_log.warn(message);
}
}
}
private SolrInputDocument prepareSolrDocument(final Record record) {
// create solr input document
final SolrInputDocument document = new SolrInputDocument();
final String id = record.getId();
document.addField(Record.RECORD_ID, id);
// set document boost if available
final UpdateParams params = new UpdateParams(SolrParams.getSolrParams(record));
final Float documentBoost = params.getDocumentBoost(false);
if (documentBoost != null) {
document.setDocumentBoost(documentBoost);
}
return document;
}
private boolean isSystemKey(final String key) {
return StringUtils.startsWith(key, "_");
}
}