/*
 * 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 java.util.List;
import java.util.Map;
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;

/**
 * For reading/writing from/to an HBase store (Hadoop database).
 * 
 * Generated by camel-package-maven-plugin - do not edit this file!
 */
@Generated("org.apache.camel.maven.packaging.EndpointDslMojo")
public interface HBaseEndpointBuilderFactory {


    /**
     * Builder for endpoint consumers for the HBase component.
     */
    public interface HBaseEndpointConsumerBuilder
            extends
                EndpointConsumerBuilder {
        default AdvancedHBaseEndpointConsumerBuilder advanced() {
            return (AdvancedHBaseEndpointConsumerBuilder) this;
        }
        /**
         * To use a custom CellMappingStrategyFactory that is responsible for
         * mapping cells.
         * 
         * The option is a:
         * <code>org.apache.camel.component.hbase.mapping.CellMappingStrategyFactory</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointConsumerBuilder cellMappingStrategyFactory(
                Object cellMappingStrategyFactory) {
            doSetProperty("cellMappingStrategyFactory", cellMappingStrategyFactory);
            return this;
        }
        /**
         * To use a custom CellMappingStrategyFactory that is responsible for
         * mapping cells.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.hbase.mapping.CellMappingStrategyFactory</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointConsumerBuilder cellMappingStrategyFactory(
                String cellMappingStrategyFactory) {
            doSetProperty("cellMappingStrategyFactory", cellMappingStrategyFactory);
            return this;
        }
        /**
         * A list of filters to use.
         * 
         * The option is a:
         * <code>java.util.List&lt;org.apache.hadoop.hbase.filter.Filter&gt;</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointConsumerBuilder filters(List<Object> filters) {
            doSetProperty("filters", filters);
            return this;
        }
        /**
         * A list of filters to use.
         * 
         * The option will be converted to a
         * <code>java.util.List&lt;org.apache.hadoop.hbase.filter.Filter&gt;</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointConsumerBuilder filters(String filters) {
            doSetProperty("filters", filters);
            return this;
        }
        /**
         * The class name of a custom mapping strategy implementation.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointConsumerBuilder mappingStrategyClassName(
                String mappingStrategyClassName) {
            doSetProperty("mappingStrategyClassName", mappingStrategyClassName);
            return this;
        }
        /**
         * The strategy to use for mapping Camel messages to HBase columns.
         * Supported values: header, or body.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointConsumerBuilder mappingStrategyName(
                String mappingStrategyName) {
            doSetProperty("mappingStrategyName", mappingStrategyName);
            return this;
        }
        /**
         * To map the key/values from the Map to a HBaseRow. The following keys
         * is supported: rowId - The id of the row. This has limited use as the
         * row usually changes per Exchange. rowType - The type to covert row id
         * to. Supported operations: CamelHBaseScan. family - The column family.
         * Supports a number suffix for referring to more than one columns.
         * qualifier - The column qualifier. Supports a number suffix for
         * referring to more than one columns. value - The value. Supports a
         * number suffix for referring to more than one columns valueType - The
         * value type. Supports a number suffix for referring to more than one
         * columns. Supported operations: CamelHBaseGet, and CamelHBaseScan.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.lang.Object&gt;</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointConsumerBuilder rowMapping(
                Map<String, Object> rowMapping) {
            doSetProperty("rowMapping", rowMapping);
            return this;
        }
        /**
         * To map the key/values from the Map to a HBaseRow. The following keys
         * is supported: rowId - The id of the row. This has limited use as the
         * row usually changes per Exchange. rowType - The type to covert row id
         * to. Supported operations: CamelHBaseScan. family - The column family.
         * Supports a number suffix for referring to more than one columns.
         * qualifier - The column qualifier. Supports a number suffix for
         * referring to more than one columns. value - The value. Supports a
         * number suffix for referring to more than one columns valueType - The
         * value type. Supports a number suffix for referring to more than one
         * columns. Supported operations: CamelHBaseGet, and CamelHBaseScan.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String, java.lang.Object&gt;</code>
         * type.
         * 
         * Group: common
         */
        default HBaseEndpointConsumerBuilder rowMapping(String rowMapping) {
            doSetProperty("rowMapping", rowMapping);
            return this;
        }
        /**
         * An instance of org.apache.camel.component.hbase.model.HBaseRow which
         * describes how each row should be modeled.
         * 
         * The option is a:
         * <code>org.apache.camel.component.hbase.model.HBaseRow</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointConsumerBuilder rowModel(Object rowModel) {
            doSetProperty("rowModel", rowModel);
            return this;
        }
        /**
         * An instance of org.apache.camel.component.hbase.model.HBaseRow which
         * describes how each row should be modeled.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.hbase.model.HBaseRow</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointConsumerBuilder rowModel(String rowModel) {
            doSetProperty("rowModel", rowModel);
            return this;
        }
        /**
         * Defines privileges to communicate with HBase such as using kerberos.
         * 
         * The option is a:
         * <code>org.apache.hadoop.security.UserGroupInformation</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointConsumerBuilder userGroupInformation(
                Object userGroupInformation) {
            doSetProperty("userGroupInformation", userGroupInformation);
            return this;
        }
        /**
         * Defines privileges to communicate with HBase such as using kerberos.
         * 
         * The option will be converted to a
         * <code>org.apache.hadoop.security.UserGroupInformation</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointConsumerBuilder userGroupInformation(
                String userGroupInformation) {
            doSetProperty("userGroupInformation", userGroupInformation);
            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 is a: <code>boolean</code> type.
         * 
         * Group: consumer
         */
        default HBaseEndpointConsumerBuilder 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 HBaseEndpointConsumerBuilder bridgeErrorHandler(
                String bridgeErrorHandler) {
            doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
            return this;
        }
        /**
         * Gets the maximum number of messages as a limit to poll at each
         * polling. Is default unlimited, but use 0 or negative number to
         * disable it as unlimited.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: consumer
         */
        default HBaseEndpointConsumerBuilder maxMessagesPerPoll(
                int maxMessagesPerPoll) {
            doSetProperty("maxMessagesPerPoll", maxMessagesPerPoll);
            return this;
        }
        /**
         * Gets the maximum number of messages as a limit to poll at each
         * polling. Is default unlimited, but use 0 or negative number to
         * disable it as unlimited.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: consumer
         */
        default HBaseEndpointConsumerBuilder maxMessagesPerPoll(
                String maxMessagesPerPoll) {
            doSetProperty("maxMessagesPerPoll", maxMessagesPerPoll);
            return this;
        }
        /**
         * The HBase operation to perform.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: consumer
         */
        default HBaseEndpointConsumerBuilder operation(String operation) {
            doSetProperty("operation", operation);
            return this;
        }
        /**
         * If the option is true, Camel HBase Consumer will remove the rows
         * which it processes.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: consumer
         */
        default HBaseEndpointConsumerBuilder remove(boolean remove) {
            doSetProperty("remove", remove);
            return this;
        }
        /**
         * If the option is true, Camel HBase Consumer will remove the rows
         * which it processes.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: consumer
         */
        default HBaseEndpointConsumerBuilder remove(String remove) {
            doSetProperty("remove", remove);
            return this;
        }
        /**
         * To use a custom HBaseRemoveHandler that is executed when a row is to
         * be removed.
         * 
         * The option is a:
         * <code>org.apache.camel.component.hbase.HBaseRemoveHandler</code>
         * type.
         * 
         * Group: consumer
         */
        default HBaseEndpointConsumerBuilder removeHandler(Object removeHandler) {
            doSetProperty("removeHandler", removeHandler);
            return this;
        }
        /**
         * To use a custom HBaseRemoveHandler that is executed when a row is to
         * be removed.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.hbase.HBaseRemoveHandler</code>
         * type.
         * 
         * Group: consumer
         */
        default HBaseEndpointConsumerBuilder removeHandler(String removeHandler) {
            doSetProperty("removeHandler", removeHandler);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint consumers for the HBase component.
     */
    public interface AdvancedHBaseEndpointConsumerBuilder
            extends
                EndpointConsumerBuilder {
        default HBaseEndpointConsumerBuilder basic() {
            return (HBaseEndpointConsumerBuilder) 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 AdvancedHBaseEndpointConsumerBuilder 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 AdvancedHBaseEndpointConsumerBuilder 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 AdvancedHBaseEndpointConsumerBuilder 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 AdvancedHBaseEndpointConsumerBuilder 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 AdvancedHBaseEndpointConsumerBuilder 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 AdvancedHBaseEndpointConsumerBuilder 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 AdvancedHBaseEndpointConsumerBuilder 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 AdvancedHBaseEndpointConsumerBuilder synchronous(
                String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
    }

    /**
     * Builder for endpoint producers for the HBase component.
     */
    public interface HBaseEndpointProducerBuilder
            extends
                EndpointProducerBuilder {
        default AdvancedHBaseEndpointProducerBuilder advanced() {
            return (AdvancedHBaseEndpointProducerBuilder) this;
        }
        /**
         * To use a custom CellMappingStrategyFactory that is responsible for
         * mapping cells.
         * 
         * The option is a:
         * <code>org.apache.camel.component.hbase.mapping.CellMappingStrategyFactory</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointProducerBuilder cellMappingStrategyFactory(
                Object cellMappingStrategyFactory) {
            doSetProperty("cellMappingStrategyFactory", cellMappingStrategyFactory);
            return this;
        }
        /**
         * To use a custom CellMappingStrategyFactory that is responsible for
         * mapping cells.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.hbase.mapping.CellMappingStrategyFactory</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointProducerBuilder cellMappingStrategyFactory(
                String cellMappingStrategyFactory) {
            doSetProperty("cellMappingStrategyFactory", cellMappingStrategyFactory);
            return this;
        }
        /**
         * A list of filters to use.
         * 
         * The option is a:
         * <code>java.util.List&lt;org.apache.hadoop.hbase.filter.Filter&gt;</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointProducerBuilder filters(List<Object> filters) {
            doSetProperty("filters", filters);
            return this;
        }
        /**
         * A list of filters to use.
         * 
         * The option will be converted to a
         * <code>java.util.List&lt;org.apache.hadoop.hbase.filter.Filter&gt;</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointProducerBuilder filters(String filters) {
            doSetProperty("filters", filters);
            return this;
        }
        /**
         * The class name of a custom mapping strategy implementation.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointProducerBuilder mappingStrategyClassName(
                String mappingStrategyClassName) {
            doSetProperty("mappingStrategyClassName", mappingStrategyClassName);
            return this;
        }
        /**
         * The strategy to use for mapping Camel messages to HBase columns.
         * Supported values: header, or body.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointProducerBuilder mappingStrategyName(
                String mappingStrategyName) {
            doSetProperty("mappingStrategyName", mappingStrategyName);
            return this;
        }
        /**
         * To map the key/values from the Map to a HBaseRow. The following keys
         * is supported: rowId - The id of the row. This has limited use as the
         * row usually changes per Exchange. rowType - The type to covert row id
         * to. Supported operations: CamelHBaseScan. family - The column family.
         * Supports a number suffix for referring to more than one columns.
         * qualifier - The column qualifier. Supports a number suffix for
         * referring to more than one columns. value - The value. Supports a
         * number suffix for referring to more than one columns valueType - The
         * value type. Supports a number suffix for referring to more than one
         * columns. Supported operations: CamelHBaseGet, and CamelHBaseScan.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.lang.Object&gt;</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointProducerBuilder rowMapping(
                Map<String, Object> rowMapping) {
            doSetProperty("rowMapping", rowMapping);
            return this;
        }
        /**
         * To map the key/values from the Map to a HBaseRow. The following keys
         * is supported: rowId - The id of the row. This has limited use as the
         * row usually changes per Exchange. rowType - The type to covert row id
         * to. Supported operations: CamelHBaseScan. family - The column family.
         * Supports a number suffix for referring to more than one columns.
         * qualifier - The column qualifier. Supports a number suffix for
         * referring to more than one columns. value - The value. Supports a
         * number suffix for referring to more than one columns valueType - The
         * value type. Supports a number suffix for referring to more than one
         * columns. Supported operations: CamelHBaseGet, and CamelHBaseScan.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String, java.lang.Object&gt;</code>
         * type.
         * 
         * Group: common
         */
        default HBaseEndpointProducerBuilder rowMapping(String rowMapping) {
            doSetProperty("rowMapping", rowMapping);
            return this;
        }
        /**
         * An instance of org.apache.camel.component.hbase.model.HBaseRow which
         * describes how each row should be modeled.
         * 
         * The option is a:
         * <code>org.apache.camel.component.hbase.model.HBaseRow</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointProducerBuilder rowModel(Object rowModel) {
            doSetProperty("rowModel", rowModel);
            return this;
        }
        /**
         * An instance of org.apache.camel.component.hbase.model.HBaseRow which
         * describes how each row should be modeled.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.hbase.model.HBaseRow</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointProducerBuilder rowModel(String rowModel) {
            doSetProperty("rowModel", rowModel);
            return this;
        }
        /**
         * Defines privileges to communicate with HBase such as using kerberos.
         * 
         * The option is a:
         * <code>org.apache.hadoop.security.UserGroupInformation</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointProducerBuilder userGroupInformation(
                Object userGroupInformation) {
            doSetProperty("userGroupInformation", userGroupInformation);
            return this;
        }
        /**
         * Defines privileges to communicate with HBase such as using kerberos.
         * 
         * The option will be converted to a
         * <code>org.apache.hadoop.security.UserGroupInformation</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointProducerBuilder userGroupInformation(
                String userGroupInformation) {
            doSetProperty("userGroupInformation", userGroupInformation);
            return this;
        }
        /**
         * Whether the producer should be started lazy (on the first message).
         * By starting lazy you can use this to allow CamelContext and routes to
         * startup in situations where a producer may otherwise fail during
         * starting and cause the route to fail being started. By deferring this
         * startup to be lazy then the startup failure can be handled during
         * routing messages via Camel's routing error handlers. Beware that when
         * the first message is processed then creating and starting the
         * producer may take a little time and prolong the total processing time
         * of the processing.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default HBaseEndpointProducerBuilder lazyStartProducer(
                boolean lazyStartProducer) {
            doSetProperty("lazyStartProducer", lazyStartProducer);
            return this;
        }
        /**
         * Whether the producer should be started lazy (on the first message).
         * By starting lazy you can use this to allow CamelContext and routes to
         * startup in situations where a producer may otherwise fail during
         * starting and cause the route to fail being started. By deferring this
         * startup to be lazy then the startup failure can be handled during
         * routing messages via Camel's routing error handlers. Beware that when
         * the first message is processed then creating and starting the
         * producer may take a little time and prolong the total processing time
         * of the processing.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default HBaseEndpointProducerBuilder lazyStartProducer(
                String lazyStartProducer) {
            doSetProperty("lazyStartProducer", lazyStartProducer);
            return this;
        }
        /**
         * The maximum number of rows to scan.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: producer
         */
        default HBaseEndpointProducerBuilder maxResults(int maxResults) {
            doSetProperty("maxResults", maxResults);
            return this;
        }
        /**
         * The maximum number of rows to scan.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: producer
         */
        default HBaseEndpointProducerBuilder maxResults(String maxResults) {
            doSetProperty("maxResults", maxResults);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint producers for the HBase component.
     */
    public interface AdvancedHBaseEndpointProducerBuilder
            extends
                EndpointProducerBuilder {
        default HBaseEndpointProducerBuilder basic() {
            return (HBaseEndpointProducerBuilder) 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 AdvancedHBaseEndpointProducerBuilder 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 AdvancedHBaseEndpointProducerBuilder 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 AdvancedHBaseEndpointProducerBuilder 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 AdvancedHBaseEndpointProducerBuilder synchronous(
                String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
    }

    /**
     * Builder for endpoint for the HBase component.
     */
    public interface HBaseEndpointBuilder
            extends
                HBaseEndpointConsumerBuilder, HBaseEndpointProducerBuilder {
        default AdvancedHBaseEndpointBuilder advanced() {
            return (AdvancedHBaseEndpointBuilder) this;
        }
        /**
         * To use a custom CellMappingStrategyFactory that is responsible for
         * mapping cells.
         * 
         * The option is a:
         * <code>org.apache.camel.component.hbase.mapping.CellMappingStrategyFactory</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointBuilder cellMappingStrategyFactory(
                Object cellMappingStrategyFactory) {
            doSetProperty("cellMappingStrategyFactory", cellMappingStrategyFactory);
            return this;
        }
        /**
         * To use a custom CellMappingStrategyFactory that is responsible for
         * mapping cells.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.hbase.mapping.CellMappingStrategyFactory</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointBuilder cellMappingStrategyFactory(
                String cellMappingStrategyFactory) {
            doSetProperty("cellMappingStrategyFactory", cellMappingStrategyFactory);
            return this;
        }
        /**
         * A list of filters to use.
         * 
         * The option is a:
         * <code>java.util.List&lt;org.apache.hadoop.hbase.filter.Filter&gt;</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointBuilder filters(List<Object> filters) {
            doSetProperty("filters", filters);
            return this;
        }
        /**
         * A list of filters to use.
         * 
         * The option will be converted to a
         * <code>java.util.List&lt;org.apache.hadoop.hbase.filter.Filter&gt;</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointBuilder filters(String filters) {
            doSetProperty("filters", filters);
            return this;
        }
        /**
         * The class name of a custom mapping strategy implementation.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointBuilder mappingStrategyClassName(
                String mappingStrategyClassName) {
            doSetProperty("mappingStrategyClassName", mappingStrategyClassName);
            return this;
        }
        /**
         * The strategy to use for mapping Camel messages to HBase columns.
         * Supported values: header, or body.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointBuilder mappingStrategyName(
                String mappingStrategyName) {
            doSetProperty("mappingStrategyName", mappingStrategyName);
            return this;
        }
        /**
         * To map the key/values from the Map to a HBaseRow. The following keys
         * is supported: rowId - The id of the row. This has limited use as the
         * row usually changes per Exchange. rowType - The type to covert row id
         * to. Supported operations: CamelHBaseScan. family - The column family.
         * Supports a number suffix for referring to more than one columns.
         * qualifier - The column qualifier. Supports a number suffix for
         * referring to more than one columns. value - The value. Supports a
         * number suffix for referring to more than one columns valueType - The
         * value type. Supports a number suffix for referring to more than one
         * columns. Supported operations: CamelHBaseGet, and CamelHBaseScan.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.lang.Object&gt;</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointBuilder rowMapping(Map<String, Object> rowMapping) {
            doSetProperty("rowMapping", rowMapping);
            return this;
        }
        /**
         * To map the key/values from the Map to a HBaseRow. The following keys
         * is supported: rowId - The id of the row. This has limited use as the
         * row usually changes per Exchange. rowType - The type to covert row id
         * to. Supported operations: CamelHBaseScan. family - The column family.
         * Supports a number suffix for referring to more than one columns.
         * qualifier - The column qualifier. Supports a number suffix for
         * referring to more than one columns. value - The value. Supports a
         * number suffix for referring to more than one columns valueType - The
         * value type. Supports a number suffix for referring to more than one
         * columns. Supported operations: CamelHBaseGet, and CamelHBaseScan.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String, java.lang.Object&gt;</code>
         * type.
         * 
         * Group: common
         */
        default HBaseEndpointBuilder rowMapping(String rowMapping) {
            doSetProperty("rowMapping", rowMapping);
            return this;
        }
        /**
         * An instance of org.apache.camel.component.hbase.model.HBaseRow which
         * describes how each row should be modeled.
         * 
         * The option is a:
         * <code>org.apache.camel.component.hbase.model.HBaseRow</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointBuilder rowModel(Object rowModel) {
            doSetProperty("rowModel", rowModel);
            return this;
        }
        /**
         * An instance of org.apache.camel.component.hbase.model.HBaseRow which
         * describes how each row should be modeled.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.hbase.model.HBaseRow</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointBuilder rowModel(String rowModel) {
            doSetProperty("rowModel", rowModel);
            return this;
        }
        /**
         * Defines privileges to communicate with HBase such as using kerberos.
         * 
         * The option is a:
         * <code>org.apache.hadoop.security.UserGroupInformation</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointBuilder userGroupInformation(
                Object userGroupInformation) {
            doSetProperty("userGroupInformation", userGroupInformation);
            return this;
        }
        /**
         * Defines privileges to communicate with HBase such as using kerberos.
         * 
         * The option will be converted to a
         * <code>org.apache.hadoop.security.UserGroupInformation</code> type.
         * 
         * Group: common
         */
        default HBaseEndpointBuilder userGroupInformation(
                String userGroupInformation) {
            doSetProperty("userGroupInformation", userGroupInformation);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint for the HBase component.
     */
    public interface AdvancedHBaseEndpointBuilder
            extends
                AdvancedHBaseEndpointConsumerBuilder, AdvancedHBaseEndpointProducerBuilder {
        default HBaseEndpointBuilder basic() {
            return (HBaseEndpointBuilder) 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 AdvancedHBaseEndpointBuilder 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 AdvancedHBaseEndpointBuilder 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 AdvancedHBaseEndpointBuilder 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 AdvancedHBaseEndpointBuilder synchronous(String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
    }
    /**
     * HBase (camel-hbase)
     * For reading/writing from/to an HBase store (Hadoop database).
     * 
     * Category: hadoop
     * Since: 2.10
     * Maven coordinates: org.apache.camel:camel-hbase
     * 
     * Syntax: <code>hbase:tableName</code>
     * 
     * Path parameter: tableName (required)
     * The name of the table
     */
    default HBaseEndpointBuilder hbase(String path) {
        class HBaseEndpointBuilderImpl extends AbstractEndpointBuilder implements HBaseEndpointBuilder, AdvancedHBaseEndpointBuilder {
            public HBaseEndpointBuilderImpl(String path) {
                super("hbase", path);
            }
        }
        return new HBaseEndpointBuilderImpl(path);
    }
}