/*
 * 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.Map;
import javax.annotation.Generated;
import org.apache.camel.builder.EndpointConsumerBuilder;
import org.apache.camel.builder.EndpointProducerBuilder;
import org.apache.camel.builder.endpoint.AbstractEndpointBuilder;
import org.apache.camel.spi.HeaderFilterStrategy;

/**
 * To exchange data with external Websocket servers using Async Http Client.
 * 
 * Generated by camel-package-maven-plugin - do not edit this file!
 */
@Generated("org.apache.camel.maven.packaging.EndpointDslMojo")
public interface WsEndpointBuilderFactory {


    /**
     * Builder for endpoint consumers for the AHC Websocket component.
     */
    public interface WsEndpointConsumerBuilder
            extends
                EndpointConsumerBuilder {
        default AdvancedWsEndpointConsumerBuilder advanced() {
            return (AdvancedWsEndpointConsumerBuilder) this;
        }
        /**
         * Whether to send an message if the web-socket listener received an
         * error.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: consumer
         */
        default WsEndpointConsumerBuilder sendMessageOnError(
                boolean sendMessageOnError) {
            doSetProperty("sendMessageOnError", sendMessageOnError);
            return this;
        }
        /**
         * Whether to send an message if the web-socket listener received an
         * error.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: consumer
         */
        default WsEndpointConsumerBuilder sendMessageOnError(
                String sendMessageOnError) {
            doSetProperty("sendMessageOnError", sendMessageOnError);
            return this;
        }
        /**
         * If the option is true, then the Exchange.HTTP_URI header is ignored,
         * and use the endpoint's URI for request. You may also set the
         * throwExceptionOnFailure to be false to let the AhcProducer send all
         * the fault response back.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointConsumerBuilder bridgeEndpoint(boolean bridgeEndpoint) {
            doSetProperty("bridgeEndpoint", bridgeEndpoint);
            return this;
        }
        /**
         * If the option is true, then the Exchange.HTTP_URI header is ignored,
         * and use the endpoint's URI for request. You may also set the
         * throwExceptionOnFailure to be false to let the AhcProducer send all
         * the fault response back.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointConsumerBuilder bridgeEndpoint(String bridgeEndpoint) {
            doSetProperty("bridgeEndpoint", bridgeEndpoint);
            return this;
        }
        /**
         * The initial in-memory buffer size used when transferring data between
         * Camel and AHC Client.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: producer
         */
        default WsEndpointConsumerBuilder bufferSize(int bufferSize) {
            doSetProperty("bufferSize", bufferSize);
            return this;
        }
        /**
         * The initial in-memory buffer size used when transferring data between
         * Camel and AHC Client.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: producer
         */
        default WsEndpointConsumerBuilder bufferSize(String bufferSize) {
            doSetProperty("bufferSize", bufferSize);
            return this;
        }
        /**
         * To use a custom HeaderFilterStrategy to filter header to and from
         * Camel message.
         * 
         * The option is a:
         * <code>org.apache.camel.spi.HeaderFilterStrategy</code> type.
         * 
         * Group: producer
         */
        default WsEndpointConsumerBuilder headerFilterStrategy(
                HeaderFilterStrategy headerFilterStrategy) {
            doSetProperty("headerFilterStrategy", headerFilterStrategy);
            return this;
        }
        /**
         * To use a custom HeaderFilterStrategy to filter header to and from
         * Camel message.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.spi.HeaderFilterStrategy</code> type.
         * 
         * Group: producer
         */
        default WsEndpointConsumerBuilder headerFilterStrategy(
                String headerFilterStrategy) {
            doSetProperty("headerFilterStrategy", headerFilterStrategy);
            return this;
        }
        /**
         * Option to disable throwing the AhcOperationFailedException in case of
         * failed responses from the remote server. This allows you to get all
         * responses regardless of the HTTP status code.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointConsumerBuilder throwExceptionOnFailure(
                boolean throwExceptionOnFailure) {
            doSetProperty("throwExceptionOnFailure", throwExceptionOnFailure);
            return this;
        }
        /**
         * Option to disable throwing the AhcOperationFailedException in case of
         * failed responses from the remote server. This allows you to get all
         * responses regardless of the HTTP status code.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointConsumerBuilder throwExceptionOnFailure(
                String throwExceptionOnFailure) {
            doSetProperty("throwExceptionOnFailure", throwExceptionOnFailure);
            return this;
        }
        /**
         * If enabled and an Exchange failed processing on the consumer side,
         * and if the caused Exception was send back serialized in the response
         * as a application/x-java-serialized-object content type (for example
         * using Jetty or Servlet Camel components). On the producer side the
         * exception will be deserialized and thrown as is, instead of the
         * AhcOperationFailedException. The caused exception is required to be
         * serialized. This is by default turned off. If you enable this then be
         * aware that Java will deserialize the incoming data from the request
         * to Java and that can be a potential security risk.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointConsumerBuilder transferException(
                boolean transferException) {
            doSetProperty("transferException", transferException);
            return this;
        }
        /**
         * If enabled and an Exchange failed processing on the consumer side,
         * and if the caused Exception was send back serialized in the response
         * as a application/x-java-serialized-object content type (for example
         * using Jetty or Servlet Camel components). On the producer side the
         * exception will be deserialized and thrown as is, instead of the
         * AhcOperationFailedException. The caused exception is required to be
         * serialized. This is by default turned off. If you enable this then be
         * aware that Java will deserialize the incoming data from the request
         * to Java and that can be a potential security risk.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointConsumerBuilder transferException(
                String transferException) {
            doSetProperty("transferException", transferException);
            return this;
        }
        /**
         * Reference to a org.apache.camel.support.jsse.SSLContextParameters in
         * the Registry. This reference overrides any configured
         * SSLContextParameters at the component level. See Using the JSSE
         * Configuration Utility. Note that configuring this option will
         * override any SSL/TLS configuration options provided through the
         * clientConfig option at the endpoint or component level.
         * 
         * The option is a:
         * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
         * 
         * Group: security
         */
        default WsEndpointConsumerBuilder sslContextParameters(
                Object sslContextParameters) {
            doSetProperty("sslContextParameters", sslContextParameters);
            return this;
        }
        /**
         * Reference to a org.apache.camel.support.jsse.SSLContextParameters in
         * the Registry. This reference overrides any configured
         * SSLContextParameters at the component level. See Using the JSSE
         * Configuration Utility. Note that configuring this option will
         * override any SSL/TLS configuration options provided through the
         * clientConfig option at the endpoint or component level.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
         * 
         * Group: security
         */
        default WsEndpointConsumerBuilder sslContextParameters(
                String sslContextParameters) {
            doSetProperty("sslContextParameters", sslContextParameters);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint consumers for the AHC Websocket component.
     */
    public interface AdvancedWsEndpointConsumerBuilder
            extends
                EndpointConsumerBuilder {
        default WsEndpointConsumerBuilder basic() {
            return (WsEndpointConsumerBuilder) 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 AdvancedWsEndpointConsumerBuilder 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 AdvancedWsEndpointConsumerBuilder basicPropertyBinding(
                String basicPropertyBinding) {
            doSetProperty("basicPropertyBinding", basicPropertyBinding);
            return this;
        }
        /**
         * To use a custom AhcBinding which allows to control how to bind
         * between AHC and Camel.
         * 
         * The option is a:
         * <code>org.apache.camel.component.ahc.AhcBinding</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointConsumerBuilder binding(Object binding) {
            doSetProperty("binding", binding);
            return this;
        }
        /**
         * To use a custom AhcBinding which allows to control how to bind
         * between AHC and Camel.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.ahc.AhcBinding</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointConsumerBuilder binding(String binding) {
            doSetProperty("binding", binding);
            return this;
        }
        /**
         * To configure the AsyncHttpClient to use a custom
         * com.ning.http.client.AsyncHttpClientConfig instance.
         * 
         * The option is a:
         * <code>org.asynchttpclient.AsyncHttpClientConfig</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointConsumerBuilder clientConfig(
                Object clientConfig) {
            doSetProperty("clientConfig", clientConfig);
            return this;
        }
        /**
         * To configure the AsyncHttpClient to use a custom
         * com.ning.http.client.AsyncHttpClientConfig instance.
         * 
         * The option will be converted to a
         * <code>org.asynchttpclient.AsyncHttpClientConfig</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointConsumerBuilder clientConfig(
                String clientConfig) {
            doSetProperty("clientConfig", clientConfig);
            return this;
        }
        /**
         * To configure the AsyncHttpClientConfig using the key/values from the
         * Map.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.lang.Object&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointConsumerBuilder clientConfigOptions(
                Map<String, Object> clientConfigOptions) {
            doSetProperty("clientConfigOptions", clientConfigOptions);
            return this;
        }
        /**
         * To configure the AsyncHttpClientConfig using the key/values from the
         * Map.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String, java.lang.Object&gt;</code>
         * type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointConsumerBuilder clientConfigOptions(
                String clientConfigOptions) {
            doSetProperty("clientConfigOptions", clientConfigOptions);
            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 AdvancedWsEndpointConsumerBuilder 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 AdvancedWsEndpointConsumerBuilder synchronous(String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
        /**
         * To configure the AsyncHttpClientConfig Realm using the key/values
         * from the Map.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.lang.Object&gt;</code> type.
         * 
         * Group: security
         */
        default AdvancedWsEndpointConsumerBuilder clientConfigRealmOptions(
                Map<String, Object> clientConfigRealmOptions) {
            doSetProperty("clientConfigRealmOptions", clientConfigRealmOptions);
            return this;
        }
        /**
         * To configure the AsyncHttpClientConfig Realm using the key/values
         * from the Map.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String, java.lang.Object&gt;</code>
         * type.
         * 
         * Group: security
         */
        default AdvancedWsEndpointConsumerBuilder clientConfigRealmOptions(
                String clientConfigRealmOptions) {
            doSetProperty("clientConfigRealmOptions", clientConfigRealmOptions);
            return this;
        }
    }

    /**
     * Builder for endpoint producers for the AHC Websocket component.
     */
    public interface WsEndpointProducerBuilder
            extends
                EndpointProducerBuilder {
        default AdvancedWsEndpointProducerBuilder advanced() {
            return (AdvancedWsEndpointProducerBuilder) this;
        }
        /**
         * To enable streaming to send data as multiple text fragments.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder useStreaming(boolean useStreaming) {
            doSetProperty("useStreaming", useStreaming);
            return this;
        }
        /**
         * To enable streaming to send data as multiple text fragments.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder useStreaming(String useStreaming) {
            doSetProperty("useStreaming", useStreaming);
            return this;
        }
        /**
         * If the option is true, then the Exchange.HTTP_URI header is ignored,
         * and use the endpoint's URI for request. You may also set the
         * throwExceptionOnFailure to be false to let the AhcProducer send all
         * the fault response back.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder bridgeEndpoint(boolean bridgeEndpoint) {
            doSetProperty("bridgeEndpoint", bridgeEndpoint);
            return this;
        }
        /**
         * If the option is true, then the Exchange.HTTP_URI header is ignored,
         * and use the endpoint's URI for request. You may also set the
         * throwExceptionOnFailure to be false to let the AhcProducer send all
         * the fault response back.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder bridgeEndpoint(String bridgeEndpoint) {
            doSetProperty("bridgeEndpoint", bridgeEndpoint);
            return this;
        }
        /**
         * The initial in-memory buffer size used when transferring data between
         * Camel and AHC Client.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder bufferSize(int bufferSize) {
            doSetProperty("bufferSize", bufferSize);
            return this;
        }
        /**
         * The initial in-memory buffer size used when transferring data between
         * Camel and AHC Client.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder bufferSize(String bufferSize) {
            doSetProperty("bufferSize", bufferSize);
            return this;
        }
        /**
         * Define if the Connection Close header has to be added to HTTP
         * Request. This parameter is false by default.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder connectionClose(
                boolean connectionClose) {
            doSetProperty("connectionClose", connectionClose);
            return this;
        }
        /**
         * Define if the Connection Close header has to be added to HTTP
         * Request. This parameter is false by default.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder connectionClose(String connectionClose) {
            doSetProperty("connectionClose", connectionClose);
            return this;
        }
        /**
         * Configure a cookie handler to maintain a HTTP session.
         * 
         * The option is a:
         * <code>org.apache.camel.http.common.cookie.CookieHandler</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder cookieHandler(Object cookieHandler) {
            doSetProperty("cookieHandler", cookieHandler);
            return this;
        }
        /**
         * Configure a cookie handler to maintain a HTTP session.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.http.common.cookie.CookieHandler</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder cookieHandler(String cookieHandler) {
            doSetProperty("cookieHandler", cookieHandler);
            return this;
        }
        /**
         * To use a custom HeaderFilterStrategy to filter header to and from
         * Camel message.
         * 
         * The option is a:
         * <code>org.apache.camel.spi.HeaderFilterStrategy</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder headerFilterStrategy(
                HeaderFilterStrategy headerFilterStrategy) {
            doSetProperty("headerFilterStrategy", headerFilterStrategy);
            return this;
        }
        /**
         * To use a custom HeaderFilterStrategy to filter header to and from
         * Camel message.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.spi.HeaderFilterStrategy</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder headerFilterStrategy(
                String headerFilterStrategy) {
            doSetProperty("headerFilterStrategy", headerFilterStrategy);
            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 WsEndpointProducerBuilder 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 WsEndpointProducerBuilder lazyStartProducer(
                String lazyStartProducer) {
            doSetProperty("lazyStartProducer", lazyStartProducer);
            return this;
        }
        /**
         * Option to disable throwing the AhcOperationFailedException in case of
         * failed responses from the remote server. This allows you to get all
         * responses regardless of the HTTP status code.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder throwExceptionOnFailure(
                boolean throwExceptionOnFailure) {
            doSetProperty("throwExceptionOnFailure", throwExceptionOnFailure);
            return this;
        }
        /**
         * Option to disable throwing the AhcOperationFailedException in case of
         * failed responses from the remote server. This allows you to get all
         * responses regardless of the HTTP status code.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder throwExceptionOnFailure(
                String throwExceptionOnFailure) {
            doSetProperty("throwExceptionOnFailure", throwExceptionOnFailure);
            return this;
        }
        /**
         * If enabled and an Exchange failed processing on the consumer side,
         * and if the caused Exception was send back serialized in the response
         * as a application/x-java-serialized-object content type (for example
         * using Jetty or Servlet Camel components). On the producer side the
         * exception will be deserialized and thrown as is, instead of the
         * AhcOperationFailedException. The caused exception is required to be
         * serialized. This is by default turned off. If you enable this then be
         * aware that Java will deserialize the incoming data from the request
         * to Java and that can be a potential security risk.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder transferException(
                boolean transferException) {
            doSetProperty("transferException", transferException);
            return this;
        }
        /**
         * If enabled and an Exchange failed processing on the consumer side,
         * and if the caused Exception was send back serialized in the response
         * as a application/x-java-serialized-object content type (for example
         * using Jetty or Servlet Camel components). On the producer side the
         * exception will be deserialized and thrown as is, instead of the
         * AhcOperationFailedException. The caused exception is required to be
         * serialized. This is by default turned off. If you enable this then be
         * aware that Java will deserialize the incoming data from the request
         * to Java and that can be a potential security risk.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointProducerBuilder transferException(
                String transferException) {
            doSetProperty("transferException", transferException);
            return this;
        }
        /**
         * Reference to a org.apache.camel.support.jsse.SSLContextParameters in
         * the Registry. This reference overrides any configured
         * SSLContextParameters at the component level. See Using the JSSE
         * Configuration Utility. Note that configuring this option will
         * override any SSL/TLS configuration options provided through the
         * clientConfig option at the endpoint or component level.
         * 
         * The option is a:
         * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
         * 
         * Group: security
         */
        default WsEndpointProducerBuilder sslContextParameters(
                Object sslContextParameters) {
            doSetProperty("sslContextParameters", sslContextParameters);
            return this;
        }
        /**
         * Reference to a org.apache.camel.support.jsse.SSLContextParameters in
         * the Registry. This reference overrides any configured
         * SSLContextParameters at the component level. See Using the JSSE
         * Configuration Utility. Note that configuring this option will
         * override any SSL/TLS configuration options provided through the
         * clientConfig option at the endpoint or component level.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
         * 
         * Group: security
         */
        default WsEndpointProducerBuilder sslContextParameters(
                String sslContextParameters) {
            doSetProperty("sslContextParameters", sslContextParameters);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint producers for the AHC Websocket component.
     */
    public interface AdvancedWsEndpointProducerBuilder
            extends
                EndpointProducerBuilder {
        default WsEndpointProducerBuilder basic() {
            return (WsEndpointProducerBuilder) 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 AdvancedWsEndpointProducerBuilder 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 AdvancedWsEndpointProducerBuilder basicPropertyBinding(
                String basicPropertyBinding) {
            doSetProperty("basicPropertyBinding", basicPropertyBinding);
            return this;
        }
        /**
         * To use a custom AhcBinding which allows to control how to bind
         * between AHC and Camel.
         * 
         * The option is a:
         * <code>org.apache.camel.component.ahc.AhcBinding</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointProducerBuilder binding(Object binding) {
            doSetProperty("binding", binding);
            return this;
        }
        /**
         * To use a custom AhcBinding which allows to control how to bind
         * between AHC and Camel.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.ahc.AhcBinding</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointProducerBuilder binding(String binding) {
            doSetProperty("binding", binding);
            return this;
        }
        /**
         * To configure the AsyncHttpClient to use a custom
         * com.ning.http.client.AsyncHttpClientConfig instance.
         * 
         * The option is a:
         * <code>org.asynchttpclient.AsyncHttpClientConfig</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointProducerBuilder clientConfig(
                Object clientConfig) {
            doSetProperty("clientConfig", clientConfig);
            return this;
        }
        /**
         * To configure the AsyncHttpClient to use a custom
         * com.ning.http.client.AsyncHttpClientConfig instance.
         * 
         * The option will be converted to a
         * <code>org.asynchttpclient.AsyncHttpClientConfig</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointProducerBuilder clientConfig(
                String clientConfig) {
            doSetProperty("clientConfig", clientConfig);
            return this;
        }
        /**
         * To configure the AsyncHttpClientConfig using the key/values from the
         * Map.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.lang.Object&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointProducerBuilder clientConfigOptions(
                Map<String, Object> clientConfigOptions) {
            doSetProperty("clientConfigOptions", clientConfigOptions);
            return this;
        }
        /**
         * To configure the AsyncHttpClientConfig using the key/values from the
         * Map.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String, java.lang.Object&gt;</code>
         * type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointProducerBuilder clientConfigOptions(
                String clientConfigOptions) {
            doSetProperty("clientConfigOptions", clientConfigOptions);
            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 AdvancedWsEndpointProducerBuilder 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 AdvancedWsEndpointProducerBuilder synchronous(String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
        /**
         * To configure the AsyncHttpClientConfig Realm using the key/values
         * from the Map.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.lang.Object&gt;</code> type.
         * 
         * Group: security
         */
        default AdvancedWsEndpointProducerBuilder clientConfigRealmOptions(
                Map<String, Object> clientConfigRealmOptions) {
            doSetProperty("clientConfigRealmOptions", clientConfigRealmOptions);
            return this;
        }
        /**
         * To configure the AsyncHttpClientConfig Realm using the key/values
         * from the Map.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String, java.lang.Object&gt;</code>
         * type.
         * 
         * Group: security
         */
        default AdvancedWsEndpointProducerBuilder clientConfigRealmOptions(
                String clientConfigRealmOptions) {
            doSetProperty("clientConfigRealmOptions", clientConfigRealmOptions);
            return this;
        }
    }

    /**
     * Builder for endpoint for the AHC Websocket component.
     */
    public interface WsEndpointBuilder
            extends
                WsEndpointConsumerBuilder, WsEndpointProducerBuilder {
        default AdvancedWsEndpointBuilder advanced() {
            return (AdvancedWsEndpointBuilder) this;
        }
        /**
         * If the option is true, then the Exchange.HTTP_URI header is ignored,
         * and use the endpoint's URI for request. You may also set the
         * throwExceptionOnFailure to be false to let the AhcProducer send all
         * the fault response back.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointBuilder bridgeEndpoint(boolean bridgeEndpoint) {
            doSetProperty("bridgeEndpoint", bridgeEndpoint);
            return this;
        }
        /**
         * If the option is true, then the Exchange.HTTP_URI header is ignored,
         * and use the endpoint's URI for request. You may also set the
         * throwExceptionOnFailure to be false to let the AhcProducer send all
         * the fault response back.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointBuilder bridgeEndpoint(String bridgeEndpoint) {
            doSetProperty("bridgeEndpoint", bridgeEndpoint);
            return this;
        }
        /**
         * The initial in-memory buffer size used when transferring data between
         * Camel and AHC Client.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: producer
         */
        default WsEndpointBuilder bufferSize(int bufferSize) {
            doSetProperty("bufferSize", bufferSize);
            return this;
        }
        /**
         * The initial in-memory buffer size used when transferring data between
         * Camel and AHC Client.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: producer
         */
        default WsEndpointBuilder bufferSize(String bufferSize) {
            doSetProperty("bufferSize", bufferSize);
            return this;
        }
        /**
         * To use a custom HeaderFilterStrategy to filter header to and from
         * Camel message.
         * 
         * The option is a:
         * <code>org.apache.camel.spi.HeaderFilterStrategy</code> type.
         * 
         * Group: producer
         */
        default WsEndpointBuilder headerFilterStrategy(
                HeaderFilterStrategy headerFilterStrategy) {
            doSetProperty("headerFilterStrategy", headerFilterStrategy);
            return this;
        }
        /**
         * To use a custom HeaderFilterStrategy to filter header to and from
         * Camel message.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.spi.HeaderFilterStrategy</code> type.
         * 
         * Group: producer
         */
        default WsEndpointBuilder headerFilterStrategy(
                String headerFilterStrategy) {
            doSetProperty("headerFilterStrategy", headerFilterStrategy);
            return this;
        }
        /**
         * Option to disable throwing the AhcOperationFailedException in case of
         * failed responses from the remote server. This allows you to get all
         * responses regardless of the HTTP status code.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointBuilder throwExceptionOnFailure(
                boolean throwExceptionOnFailure) {
            doSetProperty("throwExceptionOnFailure", throwExceptionOnFailure);
            return this;
        }
        /**
         * Option to disable throwing the AhcOperationFailedException in case of
         * failed responses from the remote server. This allows you to get all
         * responses regardless of the HTTP status code.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointBuilder throwExceptionOnFailure(
                String throwExceptionOnFailure) {
            doSetProperty("throwExceptionOnFailure", throwExceptionOnFailure);
            return this;
        }
        /**
         * If enabled and an Exchange failed processing on the consumer side,
         * and if the caused Exception was send back serialized in the response
         * as a application/x-java-serialized-object content type (for example
         * using Jetty or Servlet Camel components). On the producer side the
         * exception will be deserialized and thrown as is, instead of the
         * AhcOperationFailedException. The caused exception is required to be
         * serialized. This is by default turned off. If you enable this then be
         * aware that Java will deserialize the incoming data from the request
         * to Java and that can be a potential security risk.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointBuilder transferException(boolean transferException) {
            doSetProperty("transferException", transferException);
            return this;
        }
        /**
         * If enabled and an Exchange failed processing on the consumer side,
         * and if the caused Exception was send back serialized in the response
         * as a application/x-java-serialized-object content type (for example
         * using Jetty or Servlet Camel components). On the producer side the
         * exception will be deserialized and thrown as is, instead of the
         * AhcOperationFailedException. The caused exception is required to be
         * serialized. This is by default turned off. If you enable this then be
         * aware that Java will deserialize the incoming data from the request
         * to Java and that can be a potential security risk.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default WsEndpointBuilder transferException(String transferException) {
            doSetProperty("transferException", transferException);
            return this;
        }
        /**
         * Reference to a org.apache.camel.support.jsse.SSLContextParameters in
         * the Registry. This reference overrides any configured
         * SSLContextParameters at the component level. See Using the JSSE
         * Configuration Utility. Note that configuring this option will
         * override any SSL/TLS configuration options provided through the
         * clientConfig option at the endpoint or component level.
         * 
         * The option is a:
         * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
         * 
         * Group: security
         */
        default WsEndpointBuilder sslContextParameters(
                Object sslContextParameters) {
            doSetProperty("sslContextParameters", sslContextParameters);
            return this;
        }
        /**
         * Reference to a org.apache.camel.support.jsse.SSLContextParameters in
         * the Registry. This reference overrides any configured
         * SSLContextParameters at the component level. See Using the JSSE
         * Configuration Utility. Note that configuring this option will
         * override any SSL/TLS configuration options provided through the
         * clientConfig option at the endpoint or component level.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.support.jsse.SSLContextParameters</code> type.
         * 
         * Group: security
         */
        default WsEndpointBuilder sslContextParameters(
                String sslContextParameters) {
            doSetProperty("sslContextParameters", sslContextParameters);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint for the AHC Websocket component.
     */
    public interface AdvancedWsEndpointBuilder
            extends
                AdvancedWsEndpointConsumerBuilder, AdvancedWsEndpointProducerBuilder {
        default WsEndpointBuilder basic() {
            return (WsEndpointBuilder) 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 AdvancedWsEndpointBuilder 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 AdvancedWsEndpointBuilder basicPropertyBinding(
                String basicPropertyBinding) {
            doSetProperty("basicPropertyBinding", basicPropertyBinding);
            return this;
        }
        /**
         * To use a custom AhcBinding which allows to control how to bind
         * between AHC and Camel.
         * 
         * The option is a:
         * <code>org.apache.camel.component.ahc.AhcBinding</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointBuilder binding(Object binding) {
            doSetProperty("binding", binding);
            return this;
        }
        /**
         * To use a custom AhcBinding which allows to control how to bind
         * between AHC and Camel.
         * 
         * The option will be converted to a
         * <code>org.apache.camel.component.ahc.AhcBinding</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointBuilder binding(String binding) {
            doSetProperty("binding", binding);
            return this;
        }
        /**
         * To configure the AsyncHttpClient to use a custom
         * com.ning.http.client.AsyncHttpClientConfig instance.
         * 
         * The option is a:
         * <code>org.asynchttpclient.AsyncHttpClientConfig</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointBuilder clientConfig(Object clientConfig) {
            doSetProperty("clientConfig", clientConfig);
            return this;
        }
        /**
         * To configure the AsyncHttpClient to use a custom
         * com.ning.http.client.AsyncHttpClientConfig instance.
         * 
         * The option will be converted to a
         * <code>org.asynchttpclient.AsyncHttpClientConfig</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointBuilder clientConfig(String clientConfig) {
            doSetProperty("clientConfig", clientConfig);
            return this;
        }
        /**
         * To configure the AsyncHttpClientConfig using the key/values from the
         * Map.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.lang.Object&gt;</code> type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointBuilder clientConfigOptions(
                Map<String, Object> clientConfigOptions) {
            doSetProperty("clientConfigOptions", clientConfigOptions);
            return this;
        }
        /**
         * To configure the AsyncHttpClientConfig using the key/values from the
         * Map.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String, java.lang.Object&gt;</code>
         * type.
         * 
         * Group: advanced
         */
        default AdvancedWsEndpointBuilder clientConfigOptions(
                String clientConfigOptions) {
            doSetProperty("clientConfigOptions", clientConfigOptions);
            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 AdvancedWsEndpointBuilder 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 AdvancedWsEndpointBuilder synchronous(String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
        /**
         * To configure the AsyncHttpClientConfig Realm using the key/values
         * from the Map.
         * 
         * The option is a: <code>java.util.Map&lt;java.lang.String,
         * java.lang.Object&gt;</code> type.
         * 
         * Group: security
         */
        default AdvancedWsEndpointBuilder clientConfigRealmOptions(
                Map<String, Object> clientConfigRealmOptions) {
            doSetProperty("clientConfigRealmOptions", clientConfigRealmOptions);
            return this;
        }
        /**
         * To configure the AsyncHttpClientConfig Realm using the key/values
         * from the Map.
         * 
         * The option will be converted to a
         * <code>java.util.Map&lt;java.lang.String, java.lang.Object&gt;</code>
         * type.
         * 
         * Group: security
         */
        default AdvancedWsEndpointBuilder clientConfigRealmOptions(
                String clientConfigRealmOptions) {
            doSetProperty("clientConfigRealmOptions", clientConfigRealmOptions);
            return this;
        }
    }
    /**
     * AHC Websocket (camel-ahc-ws)
     * To exchange data with external Websocket servers using Async Http Client.
     * 
     * Category: websocket
     * Since: 2.14
     * Maven coordinates: org.apache.camel:camel-ahc-ws
     * 
     * Syntax: <code>ahc-ws:httpUri</code>
     * 
     * Path parameter: httpUri (required)
     * The URI to use such as http://hostname:port/path
     */
    default WsEndpointBuilder ahcWs(String path) {
        return ahcWs("ahc-ws", path);
    }
    /**
     * AHC Secure Websocket (Secure) (camel-ahc-ws)
     * To exchange data with external Websocket servers using Async Http Client.
     * 
     * Category: websocket
     * Since: 2.14
     * Maven coordinates: org.apache.camel:camel-ahc-ws
     * 
     * Syntax: <code>ahc-wss:httpUri</code>
     * 
     * Path parameter: httpUri (required)
     * The URI to use such as http://hostname:port/path
     */
    default WsEndpointBuilder ahcWss(String path) {
        return ahcWs("ahc-wss", path);
    }
    /**
     * AHC Websocket (camel-ahc-ws)
     * To exchange data with external Websocket servers using Async Http Client.
     * 
     * Category: websocket
     * Since: 2.14
     * Maven coordinates: org.apache.camel:camel-ahc-ws
     */
    default WsEndpointBuilder ahcWs(String scheme, String path) {
        class WsEndpointBuilderImpl extends AbstractEndpointBuilder implements WsEndpointBuilder, AdvancedWsEndpointBuilder {
            public WsEndpointBuilderImpl(String scheme, String path) {
                super(scheme, path);
            }
        }
        return new WsEndpointBuilderImpl(scheme, path);
    }
}