@Override
 public String toString() {
   return "PluginSettings{"
       + "checkpointDocumentType='"
       + checkpointDocumentType
       + '\''
       + ", resolveConflicts="
       + resolveConflicts
       + ", wrapCounters="
       + wrapCounters
       + ", ignoreFailures="
       + ignoreFailures
       + ", ignoreDotIndexes="
       + ignoreDotIndexes
       + ", dynamicTypePath='"
       + dynamicTypePath
       + '\''
       + ", maxConcurrentRequests="
       + maxConcurrentRequests
       + ", bulkIndexRetries="
       + bulkIndexRetries
       + ", bulkIndexRetryWaitMs="
       + bulkIndexRetryWaitMs
       + ", typeSelector="
       + typeSelector.getClass().getCanonicalName()
       + ", parentSelector="
       + parentSelector.getClass().getCanonicalName()
       + ", keyFilter="
       + keyFilter.getClass().getCanonicalName()
       + ", documentTypeRoutingFields="
       + documentTypeRoutingFields
       + ", ignoreDeletes="
       + ignoreDeletes
       + ", includeIndexes="
       + includeIndexes
       + '}';
 }
  @Inject
  public CouchbaseCAPITransportImpl(
      Settings settings,
      RestController restController,
      NetworkService networkService,
      IndicesService indicesService,
      MetaDataMappingService metaDataMappingService,
      Client client) {
    super(settings);
    this.networkService = networkService;
    this.indicesService = indicesService;
    this.metaDataMappingService = metaDataMappingService;
    this.client = client;
    this.port = settings.get("couchbase.port", "9091-10091");
    this.bindHost = componentSettings.get("bind_host");
    this.publishHost = componentSettings.get("publish_host");
    this.username = settings.get("couchbase.username", "Administrator");
    this.password = settings.get("couchbase.password", "");

    this.bucketUUIDCacheEvictMs = settings.getAsLong("couchbase.bucketUUIDCacheEvictMs", 300000L);
    this.bucketUUIDCache =
        CacheBuilder.newBuilder()
            .expireAfterWrite(this.bucketUUIDCacheEvictMs, TimeUnit.MILLISECONDS)
            .build();

    int defaultNumVbuckets = 1024;
    if (System.getProperty("os.name").toLowerCase().contains("mac")) {
      logger.info("Detected platform is Mac, changing default num_vbuckets to 64");
      defaultNumVbuckets = 64;
    }
    this.numVbuckets = settings.getAsInt("couchbase.num_vbuckets", defaultNumVbuckets);

    pluginSettings = new PluginSettings();
    pluginSettings.setCheckpointDocumentType(
        settings.get(
            "couchbase.typeSelector.checkpointDocumentType",
            PluginSettings.DEFAULT_DOCUMENT_TYPE_CHECKPOINT));
    pluginSettings.setDynamicTypePath(settings.get("couchbase.dynamicTypePath"));
    pluginSettings.setResolveConflicts(settings.getAsBoolean("couchbase.resolveConflicts", true));
    pluginSettings.setWrapCounters(settings.getAsBoolean("couchbase.wrapCounters", false));
    pluginSettings.setMaxConcurrentRequests(
        settings.getAsLong("couchbase.maxConcurrentRequests", 1024L));
    pluginSettings.setBulkIndexRetries(settings.getAsLong("couchbase.bulkIndexRetries", 10L));
    pluginSettings.setBulkIndexRetryWaitMs(
        settings.getAsLong("couchbase.bulkIndexRetryWaitMs", 1000L));
    pluginSettings.setIgnoreDeletes(
        new ArrayList<String>(
            Arrays.asList(settings.get("couchbase.ignoreDeletes", "").split("[:,;\\s]"))));
    pluginSettings.getIgnoreDeletes().removeAll(Arrays.asList("", null));
    pluginSettings.setIgnoreFailures(settings.getAsBoolean("couchbase.ignoreFailures", false));
    pluginSettings.setDocumentTypeRoutingFields(
        settings.getByPrefix("couchbase.documentTypeRoutingFields.").getAsMap());
    pluginSettings.setIgnoreDotIndexes(settings.getAsBoolean("couchbase.ignoreDotIndexes", true));
    pluginSettings.setIncludeIndexes(
        new ArrayList<String>(
            Arrays.asList(settings.get("couchbase.includeIndexes", "").split("[:,;\\s]"))));
    pluginSettings.getIncludeIndexes().removeAll(Arrays.asList("", null));

    TypeSelector typeSelector;
    Class<? extends TypeSelector> typeSelectorClass =
        settings.<TypeSelector>getAsClass("couchbase.typeSelector", DefaultTypeSelector.class);
    try {
      typeSelector = typeSelectorClass.newInstance();
    } catch (Exception e) {
      throw new ElasticsearchException("couchbase.typeSelector", e);
    }
    typeSelector.configure(settings);
    pluginSettings.setTypeSelector(typeSelector);

    ParentSelector parentSelector;
    Class<? extends ParentSelector> parentSelectorClass =
        settings.<ParentSelector>getAsClass(
            "couchbase.parentSelector", DefaultParentSelector.class);
    try {
      parentSelector = parentSelectorClass.newInstance();
    } catch (Exception e) {
      throw new ElasticsearchException("couchbase.parentSelector", e);
    }
    parentSelector.configure(settings);
    pluginSettings.setParentSelector(parentSelector);

    KeyFilter keyFilter;
    Class<? extends KeyFilter> keyFilterClass =
        settings.<KeyFilter>getAsClass("couchbase.keyFilter", DefaultKeyFilter.class);
    try {
      keyFilter = keyFilterClass.newInstance();
    } catch (Exception e) {
      throw new ElasticsearchException("couchbase.keyFilter", e);
    }
    keyFilter.configure(settings);
    pluginSettings.setKeyFilter(keyFilter);

    // Log settings info
    logger.info(
        "Couchbase transport will ignore delete/expiration operations for these buckets: {}",
        pluginSettings.getIgnoreDeletes());
    logger.info(
        "Couchbase transport will ignore indexing failures and not throw exception to Couchbase: {}",
        pluginSettings.getIgnoreFailures());
    logger.info(
        "Couchbase transport is using type selector: {}",
        typeSelector.getClass().getCanonicalName());
    logger.info(
        "Couchbase transport is using parent selector: {}",
        parentSelector.getClass().getCanonicalName());
    logger.info(
        "Couchbase transport is using key filter: {}", keyFilter.getClass().getCanonicalName());
    for (String key : pluginSettings.getDocumentTypeRoutingFields().keySet()) {
      String routingField = pluginSettings.getDocumentTypeRoutingFields().get(key);
      logger.info("Using field {} as routing for type {}", routingField, key);
    }
    logger.info("Plugin Settings: {}", pluginSettings.toString());
  }