private RuntimeBeanReference getConversionService(
     Element element, Object source, ParserContext parserContext) {
   RuntimeBeanReference conversionServiceRef;
   if (element.hasAttribute("conversion-service")) {
     conversionServiceRef = new RuntimeBeanReference(element.getAttribute("conversion-service"));
   } else {
     RootBeanDefinition conversionDef =
         new RootBeanDefinition(FormattingConversionServiceFactoryBean.class);
     conversionDef.setSource(source);
     conversionDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
     String conversionName =
         parserContext.getReaderContext().registerWithGeneratedName(conversionDef);
     parserContext.registerComponent(new BeanComponentDefinition(conversionDef, conversionName));
     conversionServiceRef = new RuntimeBeanReference(conversionName);
   }
   return conversionServiceRef;
 }
 private RuntimeBeanReference getValidator(
     Element element, Object source, ParserContext parserContext) {
   if (element.hasAttribute("validator")) {
     return new RuntimeBeanReference(element.getAttribute("validator"));
   } else if (javaxValidationPresent) {
     RootBeanDefinition validatorDef =
         new RootBeanDefinition(
             "org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean");
     validatorDef.setSource(source);
     validatorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
     String validatorName =
         parserContext.getReaderContext().registerWithGeneratedName(validatorDef);
     parserContext.registerComponent(new BeanComponentDefinition(validatorDef, validatorName));
     return new RuntimeBeanReference(validatorName);
   } else {
     return null;
   }
 }
  private RuntimeBeanReference getContentNegotiationManager(
      Element element, Object source, ParserContext parserContext) {

    RuntimeBeanReference beanRef;
    if (element.hasAttribute("content-negotiation-manager")) {
      String name = element.getAttribute("content-negotiation-manager");
      beanRef = new RuntimeBeanReference(name);
    } else {
      RootBeanDefinition factoryBeanDef =
          new RootBeanDefinition(ContentNegotiationManagerFactoryBean.class);
      factoryBeanDef.setSource(source);
      factoryBeanDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
      factoryBeanDef.getPropertyValues().add("mediaTypes", getDefaultMediaTypes());

      String name = CONTENT_NEGOTIATION_MANAGER_BEAN_NAME;
      parserContext.getReaderContext().getRegistry().registerBeanDefinition(name, factoryBeanDef);
      parserContext.registerComponent(new BeanComponentDefinition(factoryBeanDef, name));
      beanRef = new RuntimeBeanReference(name);
    }
    return beanRef;
  }
 private RootBeanDefinition createConverterDefinition(Class<?> converterClass, Object source) {
   RootBeanDefinition beanDefinition = new RootBeanDefinition(converterClass);
   beanDefinition.setSource(source);
   beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
   return beanDefinition;
 }
  @Override
  public BeanDefinition parse(Element element, ParserContext parserContext) {
    Object source = parserContext.extractSource(element);
    XmlReaderContext readerContext = parserContext.getReaderContext();

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

    RuntimeBeanReference contentNegotiationManager =
        getContentNegotiationManager(element, source, parserContext);

    RootBeanDefinition handlerMappingDef =
        new RootBeanDefinition(RequestMappingHandlerMapping.class);
    handlerMappingDef.setSource(source);
    handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    handlerMappingDef.getPropertyValues().add("order", 0);
    handlerMappingDef
        .getPropertyValues()
        .add("contentNegotiationManager", contentNegotiationManager);

    if (element.hasAttribute("enable-matrix-variables")) {
      Boolean enableMatrixVariables =
          Boolean.valueOf(element.getAttribute("enable-matrix-variables"));
      handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
    } else if (element.hasAttribute("enableMatrixVariables")) {
      Boolean enableMatrixVariables =
          Boolean.valueOf(element.getAttribute("enableMatrixVariables"));
      handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
    }

    configurePathMatchingProperties(handlerMappingDef, element, parserContext);
    readerContext
        .getRegistry()
        .registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME, handlerMappingDef);

    RuntimeBeanReference corsConfigurationsRef =
        MvcNamespaceUtils.registerCorsConfigurations(null, parserContext, source);
    handlerMappingDef.getPropertyValues().add("corsConfigurations", corsConfigurationsRef);

    RuntimeBeanReference conversionService = getConversionService(element, source, parserContext);
    RuntimeBeanReference validator = getValidator(element, source, parserContext);
    RuntimeBeanReference messageCodesResolver = getMessageCodesResolver(element);

    RootBeanDefinition bindingDef = new RootBeanDefinition(ConfigurableWebBindingInitializer.class);
    bindingDef.setSource(source);
    bindingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    bindingDef.getPropertyValues().add("conversionService", conversionService);
    bindingDef.getPropertyValues().add("validator", validator);
    bindingDef.getPropertyValues().add("messageCodesResolver", messageCodesResolver);

    ManagedList<?> messageConverters = getMessageConverters(element, source, parserContext);
    ManagedList<?> argumentResolvers = getArgumentResolvers(element, parserContext);
    ManagedList<?> returnValueHandlers = getReturnValueHandlers(element, parserContext);
    String asyncTimeout = getAsyncTimeout(element);
    RuntimeBeanReference asyncExecutor = getAsyncExecutor(element);
    ManagedList<?> callableInterceptors = getCallableInterceptors(element, source, parserContext);
    ManagedList<?> deferredResultInterceptors =
        getDeferredResultInterceptors(element, source, parserContext);

    RootBeanDefinition handlerAdapterDef =
        new RootBeanDefinition(RequestMappingHandlerAdapter.class);
    handlerAdapterDef.setSource(source);
    handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    handlerAdapterDef
        .getPropertyValues()
        .add("contentNegotiationManager", contentNegotiationManager);
    handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);
    handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);
    addRequestBodyAdvice(handlerAdapterDef);
    addResponseBodyAdvice(handlerAdapterDef);

    if (element.hasAttribute("ignore-default-model-on-redirect")) {
      Boolean ignoreDefaultModel =
          Boolean.valueOf(element.getAttribute("ignore-default-model-on-redirect"));
      handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);
    } else if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {
      // "ignoreDefaultModelOnRedirect" spelling is deprecated
      Boolean ignoreDefaultModel =
          Boolean.valueOf(element.getAttribute("ignoreDefaultModelOnRedirect"));
      handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);
    }

    if (argumentResolvers != null) {
      handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);
    }
    if (returnValueHandlers != null) {
      handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
    }
    if (asyncTimeout != null) {
      handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout);
    }
    if (asyncExecutor != null) {
      handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);
    }

    handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);
    handlerAdapterDef
        .getPropertyValues()
        .add("deferredResultInterceptors", deferredResultInterceptors);
    readerContext
        .getRegistry()
        .registerBeanDefinition(HANDLER_ADAPTER_BEAN_NAME, handlerAdapterDef);

    String uriCompContribName = MvcUriComponentsBuilder.MVC_URI_COMPONENTS_CONTRIBUTOR_BEAN_NAME;
    RootBeanDefinition uriCompContribDef =
        new RootBeanDefinition(CompositeUriComponentsContributorFactoryBean.class);
    uriCompContribDef.setSource(source);
    uriCompContribDef.getPropertyValues().addPropertyValue("handlerAdapter", handlerAdapterDef);
    uriCompContribDef.getPropertyValues().addPropertyValue("conversionService", conversionService);
    readerContext.getRegistry().registerBeanDefinition(uriCompContribName, uriCompContribDef);

    RootBeanDefinition csInterceptorDef =
        new RootBeanDefinition(ConversionServiceExposingInterceptor.class);
    csInterceptorDef.setSource(source);
    csInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, conversionService);
    RootBeanDefinition mappedCsInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
    mappedCsInterceptorDef.setSource(source);
    mappedCsInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    mappedCsInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
    mappedCsInterceptorDef
        .getConstructorArgumentValues()
        .addIndexedArgumentValue(1, csInterceptorDef);
    String mappedInterceptorName = readerContext.registerWithGeneratedName(mappedCsInterceptorDef);

    RootBeanDefinition exceptionHandlerExceptionResolver =
        new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);
    exceptionHandlerExceptionResolver.setSource(source);
    exceptionHandlerExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    exceptionHandlerExceptionResolver
        .getPropertyValues()
        .add("contentNegotiationManager", contentNegotiationManager);
    exceptionHandlerExceptionResolver
        .getPropertyValues()
        .add("messageConverters", messageConverters);
    exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0);
    addResponseBodyAdvice(exceptionHandlerExceptionResolver);

    String methodExceptionResolverName =
        readerContext.registerWithGeneratedName(exceptionHandlerExceptionResolver);

    RootBeanDefinition responseStatusExceptionResolver =
        new RootBeanDefinition(ResponseStatusExceptionResolver.class);
    responseStatusExceptionResolver.setSource(source);
    responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    responseStatusExceptionResolver.getPropertyValues().add("order", 1);
    String responseStatusExceptionResolverName =
        readerContext.registerWithGeneratedName(responseStatusExceptionResolver);

    RootBeanDefinition defaultExceptionResolver =
        new RootBeanDefinition(DefaultHandlerExceptionResolver.class);
    defaultExceptionResolver.setSource(source);
    defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    defaultExceptionResolver.getPropertyValues().add("order", 2);
    String defaultExceptionResolverName =
        readerContext.registerWithGeneratedName(defaultExceptionResolver);

    parserContext.registerComponent(
        new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
    parserContext.registerComponent(
        new BeanComponentDefinition(handlerAdapterDef, HANDLER_ADAPTER_BEAN_NAME));
    parserContext.registerComponent(
        new BeanComponentDefinition(uriCompContribDef, uriCompContribName));
    parserContext.registerComponent(
        new BeanComponentDefinition(
            exceptionHandlerExceptionResolver, methodExceptionResolverName));
    parserContext.registerComponent(
        new BeanComponentDefinition(
            responseStatusExceptionResolver, responseStatusExceptionResolverName));
    parserContext.registerComponent(
        new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));
    parserContext.registerComponent(
        new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));

    // Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off"
    MvcNamespaceUtils.registerDefaultComponents(parserContext, source);

    parserContext.popAndRegisterContainingComponent();

    return null;
  }