use of io.crnk.core.engine.document.Resource in project crnk-framework by crnk-project.
the class DependencyOrderStrategyTest method addManyDependency.
private void addManyDependency(Operation op1, Operation op2, String relationshipName) {
Resource resource1 = op1.getValue();
Resource resource2 = op2.getValue();
Relationship relationship = resource1.getRelationships().get(relationshipName);
if (relationship == null) {
relationship = new Relationship();
relationship.setData((Nullable) Nullable.of(new ArrayList<ResourceIdentifier>()));
resource1.getRelationships().put(relationshipName, relationship);
}
ResourceIdentifier resourceId = new ResourceIdentifier(resource2.getId(), resource2.getType());
relationship.getCollectionData().get().add(resourceId);
}
use of io.crnk.core.engine.document.Resource in project crnk-framework by crnk-project.
the class OperationsDeleteRelationTest method testDeleteRelation.
@Test
public void testDeleteRelation() {
PersonEntity person1 = newPerson("1");
PersonEntity person2 = newPerson("2");
MovieEntity movie = newMovie("test");
movie.setDirectors(new HashSet<>(Arrays.asList(person1, person2)));
OperationsCall insertCall = operationsClient.createCall();
insertCall.add(HttpMethod.POST, movie);
insertCall.add(HttpMethod.POST, person1);
insertCall.add(HttpMethod.POST, person2);
insertCall.execute();
QuerySpec querySpec = new QuerySpec(MovieEntity.class);
querySpec.includeRelation(Arrays.asList("directors"));
MovieEntity updatedMovie = movieRepo.findOne(movie.getId(), querySpec);
Set<PersonEntity> directors = updatedMovie.getDirectors();
PersonEntity deletedDirector = directors.iterator().next();
directors.remove(deletedDirector);
OperationsCall call = operationsClient.createCall();
call.add(HttpMethod.PATCH, updatedMovie);
call.add(HttpMethod.DELETE, deletedDirector);
call.execute();
// check whether updated relationship is included in the response
Resource movieResource = call.getResponse(0).getSingleData().get();
Relationship directorsRelationship = movieResource.getRelationships().get("directors");
List<ResourceIdentifier> directorIds = directorsRelationship.getCollectionData().get();
Assert.assertEquals(1, directorIds.size());
}
use of io.crnk.core.engine.document.Resource 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);
}
use of io.crnk.core.engine.document.Resource 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;
}
use of io.crnk.core.engine.document.Resource in project crnk-framework by crnk-project.
the class IncludeLookupSetter method setIncludedElements.
public void setIncludedElements(Document document, Object entity, QueryAdapter queryAdapter, DocumentMappingConfig mappingConfig) {
QueryAdapter inclusionQueryAdapter = queryAdapter;
if (!allowPagination && !(queryAdapter instanceof QueryParamsAdapter) && queryAdapter != null) {
// offset/limit cannot properly work for nested inclusions if becomes cyclic
inclusionQueryAdapter = queryAdapter.duplicate();
if (queryAdapter.getResourceInformation().getPagingBehavior() != null) {
inclusionQueryAdapter.setPagingSpec(queryAdapter.getResourceInformation().getPagingBehavior().createEmptyPagingSpec());
}
}
List<Object> entityList = DocumentMapperUtil.toList(entity);
List<Resource> dataList = DocumentMapperUtil.toList(document.getData().get());
Map<ResourceIdentifier, Resource> dataMap = new HashMap<>();
Map<ResourceIdentifier, Object> entityMap = new HashMap<>();
for (int i = 0; i < dataList.size(); i++) {
Resource dataElement = dataList.get(i);
ResourceIdentifier id = dataElement.toIdentifier();
entityMap.put(id, entityList.get(i));
dataMap.put(id, dataElement);
}
Map<ResourceIdentifier, Resource> resourceMap = new HashMap<>();
resourceMap.putAll(dataMap);
Set<ResourceIdentifier> inclusions = new HashSet<>();
PopulatedCache populatedCache = new PopulatedCache();
RepositoryMethodParameterProvider parameterProvider = mappingConfig.getParameterProvider();
Set<String> fieldsWithEnforcedIdSerialization = mappingConfig.getFieldsWithEnforcedIdSerialization();
ResourceMappingConfig resourceMappingConfig = mappingConfig.getResourceMapping();
ArrayList<ResourceField> stack = new ArrayList<>();
populate(dataList, inclusions, resourceMap, entityMap, stack, inclusionQueryAdapter, parameterProvider, fieldsWithEnforcedIdSerialization, populatedCache, resourceMappingConfig);
// no need to include resources included in the data section
inclusions.removeAll(dataMap.keySet());
// setup included section
ArrayList<Resource> included = new ArrayList<>();
for (ResourceIdentifier inclusionId : inclusions) {
Resource includedResource = resourceMap.get(inclusionId);
PreconditionUtil.assertNotNull("resource not found", includedResource);
included.add(includedResource);
}
Collections.sort(included);
LOGGER.debug("Extracted included resources {}", included.toString());
document.setIncluded(included);
}
Aggregations