class IndexingItemBuilder {

  public Item build() {
    checkArgument(!Strings.isNullOrEmpty(name), "item name can not be null");
    checkNotNull(values, "values can not be null");
    Item item = new Item();
    item.setName(name);
    if (acl != null) {
      acl.applyTo(item);
    }
    ItemMetadata metadata = new ItemMetadata();
    setFromFieldOrValues(objectType, configObjectType, values, StructuredData.STRING_CONVERTER,
        Strings::isNullOrEmpty, Function.identity(),
        itemObjectType -> {
          metadata.setObjectType(itemObjectType);
          item.setStructuredData(
              new ItemStructuredData().setObject(
                  StructuredData.getStructuredData(itemObjectType, values)));
        });
    setFromFieldOrValues(mimeType, configMimeType, values, StructuredData.STRING_CONVERTER,
        Strings::isNullOrEmpty, Function.identity(), metadata::setMimeType);
    setFromFieldOrValues(title, configTitle, values, StructuredData.STRING_CONVERTER,
        Strings::isNullOrEmpty, Function.identity(), metadata::setTitle);
    setFromFieldOrValues(url, configUrl, values, StructuredData.STRING_CONVERTER,
        Strings::isNullOrEmpty, Function.identity(), metadata::setSourceRepositoryUrl);
    setFromFieldOrValues(language, configLanguage, values, StructuredData.STRING_CONVERTER,
        Strings::isNullOrEmpty, Function.identity(), metadata::setContentLanguage);
    setFromFieldOrValues(updateTime, configUpdateTime, values, StructuredData.DATETIME_CONVERTER,
        Objects::isNull, DateTime::toStringRfc3339, metadata::setUpdateTime);
    setFromFieldOrValues(createTime, configCreateTime, values, StructuredData.DATETIME_CONVERTER,
        Objects::isNull, DateTime::toStringRfc3339, metadata::setCreateTime);
    setFromFieldOrValues(hash, configHash, values, StructuredData.STRING_CONVERTER,
        Strings::isNullOrEmpty, Function.identity(), metadata::setHash);
    setFromFieldOrValues(containerName, configContainerName, values,
        StructuredData.STRING_CONVERTER, Strings::isNullOrEmpty, Function.identity(),
        metadata::setContainerName);
    if (searchQuality != null) {
      metadata.setSearchQualityMetadata(searchQuality);
    } else {
      SearchQualityMetadata searchQualityMetadata = new SearchQualityMetadata();
      setFromFieldOrValues(searchQualityMetadataQuality, configSearchQualityMetadataQuality,
          values, StructuredData.DOUBLE_CONVERTER, Objects::isNull, Function.identity(),
          searchQualityMetadata::setQuality);
      if (searchQualityMetadata.getQuality() != null) {
        metadata.setSearchQualityMetadata(searchQualityMetadata);
      }
    }
    if (version != null) {
      item.encodeVersion(version);
    }
    if (payload != null) {
      item.encodePayload(payload);
    }
    if (!Strings.isNullOrEmpty(queue)) {
      item.setQueue(queue);
    }
    if (itemType != null) {
      item.setItemType(itemType.name());
    }
    item.setMetadata(metadata);
    return item;
  }

  public  IndexingItemBuilder(String name);
  private  IndexingItemBuilder(String name, ConfigDefaults config);

}