private List<Descriptor> getProjectionDescriptor(Class<?> type, HttpMethod method) {

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

    ProjectionDefinitionConfiguration projectionConfiguration =
        configuration.projectionConfiguration();

    return projectionConfiguration.hasProjectionFor(type)
        ? Arrays.asList(buildProjectionDescriptor(mappings.getMetadataFor(type)))
        : Collections.<Descriptor>emptyList();
  }
  /**
   * 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();
  }
  /** @see DATAREST-221 */
  @Test
  public void invokesProjectionFactoryIfProjectionFound() {

    configuration.addProjection(Sample.class, Object.class);

    Projector projector = new PersistentEntityProjector(configuration, factory, "sample");
    Object source = new Object();
    projector.project(source);

    verify(factory, times(1)).createProjection(source, Sample.class);
  }
  /**
   * 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;
  }