| /** |
| * |
| */ |
| 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, "_"); |
| } |
| |
| } |