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

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

/**
 * The cometd component is a transport for working with the Jetty implementation
 * of the cometd/bayeux protocol.
 * 
 * Generated by camel-package-maven-plugin - do not edit this file!
 */
@Generated("org.apache.camel.maven.packaging.EndpointDslMojo")
public interface CometdEndpointBuilderFactory {


    /**
     * Builder for endpoint consumers for the CometD component.
     */
    public interface CometdEndpointConsumerBuilder
            extends
                EndpointConsumerBuilder {
        default AdvancedCometdEndpointConsumerBuilder advanced() {
            return (AdvancedCometdEndpointConsumerBuilder) this;
        }
        /**
         * The origins domain that support to cross, if the crosssOriginFilterOn
         * is true.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder allowedOrigins(
                String allowedOrigins) {
            doSetProperty("allowedOrigins", allowedOrigins);
            return this;
        }
        /**
         * The root directory for the web resources or classpath. Use the
         * protocol file: or classpath: depending if you want that the component
         * loads the resource from file system or classpath. Classpath is
         * required for OSGI deployment where the resources are packaged in the
         * jar.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder baseResource(String baseResource) {
            doSetProperty("baseResource", baseResource);
            return this;
        }
        /**
         * If true, the server will support for cross-domain filtering.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder crossOriginFilterOn(
                boolean crossOriginFilterOn) {
            doSetProperty("crossOriginFilterOn", crossOriginFilterOn);
            return this;
        }
        /**
         * If true, the server will support for cross-domain filtering.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder crossOriginFilterOn(
                String crossOriginFilterOn) {
            doSetProperty("crossOriginFilterOn", crossOriginFilterOn);
            return this;
        }
        /**
         * The filterPath will be used by the CrossOriginFilter, if the
         * crosssOriginFilterOn is true.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder filterPath(String filterPath) {
            doSetProperty("filterPath", filterPath);
            return this;
        }
        /**
         * The client side poll timeout in milliseconds. How long a client will
         * wait between reconnects.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder interval(int interval) {
            doSetProperty("interval", interval);
            return this;
        }
        /**
         * The client side poll timeout in milliseconds. How long a client will
         * wait between reconnects.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder interval(String interval) {
            doSetProperty("interval", interval);
            return this;
        }
        /**
         * If true, the server will accept JSON wrapped in a comment and will
         * generate JSON wrapped in a comment. This is a defence against Ajax
         * Hijacking.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder jsonCommented(
                boolean jsonCommented) {
            doSetProperty("jsonCommented", jsonCommented);
            return this;
        }
        /**
         * If true, the server will accept JSON wrapped in a comment and will
         * generate JSON wrapped in a comment. This is a defence against Ajax
         * Hijacking.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder jsonCommented(String jsonCommented) {
            doSetProperty("jsonCommented", jsonCommented);
            return this;
        }
        /**
         * Logging level. 0=none, 1=info, 2=debug.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder logLevel(int logLevel) {
            doSetProperty("logLevel", logLevel);
            return this;
        }
        /**
         * Logging level. 0=none, 1=info, 2=debug.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder logLevel(String logLevel) {
            doSetProperty("logLevel", logLevel);
            return this;
        }
        /**
         * The max client side poll timeout in milliseconds. A client will be
         * removed if a connection is not received in this time.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder maxInterval(int maxInterval) {
            doSetProperty("maxInterval", maxInterval);
            return this;
        }
        /**
         * The max client side poll timeout in milliseconds. A client will be
         * removed if a connection is not received in this time.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder maxInterval(String maxInterval) {
            doSetProperty("maxInterval", maxInterval);
            return this;
        }
        /**
         * The client side poll timeout, if multiple connections are detected
         * from the same browser.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder multiFrameInterval(
                int multiFrameInterval) {
            doSetProperty("multiFrameInterval", multiFrameInterval);
            return this;
        }
        /**
         * The client side poll timeout, if multiple connections are detected
         * from the same browser.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder multiFrameInterval(
                String multiFrameInterval) {
            doSetProperty("multiFrameInterval", multiFrameInterval);
            return this;
        }
        /**
         * The server side poll timeout in milliseconds. This is how long the
         * server will hold a reconnect request before responding.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder timeout(int timeout) {
            doSetProperty("timeout", timeout);
            return this;
        }
        /**
         * The server side poll timeout in milliseconds. This is how long the
         * server will hold a reconnect request before responding.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointConsumerBuilder timeout(String timeout) {
            doSetProperty("timeout", timeout);
            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 CometdEndpointConsumerBuilder 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 CometdEndpointConsumerBuilder bridgeErrorHandler(
                String bridgeErrorHandler) {
            doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
            return this;
        }
        /**
         * Whether to include the server session headers in the Camel message
         * when creating a Camel Message for incoming requests.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: consumer
         */
        default CometdEndpointConsumerBuilder sessionHeadersEnabled(
                boolean sessionHeadersEnabled) {
            doSetProperty("sessionHeadersEnabled", sessionHeadersEnabled);
            return this;
        }
        /**
         * Whether to include the server session headers in the Camel message
         * when creating a Camel Message for incoming requests.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: consumer
         */
        default CometdEndpointConsumerBuilder sessionHeadersEnabled(
                String sessionHeadersEnabled) {
            doSetProperty("sessionHeadersEnabled", sessionHeadersEnabled);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint consumers for the CometD component.
     */
    public interface AdvancedCometdEndpointConsumerBuilder
            extends
                EndpointConsumerBuilder {
        default CometdEndpointConsumerBuilder basic() {
            return (CometdEndpointConsumerBuilder) 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 AdvancedCometdEndpointConsumerBuilder 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 AdvancedCometdEndpointConsumerBuilder 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 AdvancedCometdEndpointConsumerBuilder 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 AdvancedCometdEndpointConsumerBuilder 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 AdvancedCometdEndpointConsumerBuilder 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 AdvancedCometdEndpointConsumerBuilder basicPropertyBinding(
                String basicPropertyBinding) {
            doSetProperty("basicPropertyBinding", basicPropertyBinding);
            return this;
        }
        /**
         * Sets whether synchronous processing should be strictly used, or Camel
         * is allowed to use asynchronous processing (if supported).
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedCometdEndpointConsumerBuilder 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 AdvancedCometdEndpointConsumerBuilder synchronous(
                String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
    }

    /**
     * Builder for endpoint producers for the CometD component.
     */
    public interface CometdEndpointProducerBuilder
            extends
                EndpointProducerBuilder {
        default AdvancedCometdEndpointProducerBuilder advanced() {
            return (AdvancedCometdEndpointProducerBuilder) this;
        }
        /**
         * The origins domain that support to cross, if the crosssOriginFilterOn
         * is true.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder allowedOrigins(
                String allowedOrigins) {
            doSetProperty("allowedOrigins", allowedOrigins);
            return this;
        }
        /**
         * The root directory for the web resources or classpath. Use the
         * protocol file: or classpath: depending if you want that the component
         * loads the resource from file system or classpath. Classpath is
         * required for OSGI deployment where the resources are packaged in the
         * jar.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder baseResource(String baseResource) {
            doSetProperty("baseResource", baseResource);
            return this;
        }
        /**
         * If true, the server will support for cross-domain filtering.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder crossOriginFilterOn(
                boolean crossOriginFilterOn) {
            doSetProperty("crossOriginFilterOn", crossOriginFilterOn);
            return this;
        }
        /**
         * If true, the server will support for cross-domain filtering.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder crossOriginFilterOn(
                String crossOriginFilterOn) {
            doSetProperty("crossOriginFilterOn", crossOriginFilterOn);
            return this;
        }
        /**
         * The filterPath will be used by the CrossOriginFilter, if the
         * crosssOriginFilterOn is true.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder filterPath(String filterPath) {
            doSetProperty("filterPath", filterPath);
            return this;
        }
        /**
         * The client side poll timeout in milliseconds. How long a client will
         * wait between reconnects.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder interval(int interval) {
            doSetProperty("interval", interval);
            return this;
        }
        /**
         * The client side poll timeout in milliseconds. How long a client will
         * wait between reconnects.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder interval(String interval) {
            doSetProperty("interval", interval);
            return this;
        }
        /**
         * If true, the server will accept JSON wrapped in a comment and will
         * generate JSON wrapped in a comment. This is a defence against Ajax
         * Hijacking.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder jsonCommented(
                boolean jsonCommented) {
            doSetProperty("jsonCommented", jsonCommented);
            return this;
        }
        /**
         * If true, the server will accept JSON wrapped in a comment and will
         * generate JSON wrapped in a comment. This is a defence against Ajax
         * Hijacking.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder jsonCommented(String jsonCommented) {
            doSetProperty("jsonCommented", jsonCommented);
            return this;
        }
        /**
         * Logging level. 0=none, 1=info, 2=debug.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder logLevel(int logLevel) {
            doSetProperty("logLevel", logLevel);
            return this;
        }
        /**
         * Logging level. 0=none, 1=info, 2=debug.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder logLevel(String logLevel) {
            doSetProperty("logLevel", logLevel);
            return this;
        }
        /**
         * The max client side poll timeout in milliseconds. A client will be
         * removed if a connection is not received in this time.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder maxInterval(int maxInterval) {
            doSetProperty("maxInterval", maxInterval);
            return this;
        }
        /**
         * The max client side poll timeout in milliseconds. A client will be
         * removed if a connection is not received in this time.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder maxInterval(String maxInterval) {
            doSetProperty("maxInterval", maxInterval);
            return this;
        }
        /**
         * The client side poll timeout, if multiple connections are detected
         * from the same browser.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder multiFrameInterval(
                int multiFrameInterval) {
            doSetProperty("multiFrameInterval", multiFrameInterval);
            return this;
        }
        /**
         * The client side poll timeout, if multiple connections are detected
         * from the same browser.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder multiFrameInterval(
                String multiFrameInterval) {
            doSetProperty("multiFrameInterval", multiFrameInterval);
            return this;
        }
        /**
         * The server side poll timeout in milliseconds. This is how long the
         * server will hold a reconnect request before responding.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder timeout(int timeout) {
            doSetProperty("timeout", timeout);
            return this;
        }
        /**
         * The server side poll timeout in milliseconds. This is how long the
         * server will hold a reconnect request before responding.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointProducerBuilder timeout(String timeout) {
            doSetProperty("timeout", timeout);
            return this;
        }
        /**
         * Whether to disconnect local sessions after publishing a message to
         * its channel. Disconnecting local session is needed as they are not
         * swept by default by CometD, and therefore you can run out of memory.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: producer
         */
        default CometdEndpointProducerBuilder disconnectLocalSession(
                boolean disconnectLocalSession) {
            doSetProperty("disconnectLocalSession", disconnectLocalSession);
            return this;
        }
        /**
         * Whether to disconnect local sessions after publishing a message to
         * its channel. Disconnecting local session is needed as they are not
         * swept by default by CometD, and therefore you can run out of memory.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: producer
         */
        default CometdEndpointProducerBuilder disconnectLocalSession(
                String disconnectLocalSession) {
            doSetProperty("disconnectLocalSession", disconnectLocalSession);
            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 CometdEndpointProducerBuilder 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 CometdEndpointProducerBuilder lazyStartProducer(
                String lazyStartProducer) {
            doSetProperty("lazyStartProducer", lazyStartProducer);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint producers for the CometD component.
     */
    public interface AdvancedCometdEndpointProducerBuilder
            extends
                EndpointProducerBuilder {
        default CometdEndpointProducerBuilder basic() {
            return (CometdEndpointProducerBuilder) 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 AdvancedCometdEndpointProducerBuilder 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 AdvancedCometdEndpointProducerBuilder basicPropertyBinding(
                String basicPropertyBinding) {
            doSetProperty("basicPropertyBinding", basicPropertyBinding);
            return this;
        }
        /**
         * Sets whether synchronous processing should be strictly used, or Camel
         * is allowed to use asynchronous processing (if supported).
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedCometdEndpointProducerBuilder 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 AdvancedCometdEndpointProducerBuilder synchronous(
                String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
    }

    /**
     * Builder for endpoint for the CometD component.
     */
    public interface CometdEndpointBuilder
            extends
                CometdEndpointConsumerBuilder, CometdEndpointProducerBuilder {
        default AdvancedCometdEndpointBuilder advanced() {
            return (AdvancedCometdEndpointBuilder) this;
        }
        /**
         * The origins domain that support to cross, if the crosssOriginFilterOn
         * is true.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder allowedOrigins(String allowedOrigins) {
            doSetProperty("allowedOrigins", allowedOrigins);
            return this;
        }
        /**
         * The root directory for the web resources or classpath. Use the
         * protocol file: or classpath: depending if you want that the component
         * loads the resource from file system or classpath. Classpath is
         * required for OSGI deployment where the resources are packaged in the
         * jar.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder baseResource(String baseResource) {
            doSetProperty("baseResource", baseResource);
            return this;
        }
        /**
         * If true, the server will support for cross-domain filtering.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder crossOriginFilterOn(
                boolean crossOriginFilterOn) {
            doSetProperty("crossOriginFilterOn", crossOriginFilterOn);
            return this;
        }
        /**
         * If true, the server will support for cross-domain filtering.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder crossOriginFilterOn(
                String crossOriginFilterOn) {
            doSetProperty("crossOriginFilterOn", crossOriginFilterOn);
            return this;
        }
        /**
         * The filterPath will be used by the CrossOriginFilter, if the
         * crosssOriginFilterOn is true.
         * 
         * The option is a: <code>java.lang.String</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder filterPath(String filterPath) {
            doSetProperty("filterPath", filterPath);
            return this;
        }
        /**
         * The client side poll timeout in milliseconds. How long a client will
         * wait between reconnects.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder interval(int interval) {
            doSetProperty("interval", interval);
            return this;
        }
        /**
         * The client side poll timeout in milliseconds. How long a client will
         * wait between reconnects.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder interval(String interval) {
            doSetProperty("interval", interval);
            return this;
        }
        /**
         * If true, the server will accept JSON wrapped in a comment and will
         * generate JSON wrapped in a comment. This is a defence against Ajax
         * Hijacking.
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder jsonCommented(boolean jsonCommented) {
            doSetProperty("jsonCommented", jsonCommented);
            return this;
        }
        /**
         * If true, the server will accept JSON wrapped in a comment and will
         * generate JSON wrapped in a comment. This is a defence against Ajax
         * Hijacking.
         * 
         * The option will be converted to a <code>boolean</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder jsonCommented(String jsonCommented) {
            doSetProperty("jsonCommented", jsonCommented);
            return this;
        }
        /**
         * Logging level. 0=none, 1=info, 2=debug.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder logLevel(int logLevel) {
            doSetProperty("logLevel", logLevel);
            return this;
        }
        /**
         * Logging level. 0=none, 1=info, 2=debug.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder logLevel(String logLevel) {
            doSetProperty("logLevel", logLevel);
            return this;
        }
        /**
         * The max client side poll timeout in milliseconds. A client will be
         * removed if a connection is not received in this time.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder maxInterval(int maxInterval) {
            doSetProperty("maxInterval", maxInterval);
            return this;
        }
        /**
         * The max client side poll timeout in milliseconds. A client will be
         * removed if a connection is not received in this time.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder maxInterval(String maxInterval) {
            doSetProperty("maxInterval", maxInterval);
            return this;
        }
        /**
         * The client side poll timeout, if multiple connections are detected
         * from the same browser.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder multiFrameInterval(int multiFrameInterval) {
            doSetProperty("multiFrameInterval", multiFrameInterval);
            return this;
        }
        /**
         * The client side poll timeout, if multiple connections are detected
         * from the same browser.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder multiFrameInterval(
                String multiFrameInterval) {
            doSetProperty("multiFrameInterval", multiFrameInterval);
            return this;
        }
        /**
         * The server side poll timeout in milliseconds. This is how long the
         * server will hold a reconnect request before responding.
         * 
         * The option is a: <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder timeout(int timeout) {
            doSetProperty("timeout", timeout);
            return this;
        }
        /**
         * The server side poll timeout in milliseconds. This is how long the
         * server will hold a reconnect request before responding.
         * 
         * The option will be converted to a <code>int</code> type.
         * 
         * Group: common
         */
        default CometdEndpointBuilder timeout(String timeout) {
            doSetProperty("timeout", timeout);
            return this;
        }
    }

    /**
     * Advanced builder for endpoint for the CometD component.
     */
    public interface AdvancedCometdEndpointBuilder
            extends
                AdvancedCometdEndpointConsumerBuilder, AdvancedCometdEndpointProducerBuilder {
        default CometdEndpointBuilder basic() {
            return (CometdEndpointBuilder) 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 AdvancedCometdEndpointBuilder 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 AdvancedCometdEndpointBuilder basicPropertyBinding(
                String basicPropertyBinding) {
            doSetProperty("basicPropertyBinding", basicPropertyBinding);
            return this;
        }
        /**
         * Sets whether synchronous processing should be strictly used, or Camel
         * is allowed to use asynchronous processing (if supported).
         * 
         * The option is a: <code>boolean</code> type.
         * 
         * Group: advanced
         */
        default AdvancedCometdEndpointBuilder 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 AdvancedCometdEndpointBuilder synchronous(String synchronous) {
            doSetProperty("synchronous", synchronous);
            return this;
        }
    }
    /**
     * CometD (camel-cometd)
     * The cometd component is a transport for working with the Jetty
     * implementation of the cometd/bayeux protocol.
     * 
     * Category: websocket
     * Since: 2.0
     * Maven coordinates: org.apache.camel:camel-cometd
     * 
     * Syntax: <code>cometd:host:port/channelName</code>
     * 
     * Path parameter: host (required)
     * Hostname
     * 
     * Path parameter: port (required)
     * Host port number
     * 
     * Path parameter: channelName (required)
     * The channelName represents a topic that can be subscribed to by the Camel
     * endpoints.
     */
    default CometdEndpointBuilder cometd(String path) {
        return cometd("cometd", path);
    }
    /**
     * CometD (Secure) (camel-cometd)
     * The cometd component is a transport for working with the Jetty
     * implementation of the cometd/bayeux protocol.
     * 
     * Category: websocket
     * Since: 2.0
     * Maven coordinates: org.apache.camel:camel-cometd
     * 
     * Syntax: <code>cometds:host:port/channelName</code>
     * 
     * Path parameter: host (required)
     * Hostname
     * 
     * Path parameter: port (required)
     * Host port number
     * 
     * Path parameter: channelName (required)
     * The channelName represents a topic that can be subscribed to by the Camel
     * endpoints.
     */
    default CometdEndpointBuilder cometds(String path) {
        return cometd("cometds", path);
    }
    /**
     * CometD (camel-cometd)
     * The cometd component is a transport for working with the Jetty
     * implementation of the cometd/bayeux protocol.
     * 
     * Category: websocket
     * Since: 2.0
     * Maven coordinates: org.apache.camel:camel-cometd
     */
    default CometdEndpointBuilder cometd(String scheme, String path) {
        class CometdEndpointBuilderImpl extends AbstractEndpointBuilder implements CometdEndpointBuilder, AdvancedCometdEndpointBuilder {
            public CometdEndpointBuilderImpl(String scheme, String path) {
                super(scheme, path);
            }
        }
        return new CometdEndpointBuilderImpl(scheme, path);
    }
}