/**
   * Register a {@link WebSocketHandlerMappingFactoryBean} which could also be overridden by the
   * user by simply using {@link org.springframework.web.socket.config.annotation.EnableWebSocket}
   *
   * <p>In addition, checks if the {@code javax.servlet.Servlet} class is present on the classpath.
   * When Spring Integration WebSocket support is used only as a WebSocket client, there is no
   * reason to use and register the Spring WebSocket server components.
   *
   * <p>Note, there is no XML equivalent for the {@link
   * org.springframework.web.socket.config.annotation .EnableWebSocket} in the Spring WebSocket.
   * therefore this registration can be used to process {@link WebSocketConfigurer} implementations
   * without annotation configuration. From other side it can be used to replace {@link
   * org.springframework.web.socket.config.annotation.EnableWebSocket} in the Spring Integration
   * applications when {@link org.springframework.integration.config.EnableIntegration} is in use.
   */
  private void registerEnableWebSocketIfNecessary(BeanDefinitionRegistry registry) {
    if (servletPresent) {
      if (!registry.containsBeanDefinition("defaultSockJsTaskScheduler")) {
        BeanDefinitionBuilder sockJsTaskSchedulerBuilder =
            BeanDefinitionBuilder.genericBeanDefinition(ThreadPoolTaskScheduler.class)
                .addPropertyValue("threadNamePrefix", "SockJS-")
                .addPropertyValue("poolSize", Runtime.getRuntime().availableProcessors())
                .addPropertyValue("removeOnCancelPolicy", true);

        registry.registerBeanDefinition(
            "defaultSockJsTaskScheduler", sockJsTaskSchedulerBuilder.getBeanDefinition());
      }

      if (!registry.containsBeanDefinition(DelegatingWebSocketConfiguration.class.getName())
          && !registry.containsBeanDefinition(WEB_SOCKET_HANDLER_MAPPING_BEAN_NAME)) {
        BeanDefinitionBuilder enableWebSocketBuilder =
            BeanDefinitionBuilder.genericBeanDefinition(WebSocketHandlerMappingFactoryBean.class)
                .setRole(BeanDefinition.ROLE_INFRASTRUCTURE)
                .addConstructorArgReference("defaultSockJsTaskScheduler");

        registry.registerBeanDefinition(
            WEB_SOCKET_HANDLER_MAPPING_BEAN_NAME, enableWebSocketBuilder.getBeanDefinition());
      }
    }
  }
  @Override
  public BeanDefinition parse(Element element, ParserContext parserContext) {
    Object source = parserContext.extractSource(element);

    CompositeComponentDefinition compDefinition =
        new CompositeComponentDefinition(element.getTagName(), source);
    parserContext.pushContainingComponent(compDefinition);

    BeanDefinitionRegistry registry = parserContext.getRegistry();

    if (registry.containsBeanDefinition(STAT_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      parserContext
          .getReaderContext()
          .error("Only one DruidStatBeanDefinitionParser may exist within the context.", source);
    } else {
      BeanDefinitionBuilder builder =
          BeanDefinitionBuilder.genericBeanDefinition(STAT_ANNOTATION_PROCESSOR_BEAN_CLASS);
      builder.getRawBeanDefinition().setSource(source);
      registerComponent(parserContext, builder, STAT_ANNOTATION_PROCESSOR_BEAN_NAME);
    }

    if (!registry.containsBeanDefinition(STAT_ANNOTATION_ADVICE_BEAN_NAME)) {
      BeanDefinitionBuilder builder =
          BeanDefinitionBuilder.genericBeanDefinition(STAT_ANNOTATION_ADVICE_BEAN_CLASS);
      builder.getRawBeanDefinition().setSource(source);
      registerComponent(parserContext, builder, STAT_ANNOTATION_ADVICE_BEAN_NAME);
    }

    parserContext.popAndRegisterContainingComponent();

    return null;
  }
  @Override
  protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
    final BeanDefinitionBuilder builder =
        BeanDefinitionBuilder.genericBeanDefinition(ContentEnricher.class);

    IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "request-channel");
    IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "request-timeout");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "reply-timeout");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply");

    List<Element> subElements = DomUtils.getChildElementsByTagName(element, "property");
    if (!CollectionUtils.isEmpty(subElements)) {
      ManagedMap<String, Object> expressions = new ManagedMap<String, Object>();
      for (Element subElement : subElements) {
        String name = subElement.getAttribute("name");
        BeanDefinition beanDefinition =
            IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression(
                "value", "expression", parserContext, subElement, true);
        expressions.put(name, beanDefinition);
      }
      builder.addPropertyValue("propertyExpressions", expressions);
    }

    subElements = DomUtils.getChildElementsByTagName(element, "header");
    if (!CollectionUtils.isEmpty(subElements)) {
      ManagedMap<String, Object> expressions = new ManagedMap<String, Object>();
      for (Element subElement : subElements) {
        String name = subElement.getAttribute("name");
        BeanDefinition expressionDefinition =
            IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression(
                "value", "expression", parserContext, subElement, true);
        BeanDefinitionBuilder valueProcessorBuilder =
            BeanDefinitionBuilder.genericBeanDefinition(
                IntegrationNamespaceUtils.BASE_PACKAGE
                    + ".transformer.support.ExpressionEvaluatingHeaderValueMessageProcessor");
        valueProcessorBuilder
            .addConstructorArgValue(expressionDefinition)
            .addConstructorArgValue(subElement.getAttribute("type"));
        IntegrationNamespaceUtils.setValueIfAttributeDefined(
            valueProcessorBuilder, subElement, "overwrite");
        expressions.put(name, valueProcessorBuilder.getBeanDefinition());
      }
      builder.addPropertyValue("headerExpressions", expressions);
    }

    IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "should-clone-payload");

    String requestPayloadExpression = element.getAttribute("request-payload-expression");

    if (StringUtils.hasText(requestPayloadExpression)) {
      BeanDefinitionBuilder expressionBuilder =
          BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class);
      expressionBuilder.addConstructorArgValue(requestPayloadExpression);
      builder.addPropertyValue("requestPayloadExpression", expressionBuilder.getBeanDefinition());
    }

    return builder;
  }
  @Override
  protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
    BeanDefinitionBuilder builder =
        BeanDefinitionBuilder.genericBeanDefinition(
            "org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler");
    builder.addConstructorArgValue(element.getAttribute("url"));
    IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "http-method");

    String restTemplate = element.getAttribute("rest-template");
    if (StringUtils.hasText(restTemplate)) {
      HttpAdapterParsingUtils.verifyNoRestTemplateAttributes(element, parserContext);
      builder.addConstructorArgReference(restTemplate);
    } else {
      for (String referenceAttributeName :
          HttpAdapterParsingUtils.REST_TEMPLATE_REFERENCE_ATTRIBUTES) {
        IntegrationNamespaceUtils.setReferenceIfAttributeDefined(
            builder, element, referenceAttributeName);
      }
    }

    String headerMapper = element.getAttribute("header-mapper");
    String mappedRequestHeaders = element.getAttribute("mapped-request-headers");
    String mappedResponseHeaders = element.getAttribute("mapped-response-headers");
    if (StringUtils.hasText(headerMapper)) {
      if (StringUtils.hasText(mappedRequestHeaders) || StringUtils.hasText(mappedResponseHeaders)) {
        parserContext
            .getReaderContext()
            .error(
                "Neither 'mappped-request-headers' or 'mapped-response-headers' "
                    + "attributes are allowed when a 'header-mapper' has been specified.",
                parserContext.extractSource(element));
        return null;
      }
      builder.addPropertyReference("headerMapper", headerMapper);
    } else {
      BeanDefinitionBuilder headerMapperBuilder =
          BeanDefinitionBuilder.genericBeanDefinition(
              "org.springframework.integration.http.support.DefaultHttpHeaderMapper");
      headerMapperBuilder.setFactoryMethod("outboundMapper");
      IntegrationNamespaceUtils.setValueIfAttributeDefined(
          headerMapperBuilder, element, "mapped-request-headers", "outboundHeaderNames");
      IntegrationNamespaceUtils.setValueIfAttributeDefined(
          headerMapperBuilder, element, "mapped-response-headers", "inboundHeaderNames");
      builder.addPropertyValue("headerMapper", headerMapperBuilder.getBeanDefinition());
    }
    IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "charset");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        builder, element, "extract-request-payload", "extractPayload");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        builder, element, "expected-response-type");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        builder, element, "reply-timeout", "sendTimeout");
    IntegrationNamespaceUtils.setReferenceIfAttributeDefined(
        builder, element, "reply-channel", "outputChannel");
    HttpAdapterParsingUtils.configureUriVariableExpressions(builder, element);
    IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "transfer-cookies");
    return builder;
  }
  /**
   * Create a new {@link BeanDefinitionBuilder} for the class {@link StoredProcExecutor}. Initialize
   * the wrapped {@link StoredProcExecutor} with common properties.
   *
   * @param element Must not be Null
   * @param parserContext Must not be Null
   * @return The {@link BeanDefinitionBuilder} for the {@link StoredProcExecutor}
   */
  public static BeanDefinitionBuilder getStoredProcExecutorBuilder(
      final Element element, final ParserContext parserContext) {

    Assert.notNull(element, "The provided element must not be Null.");
    Assert.notNull(parserContext, "The provided parserContext must not be Null.");

    final String dataSourceRef = element.getAttribute("data-source");

    final BeanDefinitionBuilder storedProcExecutorBuilder =
        BeanDefinitionBuilder.genericBeanDefinition(StoredProcExecutor.class);
    storedProcExecutorBuilder.addConstructorArgReference(dataSourceRef);

    final String storedProcedureName = element.getAttribute("stored-procedure-name");
    final String storedProcedureNameExpression =
        element.getAttribute("stored-procedure-name-expression");
    boolean hasStoredProcedureName = StringUtils.hasText(storedProcedureName);
    boolean hasStoredProcedureNameExpression = StringUtils.hasText(storedProcedureNameExpression);

    if (!(hasStoredProcedureName ^ hasStoredProcedureNameExpression)) {
      parserContext
          .getReaderContext()
          .error(
              "Exactly one of 'stored-procedure-name' or 'stored-procedure-name-expression' is required",
              element);
    }

    BeanDefinitionBuilder expressionBuilder;
    if (hasStoredProcedureNameExpression) {
      expressionBuilder = BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class);
      expressionBuilder.addConstructorArgValue(storedProcedureNameExpression);
    } else {
      expressionBuilder = BeanDefinitionBuilder.genericBeanDefinition(LiteralExpression.class);
      expressionBuilder.addConstructorArgValue(storedProcedureName);
    }
    storedProcExecutorBuilder.addPropertyValue(
        "storedProcedureNameExpression", expressionBuilder.getBeanDefinition());

    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        storedProcExecutorBuilder, element, "ignore-column-meta-data");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        storedProcExecutorBuilder, element, "jdbc-call-operations-cache-size");

    final ManagedList<BeanDefinition> procedureParameterList =
        StoredProcParserUtils.getProcedureParameterBeanDefinitions(element, parserContext);
    final ManagedList<BeanDefinition> sqlParameterDefinitionList =
        StoredProcParserUtils.getSqlParameterDefinitionBeanDefinitions(element, parserContext);

    if (!procedureParameterList.isEmpty()) {
      storedProcExecutorBuilder.addPropertyValue("procedureParameters", procedureParameterList);
    }
    if (!sqlParameterDefinitionList.isEmpty()) {
      storedProcExecutorBuilder.addPropertyValue("sqlParameters", sqlParameterDefinitionList);
    }

    return storedProcExecutorBuilder;
  }
  /**
   * @param storedProcComponent
   * @param parserContext
   */
  public static ManagedList<BeanDefinition> getSqlParameterDefinitionBeanDefinitions(
      Element storedProcComponent, ParserContext parserContext) {
    List<Element> sqlParameterDefinitionChildElements =
        DomUtils.getChildElementsByTagName(storedProcComponent, "sql-parameter-definition");
    ManagedList<BeanDefinition> sqlParameterList = new ManagedList<BeanDefinition>();

    for (Element childElement : sqlParameterDefinitionChildElements) {

      String name = childElement.getAttribute("name");
      String sqlType = childElement.getAttribute("type");
      String direction = childElement.getAttribute("direction");
      String scale = childElement.getAttribute("scale");

      final BeanDefinitionBuilder parameterBuilder;

      if ("OUT".equalsIgnoreCase(direction)) {
        parameterBuilder = BeanDefinitionBuilder.genericBeanDefinition(SqlOutParameter.class);
      } else if ("INOUT".equalsIgnoreCase(direction)) {
        parameterBuilder = BeanDefinitionBuilder.genericBeanDefinition(SqlInOutParameter.class);
      } else {
        parameterBuilder = BeanDefinitionBuilder.genericBeanDefinition(SqlParameter.class);
      }

      if (StringUtils.hasText(name)) {
        parameterBuilder.addConstructorArgValue(name);
      } else {
        parserContext
            .getReaderContext()
            .error(
                "The 'name' attribute must be set for the Sql parameter element.",
                storedProcComponent);
      }

      if (StringUtils.hasText(sqlType)) {

        JdbcTypesEnum jdbcTypeEnum = JdbcTypesEnum.convertToJdbcTypesEnum(sqlType);

        if (jdbcTypeEnum != null) {
          parameterBuilder.addConstructorArgValue(jdbcTypeEnum.getCode());
        } else {
          parameterBuilder.addConstructorArgValue(sqlType);
        }

      } else {
        parameterBuilder.addConstructorArgValue(Types.VARCHAR);
      }

      if (StringUtils.hasText(scale)) {
        parameterBuilder.addConstructorArgValue(new TypedStringValue(scale, Integer.class));
      }

      sqlParameterList.add(parameterBuilder.getBeanDefinition());
    }
    return sqlParameterList;
  }
 /**
  * Parse a "transactional" element and configure a {@link TransactionInterceptor} with
  * "transactionManager" and other "transactionDefinition" properties. For example, this advisor
  * will be applied on the Polling Task proxy
  *
  * @see AbstractPollingEndpoint
  */
 public static BeanDefinition configureTransactionAttributes(Element txElement) {
   BeanDefinition txDefinition = configureTransactionDefinition(txElement);
   BeanDefinitionBuilder attributeSourceBuilder =
       BeanDefinitionBuilder.genericBeanDefinition(MatchAlwaysTransactionAttributeSource.class);
   attributeSourceBuilder.addPropertyValue("transactionAttribute", txDefinition);
   BeanDefinitionBuilder txInterceptorBuilder =
       BeanDefinitionBuilder.genericBeanDefinition(TransactionInterceptor.class);
   txInterceptorBuilder.addPropertyReference(
       "transactionManager", txElement.getAttribute("transaction-manager"));
   txInterceptorBuilder.addPropertyValue(
       "transactionAttributeSource", attributeSourceBuilder.getBeanDefinition());
   return txInterceptorBuilder.getBeanDefinition();
 }
  @Override
  protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
    BeanDefinitionBuilder metadataBuilder =
        BeanDefinitionBuilder.genericBeanDefinition(PollerMetadata.class);
    if (element.hasAttribute("ref")) {
      parserContext
          .getReaderContext()
          .error(
              "the 'ref' attribute must not be present on the top-level 'poller' element", element);
    }

    configureTrigger(element, metadataBuilder, parserContext);

    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        metadataBuilder, element, "max-messages-per-poll");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        metadataBuilder, element, "receive-timeout");
    IntegrationNamespaceUtils.setReferenceIfAttributeDefined(
        metadataBuilder, element, "task-executor");

    Element txElement = DomUtils.getChildElementByTagName(element, "transactional");
    Element adviceChainElement = DomUtils.getChildElementByTagName(element, "advice-chain");
    IntegrationNamespaceUtils.configureAndSetAdviceChainIfPresent(
        adviceChainElement, txElement, metadataBuilder.getRawBeanDefinition(), parserContext);

    if (txElement != null) {
      IntegrationNamespaceUtils.setReferenceIfAttributeDefined(
          metadataBuilder,
          txElement,
          "synchronization-factory",
          "transactionSynchronizationFactory");
    } else if (adviceChainElement != null) {
      IntegrationNamespaceUtils.setReferenceIfAttributeDefined(
          metadataBuilder,
          adviceChainElement,
          "synchronization-factory",
          "transactionSynchronizationFactory");
    }

    String errorChannel = element.getAttribute("error-channel");
    if (StringUtils.hasText(errorChannel)) {
      BeanDefinitionBuilder errorHandler =
          BeanDefinitionBuilder.genericBeanDefinition(MessagePublishingErrorHandler.class);
      errorHandler.addPropertyReference("defaultErrorChannel", errorChannel);
      metadataBuilder.addPropertyValue("errorHandler", errorHandler.getBeanDefinition());
    }
    return metadataBuilder.getBeanDefinition();
  }
  @Override
  protected void doParse(
      Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
    super.doParse(element, parserContext, builder);

    BeanDefinitionBuilder redisConfigBeanBuilder =
        BeanDefinitionBuilder.genericBeanDefinition(RedisConnectionFactoryConfig.class.getName());

    BeanDefinition cloudPoolConfiguration = null;
    Element poolElement = DomUtils.getChildElementByTagName(element, ELEMENT_POOL);
    if (poolElement != null) {
      cloudPoolConfiguration = parsePoolElement(poolElement, parserContext);
    }
    redisConfigBeanBuilder.addConstructorArgValue(cloudPoolConfiguration);

    Element propertiesElement = DomUtils.getChildElementByTagName(element, CONNECTION_PROPERTIES);
    if (propertiesElement != null) {
      Map<?, ?> properties =
          parserContext
              .getDelegate()
              .parseMapElement(propertiesElement, builder.getRawBeanDefinition());
      redisConfigBeanBuilder.addConstructorArgValue(properties);
    }

    builder.addConstructorArgValue(redisConfigBeanBuilder.getBeanDefinition());
  }
 @Override
 protected void createOperationsBean(BeanDefinitionRegistry registry) {
   String beanName = "s3ResourceTemplate";
   BeanDefinitionBuilder builder =
       BeanDefinitionBuilder.genericBeanDefinition(S3ResourceTemplate.class);
   registry.registerBeanDefinition(beanName, builder.getBeanDefinition());
 }
  @Override
  protected AbstractBeanDefinition parseInternal(Element elem, ParserContext parserContext) {
    String elemNsPrefix = elem.getPrefix(),
        elemNsUri = elem.getNamespaceURI(),
        elemLocalName = elem.getLocalName();
    Class<?> beanClass = this.getBeanClass(elem);
    AbstractBeanDefinition beanDef =
        BeanDefinitionBuilder.genericBeanDefinition(beanClass).getRawBeanDefinition();

    try {
      this.parseDefinition(
          parserContext,
          parserContext.getRegistry(),
          elem,
          elemNsPrefix,
          elemNsUri,
          elemLocalName,
          beanDef);
    } catch (Exception e) {
      throw new FatalBeanException(
          String.format(
              "Unable to parse bean definition (class=%s) XML element (nsPrefix=%s, nsUri=%s, localName=%s).",
              beanClass, elemNsPrefix, elemNsUri, elemLocalName),
          e);
    }

    return beanDef;
  }
  private ManagedList<AbstractBeanDefinition> parseListeners(
      Element element, ParserContext parserContext) {
    List<Element> listenersElements =
        DomUtils.getChildElementsByTagName(element, LISTENERS_ELEMENT);

    ManagedList<AbstractBeanDefinition> listeners = new ManagedList<AbstractBeanDefinition>();

    if (listenersElements.size() == 1) {
      Element listenersElement = listenersElements.get(0);
      CompositeComponentDefinition compositeDef =
          new CompositeComponentDefinition(
              listenersElement.getTagName(), parserContext.extractSource(element));
      parserContext.pushContainingComponent(compositeDef);
      listeners.setMergeEnabled(false);
      List<Element> listenerElements =
          DomUtils.getChildElementsByTagName(listenersElement, LISTENER_ELEMENT);
      for (Element listenerElement : listenerElements) {
        BeanDefinitionBuilder bd = BeanDefinitionBuilder.genericBeanDefinition(listenerType);
        bd.addPropertyValue(
            "delegate", new RuntimeBeanReference(listenerElement.getAttribute(REF_ATTRIBUTE)));
        listeners.add(bd.getBeanDefinition());
      }
      parserContext.popAndRegisterContainingComponent();
    } else if (listenersElements.size() > 1) {
      parserContext
          .getReaderContext()
          .error(
              "The '<listeners/>' element may not appear more than once in a single <job/>.",
              element);
    }

    return listeners;
  }
  @Override
  protected void doParse(
      final Element element,
      final ParserContext parserContext,
      final BeanDefinitionBuilder builder) {
    String serviceRef = element.getAttribute("service-ref");
    builder.addConstructorArgValue(":" + serviceRef);
    builder.addConstructorArgReference(serviceRef);
    String marker = element.getAttribute("marker");
    if (StringUtils.hasLength(marker)) {
      Class<?> theClass =
          ClassUtils.resolveClassName(marker, Thread.currentThread().getContextClassLoader());
      if (!theClass.isAnnotation()) {
        throw new ConfigurationException(
            String.format("The class '%s' is not an annotation", marker));
      }
      builder.addPropertyValue("markerAnnotation", theClass);
    }

    // Register the post processor if there is not already one in this context
    String beanName = NamespaceBeanFactoryPostProcessor.class.getName();
    if (!parserContext.getRegistry().containsBeanDefinition(beanName)) {
      BeanDefinitionBuilder namespacePostProcessor =
          BeanDefinitionBuilder.genericBeanDefinition(NamespaceBeanFactoryPostProcessor.class);
      parserContext.registerBeanComponent(
          new BeanComponentDefinition(namespacePostProcessor.getBeanDefinition(), beanName));
    }
  }
  @Override
  protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
    BeanDefinitionBuilder builder =
        BeanDefinitionBuilder.genericBeanDefinition(AmqpOutboundEndpoint.class);
    String amqpTemplateRef = element.getAttribute("amqp-template");
    if (!StringUtils.hasText(amqpTemplateRef)) {
      amqpTemplateRef = "amqpTemplate";
    }
    builder.addConstructorArgReference(amqpTemplateRef);
    IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "exchange-name", true);
    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        builder, element, "exchange-name-expression");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "routing-key", true);
    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        builder, element, "routing-key-expression");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "default-delivery-mode");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "lazy-connect");

    IntegrationNamespaceUtils.configureHeaderMapper(
        element, builder, parserContext, DefaultAmqpHeaderMapper.class, null);

    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        builder, element, "confirm-correlation-expression");
    IntegrationNamespaceUtils.setReferenceIfAttributeDefined(
        builder, element, "confirm-ack-channel");
    IntegrationNamespaceUtils.setReferenceIfAttributeDefined(
        builder, element, "confirm-nack-channel");
    IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "return-channel");

    return builder.getBeanDefinition();
  }
 /**
  * Builds and configures a {@link BeanDefinitionBuilder} for {@link
  * HdfsStoreMessageHandlerFactoryBean}.
  *
  * @param element The element.
  * @param parserContext The parser context.
  * @return The bean definition builder
  */
 static BeanDefinitionBuilder configure(Element element, ParserContext parserContext) {
   BeanDefinitionBuilder builder =
       BeanDefinitionBuilder.genericBeanDefinition(HdfsStoreMessageHandlerFactoryBean.class);
   IntegrationNamespaceUtils.setReferenceIfAttributeDefined(
       builder, element, "writer", "storeWriter");
   IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup");
   return builder;
 }
  @Override
  protected BeanMetadataElement parseSource(Element element, ParserContext parserContext) {

    final BeanDefinitionBuilder jpaPollingChannelAdapterBuilder =
        BeanDefinitionBuilder.genericBeanDefinition(JpaPollingChannelAdapter.class);

    final BeanDefinitionBuilder jpaExecutorBuilder =
        JpaParserUtils.getJpaExecutorBuilder(element, parserContext);

    String maxNumberOfResults = element.getAttribute("max-number-of-results");
    boolean hasMaxNumberOfResults = StringUtils.hasText(maxNumberOfResults);

    String maxResults = element.getAttribute("max-results");
    boolean hasMaxResults = StringUtils.hasText(maxResults);

    if (hasMaxNumberOfResults) {
      parserContext
          .getReaderContext()
          .warning("'max-number-of-results' is deprecated in favor of 'max-results'", element);
      if (hasMaxResults) {
        parserContext
            .getReaderContext()
            .error("'max-number-of-results' and 'max-results' are mutually exclusive", element);
      } else {
        element.setAttribute("max-results", maxNumberOfResults);
      }
    }

    BeanDefinition definition =
        IntegrationNamespaceUtils.createExpressionDefinitionFromValueOrExpression(
            "max-results", "max-results-expression", parserContext, element, false);
    if (definition != null) {
      jpaExecutorBuilder.addPropertyValue("maxResultsExpression", definition);
    }
    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        jpaExecutorBuilder, element, "delete-after-poll");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        jpaExecutorBuilder, element, "flush-after-delete", "flush");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        jpaExecutorBuilder, element, "delete-in-batch");
    IntegrationNamespaceUtils.setValueIfAttributeDefined(
        jpaExecutorBuilder, element, "expect-single-result");
    IntegrationNamespaceUtils.setReferenceIfAttributeDefined(
        jpaExecutorBuilder, element, "parameter-source");

    final BeanDefinition jpaExecutorBuilderBeanDefinition = jpaExecutorBuilder.getBeanDefinition();
    final String channelAdapterId =
        this.resolveId(
            element, jpaPollingChannelAdapterBuilder.getRawBeanDefinition(), parserContext);
    final String jpaExecutorBeanName = channelAdapterId + ".jpaExecutor";

    parserContext.registerBeanComponent(
        new BeanComponentDefinition(jpaExecutorBuilderBeanDefinition, jpaExecutorBeanName));

    jpaPollingChannelAdapterBuilder.addConstructorArgReference(jpaExecutorBeanName);

    return jpaPollingChannelAdapterBuilder.getBeanDefinition();
  }
  @Override
  protected void doParse(
      Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
    String scriptLocation = element.getAttribute(LOCATION_ATTRIBUTE);
    String scriptText = DomUtils.getTextValue(element);
    if (!(StringUtils.hasText(scriptLocation) ^ StringUtils.hasText(scriptText))) {
      parserContext
          .getReaderContext()
          .error(
              "Either the 'location' attribute or inline script text must be provided, but not both.",
              element);
      return;
    }

    List<Element> variableElements = DomUtils.getChildElementsByTagName(element, "variable");
    String scriptVariableGeneratorName = element.getAttribute("script-variable-generator");

    if (StringUtils.hasText(scriptVariableGeneratorName) && variableElements.size() > 0) {
      parserContext
          .getReaderContext()
          .error(
              "'script-variable-generator' and 'variable' sub-elements are mutually exclusive.",
              element);
      return;
    }

    if (StringUtils.hasText(scriptLocation)) {
      builder.addConstructorArgValue(
          this.resolveScriptLocation(element, parserContext.getReaderContext(), scriptLocation));
    } else {
      if (getScriptSourceClassName() != null) {
        builder.addConstructorArgValue(
            new StaticScriptSource(scriptText, getScriptSourceClassName()));
      } else {
        builder.addConstructorArgValue(new StaticScriptSource(scriptText));
      }
    }

    BeanMetadataElement scriptVariableGeneratorDef = null;

    if (!StringUtils.hasText(scriptVariableGeneratorName)) {
      BeanDefinitionBuilder scriptVariableGeneratorBuilder =
          BeanDefinitionBuilder.genericBeanDefinition(DefaultScriptVariableGenerator.class);
      ManagedMap<String, Object> variableMap =
          buildVariablesMap(element, parserContext, variableElements);
      if (!CollectionUtils.isEmpty(variableMap)) {
        scriptVariableGeneratorBuilder.addConstructorArgValue(variableMap);
      }
      scriptVariableGeneratorDef = scriptVariableGeneratorBuilder.getBeanDefinition();
    } else {
      scriptVariableGeneratorDef = new RuntimeBeanReference(scriptVariableGeneratorName);
    }

    builder.addConstructorArgValue(scriptVariableGeneratorDef);
    postProcess(builder, element, parserContext);
  }
  private BeanDefinition parsePath(Element element, ParserContext parserContext) {
    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SearchPath.class);
    String type = defaultIfNull(trimToNull(element.getAttribute("type")), "relative");
    String path = trimToEmpty(element.getTextContent());

    builder.addConstructorArgValue(path);
    builder.addConstructorArgValue("relative".equals(type));

    return builder.getBeanDefinition();
  }
 private void loadImplementor(BeanDefinitionBuilder bean, String val) {
   if (!StringUtils.isEmpty(val)) {
     bean.addPropertyValue("checkBlockConstruct", Boolean.TRUE);
     if (val.startsWith("#")) {
       bean.addConstructorArgReference(val.substring(1));
     } else {
       bean.addConstructorArgValue(
           BeanDefinitionBuilder.genericBeanDefinition(val).getBeanDefinition());
     }
   }
 }
  /**
   * Create a new {@link BeanDefinitionBuilder} for the class {@link SIAdapterUpperPrefixExecutor}.
   * Initialize the wrapped {@link SIAdapterUpperPrefixExecutor} with common properties.
   *
   * @param element Must not be null
   * @param parserContext Must not be null
   * @return The BeanDefinitionBuilder for the SIAdapterUpperPrefixExecutor
   */
  public static BeanDefinitionBuilder getSIAdapterUpperPrefixExecutorBuilder(
      final Element element, final ParserContext parserContext) {

    Assert.notNull(element, "The provided element must not be null.");
    Assert.notNull(parserContext, "The provided parserContext must not be null.");

    final BeanDefinitionBuilder siAdapterLowerPrefixExecutorBuilder =
        BeanDefinitionBuilder.genericBeanDefinition(SIAdapterUpperPrefixExecutor.class);

    return siAdapterLowerPrefixExecutorBuilder;
  }
 /**
  * Parse attributes of "transactional" element and configure a {@link DefaultTransactionAttribute}
  * with provided "transactionDefinition" properties.
  */
 public static BeanDefinition configureTransactionDefinition(Element txElement) {
   BeanDefinitionBuilder txDefinitionBuilder =
       BeanDefinitionBuilder.genericBeanDefinition(DefaultTransactionAttribute.class);
   txDefinitionBuilder.addPropertyValue(
       "propagationBehaviorName", "PROPAGATION_" + txElement.getAttribute("propagation"));
   txDefinitionBuilder.addPropertyValue(
       "isolationLevelName", "ISOLATION_" + txElement.getAttribute("isolation"));
   txDefinitionBuilder.addPropertyValue("timeout", txElement.getAttribute("timeout"));
   txDefinitionBuilder.addPropertyValue("readOnly", txElement.getAttribute("read-only"));
   return txDefinitionBuilder.getBeanDefinition();
 }
  private void parseEntries(
      Element element, String name, EntryType type, List<BeanDefinition> entries) {
    List<Element> cp = DomUtils.getChildElementsByTagName(element, name);

    for (Element entry : cp) {
      BeanDefinitionBuilder bd = BeanDefinitionBuilder.genericBeanDefinition(CacheEntry.class);
      bd.addConstructorArgValue(type);
      bd.addConstructorArgValue(entry.getAttribute("value"));
      entries.add(bd.getBeanDefinition());
    }
  }
  @Override
  protected BeanDefinitionBuilder getBeanDefinitionBuilder(
      Element element, ParserContext parserContext) {
    BeanDefinitionBuilder builder =
        BeanDefinitionBuilder.genericBeanDefinition(
            "com.consol.citrus.channel.SyncMessageChannelReceiver");

    BeanDefinitionParserUtils.setPropertyReference(
        builder, element.getAttribute("reply-message-correlator"), "correlator");

    return builder;
  }
  /**
   * Parse the split and turn it into a list of transitions.
   *
   * @param element the &lt;split/gt; element to parse
   * @param parserContext the parser context for the bean factory
   * @return a collection of bean definitions for {@link
   *     org.springframework.batch.core.job.flow.support.StateTransition} instances objects
   */
  public Collection<BeanDefinition> parse(Element element, ParserContext parserContext) {

    String idAttribute = element.getAttribute("id");

    BeanDefinitionBuilder stateBuilder =
        BeanDefinitionBuilder.genericBeanDefinition(
            "org.springframework.batch.core.job.flow.support.state.SplitState");

    String taskExecutorBeanId = element.getAttribute("task-executor");
    if (StringUtils.hasText(taskExecutorBeanId)) {
      RuntimeBeanReference taskExecutorRef = new RuntimeBeanReference(taskExecutorBeanId);
      stateBuilder.addPropertyValue("taskExecutor", taskExecutorRef);
    }

    List<Element> flowElements = DomUtils.getChildElementsByTagName(element, "flow");

    if (flowElements.size() < 2) {
      parserContext
          .getReaderContext()
          .error("A <split/> must contain at least two 'flow' elements.", element);
    }

    Collection<BeanDefinition> flows = new ManagedList<BeanDefinition>();
    int i = 0;
    String prefix = idAttribute;
    for (Element nextElement : flowElements) {
      String ref = nextElement.getAttribute(PARENT_ATTR);
      if (StringUtils.hasText(ref)) {
        if (nextElement.getElementsByTagName("*").getLength() > 0) {
          parserContext
              .getReaderContext()
              .error(
                  "A <flow/> in a <split/> must have ref= or nested <flow/>, but not both.",
                  nextElement);
        }
        AbstractBeanDefinition flowDefinition = new GenericBeanDefinition();
        flowDefinition.setParentName(ref);
        MutablePropertyValues propertyValues = flowDefinition.getPropertyValues();
        propertyValues.addPropertyValue("name", prefix + "." + i);
        flows.add(flowDefinition);
      } else {
        InlineFlowParser flowParser = new InlineFlowParser(prefix + "." + i, jobFactoryRef);
        flows.add(flowParser.parse(nextElement, parserContext));
      }
      i++;
    }

    stateBuilder.addConstructorArgValue(flows);
    stateBuilder.addConstructorArgValue(prefix);

    return InlineFlowParser.getNextElements(
        parserContext, stateBuilder.getBeanDefinition(), element);
  }
  /**
   * Build the POJO with the username and password.
   *
   * @param element the HTTPMetadataProvider parser.
   * @return the bean definition with the username and password.
   */
  private BeanDefinition buildBasicCredentials(Element element) {
    BeanDefinitionBuilder builder =
        BeanDefinitionBuilder.genericBeanDefinition(UsernamePasswordCredentials.class);

    builder.setLazyInit(true);

    builder.addConstructorArgValue(
        StringSupport.trimOrNull(element.getAttributeNS(null, BASIC_AUTH_USER)));
    builder.addConstructorArgValue(
        StringSupport.trimOrNull(element.getAttributeNS(null, BASIC_AUTH_PASSWORD)));

    return builder.getBeanDefinition();
  }
  @Override
  protected AbstractBeanDefinition doParse(
      Element element, ParserContext parserContext, String channelName) {

    BeanDefinitionBuilder builder =
        BeanDefinitionBuilder.genericBeanDefinition(MqttPahoMessageDrivenChannelAdapter.class);

    MqttParserUtils.parseCommon(element, builder);
    builder.addConstructorArgValue(element.getAttribute("topics"));
    builder.addPropertyReference("outputChannel", channelName);

    return builder.getBeanDefinition();
  }
  /**
   * @param storedProcComponent
   * @param parserContext
   */
  public static ManagedList<BeanDefinition> getProcedureParameterBeanDefinitions(
      Element storedProcComponent, ParserContext parserContext) {

    ManagedList<BeanDefinition> procedureParameterList = new ManagedList<BeanDefinition>();

    List<Element> parameterChildElements =
        DomUtils.getChildElementsByTagName(storedProcComponent, "parameter");

    for (Element childElement : parameterChildElements) {

      BeanDefinitionBuilder parameterBuilder =
          BeanDefinitionBuilder.genericBeanDefinition(ProcedureParameter.class);

      String name = childElement.getAttribute("name");
      String expression = childElement.getAttribute("expression");
      String value = childElement.getAttribute("value");
      String type = childElement.getAttribute("type");

      if (StringUtils.hasText(name)) {
        parameterBuilder.addPropertyValue("name", name);
      }

      if (StringUtils.hasText(expression)) {
        parameterBuilder.addPropertyValue("expression", expression);
      }

      if (StringUtils.hasText(value)) {

        if (!StringUtils.hasText(type)) {

          if (LOGGER.isInfoEnabled()) {
            LOGGER.info(
                String.format(
                    "Type attribute not set for Store "
                        + "Procedure parameter '%s'. Defaulting to "
                        + "'java.lang.String'.",
                    value));
          }

          parameterBuilder.addPropertyValue("value", new TypedStringValue(value, String.class));

        } else {
          parameterBuilder.addPropertyValue("value", new TypedStringValue(value, type));
        }
      }

      procedureParameterList.add(parameterBuilder.getBeanDefinition());
    }

    return procedureParameterList;
  }
  /** {@inheritDoc} */
  @Override
  protected void addSAMLDecoders(
      @Nonnull final Element config,
      @Nonnull final ParserContext parserContext,
      @Nonnull final BeanDefinitionBuilder builder) {

    BeanDefinitionBuilder subBuilder =
        BeanDefinitionBuilder.genericBeanDefinition(TransformingNameIDDecoder.class);
    subBuilder.setInitMethodName("initialize");
    subBuilder.setDestroyMethodName("destroy");

    final String id = StringSupport.trimOrNull(config.getAttributeNS(null, "id"));
    subBuilder.addPropertyValue("id", id);
    builder.addConstructorArgValue(subBuilder.getBeanDefinition());

    subBuilder =
        BeanDefinitionBuilder.genericBeanDefinition(TransformingNameIdentifierDecoder.class);
    subBuilder.setInitMethodName("initialize");
    subBuilder.setDestroyMethodName("destroy");

    subBuilder.addPropertyValue("id", id);
    builder.addConstructorArgValue(subBuilder.getBeanDefinition());
  }
 private Object resolveScriptLocation(
     Element element, XmlReaderContext readerContext, String scriptLocation) {
   String refreshDelayText = element.getAttribute(REFRESH_CHECK_DELAY_ATTRIBUTE);
   String beanClassName = RefreshableResourceScriptSource.class.getName();
   BeanDefinitionBuilder resourceScriptSourceBuilder =
       BeanDefinitionBuilder.genericBeanDefinition(beanClassName);
   resourceScriptSourceBuilder.addConstructorArgValue(scriptLocation);
   if (StringUtils.hasText(refreshDelayText)) {
     resourceScriptSourceBuilder.addConstructorArgValue(refreshDelayText);
   } else {
     resourceScriptSourceBuilder.addConstructorArgValue(-1L);
   }
   return resourceScriptSourceBuilder.getBeanDefinition();
 }
 @Override
 protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
   Class<?> clazz = determineClass(element, parserContext);
   BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(clazz);
   builder.addConstructorArgReference(element.getAttribute("twitter-template"));
   String tweetDataExpression = element.getAttribute("tweet-data-expression");
   if (StringUtils.hasText(tweetDataExpression)) {
     builder.addPropertyValue(
         "tweetDataExpression",
         BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class)
             .addConstructorArgValue(tweetDataExpression)
             .getBeanDefinition());
   }
   return builder.getBeanDefinition();
 }