/*
 * 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 java.util.Properties;
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;

/**
 * The atomix-map component is used to access Atomix's distributed map.
 * 
 * Generated by camel-package-maven-plugin - do not edit this file!
 */
@Generated("org.apache.camel.maven.packaging.EndpointDslMojo")
public interface AtomixMapEndpointBuilderFactory {


    /**
     * Builder for endpoint consumers for the Atomix Map component.
     */
    public interface AtomixMapEndpointConsumerBuilder
            extends
                EndpointConsumerBuilder {
        default AdvancedAtomixMapEndpointConsumerBuilder advanced() {
            return (AdvancedAtomixMapEndpointConsumerBuilder) this;
        }
        /**
         * The Atomix instance to use.
         * 
         * The option is a: <code>io.atomix.AtomixClient</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder atomix(Object atomix) {
            doSetProperty("atomix", atomix);
            return this;
        }
        /**
         * The Atomix instance to use.
         * 
         * The option will be converted to a <code>io.atomix.AtomixClient</code>
         * type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder atomix(String atomix) {
            doSetProperty("atomix", atomix);
            return this;
        }
        /**
         * The Atomix configuration uri.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder configurationUri(
                String configurationUri) {
            doSetProperty("configurationUri", configurationUri);
            return this;
        }
        /**
         * The default action.
         * 
         * The option is a:
         * <code>org.apache.camel.component.atomix.client.map.AtomixMap$Action</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder defaultAction(
                Action defaultAction) {
            doSetProperty("defaultAction", defaultAction);
            return this;
        }
        /**
         * The default action.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.atomix.client.map.AtomixMap$Action</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder defaultAction(
                String defaultAction) {
            doSetProperty("defaultAction", defaultAction);
            return this;
        }
        /**
         * The key to use if none is set in the header or to listen for events
         * for a specific key.
         * 
         * The option is a: <code>java.lang.Object</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder key(Object key) {
            doSetProperty("key", key);
            return this;
        }
        /**
         * The key to use if none is set in the header or to listen for events
         * for a specific key.
         * 
         * The option will be converted to a <code>java.lang.Object</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder key(String key) {
            doSetProperty("key", key);
            return this;
        }
        /**
         * The address of the nodes composing the cluster.
         * 
         * The option is a:
         * <code>java.util.List&lt;io.atomix.catalyst.transport.Address&gt;</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder nodes(List<Object> nodes) {
            doSetProperty("nodes", nodes);
            return this;
        }
        /**
         * The address of the nodes composing the cluster.
         * 
         * The option will be converted to a
         * <code>java.util.List&lt;io.atomix.catalyst.transport.Address&gt;</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder nodes(String nodes) {
            doSetProperty("nodes", nodes);
            return this;
        }
        /**
         * The header that wil carry the result.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder resultHeader(
                String resultHeader) {
            doSetProperty("resultHeader", resultHeader);
            return this;
        }
        /**
         * The class name (fqn) of the Atomix transport.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder transportClassName(
                String transportClassName) {
            doSetProperty("transportClassName", transportClassName);
            return this;
        }
        /**
         * The resource ttl.
         * 
         * The option is a: <code>long</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder ttl(long ttl) {
            doSetProperty("ttl", ttl);
            return this;
        }
        /**
         * The resource ttl.
         * 
         * The option will be converted to a <code>long</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointConsumerBuilder ttl(String ttl) {
            doSetProperty("ttl", ttl);
            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 AtomixMapEndpointConsumerBuilder 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 AtomixMapEndpointConsumerBuilder bridgeErrorHandler(
                String bridgeErrorHandler) {
            doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint consumers for the Atomix Map component.
     */
    public interface AdvancedAtomixMapEndpointConsumerBuilder
            extends
                EndpointConsumerBuilder {
        default AtomixMapEndpointConsumerBuilder basic() {
            return (AtomixMapEndpointConsumerBuilder) 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 AdvancedAtomixMapEndpointConsumerBuilder 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 AdvancedAtomixMapEndpointConsumerBuilder 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 AdvancedAtomixMapEndpointConsumerBuilder 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 AdvancedAtomixMapEndpointConsumerBuilder 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 AdvancedAtomixMapEndpointConsumerBuilder 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 AdvancedAtomixMapEndpointConsumerBuilder basicPropertyBinding(
                String basicPropertyBinding) {
            doSetProperty("basicPropertyBinding", basicPropertyBinding);
            return this;
        }
        /**
         * The cluster wide default resource configuration.
         * 
         * The option is a: <code>java.util.Properties</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointConsumerBuilder defaultResourceConfig(
                Properties defaultResourceConfig) {
            doSetProperty("defaultResourceConfig", defaultResourceConfig);
            return this;
        }
        /**
         * The cluster wide default resource configuration.
         * 
         * The option will be converted to a <code>java.util.Properties</code>
         * type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointConsumerBuilder defaultResourceConfig(
                String defaultResourceConfig) {
            doSetProperty("defaultResourceConfig", defaultResourceConfig);
            return this;
        }
        /**
         * The local default resource options.
         * 
         * The option is a: <code>java.util.Properties</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointConsumerBuilder defaultResourceOptions(
                Properties defaultResourceOptions) {
            doSetProperty("defaultResourceOptions", defaultResourceOptions);
            return this;
        }
        /**
         * The local default resource options.
         * 
         * The option will be converted to a <code>java.util.Properties</code>
         * type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointConsumerBuilder defaultResourceOptions(
                String defaultResourceOptions) {
            doSetProperty("defaultResourceOptions", defaultResourceOptions);
            return this;
        }
        /**
         * Sets if the local member should join groups as PersistentMember or
         * not. If set to ephemeral the local member will receive an auto
         * generated ID thus the local one is ignored.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointConsumerBuilder ephemeral(
                boolean ephemeral) {
            doSetProperty("ephemeral", ephemeral);
            return this;
        }
        /**
         * Sets if the local member should join groups as PersistentMember or
         * not. If set to ephemeral the local member will receive an auto
         * generated ID thus the local one is ignored.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointConsumerBuilder ephemeral(
                String ephemeral) {
            doSetProperty("ephemeral", ephemeral);
            return this;
        }
        /**
         * The read consistency level.
         * 
         * The option is a: <code>io.atomix.resource.ReadConsistency</code>
         * type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointConsumerBuilder readConsistency(
                ReadConsistency readConsistency) {
            doSetProperty("readConsistency", readConsistency);
            return this;
        }
        /**
         * The read consistency level.
         * 
         * The option will be converted to a
         * <code>io.atomix.resource.ReadConsistency</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointConsumerBuilder readConsistency(
                String readConsistency) {
            doSetProperty("readConsistency", readConsistency);
            return this;
        }
        /**
         * Cluster wide resources configuration.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.util.Properties&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointConsumerBuilder resourceConfigs(
                Map<String, Properties> resourceConfigs) {
            doSetProperty("resourceConfigs", resourceConfigs);
            return this;
        }
        /**
         * Cluster wide resources configuration.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String,
         * java.util.Properties&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointConsumerBuilder resourceConfigs(
                String resourceConfigs) {
            doSetProperty("resourceConfigs", resourceConfigs);
            return this;
        }
        /**
         * Local resources configurations.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.util.Properties&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointConsumerBuilder resourceOptions(
                Map<String, Properties> resourceOptions) {
            doSetProperty("resourceOptions", resourceOptions);
            return this;
        }
        /**
         * Local resources configurations.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String,
         * java.util.Properties&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointConsumerBuilder resourceOptions(
                String resourceOptions) {
            doSetProperty("resourceOptions", resourceOptions);
            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 AdvancedAtomixMapEndpointConsumerBuilder 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 AdvancedAtomixMapEndpointConsumerBuilder synchronous(
                String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
    }

    /**
     * Builder for endpoint producers for the Atomix Map component.
     */
    public interface AtomixMapEndpointProducerBuilder
            extends
                EndpointProducerBuilder {
        default AdvancedAtomixMapEndpointProducerBuilder advanced() {
            return (AdvancedAtomixMapEndpointProducerBuilder) this;
        }
        /**
         * The Atomix instance to use.
         * 
         * The option is a: <code>io.atomix.AtomixClient</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder atomix(Object atomix) {
            doSetProperty("atomix", atomix);
            return this;
        }
        /**
         * The Atomix instance to use.
         * 
         * The option will be converted to a <code>io.atomix.AtomixClient</code>
         * type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder atomix(String atomix) {
            doSetProperty("atomix", atomix);
            return this;
        }
        /**
         * The Atomix configuration uri.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder configurationUri(
                String configurationUri) {
            doSetProperty("configurationUri", configurationUri);
            return this;
        }
        /**
         * The default action.
         * 
         * The option is a:
         * <code>org.apache.camel.component.atomix.client.map.AtomixMap$Action</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder defaultAction(
                Action defaultAction) {
            doSetProperty("defaultAction", defaultAction);
            return this;
        }
        /**
         * The default action.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.atomix.client.map.AtomixMap$Action</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder defaultAction(
                String defaultAction) {
            doSetProperty("defaultAction", defaultAction);
            return this;
        }
        /**
         * The key to use if none is set in the header or to listen for events
         * for a specific key.
         * 
         * The option is a: <code>java.lang.Object</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder key(Object key) {
            doSetProperty("key", key);
            return this;
        }
        /**
         * The key to use if none is set in the header or to listen for events
         * for a specific key.
         * 
         * The option will be converted to a <code>java.lang.Object</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder key(String key) {
            doSetProperty("key", key);
            return this;
        }
        /**
         * The address of the nodes composing the cluster.
         * 
         * The option is a:
         * <code>java.util.List&lt;io.atomix.catalyst.transport.Address&gt;</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder nodes(List<Object> nodes) {
            doSetProperty("nodes", nodes);
            return this;
        }
        /**
         * The address of the nodes composing the cluster.
         * 
         * The option will be converted to a
         * <code>java.util.List&lt;io.atomix.catalyst.transport.Address&gt;</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder nodes(String nodes) {
            doSetProperty("nodes", nodes);
            return this;
        }
        /**
         * The header that wil carry the result.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder resultHeader(
                String resultHeader) {
            doSetProperty("resultHeader", resultHeader);
            return this;
        }
        /**
         * The class name (fqn) of the Atomix transport.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder transportClassName(
                String transportClassName) {
            doSetProperty("transportClassName", transportClassName);
            return this;
        }
        /**
         * The resource ttl.
         * 
         * The option is a: <code>long</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder ttl(long ttl) {
            doSetProperty("ttl", ttl);
            return this;
        }
        /**
         * The resource ttl.
         * 
         * The option will be converted to a <code>long</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointProducerBuilder ttl(String ttl) {
            doSetProperty("ttl", ttl);
            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 AtomixMapEndpointProducerBuilder 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 AtomixMapEndpointProducerBuilder lazyStartProducer(
                String lazyStartProducer) {
            doSetProperty("lazyStartProducer", lazyStartProducer);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint producers for the Atomix Map component.
     */
    public interface AdvancedAtomixMapEndpointProducerBuilder
            extends
                EndpointProducerBuilder {
        default AtomixMapEndpointProducerBuilder basic() {
            return (AtomixMapEndpointProducerBuilder) 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 AdvancedAtomixMapEndpointProducerBuilder 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 AdvancedAtomixMapEndpointProducerBuilder basicPropertyBinding(
                String basicPropertyBinding) {
            doSetProperty("basicPropertyBinding", basicPropertyBinding);
            return this;
        }
        /**
         * The cluster wide default resource configuration.
         * 
         * The option is a: <code>java.util.Properties</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointProducerBuilder defaultResourceConfig(
                Properties defaultResourceConfig) {
            doSetProperty("defaultResourceConfig", defaultResourceConfig);
            return this;
        }
        /**
         * The cluster wide default resource configuration.
         * 
         * The option will be converted to a <code>java.util.Properties</code>
         * type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointProducerBuilder defaultResourceConfig(
                String defaultResourceConfig) {
            doSetProperty("defaultResourceConfig", defaultResourceConfig);
            return this;
        }
        /**
         * The local default resource options.
         * 
         * The option is a: <code>java.util.Properties</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointProducerBuilder defaultResourceOptions(
                Properties defaultResourceOptions) {
            doSetProperty("defaultResourceOptions", defaultResourceOptions);
            return this;
        }
        /**
         * The local default resource options.
         * 
         * The option will be converted to a <code>java.util.Properties</code>
         * type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointProducerBuilder defaultResourceOptions(
                String defaultResourceOptions) {
            doSetProperty("defaultResourceOptions", defaultResourceOptions);
            return this;
        }
        /**
         * Sets if the local member should join groups as PersistentMember or
         * not. If set to ephemeral the local member will receive an auto
         * generated ID thus the local one is ignored.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointProducerBuilder ephemeral(
                boolean ephemeral) {
            doSetProperty("ephemeral", ephemeral);
            return this;
        }
        /**
         * Sets if the local member should join groups as PersistentMember or
         * not. If set to ephemeral the local member will receive an auto
         * generated ID thus the local one is ignored.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointProducerBuilder ephemeral(
                String ephemeral) {
            doSetProperty("ephemeral", ephemeral);
            return this;
        }
        /**
         * The read consistency level.
         * 
         * The option is a: <code>io.atomix.resource.ReadConsistency</code>
         * type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointProducerBuilder readConsistency(
                ReadConsistency readConsistency) {
            doSetProperty("readConsistency", readConsistency);
            return this;
        }
        /**
         * The read consistency level.
         * 
         * The option will be converted to a
         * <code>io.atomix.resource.ReadConsistency</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointProducerBuilder readConsistency(
                String readConsistency) {
            doSetProperty("readConsistency", readConsistency);
            return this;
        }
        /**
         * Cluster wide resources configuration.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.util.Properties&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointProducerBuilder resourceConfigs(
                Map<String, Properties> resourceConfigs) {
            doSetProperty("resourceConfigs", resourceConfigs);
            return this;
        }
        /**
         * Cluster wide resources configuration.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String,
         * java.util.Properties&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointProducerBuilder resourceConfigs(
                String resourceConfigs) {
            doSetProperty("resourceConfigs", resourceConfigs);
            return this;
        }
        /**
         * Local resources configurations.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.util.Properties&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointProducerBuilder resourceOptions(
                Map<String, Properties> resourceOptions) {
            doSetProperty("resourceOptions", resourceOptions);
            return this;
        }
        /**
         * Local resources configurations.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String,
         * java.util.Properties&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointProducerBuilder resourceOptions(
                String resourceOptions) {
            doSetProperty("resourceOptions", resourceOptions);
            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 AdvancedAtomixMapEndpointProducerBuilder 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 AdvancedAtomixMapEndpointProducerBuilder synchronous(
                String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
    }

    /**
     * Builder for endpoint for the Atomix Map component.
     */
    public interface AtomixMapEndpointBuilder
            extends
                AtomixMapEndpointConsumerBuilder, AtomixMapEndpointProducerBuilder {
        default AdvancedAtomixMapEndpointBuilder advanced() {
            return (AdvancedAtomixMapEndpointBuilder) this;
        }
        /**
         * The Atomix instance to use.
         * 
         * The option is a: <code>io.atomix.AtomixClient</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder atomix(Object atomix) {
            doSetProperty("atomix", atomix);
            return this;
        }
        /**
         * The Atomix instance to use.
         * 
         * The option will be converted to a <code>io.atomix.AtomixClient</code>
         * type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder atomix(String atomix) {
            doSetProperty("atomix", atomix);
            return this;
        }
        /**
         * The Atomix configuration uri.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder configurationUri(
                String configurationUri) {
            doSetProperty("configurationUri", configurationUri);
            return this;
        }
        /**
         * The default action.
         * 
         * The option is a:
         * <code>org.apache.camel.component.atomix.client.map.AtomixMap$Action</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder defaultAction(Action defaultAction) {
            doSetProperty("defaultAction", defaultAction);
            return this;
        }
        /**
         * The default action.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.atomix.client.map.AtomixMap$Action</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder defaultAction(String defaultAction) {
            doSetProperty("defaultAction", defaultAction);
            return this;
        }
        /**
         * The key to use if none is set in the header or to listen for events
         * for a specific key.
         * 
         * The option is a: <code>java.lang.Object</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder key(Object key) {
            doSetProperty("key", key);
            return this;
        }
        /**
         * The key to use if none is set in the header or to listen for events
         * for a specific key.
         * 
         * The option will be converted to a <code>java.lang.Object</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder key(String key) {
            doSetProperty("key", key);
            return this;
        }
        /**
         * The address of the nodes composing the cluster.
         * 
         * The option is a:
         * <code>java.util.List&lt;io.atomix.catalyst.transport.Address&gt;</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder nodes(List<Object> nodes) {
            doSetProperty("nodes", nodes);
            return this;
        }
        /**
         * The address of the nodes composing the cluster.
         * 
         * The option will be converted to a
         * <code>java.util.List&lt;io.atomix.catalyst.transport.Address&gt;</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder nodes(String nodes) {
            doSetProperty("nodes", nodes);
            return this;
        }
        /**
         * The header that wil carry the result.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder resultHeader(String resultHeader) {
            doSetProperty("resultHeader", resultHeader);
            return this;
        }
        /**
         * The class name (fqn) of the Atomix transport.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder transportClassName(
                String transportClassName) {
            doSetProperty("transportClassName", transportClassName);
            return this;
        }
        /**
         * The resource ttl.
         * 
         * The option is a: <code>long</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder ttl(long ttl) {
            doSetProperty("ttl", ttl);
            return this;
        }
        /**
         * The resource ttl.
         * 
         * The option will be converted to a <code>long</code> type.
         * 
         * Group: common
         */
        default AtomixMapEndpointBuilder ttl(String ttl) {
            doSetProperty("ttl", ttl);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint for the Atomix Map component.
     */
    public interface AdvancedAtomixMapEndpointBuilder
            extends
                AdvancedAtomixMapEndpointConsumerBuilder, AdvancedAtomixMapEndpointProducerBuilder {
        default AtomixMapEndpointBuilder basic() {
            return (AtomixMapEndpointBuilder) 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 AdvancedAtomixMapEndpointBuilder 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 AdvancedAtomixMapEndpointBuilder basicPropertyBinding(
                String basicPropertyBinding) {
            doSetProperty("basicPropertyBinding", basicPropertyBinding);
            return this;
        }
        /**
         * The cluster wide default resource configuration.
         * 
         * The option is a: <code>java.util.Properties</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointBuilder defaultResourceConfig(
                Properties defaultResourceConfig) {
            doSetProperty("defaultResourceConfig", defaultResourceConfig);
            return this;
        }
        /**
         * The cluster wide default resource configuration.
         * 
         * The option will be converted to a <code>java.util.Properties</code>
         * type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointBuilder defaultResourceConfig(
                String defaultResourceConfig) {
            doSetProperty("defaultResourceConfig", defaultResourceConfig);
            return this;
        }
        /**
         * The local default resource options.
         * 
         * The option is a: <code>java.util.Properties</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointBuilder defaultResourceOptions(
                Properties defaultResourceOptions) {
            doSetProperty("defaultResourceOptions", defaultResourceOptions);
            return this;
        }
        /**
         * The local default resource options.
         * 
         * The option will be converted to a <code>java.util.Properties</code>
         * type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointBuilder defaultResourceOptions(
                String defaultResourceOptions) {
            doSetProperty("defaultResourceOptions", defaultResourceOptions);
            return this;
        }
        /**
         * Sets if the local member should join groups as PersistentMember or
         * not. If set to ephemeral the local member will receive an auto
         * generated ID thus the local one is ignored.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointBuilder ephemeral(boolean ephemeral) {
            doSetProperty("ephemeral", ephemeral);
            return this;
        }
        /**
         * Sets if the local member should join groups as PersistentMember or
         * not. If set to ephemeral the local member will receive an auto
         * generated ID thus the local one is ignored.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointBuilder ephemeral(String ephemeral) {
            doSetProperty("ephemeral", ephemeral);
            return this;
        }
        /**
         * The read consistency level.
         * 
         * The option is a: <code>io.atomix.resource.ReadConsistency</code>
         * type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointBuilder readConsistency(
                ReadConsistency readConsistency) {
            doSetProperty("readConsistency", readConsistency);
            return this;
        }
        /**
         * The read consistency level.
         * 
         * The option will be converted to a
         * <code>io.atomix.resource.ReadConsistency</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointBuilder readConsistency(
                String readConsistency) {
            doSetProperty("readConsistency", readConsistency);
            return this;
        }
        /**
         * Cluster wide resources configuration.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.util.Properties&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointBuilder resourceConfigs(
                Map<String, Properties> resourceConfigs) {
            doSetProperty("resourceConfigs", resourceConfigs);
            return this;
        }
        /**
         * Cluster wide resources configuration.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String,
         * java.util.Properties&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointBuilder resourceConfigs(
                String resourceConfigs) {
            doSetProperty("resourceConfigs", resourceConfigs);
            return this;
        }
        /**
         * Local resources configurations.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.util.Properties&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointBuilder resourceOptions(
                Map<String, Properties> resourceOptions) {
            doSetProperty("resourceOptions", resourceOptions);
            return this;
        }
        /**
         * Local resources configurations.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String,
         * java.util.Properties&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedAtomixMapEndpointBuilder resourceOptions(
                String resourceOptions) {
            doSetProperty("resourceOptions", resourceOptions);
            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 AdvancedAtomixMapEndpointBuilder 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 AdvancedAtomixMapEndpointBuilder synchronous(String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
    }

    /**
     * Proxy enum for
     * <code>org.apache.camel.component.atomix.client.map.AtomixMap$Action</code> enum.
     */
    enum Action {
        PUT,
        PUT_IF_ABSENT,
        GET,
        CLEAR,
        SIZE,
        CONTAINS_KEY,
        CONTAINS_VALUE,
        IS_EMPTY,
        ENTRY_SET,
        REMOVE,
        REPLACE,
        VALUES;
    }

    /**
     * Proxy enum for <code>io.atomix.resource.ReadConsistency</code> enum.
     */
    enum ReadConsistency {
        ATOMIC,
        ATOMIC_LEASE,
        SEQUENTIAL,
        LOCAL;
    }
    /**
     * Atomix Map (camel-atomix)
     * The atomix-map component is used to access Atomix's distributed map.
     * 
     * Category: clustering
     * Since: 2.20
     * Maven coordinates: org.apache.camel:camel-atomix
     * 
     * Syntax: <code>atomix-map:resourceName</code>
     * 
     * Path parameter: resourceName (required)
     * The distributed resource name
     */
    default AtomixMapEndpointBuilder atomixMap(String path) {
        class AtomixMapEndpointBuilderImpl extends AbstractEndpointBuilder implements AtomixMapEndpointBuilder, AdvancedAtomixMapEndpointBuilder {
            public AtomixMapEndpointBuilderImpl(String path) {
                super("atomix-map", path);
            }
        }
        return new AtomixMapEndpointBuilderImpl(path);
    }
}