/*
   * (non-Javadoc)
   * @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry)
   */
  @Override
  public void registerBeanDefinitions(
      AnnotationMetadata metadata, BeanDefinitionRegistry registry) {

    linkBuilderBeanDefinitionRegistrar.registerBeanDefinitions(metadata, registry);

    Map<String, Object> attributes =
        metadata.getAnnotationAttributes(EnableHypermediaSupport.class.getName());
    Collection<HypermediaType> types = Arrays.asList((HypermediaType[]) attributes.get("type"));

    for (HypermediaType type : types) {

      if (JSONPATH_PRESENT) {

        AbstractBeanDefinition linkDiscovererBeanDefinition = getLinkDiscovererBeanDefinition(type);
        registerBeanDefinition(
            new BeanDefinitionHolder(
                linkDiscovererBeanDefinition,
                BeanDefinitionReaderUtils.generateBeanName(linkDiscovererBeanDefinition, registry)),
            registry);
      }
    }

    if (types.contains(HypermediaType.HAL)) {

      if (JACKSON2_PRESENT) {

        BeanDefinitionBuilder halQueryMapperBuilder = rootBeanDefinition(ObjectMapper.class);
        registerSourcedBeanDefinition(
            halQueryMapperBuilder, metadata, registry, HAL_OBJECT_MAPPER_BEAN_NAME);

        BeanDefinitionBuilder customizerBeanDefinition =
            rootBeanDefinition(DefaultObjectMapperCustomizer.class);
        registerSourcedBeanDefinition(customizerBeanDefinition, metadata, registry);

        BeanDefinitionBuilder builder =
            rootBeanDefinition(Jackson2ModuleRegisteringBeanPostProcessor.class);
        registerSourcedBeanDefinition(builder, metadata, registry);
      }
    }

    if (!types.isEmpty()) {

      BeanDefinitionBuilder linkDiscoverersRegistryBuilder =
          BeanDefinitionBuilder.rootBeanDefinition(PluginRegistryFactoryBean.class);
      linkDiscoverersRegistryBuilder.addPropertyValue("type", LinkDiscoverer.class);
      registerSourcedBeanDefinition(
          linkDiscoverersRegistryBuilder, metadata, registry, LINK_DISCOVERER_REGISTRY_BEAN_NAME);

      BeanDefinitionBuilder linkDiscoverersBuilder =
          BeanDefinitionBuilder.rootBeanDefinition(LinkDiscoverers.class);
      linkDiscoverersBuilder.addConstructorArgReference(LINK_DISCOVERER_REGISTRY_BEAN_NAME);
      registerSourcedBeanDefinition(linkDiscoverersBuilder, metadata, registry);
    }

    registerRelProviderPluginRegistryAndDelegate(registry);
  }
  private static String registerSourcedBeanDefinition(
      BeanDefinitionBuilder builder,
      AnnotationMetadata metadata,
      BeanDefinitionRegistry registry,
      String name) {

    AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
    beanDefinition.setSource(metadata);

    BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, name);
    registerBeanDefinition(holder, registry);
    return name;
  }