/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.camel.builder.endpoint.dsl;

import javax.annotation.Generated;
import org.apache.camel.ExchangePattern;
import org.apache.camel.builder.EndpointConsumerBuilder;
import org.apache.camel.builder.EndpointProducerBuilder;
import org.apache.camel.builder.endpoint.AbstractEndpointBuilder;
import org.apache.camel.spi.ExceptionHandler;

/**
 * Represents a Debezium MongoDB endpoint which is used to capture changes in
 * MongoDB database so that that applications can see those changes and respond
 * to them.
 * 
 * Generated by camel-package-maven-plugin - do not edit this file!
 */
@Generated("org.apache.camel.maven.packaging.EndpointDslMojo")
public interface DebeziumMongodbEndpointBuilderFactory {


    /**
     * Builder for endpoint for the Debezium MongoDB Connector component.
     */
    public interface DebeziumMongodbEndpointBuilder
            extends
                EndpointConsumerBuilder {
        default AdvancedDebeziumMongodbEndpointBuilder advanced() {
            return (AdvancedDebeziumMongodbEndpointBuilder) this;
        }
        /**
         * Allows for bridging the consumer to the Camel routing Error Handler,
         * which mean any exceptions occurred while the consumer is trying to
         * pickup incoming messages, or the likes, will now be processed as a
         * message and handled by the routing Error Handler. By default the
         * consumer will use the org.apache.camel.spi.ExceptionHandler to deal
         * with exceptions, that will be logged at WARN or ERROR level and
         * ignored.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder bridgeErrorHandler(
                boolean bridgeErrorHandler) {
            doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
            return this;
        }
        /**
         * Allows for bridging the consumer to the Camel routing Error Handler,
         * which mean any exceptions occurred while the consumer is trying to
         * pickup incoming messages, or the likes, will now be processed as a
         * message and handled by the routing Error Handler. By default the
         * consumer will use the org.apache.camel.spi.ExceptionHandler to deal
         * with exceptions, that will be logged at WARN or ERROR level and
         * ignored.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder bridgeErrorHandler(
                String bridgeErrorHandler) {
            doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
            return this;
        }
        /**
         * The Converter class that should be used to serialize and deserialize
         * key data for offsets. The default is JSON converter.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder internalKeyConverter(
                String internalKeyConverter) {
            doSetProperty("internalKeyConverter", internalKeyConverter);
            return this;
        }
        /**
         * The Converter class that should be used to serialize and deserialize
         * value data for offsets. The default is JSON converter.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder internalValueConverter(
                String internalValueConverter) {
            doSetProperty("internalValueConverter", internalValueConverter);
            return this;
        }
        /**
         * The name of the Java class of the commit policy. It defines when
         * offsets commit has to be triggered based on the number of events
         * processed and the time elapsed since the last commit. This class must
         * implement the interface 'OffsetCommitPolicy'. The default is a
         * periodic commit policy based upon time intervals.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder offsetCommitPolicy(
                String offsetCommitPolicy) {
            doSetProperty("offsetCommitPolicy", offsetCommitPolicy);
            return this;
        }
        /**
         * Maximum number of milliseconds to wait for records to flush and
         * partition offset data to be committed to offset storage before
         * cancelling the process and restoring the offset data to be committed
         * in a future attempt. The default is 5 seconds.
         * 
         * The option is a: <code>long</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder offsetCommitTimeoutMs(
                long offsetCommitTimeoutMs) {
            doSetProperty("offsetCommitTimeoutMs", offsetCommitTimeoutMs);
            return this;
        }
        /**
         * Maximum number of milliseconds to wait for records to flush and
         * partition offset data to be committed to offset storage before
         * cancelling the process and restoring the offset data to be committed
         * in a future attempt. The default is 5 seconds.
         * 
         * The option will be converted to a <code>long</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder offsetCommitTimeoutMs(
                String offsetCommitTimeoutMs) {
            doSetProperty("offsetCommitTimeoutMs", offsetCommitTimeoutMs);
            return this;
        }
        /**
         * Interval at which to try committing offsets. The default is 1 minute.
         * 
         * The option is a: <code>long</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder offsetFlushIntervalMs(
                long offsetFlushIntervalMs) {
            doSetProperty("offsetFlushIntervalMs", offsetFlushIntervalMs);
            return this;
        }
        /**
         * Interval at which to try committing offsets. The default is 1 minute.
         * 
         * The option will be converted to a <code>long</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder offsetFlushIntervalMs(
                String offsetFlushIntervalMs) {
            doSetProperty("offsetFlushIntervalMs", offsetFlushIntervalMs);
            return this;
        }
        /**
         * The name of the Java class that is responsible for persistence of
         * connector offsets.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder offsetStorage(
                String offsetStorage) {
            doSetProperty("offsetStorage", offsetStorage);
            return this;
        }
        /**
         * Path to file where offsets are to be stored. Required when
         * offset.storage is set to the FileOffsetBackingStore.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder offsetStorageFileName(
                String offsetStorageFileName) {
            doSetProperty("offsetStorageFileName", offsetStorageFileName);
            return this;
        }
        /**
         * The number of partitions used when creating the offset storage topic.
         * Required when offset.storage is set to the 'KafkaOffsetBackingStore'.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder offsetStoragePartitions(
                int offsetStoragePartitions) {
            doSetProperty("offsetStoragePartitions", offsetStoragePartitions);
            return this;
        }
        /**
         * The number of partitions used when creating the offset storage topic.
         * Required when offset.storage is set to the 'KafkaOffsetBackingStore'.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder offsetStoragePartitions(
                String offsetStoragePartitions) {
            doSetProperty("offsetStoragePartitions", offsetStoragePartitions);
            return this;
        }
        /**
         * Replication factor used when creating the offset storage topic.
         * Required when offset.storage is set to the KafkaOffsetBackingStore.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder offsetStorageReplicationFactor(
                int offsetStorageReplicationFactor) {
            doSetProperty("offsetStorageReplicationFactor", offsetStorageReplicationFactor);
            return this;
        }
        /**
         * Replication factor used when creating the offset storage topic.
         * Required when offset.storage is set to the KafkaOffsetBackingStore.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder offsetStorageReplicationFactor(
                String offsetStorageReplicationFactor) {
            doSetProperty("offsetStorageReplicationFactor", offsetStorageReplicationFactor);
            return this;
        }
        /**
         * The name of the Kafka topic where offsets are to be stored. Required
         * when offset.storage is set to the KafkaOffsetBackingStore.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: consumer
         */
        default DebeziumMongodbEndpointBuilder offsetStorageTopic(
                String offsetStorageTopic) {
            doSetProperty("offsetStorageTopic", offsetStorageTopic);
            return this;
        }
        /**
         * Description is not available here, please check Debezium website for
         * corresponding key 'collection.blacklist' description.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder collectionBlacklist(
                String collectionBlacklist) {
            doSetProperty("collectionBlacklist", collectionBlacklist);
            return this;
        }
        /**
         * The collections for which changes are to be captured.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder collectionWhitelist(
                String collectionWhitelist) {
            doSetProperty("collectionWhitelist", collectionWhitelist);
            return this;
        }
        /**
         * The initial delay when trying to reconnect to a primary after a
         * connection cannot be made or when no primary is available. Defaults
         * to 1 second (1000 ms).
         * 
         * The option is a: <code>long</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder connectBackoffInitialDelayMs(
                long connectBackoffInitialDelayMs) {
            doSetProperty("connectBackoffInitialDelayMs", connectBackoffInitialDelayMs);
            return this;
        }
        /**
         * The initial delay when trying to reconnect to a primary after a
         * connection cannot be made or when no primary is available. Defaults
         * to 1 second (1000 ms).
         * 
         * The option will be converted to a <code>long</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder connectBackoffInitialDelayMs(
                String connectBackoffInitialDelayMs) {
            doSetProperty("connectBackoffInitialDelayMs", connectBackoffInitialDelayMs);
            return this;
        }
        /**
         * The maximum delay when trying to reconnect to a primary after a
         * connection cannot be made or when no primary is available. Defaults
         * to 120 second (120,000 ms).
         * 
         * The option is a: <code>long</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder connectBackoffMaxDelayMs(
                long connectBackoffMaxDelayMs) {
            doSetProperty("connectBackoffMaxDelayMs", connectBackoffMaxDelayMs);
            return this;
        }
        /**
         * The maximum delay when trying to reconnect to a primary after a
         * connection cannot be made or when no primary is available. Defaults
         * to 120 second (120,000 ms).
         * 
         * The option will be converted to a <code>long</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder connectBackoffMaxDelayMs(
                String connectBackoffMaxDelayMs) {
            doSetProperty("connectBackoffMaxDelayMs", connectBackoffMaxDelayMs);
            return this;
        }
        /**
         * Maximum number of failed connection attempts to a replica set primary
         * before an exception occurs and task is aborted. Defaults to 16, which
         * with the defaults for 'connect.backoff.initial.delay.ms' and
         * 'connect.backoff.max.delay.ms' results in just over 20 minutes of
         * attempts before failing.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder connectMaxAttempts(
                int connectMaxAttempts) {
            doSetProperty("connectMaxAttempts", connectMaxAttempts);
            return this;
        }
        /**
         * Maximum number of failed connection attempts to a replica set primary
         * before an exception occurs and task is aborted. Defaults to 16, which
         * with the defaults for 'connect.backoff.initial.delay.ms' and
         * 'connect.backoff.max.delay.ms' results in just over 20 minutes of
         * attempts before failing.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder connectMaxAttempts(
                String connectMaxAttempts) {
            doSetProperty("connectMaxAttempts", connectMaxAttempts);
            return this;
        }
        /**
         * The databases for which changes are to be excluded.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder databaseBlacklist(
                String databaseBlacklist) {
            doSetProperty("databaseBlacklist", databaseBlacklist);
            return this;
        }
        /**
         * The path to the file that will be used to record the database
         * history.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder databaseHistoryFileFilename(
                String databaseHistoryFileFilename) {
            doSetProperty("databaseHistoryFileFilename", databaseHistoryFileFilename);
            return this;
        }
        /**
         * The databases for which changes are to be captured.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder databaseWhitelist(
                String databaseWhitelist) {
            doSetProperty("databaseWhitelist", databaseWhitelist);
            return this;
        }
        /**
         * Description is not available here, please check Debezium website for
         * corresponding key 'field.blacklist' description.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder fieldBlacklist(
                String fieldBlacklist) {
            doSetProperty("fieldBlacklist", fieldBlacklist);
            return this;
        }
        /**
         * Description is not available here, please check Debezium website for
         * corresponding key 'field.renames' description.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder fieldRenames(String fieldRenames) {
            doSetProperty("fieldRenames", fieldRenames);
            return this;
        }
        /**
         * Length of an interval in milli-seconds in in which the connector
         * periodically sends heartbeat messages to a heartbeat topic. Use 0 to
         * disable heartbeat messages. Disabled by default.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder heartbeatIntervalMs(
                int heartbeatIntervalMs) {
            doSetProperty("heartbeatIntervalMs", heartbeatIntervalMs);
            return this;
        }
        /**
         * Length of an interval in milli-seconds in in which the connector
         * periodically sends heartbeat messages to a heartbeat topic. Use 0 to
         * disable heartbeat messages. Disabled by default.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder heartbeatIntervalMs(
                String heartbeatIntervalMs) {
            doSetProperty("heartbeatIntervalMs", heartbeatIntervalMs);
            return this;
        }
        /**
         * The prefix that is used to name heartbeat topics.Defaults to
         * __debezium-heartbeat.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder heartbeatTopicsPrefix(
                String heartbeatTopicsPrefix) {
            doSetProperty("heartbeatTopicsPrefix", heartbeatTopicsPrefix);
            return this;
        }
        /**
         * Maximum number of threads used to perform an intial sync of the
         * collections in a replica set. Defaults to 1.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder initialSyncMaxThreads(
                int initialSyncMaxThreads) {
            doSetProperty("initialSyncMaxThreads", initialSyncMaxThreads);
            return this;
        }
        /**
         * Maximum number of threads used to perform an intial sync of the
         * collections in a replica set. Defaults to 1.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder initialSyncMaxThreads(
                String initialSyncMaxThreads) {
            doSetProperty("initialSyncMaxThreads", initialSyncMaxThreads);
            return this;
        }
        /**
         * Maximum size of each batch of source records. Defaults to 2048.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder maxBatchSize(int maxBatchSize) {
            doSetProperty("maxBatchSize", maxBatchSize);
            return this;
        }
        /**
         * Maximum size of each batch of source records. Defaults to 2048.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder maxBatchSize(String maxBatchSize) {
            doSetProperty("maxBatchSize", maxBatchSize);
            return this;
        }
        /**
         * Maximum size of the queue for change events read from the database
         * log but not yet recorded or forwarded. Defaults to 8192, and should
         * always be larger than the maximum batch size.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder maxQueueSize(int maxQueueSize) {
            doSetProperty("maxQueueSize", maxQueueSize);
            return this;
        }
        /**
         * Maximum size of the queue for change events read from the database
         * log but not yet recorded or forwarded. Defaults to 8192, and should
         * always be larger than the maximum batch size.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder maxQueueSize(String maxQueueSize) {
            doSetProperty("maxQueueSize", maxQueueSize);
            return this;
        }
        /**
         * The hostname and port pairs (in the form 'host' or 'host:port') of
         * the MongoDB server(s) in the replica set.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder mongodbHosts(String mongodbHosts) {
            doSetProperty("mongodbHosts", mongodbHosts);
            return this;
        }
        /**
         * Specifies whether the addresses in 'hosts' are seeds that should be
         * used to discover all members of the cluster or replica set ('true'),
         * or whether the address(es) in 'hosts' should be used as is ('false').
         * The default is 'true'.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder mongodbMembersAutoDiscover(
                boolean mongodbMembersAutoDiscover) {
            doSetProperty("mongodbMembersAutoDiscover", mongodbMembersAutoDiscover);
            return this;
        }
        /**
         * Specifies whether the addresses in 'hosts' are seeds that should be
         * used to discover all members of the cluster or replica set ('true'),
         * or whether the address(es) in 'hosts' should be used as is ('false').
         * The default is 'true'.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder mongodbMembersAutoDiscover(
                String mongodbMembersAutoDiscover) {
            doSetProperty("mongodbMembersAutoDiscover", mongodbMembersAutoDiscover);
            return this;
        }
        /**
         * Unique name that identifies the MongoDB replica set or cluster and
         * all recorded offsets, andthat is used as a prefix for all schemas and
         * topics. Each distinct MongoDB installation should have a separate
         * namespace and monitored by at most one Debezium connector.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Required: true
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder mongodbName(String mongodbName) {
            doSetProperty("mongodbName", mongodbName);
            return this;
        }
        /**
         * Password to be used when connecting to MongoDB, if necessary.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Required: true
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder mongodbPassword(
                String mongodbPassword) {
            doSetProperty("mongodbPassword", mongodbPassword);
            return this;
        }
        /**
         * Should connector use SSL to connect to MongoDB instances.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder mongodbSslEnabled(
                boolean mongodbSslEnabled) {
            doSetProperty("mongodbSslEnabled", mongodbSslEnabled);
            return this;
        }
        /**
         * Should connector use SSL to connect to MongoDB instances.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder mongodbSslEnabled(
                String mongodbSslEnabled) {
            doSetProperty("mongodbSslEnabled", mongodbSslEnabled);
            return this;
        }
        /**
         * Whether invalid host names are allowed when using SSL. If true the
         * connection will not prevent man-in-the-middle attacks.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder mongodbSslInvalidHostnameAllowed(
                boolean mongodbSslInvalidHostnameAllowed) {
            doSetProperty("mongodbSslInvalidHostnameAllowed", mongodbSslInvalidHostnameAllowed);
            return this;
        }
        /**
         * Whether invalid host names are allowed when using SSL. If true the
         * connection will not prevent man-in-the-middle attacks.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder mongodbSslInvalidHostnameAllowed(
                String mongodbSslInvalidHostnameAllowed) {
            doSetProperty("mongodbSslInvalidHostnameAllowed", mongodbSslInvalidHostnameAllowed);
            return this;
        }
        /**
         * Database user for connecting to MongoDB, if necessary.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder mongodbUser(String mongodbUser) {
            doSetProperty("mongodbUser", mongodbUser);
            return this;
        }
        /**
         * Frequency in milliseconds to wait for new change events to appear
         * after receiving no events. Defaults to 500ms.
         * 
         * The option is a: <code>long</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder pollIntervalMs(
                long pollIntervalMs) {
            doSetProperty("pollIntervalMs", pollIntervalMs);
            return this;
        }
        /**
         * Frequency in milliseconds to wait for new change events to appear
         * after receiving no events. Defaults to 500ms.
         * 
         * The option will be converted to a <code>long</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder pollIntervalMs(
                String pollIntervalMs) {
            doSetProperty("pollIntervalMs", pollIntervalMs);
            return this;
        }
        /**
         * The number of milliseconds to delay before a snapshot will begin.
         * 
         * The option is a: <code>long</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder snapshotDelayMs(
                long snapshotDelayMs) {
            doSetProperty("snapshotDelayMs", snapshotDelayMs);
            return this;
        }
        /**
         * The number of milliseconds to delay before a snapshot will begin.
         * 
         * The option will be converted to a <code>long</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder snapshotDelayMs(
                String snapshotDelayMs) {
            doSetProperty("snapshotDelayMs", snapshotDelayMs);
            return this;
        }
        /**
         * The maximum number of records that should be loaded into memory while
         * performing a snapshot.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder snapshotFetchSize(
                int snapshotFetchSize) {
            doSetProperty("snapshotFetchSize", snapshotFetchSize);
            return this;
        }
        /**
         * The maximum number of records that should be loaded into memory while
         * performing a snapshot.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder snapshotFetchSize(
                String snapshotFetchSize) {
            doSetProperty("snapshotFetchSize", snapshotFetchSize);
            return this;
        }
        /**
         * The criteria for running a snapshot upon startup of the connector.
         * Options include: 'initial' (the default) to specify the connector
         * should always perform an initial sync when required; 'never' to
         * specify the connector should never perform an initial sync.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder snapshotMode(String snapshotMode) {
            doSetProperty("snapshotMode", snapshotMode);
            return this;
        }
        /**
         * A version of the format of the publicly visible source part in the
         * message.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder sourceStructVersion(
                String sourceStructVersion) {
            doSetProperty("sourceStructVersion", sourceStructVersion);
            return this;
        }
        /**
         * Whether delete operations should be represented by a delete event and
         * a subsquenttombstone event (true) or only by a delete event (false).
         * Emitting the tombstone event (the default behavior) allows Kafka to
         * completely delete all events pertaining to the given key once the
         * source record got deleted.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder tombstonesOnDelete(
                boolean tombstonesOnDelete) {
            doSetProperty("tombstonesOnDelete", tombstonesOnDelete);
            return this;
        }
        /**
         * Whether delete operations should be represented by a delete event and
         * a subsquenttombstone event (true) or only by a delete event (false).
         * Emitting the tombstone event (the default behavior) allows Kafka to
         * completely delete all events pertaining to the given key once the
         * source record got deleted.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: mongodb
         */
        default DebeziumMongodbEndpointBuilder tombstonesOnDelete(
                String tombstonesOnDelete) {
            doSetProperty("tombstonesOnDelete", tombstonesOnDelete);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint for the Debezium MongoDB Connector
     * component.
     */
    public interface AdvancedDebeziumMongodbEndpointBuilder
            extends
                EndpointConsumerBuilder {
        default DebeziumMongodbEndpointBuilder basic() {
            return (DebeziumMongodbEndpointBuilder) this;
        }
        /**
         * To let the consumer use a custom ExceptionHandler. Notice if the
         * option bridgeErrorHandler is enabled then this option is not in use.
         * By default the consumer will deal with exceptions, that will be
         * logged at WARN or ERROR level and ignored.
         * 
         * The option is a: <code>org.apache.camel.spi.ExceptionHandler</code>
         * type.
         * 
         * Group: consumer (advanced)
         */
        default AdvancedDebeziumMongodbEndpointBuilder exceptionHandler(
                ExceptionHandler exceptionHandler) {
            doSetProperty("exceptionHandler", exceptionHandler);
            return this;
        }
        /**
         * To let the consumer use a custom ExceptionHandler. Notice if the
         * option bridgeErrorHandler is enabled then this option is not in use.
         * By default the consumer will deal with exceptions, that will be
         * logged at WARN or ERROR level and ignored.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.spi.ExceptionHandler</code> type.
         * 
         * Group: consumer (advanced)
         */
        default AdvancedDebeziumMongodbEndpointBuilder exceptionHandler(
                String exceptionHandler) {
            doSetProperty("exceptionHandler", exceptionHandler);
            return this;
        }
        /**
         * Sets the exchange pattern when the consumer creates an exchange.
         * 
         * The option is a: <code>org.apache.camel.ExchangePattern</code> type.
         * 
         * Group: consumer (advanced)
         */
        default AdvancedDebeziumMongodbEndpointBuilder exchangePattern(
                ExchangePattern exchangePattern) {
            doSetProperty("exchangePattern", exchangePattern);
            return this;
        }
        /**
         * Sets the exchange pattern when the consumer creates an exchange.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.ExchangePattern</code> type.
         * 
         * Group: consumer (advanced)
         */
        default AdvancedDebeziumMongodbEndpointBuilder exchangePattern(
                String exchangePattern) {
            doSetProperty("exchangePattern", exchangePattern);
            return this;
        }
        /**
         * Whether the endpoint should use basic property binding (Camel 2.x) or
         * the newer property binding with additional capabilities.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedDebeziumMongodbEndpointBuilder basicPropertyBinding(
                boolean basicPropertyBinding) {
            doSetProperty("basicPropertyBinding", basicPropertyBinding);
            return this;
        }
        /**
         * Whether the endpoint should use basic property binding (Camel 2.x) or
         * the newer property binding with additional capabilities.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedDebeziumMongodbEndpointBuilder basicPropertyBinding(
                String basicPropertyBinding) {
            doSetProperty("basicPropertyBinding", basicPropertyBinding);
            return this;
        }
        /**
         * Sets whether synchronous processing should be strictly used, or Camel
         * is allowed to use asynchronous processing (if supported).
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedDebeziumMongodbEndpointBuilder synchronous(
                boolean synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
        /**
         * Sets whether synchronous processing should be strictly used, or Camel
         * is allowed to use asynchronous processing (if supported).
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedDebeziumMongodbEndpointBuilder synchronous(
                String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
    }
    /**
     * Debezium MongoDB Connector (camel-debezium-mongodb)
     * Represents a Debezium MongoDB endpoint which is used to capture changes
     * in MongoDB database so that that applications can see those changes and
     * respond to them.
     * 
     * Category: database,nosql,mongodb
     * Since: 3.0
     * Maven coordinates: org.apache.camel:camel-debezium-mongodb
     * 
     * Syntax: <code>debezium-mongodb:name</code>
     * 
     * Path parameter: name (required)
     * Unique name for the connector. Attempting to register again with the same
     * name will fail.
     */
    default DebeziumMongodbEndpointBuilder debeziumMongodb(String path) {
        class DebeziumMongodbEndpointBuilderImpl extends AbstractEndpointBuilder implements DebeziumMongodbEndpointBuilder, AdvancedDebeziumMongodbEndpointBuilder {
            public DebeziumMongodbEndpointBuilderImpl(String path) {
                super("debezium-mongodb", path);
            }
        }
        return new DebeziumMongodbEndpointBuilderImpl(path);
    }
}