private List<Descriptor> createJacksonDescriptor(String name, Class<?> type) {

    List<Descriptor> descriptors = new ArrayList<Descriptor>();

    for (BeanPropertyDefinition definition : new JacksonMetadata(mapper, type)) {

      AnnotatedMethod getter = definition.getGetter();
      Description description = getter.getAnnotation(Description.class);
      ResourceDescription fallback =
          SimpleResourceDescription.defaultFor(String.format("%s.%s", name, definition.getName()));
      ResourceDescription resourceDescription =
          description == null
              ? null
              : new AnnotationBasedResourceDescription(description, fallback);

      descriptors.add( //
          descriptor()
              . //
              name(definition.getName())
              . //
              type(Type.SEMANTIC)
              . //
              doc(getDocFor(resourceDescription))
              . //
              build());
    }

    return descriptors;
  }
  /**
   * Builds a descriptor for the projection parameter of the given resource.
   *
   * @param metadata
   * @param projectionConfiguration
   * @return
   */
  private Descriptor buildProjectionDescriptor(ResourceMetadata metadata) {

    ProjectionDefinitionConfiguration projectionConfiguration =
        configuration.projectionConfiguration();
    String projectionParameterName = projectionConfiguration.getParameterName();

    Map<String, Class<?>> projections =
        projectionConfiguration.getProjectionsFor(metadata.getDomainType());
    List<Descriptor> projectionDescriptors = new ArrayList<Descriptor>(projections.size());

    for (Entry<String, Class<?>> projection : projections.entrySet()) {

      Class<?> type = projection.getValue();
      String key =
          String.format(
              "%s.%s.%s", metadata.getRel(), projectionParameterName, projection.getKey());
      ResourceDescription fallback = SimpleResourceDescription.defaultFor(key);
      AnnotationBasedResourceDescription projectionDescription =
          new AnnotationBasedResourceDescription(type, fallback);

      projectionDescriptors.add( //
          descriptor()
              . //
              type(Type.SEMANTIC)
              . //
              name(projection.getKey())
              . //
              doc(getDocFor(projectionDescription))
              . //
              descriptors(createJacksonDescriptor(projection.getKey(), type))
              . //
              build());
    }

    return descriptor()
        . //
        type(Type.SEMANTIC)
        . //
        name(projectionParameterName)
        . //
        doc(getDocFor(SimpleResourceDescription.defaultFor(projectionParameterName)))
        . //
        descriptors(projectionDescriptors)
        .build();
  }
  /**
   * Creates the {@link Descriptor}s for pagination parameters.
   *
   * @param type
   * @return
   */
  private List<Descriptor> getPaginationDescriptors(Class<?> type, HttpMethod method) {

    RepositoryInformation information = repositories.getRepositoryInformationFor(type);

    if (!information.isPagingRepository() || !getType(method).equals(Type.SAFE)) {
      return Collections.emptyList();
    }

    Link linkToCollectionResource = entityLinks.linkToCollectionResource(type);
    List<TemplateVariable> variables = linkToCollectionResource.getVariables();
    List<Descriptor> descriptors = new ArrayList<Descriptor>(variables.size());

    ProjectionDefinitionConfiguration projectionConfiguration =
        configuration.projectionConfiguration();

    for (TemplateVariable variable : variables) {

      // Skip projection parameter
      if (projectionConfiguration.getParameterName().equals(variable.getName())) {
        continue;
      }

      ResourceDescription description =
          SimpleResourceDescription.defaultFor(variable.getDescription());

      descriptors.add( //
          descriptor()
              . //
              name(variable.getName())
              . //
              type(Type.SEMANTIC)
              . //
              doc(getDocFor(description))
              . //
              build());
    }

    return descriptors;
  }