package org.tynamo.model.elasticsearch.descriptor; import java.io.IOException; import java.util.List; import org.apache.tapestry5.func.F; import org.apache.tapestry5.func.Flow; import org.apache.tapestry5.func.Predicate; import org.apache.tapestry5.func.Worker; import org.apache.tapestry5.ioc.services.PropertyAccess; import org.elasticsearch.common.xcontent.XContentBuilder; import org.tynamo.descriptor.TynamoClassDescriptor; import org.tynamo.descriptor.TynamoPropertyDescriptor; import org.tynamo.descriptor.extension.DescriptorExtension; import org.tynamo.model.elasticsearch.annotations.ElasticSearchable; import org.tynamo.model.elasticsearch.mapping.MapperFactory; public class ElasticSearchExtension implements DescriptorExtension { private static final long serialVersionUID = 1L; private final TynamoClassDescriptor ownerDescriptor; private String indexName; private String typeName; private String idPrefix = ""; private PropertyAccess propertyAccess; public ElasticSearchExtension(TynamoClassDescriptor descriptor, PropertyAccess propertyAccess) { ownerDescriptor = descriptor; this.propertyAccess = propertyAccess; Class beanType = descriptor.getBeanType(); typeName = beanType.getName().toLowerCase().trim().replace('.', '_'); ElasticSearchable meta = (ElasticSearchable) beanType.getAnnotation(ElasticSearchable.class); if (meta.indexName().length() > 0) indexName = meta.indexName(); } /** * Gets the index name * * @return the index name */ public String getIndexName() { return indexName == null ? getTypeName() : indexName; } /** * Gets the type name * * @return the type name */ public String getTypeName() { return typeName; } /** * Gets the document id * * @param model * the model * @return the model's document id */ public String getDocumentId(Object model) { return idPrefix + propertyAccess.get(model, ownerDescriptor.getIdentifierDescriptor().getName()).toString(); } public void addModel(final Object model, final XContentBuilder builder, final MapperFactory mapperFactory) throws IOException { builder.startObject(); // for (FieldMapper field : mapping) { // field.addToDocument(model, builder); // } getElasticPropertyDescriptorFlow(ownerDescriptor.getPropertyDescriptors()).each( new Worker<TynamoPropertyDescriptor>() { @Override public void work(TynamoPropertyDescriptor descriptor) { try { mapperFactory.getMapper(descriptor).addToDocument(propertyAccess.get(model, descriptor.getName()), builder); } catch (IOException e) { throw new RuntimeException(e); } } }); builder.endObject(); } Flow<TynamoPropertyDescriptor> getElasticPropertyDescriptorFlow(List<TynamoPropertyDescriptor> propertyDescriptors) { return F.flow(ownerDescriptor.getPropertyDescriptors()).filter(new Predicate<TynamoPropertyDescriptor>() { public boolean accept(TynamoPropertyDescriptor descriptor) { return descriptor.supportsExtension(ElasticSearchFieldDescriptor.class); } }); } public void addMapping(final XContentBuilder builder, final MapperFactory mapperFactory) throws IOException { builder.startObject(); builder.startObject(getTypeName()); // TODO do we need time-to-live annotation? // if (clazz.isAnnotationPresent(ElasticSearchTtl.class)) { // String ttlValue = ((ElasticSearchTtl) clazz.getAnnotation(ElasticSearchTtl.class)).value(); // builder.startObject("_ttl"); // builder.field("enabled", true); // builder.field("default", ttlValue); // builder.endObject(); // } builder.startObject("properties"); getElasticPropertyDescriptorFlow(ownerDescriptor.getPropertyDescriptors()).each(new Worker<TynamoPropertyDescriptor>() { @Override public void work(TynamoPropertyDescriptor descriptor) { try { mapperFactory.getMapper(descriptor).addToMapping(builder); } catch (IOException e) { throw new RuntimeException(e); } }}); // for (TynamoPropertyDescriptor descriptor : ownerDescriptor.getPropertyDescriptors()) // if (descriptor.supportsExtension(ElasticSearchFieldDescriptor.class)) // mapperFactory.getMapper(descriptor).addToMapping(builder); builder.endObject(); builder.endObject(); builder.endObject(); } }