All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.avaje.ebeanservice.elastic.index.EIndexMappingsBuilder Maven / Gradle / Ivy

package com.avaje.ebeanservice.elastic.index;

import com.avaje.ebean.PersistenceIOException;
import com.avaje.ebean.plugin.BeanType;
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyAdapter;
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyMapping;
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyOptions;
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyType;
import com.avaje.ebeanservice.docstore.api.mapping.DocumentMapping;
import com.avaje.ebeanservice.elastic.support.StringBuilderWriter;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.PrettyPrinter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;

import java.io.IOException;

/**
 * Builds mapping JSON for an Index using the DocumentMapping.
 */
public class EIndexMappingsBuilder {

  private final JsonFactory jsonFactory;

  private final EIndexTypeMapping typeMapping;

  private final PrettyPrinter compactJson = new CompactJsonPrettyPrinter();

  private final PrettyPrinter prettyJson = new DefaultPrettyPrinter();

  public EIndexMappingsBuilder(JsonFactory jsonFactory) {
    this.jsonFactory = jsonFactory;
    this.typeMapping = new EIndexTypeMapping();
  }

  /**
   * Return the mapping json for a given bean type.
   */
  public String createMappingJson(BeanType beanType) {

    try {
      DocumentMapping docMapping = beanType.getDocMapping();

      StringBuilderWriter writer = new StringBuilderWriter();
      JsonGenerator gen = jsonFactory.createGenerator(writer);
      gen.setPrettyPrinter(prettyJson);

      gen.writeStartObject();

      int shards = docMapping.getShards();
      int replicas = docMapping.getReplicas();

      if (shards > 0 || replicas > 0) {
        gen.writeObjectFieldStart("settings");
        if (shards > 0) {
          gen.writeNumberField("number_of_shards", shards);
        }
        if (replicas > 0) {
          gen.writeNumberField("number_of_replicas", replicas);
        }
        gen.writeEndObject();
      }

      gen.writeObjectFieldStart("mappings");
      gen.writeObjectFieldStart(docMapping.getType());
      gen.writeObjectFieldStart("properties");

      IndexVisitor visitor = new IndexVisitor(gen, typeMapping);

      docMapping.visit(visitor);

      gen.writeEndObject();
      gen.writeEndObject();
      gen.writeEndObject();
      gen.writeEndObject();
      gen.flush();

      return writer.toString();

    } catch (IOException e) {
      throw new PersistenceIOException(e);
    }
  }

  private class IndexVisitor extends DocPropertyAdapter {

    private final JsonGenerator gen;

    private final EIndexTypeMapping typeMapping;

    public IndexVisitor(JsonGenerator gen, EIndexTypeMapping typeMapping) {
      this.gen = gen;
      this.typeMapping = typeMapping;
    }

    @Override
    public void visitProperty(DocPropertyMapping property) {

      try {
        gen.writeFieldName(property.getName());
        gen.setPrettyPrinter(compactJson);
        gen.writeStartObject();

        DocPropertyOptions options = property.getOptions();
        if (options != null && isFalse(options.getEnabled())) {
          gen.writeBooleanField("enabled", false);
        } else {

          // map from general document type to elastic type
          DocPropertyType logicalType = property.getType();
          gen.writeStringField("type", typeMapping.get(logicalType));

          if (options == null) {
            if (notAnalysed(logicalType)) {
              gen.writeStringField("index", "not_analyzed");
            }
          } else {
            if (options.isOptionsSet()) {
              gen.writeStringField("index_options", options.getOptions().name().toLowerCase());
            }
            if (isFalse(options.getIncludeInAll())) {
              gen.writeBooleanField("include_in_all", false);
            }
            if (isFalse(options.getNorms())) {
              gen.writeObjectFieldStart("norms");
              gen.writeBooleanField("enabled", false);
              gen.writeEndObject();
            }
            if (isFalse(options.getDocValues())) {
              gen.writeBooleanField("docValues", false);
            }
            if (isTrue(options.getStore())) {
              gen.writeBooleanField("store", true);
            }
            if (options.getBoost() != null) {
              gen.writeNumberField("boost", options.getBoost());
            }
            if (options.getNullValue() != null) {
              gen.writeStringField("null_value", options.getNullValue());
            }
            if (options.getCopyTo() != null) {
              gen.writeStringField("copy_to", options.getCopyTo());
            }
            if (options.getAnalyzer() != null) {
              gen.writeStringField("analyzer", options.getAnalyzer());
            }
            if (options.getSearchAnalyzer() != null) {
              gen.writeStringField("search_analyzer", options.getSearchAnalyzer());
            }
            if (isTrue(options.getCode()) || notAnalysed(logicalType)) {
              gen.writeStringField("index", "not_analyzed");

            } else if (isTrue(options.getSortable())) {
              // add raw field option
              gen.writeObjectFieldStart("fields");
              gen.writeObjectFieldStart("raw");
              gen.writeStringField("type", "string");
              gen.writeStringField("index", "not_analyzed");
              gen.writeEndObject();
              gen.writeEndObject();
            }
          }
        }
        gen.writeEndObject();
        gen.setPrettyPrinter(prettyJson);

      } catch (IOException e) {
        throw new PersistenceIOException(e);
      }
    }

    private boolean isTrue(Boolean option) {
      return Boolean.TRUE.equals(option);
    }

    private boolean isFalse(Boolean option) {
      return Boolean.FALSE.equals(option);
    }

    @Override
    public void visitBeginObject(DocPropertyMapping property) {
      try {
        gen.writeObjectFieldStart(property.getName());
        gen.writeObjectFieldStart("properties");
      } catch (IOException e) {
        throw new PersistenceIOException(e);
      }
    }

    @Override
    public void visitEndObject(DocPropertyMapping property) {
      try {
        gen.writeEndObject();
        gen.writeEndObject();
      } catch (IOException e) {
        throw new PersistenceIOException(e);
      }
    }

    @Override
    public void visitBeginList(DocPropertyMapping property) {
      try {
        gen.writeObjectFieldStart(property.getName());
        gen.writeStringField("type", "nested");
        gen.writeObjectFieldStart("properties");
      } catch (IOException e) {
        throw new PersistenceIOException(e);
      }
    }

    @Override
    public void visitEndList(DocPropertyMapping property) {
      try {
        gen.writeEndObject();
        gen.writeEndObject();
      } catch (IOException e) {
        throw new PersistenceIOException(e);
      }
    }
  }

  /**
   * Return true if this type should not be analysed.
   */
  private boolean notAnalysed(DocPropertyType logicalType) {
    switch (logicalType) {
      case ENUM: return true;
    }
    return false;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy