/** @see DATAREST-791 */
  @Test
  public void usesRepositoryInvokerToLookupRelatedInstance() throws Exception {

    KeyValuePersistentEntity<?> entity = mappingContext.getPersistentEntity(Sample.class);

    ResourceMappings mappings =
        new PersistentEntitiesResourceMappings(
            new PersistentEntities(Collections.singleton(mappingContext)));
    ResourceMetadata metadata = spy(mappings.getMetadataFor(Sample.class));
    when(metadata.getSupportedHttpMethods()).thenReturn(AllSupportedHttpMethods.INSTANCE);

    RepositoryPropertyReferenceController controller =
        new RepositoryPropertyReferenceController(repositories, invokerFactory, assembler);
    controller.setApplicationEventPublisher(publisher);

    doReturn(invoker).when(invokerFactory).getInvokerFor(Reference.class);
    doReturn(new Sample()).when(invoker).invokeFindOne(4711);
    doReturn(new Reference()).when(invoker).invokeFindOne("some-id");
    doReturn(new Sample()).when(invoker).invokeSave(any(Object.class));

    RootResourceInformation information = new RootResourceInformation(metadata, entity, invoker);
    Resources<Object> request =
        new Resources<Object>(Collections.emptySet(), new Link("/reference/some-id"));

    controller.createPropertyReference(information, HttpMethod.POST, request, 4711, "references");

    verify(invokerFactory).getInvokerFor(Reference.class);
    verify(invoker).invokeFindOne("some-id");
  }
  private Descriptor buildCollectionResourceDescriptor(
      Class<?> type,
      RootResourceInformation resourceInformation,
      Descriptor representationDescriptor,
      HttpMethod method) {

    ResourceMetadata metadata = mappings.getMetadataFor(type);

    List<Descriptor> nestedDescriptors = new ArrayList<Descriptor>();
    nestedDescriptors.addAll(getPaginationDescriptors(type, method));
    nestedDescriptors.addAll(getProjectionDescriptor(type, method));

    Type descriptorType = getType(method);
    return descriptor()
        . //
        id(prefix(method).concat(metadata.getRel()))
        . //
        name(metadata.getRel())
        . //
        type(descriptorType)
        . //
        doc(getDocFor(metadata.getDescription()))
        . //
        rt("#" + representationDescriptor.getId())
        . //
        descriptors(nestedDescriptors)
        .build();
  }
  /** @see DATAREST-111 */
  @Test
  public void looksUpRepositoryEntityControllerMethodCorrectly() throws Exception {

    when(mappings.exportsTopLevelResourceFor("people")).thenReturn(true);
    mockRequest = new MockHttpServletRequest("GET", "/people");

    HandlerMethod method = handlerMapping.lookupHandlerMethod("/people", mockRequest);

    assertThat(method, is(notNullValue()));
    assertThat(method.getMethod(), is(listEntitiesMethod));
  }
  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();
  }
  private Descriptor buildRepresentationDescriptor(Class<?> type) {

    ResourceMetadata metadata = mappings.getMetadataFor(type);

    return descriptor()
        . //
        id(getRepresentationDescriptorId(metadata))
        . //
        href(entityLinks.linkFor(type).slash("schema").toString())
        . //
        doc(getDocFor(metadata.getItemResourceDescription()))
        . //
        descriptors(buildPropertyDescriptors(type, metadata.getItemResourceRel()))
        . //
        build();
  }
  protected RepositoryRestRequest getRequest(Class<?> domainType, RequestParameters parameters) {

    Assert.notNull(domainType, "Domain type must not be null!");

    MockHttpServletRequest request = new MockHttpServletRequest();
    request.setParameters(parameters.asMap());

    ServletRequestAttributes requestAttributes = new ServletRequestAttributes(request);
    RequestContextHolder.setRequestAttributes(requestAttributes);

    PersistentEntity<?, ?> entity = repositories.getPersistentEntity(domainType);

    return new RepositoryRestRequest(
        entity,
        new ServletWebRequest(request),
        mappings.getMappingFor(domainType),
        invokerFactory.getInvokerFor(domainType));
  }
  private Collection<Descriptor> buildSearchResourceDescriptors(PersistentEntity<?, ?> entity) {

    ResourceMetadata metadata = mappings.getMetadataFor(entity.getType());
    List<Descriptor> descriptors = new ArrayList<Descriptor>();

    for (MethodResourceMapping methodMapping : metadata.getSearchResourceMappings()) {

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

      for (ParameterMetadata parameterMetadata : methodMapping.getParametersMetadata()) {

        parameterDescriptors.add( //
            descriptor()
                . //
                name(parameterMetadata.getName())
                . //
                doc(getDocFor(parameterMetadata.getDescription()))
                . //
                type(Type.SEMANTIC) //
                .build());
      }

      descriptors.add(
          descriptor()
              . //
              type(Type.SAFE)
              . //
              name(methodMapping.getRel())
              . //
              descriptors(parameterDescriptors)
              . //
              build());
    }

    return descriptors;
  }
  private Descriptor buildItemResourceDescriptor(
      RootResourceInformation resourceInformation,
      Descriptor representationDescriptor,
      HttpMethod method) {

    PersistentEntity<?, ?> entity = resourceInformation.getPersistentEntity();
    ResourceMetadata metadata = mappings.getMetadataFor(entity.getType());

    return descriptor()
        . //
        id(prefix(method).concat(metadata.getItemResourceRel()))
        . //
        name(metadata.getItemResourceRel())
        . //
        type(getType(method))
        . //
        doc(getDocFor(metadata.getItemResourceDescription()))
        . //
        rt("#".concat(representationDescriptor.getId()))
        . //
        descriptors(getProjectionDescriptor(entity.getType(), method))
        . //
        build();
  }
  /*
   * (non-Javadoc)
   * @see org.springframework.core.convert.converter.GenericConverter#convert(java.lang.Object, org.springframework.core.convert.TypeDescriptor, org.springframework.core.convert.TypeDescriptor)
   */
  @Override
  public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {

    PersistentEntity<?, ?> persistentEntity = repositories.getPersistentEntity((Class<?>) source);
    final ResourceMetadata metadata = mappings.getMappingFor(persistentEntity.getType());
    final JsonSchema jsonSchema =
        new JsonSchema(
            persistentEntity.getName(), accessor.getMessage(metadata.getItemResourceDescription()));

    persistentEntity.doWithProperties(
        new SimplePropertyHandler() {

          /*
           * (non-Javadoc)
           * @see org.springframework.data.mapping.PropertyHandler#doWithPersistentProperty(org.springframework.data.mapping.PersistentProperty)
           */
          @Override
          public void doWithPersistentProperty(PersistentProperty<?> persistentProperty) {

            Class<?> propertyType = persistentProperty.getType();
            String type = uncapitalize(propertyType.getSimpleName());

            ResourceMapping propertyMapping = metadata.getMappingFor(persistentProperty);
            ResourceDescription description = propertyMapping.getDescription();
            String message = accessor.getMessage(description);

            Property property =
                persistentProperty.isCollectionLike()
                    ? //
                    new ArrayProperty("array", message, false)
                    : new Property(type, message, false);

            jsonSchema.addProperty(persistentProperty.getName(), property);
          }
        });

    final List<Link> links = new ArrayList<Link>();

    persistentEntity.doWithAssociations(
        new SimpleAssociationHandler() {

          /*
           * (non-Javadoc)
           * @see org.springframework.data.mapping.AssociationHandler#doWithAssociation(org.springframework.data.mapping.Association)
           */
          @Override
          public void doWithAssociation(Association<? extends PersistentProperty<?>> association) {

            PersistentProperty<?> persistentProperty = association.getInverse();

            if (!metadata.isExported(persistentProperty)) {
              return;
            }

            RepositoryLinkBuilder builder =
                new RepositoryLinkBuilder(metadata, config.getBaseUri()).slash("{id}");
            maybeAddAssociationLink(builder, mappings, persistentProperty, links);
          }
        });

    jsonSchema.add(links);

    return jsonSchema;
  }
  private List<Descriptor> buildPropertyDescriptors(final Class<?> type, String baseRel) {

    final PersistentEntity<?, ?> entity = persistentEntities.getPersistentEntity(type);
    final List<Descriptor> propertyDescriptors = new ArrayList<Descriptor>();
    final JacksonMetadata jackson = new JacksonMetadata(mapper, type);
    final AssociationLinks associationLinks = new AssociationLinks(mappings);
    final ResourceMetadata metadata = mappings.getMetadataFor(entity.getType());

    entity.doWithProperties(
        new SimplePropertyHandler() {

          @Override
          public void doWithPersistentProperty(PersistentProperty<?> property) {

            BeanPropertyDefinition propertyDefinition = jackson.getDefinitionFor(property);
            ResourceMapping propertyMapping = metadata.getMappingFor(property);

            if (propertyDefinition != null) {

              if (property.isIdProperty()
                  && !configuration.isIdExposedFor(property.getOwner().getType())) {
                return;
              }

              propertyDescriptors.add( //
                  descriptor()
                      . //
                      type(Type.SEMANTIC)
                      . //
                      name(propertyDefinition.getName())
                      . //
                      doc(getDocFor(propertyMapping.getDescription()))
                      . //
                      build());
            }
          }
        });

    entity.doWithAssociations(
        new SimpleAssociationHandler() {

          @Override
          public void doWithAssociation(Association<? extends PersistentProperty<?>> association) {

            PersistentProperty<?> property = association.getInverse();

            if (!jackson.isExported(property)
                || !associationLinks.isLinkableAssociation(property)) {
              return;
            }

            ResourceMapping mapping = metadata.getMappingFor(property);

            DescriptorBuilder builder =
                descriptor()
                    . //
                    name(mapping.getRel())
                    .doc(getDocFor(mapping.getDescription()));

            ResourceMetadata targetTypeMetadata = mappings.getMetadataFor(property.getActualType());
            String localPath =
                targetTypeMetadata
                    .getRel()
                    .concat("#")
                    .concat(getRepresentationDescriptorId(targetTypeMetadata));
            Link link =
                ControllerLinkBuilder.linkTo(AlpsController.class)
                    .slash(AlpsController.ALPS_ROOT_MAPPING)
                    .slash(localPath)
                    .withSelfRel();

            builder
                . //
                type(Type.SAFE)
                . //
                rt(link.getHref());

            propertyDescriptors.add(builder.build());
          }
        });

    return propertyDescriptors;
  }
 protected ResourceMetadata getMetadata(Class<?> domainType) {
   return mappings.getMappingFor(domainType);
 }