package org.molgenis.data.elasticsearch; import com.google.common.collect.Iterables; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentGenerator; import org.molgenis.data.Entity; import org.molgenis.data.EntityManager; import org.molgenis.data.meta.AttributeType; import org.molgenis.data.meta.model.Attribute; import org.molgenis.data.meta.model.EntityType; import org.molgenis.util.MolgenisDateFormat; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.IOException; import java.sql.Date; import static java.lang.String.format; import static java.util.Objects.requireNonNull; import static org.elasticsearch.common.xcontent.XContentType.JSON; /** * Creates entities from Elasticsearch document sources and vice versa. */ @Component public class ElasticsearchEntityFactory { private static final int MAX_INDEXING_DEPTH = 1; private final EntityManager entityManager; @Autowired public ElasticsearchEntityFactory(EntityManager entityManager) { this.entityManager = requireNonNull(entityManager); } /** * Create Elasticsearch document source content from entity * * @param entity the entity to convert to document source content * @return Elasticsearch document source content */ public XContentBuilder create(Entity entity) { try { XContentBuilder contentBuilder = XContentFactory.contentBuilder(JSON); XContentGenerator generator = contentBuilder.generator(); generator.writeStartObject(); createRec(entity, generator, 0, MAX_INDEXING_DEPTH); generator.writeEndObject(); return contentBuilder; } catch (IOException e) { throw new RuntimeException(e); } } private void createRec(Entity entity, XContentGenerator generator, int depth, int maxDepth) throws IOException { for (Attribute attr : entity.getEntityType().getAtomicAttributes()) { generator.writeFieldName(attr.getName()); createRec(entity, attr, generator, depth, maxDepth); } } private void createRec(Entity entity, Attribute attr, XContentGenerator generator, int depth, int maxDepth) throws IOException { String attrName = attr.getName(); AttributeType attrType = attr.getDataType(); switch (attrType) { case BOOL: Boolean boolValue = entity.getBoolean(attrName); if (boolValue != null) { generator.writeBoolean(boolValue); } else { generator.writeNull(); } break; case DECIMAL: Double doubleValue = entity.getDouble(attrName); if (doubleValue != null) { generator.writeNumber(doubleValue); } else { generator.writeNull(); } break; case INT: Integer intValue = entity.getInt(attrName); if (intValue != null) { generator.writeNumber(intValue); } else { generator.writeNull(); } break; case LONG: Long longValue = entity.getLong(attrName); if (longValue != null) { generator.writeNumber(longValue); } else { generator.writeNull(); } break; case EMAIL: case ENUM: case HTML: case HYPERLINK: case SCRIPT: case STRING: case TEXT: String strValue = entity.getString(attrName); if (strValue != null) { generator.writeString(strValue); } else { generator.writeNull(); } break; case DATE: Date date = entity.getDate(attrName); if (date != null) { String dateValue = MolgenisDateFormat.getDateFormat().format(date); generator.writeString(dateValue); } else { generator.writeNull(); } break; case DATE_TIME: Date dateTime = entity.getDate(attrName); if (dateTime != null) { String dateTimeValue = MolgenisDateFormat.getDateTimeFormat().format(dateTime); generator.writeString(dateTimeValue); } else { generator.writeNull(); } break; case CATEGORICAL: case XREF: case FILE: { Entity xrefEntity = entity.getEntity(attrName); if (xrefEntity != null) { if (depth < maxDepth) { generator.writeStartObject(); createRec(xrefEntity, generator, depth + 1, maxDepth); generator.writeEndObject(); } else { Attribute xrefIdAttr = xrefEntity.getEntityType().getIdAttribute(); createRec(xrefEntity, xrefIdAttr, generator, depth + 1, maxDepth); } } else { generator.writeNull(); } break; } case CATEGORICAL_MREF: case MREF: case ONE_TO_MANY: { Iterable<Entity> mrefEntities = entity.getEntities(attrName); if (!Iterables.isEmpty(mrefEntities)) { generator.writeStartArray(); for (Entity mrefEntity : mrefEntities) { if (depth < maxDepth) { generator.writeStartObject(); createRec(mrefEntity, generator, depth + 1, maxDepth); generator.writeEndObject(); } else { Attribute mrefIdAttr = mrefEntity.getEntityType().getIdAttribute(); createRec(mrefEntity, mrefIdAttr, generator, depth + 1, maxDepth); } } generator.writeEndArray(); } else { generator.writeNull(); } break; } case COMPOUND: throw new RuntimeException(format("Illegal attribute type [%s]", attrType.toString())); default: throw new RuntimeException(format("Unknown attribute type [%s]", attrType.toString())); } } Entity getReference(EntityType entityType, Object idObject) { return entityManager.getReference(entityType, idObject); } }