Search in sources :

Example 31 with ResourceInformation

use of io.crnk.core.engine.information.resource.ResourceInformation in project crnk-framework by crnk-project.

the class ResourcePatch method handle.

@Override
public Response handle(JsonPath jsonPath, QueryAdapter queryAdapter, RepositoryMethodParameterProvider parameterProvider, Document requestDocument) {
    RegistryEntry endpointRegistryEntry = getRegistryEntry(jsonPath);
    final Resource resourceBody = getRequestBody(requestDocument, jsonPath, HttpMethod.PATCH);
    RegistryEntry bodyRegistryEntry = resourceRegistry.getEntry(resourceBody.getType());
    String idString = jsonPath.getIds().getIds().get(0);
    ResourceInformation resourceInformation = bodyRegistryEntry.getResourceInformation();
    Serializable resourceId = resourceInformation.parseIdString(idString);
    verifyTypes(HttpMethod.PATCH, endpointRegistryEntry, bodyRegistryEntry);
    ResourceRepositoryAdapter resourceRepository = endpointRegistryEntry.getResourceRepository(parameterProvider);
    JsonApiResponse resourceFindResponse = resourceRepository.findOne(resourceId, queryAdapter);
    Object resource = resourceFindResponse.getEntity();
    if (resource == null) {
        throw new ResourceNotFoundException(jsonPath.toString());
    }
    final Resource resourceFindData = documentMapper.toDocument(resourceFindResponse, queryAdapter, parameterProvider).getSingleData().get();
    resourceInformation.verify(resource, requestDocument);
    // extract current attributes from findOne without any manipulation by query params (such as sparse fieldsets)
    ExceptionUtil.wrapCatchedExceptions(new Callable<Object>() {

        @Override
        public Object call() throws Exception {
            String attributesFromFindOne = extractAttributesFromResourceAsJson(resourceFindData);
            Map<String, Object> attributesToUpdate = new HashMap<>(emptyIfNull(objectMapper.readValue(attributesFromFindOne, Map.class)));
            // deserialize the request JSON's attributes object into a map
            String attributesAsJson = objectMapper.writeValueAsString(resourceBody.getAttributes());
            Map<String, Object> attributesFromRequest = emptyIfNull(objectMapper.readValue(attributesAsJson, Map.class));
            // remove attributes that were omitted in the request
            Iterator<String> it = attributesToUpdate.keySet().iterator();
            while (it.hasNext()) {
                String key = it.next();
                if (!attributesFromRequest.containsKey(key)) {
                    it.remove();
                }
            }
            // walk the source map and apply target values from request
            updateValues(attributesToUpdate, attributesFromRequest);
            Map<String, JsonNode> upsertedAttributes = new HashMap<>();
            for (Map.Entry<String, Object> entry : attributesToUpdate.entrySet()) {
                JsonNode value = objectMapper.valueToTree(entry.getValue());
                upsertedAttributes.put(entry.getKey(), value);
            }
            resourceBody.setAttributes(upsertedAttributes);
            return null;
        }
    }, "failed to merge patched attributes");
    JsonApiResponse updatedResource;
    Set<String> loadedRelationshipNames;
    if (resourceInformation.getResourceClass() == Resource.class) {
        loadedRelationshipNames = getLoadedRelationshipNames(resourceBody);
        updatedResource = resourceRepository.update(resourceBody, queryAdapter);
    } else {
        setAttributes(resourceBody, resource, bodyRegistryEntry.getResourceInformation());
        setRelations(resource, bodyRegistryEntry, resourceBody, queryAdapter, parameterProvider, false);
        loadedRelationshipNames = getLoadedRelationshipNames(resourceBody);
        updatedResource = resourceRepository.update(resource, queryAdapter);
    }
    Document responseDocument = documentMapper.toDocument(updatedResource, queryAdapter, parameterProvider, loadedRelationshipNames);
    return new Response(responseDocument, 200);
}
Also used : ResourceInformation(io.crnk.core.engine.information.resource.ResourceInformation) Serializable(java.io.Serializable) Resource(io.crnk.core.engine.document.Resource) JsonNode(com.fasterxml.jackson.databind.JsonNode) Document(io.crnk.core.engine.document.Document) RegistryEntry(io.crnk.core.engine.registry.RegistryEntry) ResourceNotFoundException(io.crnk.core.exception.ResourceNotFoundException) IOException(java.io.IOException) JsonApiResponse(io.crnk.core.repository.response.JsonApiResponse) Response(io.crnk.core.engine.dispatcher.Response) RegistryEntry(io.crnk.core.engine.registry.RegistryEntry) ResourceRepositoryAdapter(io.crnk.core.engine.internal.repository.ResourceRepositoryAdapter) JsonApiResponse(io.crnk.core.repository.response.JsonApiResponse) ResourceNotFoundException(io.crnk.core.exception.ResourceNotFoundException)

Example 32 with ResourceInformation

use of io.crnk.core.engine.information.resource.ResourceInformation in project crnk-framework by crnk-project.

the class IncludeLookupSetter method lookupRelatedResourcesWithId.

private Set<Resource> lookupRelatedResourcesWithId(Collection<Resource> sourceResources, ResourceField relationshipField, QueryAdapter queryAdapter, RepositoryMethodParameterProvider parameterProvider, Map<ResourceIdentifier, Resource> resourceMap, Map<ResourceIdentifier, Object> entityMap, ResourceMappingConfig resourceMappingConfig) {
    String oppositeResourceType = relationshipField.getOppositeResourceType();
    RegistryEntry oppositeEntry = resourceRegistry.getEntry(oppositeResourceType);
    if (oppositeEntry == null) {
        throw new RepositoryNotFoundException("no resource with type " + oppositeResourceType + " found");
    }
    ResourceInformation oppositeResourceInformation = oppositeEntry.getResourceInformation();
    ResourceRepositoryAdapter oppositeResourceRepository = oppositeEntry.getResourceRepository(parameterProvider);
    if (oppositeResourceRepository == null) {
        throw new RepositoryNotFoundException("no relationship repository found for " + oppositeResourceInformation.getResourceType());
    }
    Set<Resource> related = new HashSet<>();
    Set<Object> relatedIdsToLoad = new HashSet<>();
    for (Resource sourceResource : sourceResources) {
        Relationship relationship = sourceResource.getRelationships().get(relationshipField.getJsonName());
        PreconditionUtil.assertTrue("expected relationship data to be loaded for @JsonApiResourceId annotated field", relationship.getData().isPresent());
        if (relationship.getData().get() != null) {
            for (ResourceIdentifier id : relationship.getCollectionData().get()) {
                if (resourceMap.containsKey(id)) {
                    // load from cache
                    related.add(resourceMap.get(id));
                } else {
                    relatedIdsToLoad.add(oppositeResourceInformation.parseIdString(id.getId()));
                }
            }
        }
    }
    if (!relatedIdsToLoad.isEmpty()) {
        JsonApiResponse response = oppositeResourceRepository.findAll(relatedIdsToLoad, queryAdapter);
        Collection responseList = (Collection) response.getEntity();
        for (Object responseEntity : responseList) {
            Resource relatedResource = mergeResource(responseEntity, queryAdapter, resourceMap, entityMap, resourceMappingConfig);
            related.add(relatedResource);
            Object responseEntityId = oppositeResourceInformation.getId(responseEntity);
            relatedIdsToLoad.remove(responseEntityId);
        }
        if (!relatedIdsToLoad.isEmpty()) {
            throw new ResourceNotFoundException("type=" + relationshipField.getOppositeResourceType() + ", " + "ids=" + relatedIdsToLoad);
        }
    }
    return related;
}
Also used : ResourceInformation(io.crnk.core.engine.information.resource.ResourceInformation) Resource(io.crnk.core.engine.document.Resource) RepositoryNotFoundException(io.crnk.core.exception.RepositoryNotFoundException) RegistryEntry(io.crnk.core.engine.registry.RegistryEntry) ResourceIdentifier(io.crnk.core.engine.document.ResourceIdentifier) ResourceRepositoryAdapter(io.crnk.core.engine.internal.repository.ResourceRepositoryAdapter) Relationship(io.crnk.core.engine.document.Relationship) Collection(java.util.Collection) JsonApiResponse(io.crnk.core.repository.response.JsonApiResponse) ResourceNotFoundException(io.crnk.core.exception.ResourceNotFoundException) HashSet(java.util.HashSet)

Example 33 with ResourceInformation

use of io.crnk.core.engine.information.resource.ResourceInformation in project crnk-framework by crnk-project.

the class ResourceRegistryImpl method getBaseResourceInformation.

@Override
public ResourceInformation getBaseResourceInformation(String resourceType) {
    ResourceInformation baseInformation = baseTypeCache.get(resourceType);
    if (baseInformation != null) {
        return baseInformation;
    }
    RegistryEntry entry = getEntry(resourceType);
    baseInformation = entry.getResourceInformation();
    while (baseInformation.getSuperResourceType() != null) {
        String superResourceType = baseInformation.getSuperResourceType();
        entry = getEntry(superResourceType);
        PreconditionUtil.assertNotNull(superResourceType, entry);
        baseInformation = entry.getResourceInformation();
    }
    baseTypeCache.put(resourceType, baseInformation);
    return baseInformation;
}
Also used : ResourceInformation(io.crnk.core.engine.information.resource.ResourceInformation) RegistryEntry(io.crnk.core.engine.registry.RegistryEntry)

Example 34 with ResourceInformation

use of io.crnk.core.engine.information.resource.ResourceInformation in project crnk-framework by crnk-project.

the class DefaultResourceInformationProvider method build.

public ResourceInformation build(Class<?> resourceClass, boolean allowNonResourceBaseClass) {
    List<ResourceField> resourceFields = getResourceFields(resourceClass);
    String resourceType = getResourceType(resourceClass, allowNonResourceBaseClass);
    Optional<JsonPropertyOrder> propertyOrder = ClassUtils.getAnnotation(resourceClass, JsonPropertyOrder.class);
    if (propertyOrder.isPresent()) {
        JsonPropertyOrder propertyOrderAnnotation = propertyOrder.get();
        Collections.sort(resourceFields, new FieldOrderedComparator(propertyOrderAnnotation.value(), propertyOrderAnnotation.alphabetic()));
    }
    DefaultResourceInstanceBuilder<?> instanceBuilder = new DefaultResourceInstanceBuilder(resourceClass);
    Class<?> superclass = resourceClass.getSuperclass();
    String superResourceType = superclass != Object.class && context.accept(superclass) ? context.getResourceType(superclass) : null;
    ResourceInformation information = new ResourceInformation(context.getTypeParser(), resourceClass, resourceType, superResourceType, instanceBuilder, resourceFields, pagingBehaviors.get(ClassUtils.getAnnotation(resourceClass, JsonApiResource.class).get().pagingBehavior()));
    if (!allowNonResourceBaseClass && information.getIdField() == null) {
        throw new ResourceIdNotFoundException(resourceClass.getCanonicalName());
    }
    return information;
}
Also used : FieldOrderedComparator(io.crnk.core.engine.internal.utils.FieldOrderedComparator) ResourceField(io.crnk.core.engine.information.resource.ResourceField) ResourceInformation(io.crnk.core.engine.information.resource.ResourceInformation) JsonPropertyOrder(com.fasterxml.jackson.annotation.JsonPropertyOrder) ResourceIdNotFoundException(io.crnk.core.exception.ResourceIdNotFoundException)

Example 35 with ResourceInformation

use of io.crnk.core.engine.information.resource.ResourceInformation in project crnk-framework by crnk-project.

the class RelationshipsResourceUpsert method handle.

@Override
public final Response handle(JsonPath jsonPath, QueryAdapter queryAdapter, RepositoryMethodParameterProvider parameterProvider, Document requestBody) {
    String resourceName = jsonPath.getResourceType();
    PathIds resourceIds = jsonPath.getIds();
    RegistryEntry registryEntry = getRegistryEntry(resourceName);
    assertRequestDocument(requestBody, HttpMethod.POST, resourceName);
    Serializable castedResourceId = getResourceId(resourceIds, registryEntry);
    ResourceField relationshipField = registryEntry.getResourceInformation().findRelationshipFieldByName(jsonPath.getElementName());
    verifyFieldNotNull(relationshipField, jsonPath.getElementName());
    ResourceRepositoryAdapter resourceRepository = registryEntry.getResourceRepository(parameterProvider);
    @SuppressWarnings("unchecked") Object resource = resourceRepository.findOne(castedResourceId, queryAdapter).getEntity();
    ResourceInformation targetInformation = getRegistryEntry(relationshipField.getOppositeResourceType()).getResourceInformation();
    @SuppressWarnings("unchecked") RelationshipRepositoryAdapter relationshipRepositoryForClass = registryEntry.getRelationshipRepository(relationshipField, parameterProvider);
    if (Iterable.class.isAssignableFrom(relationshipField.getType())) {
        Iterable<ResourceIdentifier> dataBodies = (Iterable<ResourceIdentifier>) (requestBody.isMultiple() ? requestBody.getData().get() : Collections.singletonList(requestBody.getData().get()));
        processToManyRelationship(resource, targetInformation, relationshipField, dataBodies, queryAdapter, relationshipRepositoryForClass);
    } else {
        if (requestBody.isMultiple()) {
            throw new RequestBodyException(HttpMethod.POST, resourceName, "Multiple data in body");
        }
        ResourceIdentifier dataBody = (ResourceIdentifier) requestBody.getData().get();
        processToOneRelationship(resource, targetInformation, relationshipField, dataBody, queryAdapter, relationshipRepositoryForClass);
    }
    return new Response(new Document(), HttpStatus.NO_CONTENT_204);
}
Also used : Serializable(java.io.Serializable) ResourceInformation(io.crnk.core.engine.information.resource.ResourceInformation) Document(io.crnk.core.engine.document.Document) RegistryEntry(io.crnk.core.engine.registry.RegistryEntry) RelationshipRepositoryAdapter(io.crnk.core.engine.internal.repository.RelationshipRepositoryAdapter) Response(io.crnk.core.engine.dispatcher.Response) ResourceField(io.crnk.core.engine.information.resource.ResourceField) ResourceIdentifier(io.crnk.core.engine.document.ResourceIdentifier) RequestBodyException(io.crnk.core.exception.RequestBodyException) ResourceRepositoryAdapter(io.crnk.core.engine.internal.repository.ResourceRepositoryAdapter) PathIds(io.crnk.core.engine.internal.dispatcher.path.PathIds)

Aggregations

ResourceInformation (io.crnk.core.engine.information.resource.ResourceInformation)167 Test (org.junit.Test)79 ResourceField (io.crnk.core.engine.information.resource.ResourceField)76 RegistryEntry (io.crnk.core.engine.registry.RegistryEntry)60 QuerySpec (io.crnk.core.queryspec.QuerySpec)16 Resource (io.crnk.core.engine.document.Resource)15 ResourceRegistry (io.crnk.core.engine.registry.ResourceRegistry)15 QueryAdapter (io.crnk.core.engine.query.QueryAdapter)9 Task (io.crnk.core.mock.models.Task)9 JsonApiResponse (io.crnk.core.repository.response.JsonApiResponse)9 HashSet (java.util.HashSet)9 Collection (java.util.Collection)8 Relationship (io.crnk.core.engine.document.Relationship)7 HttpMethod (io.crnk.core.engine.http.HttpMethod)7 ResourceRepositoryAdapter (io.crnk.core.engine.internal.repository.ResourceRepositoryAdapter)7 QuerySpecAdapter (io.crnk.core.queryspec.internal.QuerySpecAdapter)7 OffsetLimitPagingBehavior (io.crnk.core.queryspec.pagingspec.OffsetLimitPagingBehavior)7 DefaultResourceList (io.crnk.core.resource.list.DefaultResourceList)7 Set (java.util.Set)7 JsonNode (com.fasterxml.jackson.databind.JsonNode)6