use of io.crnk.core.engine.registry.RegistryEntry in project crnk-framework by crnk-project.
the class ResourceMetaFilter method adjustFieldForRequest.
private MetaElement adjustFieldForRequest(MetaResourceField field) {
MetaResource metaResource = (MetaResource) field.getParent();
Module.ModuleContext moduleContext = context.getModuleContext();
RegistryEntry entry = moduleContext.getResourceRegistry().getEntry(metaResource.getResourceType());
ResourceInformation resourceInformation = entry.getResourceInformation();
ResourceField fieldInformation = resourceInformation.findFieldByUnderlyingName(field.getName());
ResourceFilterDirectory filterBehaviorProvider = moduleContext.getResourceFilterDirectory();
boolean readable = metaResource.isReadable() && filterBehaviorProvider.get(fieldInformation, HttpMethod.GET) == FilterBehavior.NONE;
boolean insertable = metaResource.isInsertable() && filterBehaviorProvider.get(fieldInformation, HttpMethod.POST) == FilterBehavior.NONE;
boolean updatable = metaResource.isUpdatable() && filterBehaviorProvider.get(fieldInformation, HttpMethod.PATCH) == FilterBehavior.NONE;
// hide element if no permission
if (!readable && !insertable && !updatable) {
return null;
}
if (field.isUpdatable() != updatable || field.isInsertable() != insertable) {
MetaResourceField clone = (MetaResourceField) field.duplicate();
clone.setInsertable(insertable);
clone.setUpdatable(updatable);
return clone;
}
return field;
}
use of io.crnk.core.engine.registry.RegistryEntry 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.registry.RegistryEntry in project crnk-framework by crnk-project.
the class ResourceUpsert method setRelationsField.
protected void setRelationsField(Object newResource, RegistryEntry registryEntry, Map.Entry<String, Relationship> property, QueryAdapter queryAdapter, RepositoryMethodParameterProvider parameterProvider) {
Relationship relationship = property.getValue();
if (relationship.getData().isPresent()) {
String propertyName = property.getKey();
ResourceField relationshipField = registryEntry.getResourceInformation().findRelationshipFieldByName(propertyName);
List<ResourceIdentifier> relationshipIds = relationship.getCollectionData().get();
for (ResourceModificationFilter filter : modificationFilters) {
relationshipIds = filter.modifyManyRelationship(newResource, relationshipField, ResourceRelationshipModificationType.SET, relationshipIds);
}
List relationshipTypedIds = new LinkedList<>();
for (ResourceIdentifier resourceId : relationshipIds) {
RegistryEntry entry = resourceRegistry.getEntry(resourceId.getType());
Class idFieldType = entry.getResourceInformation().getIdField().getType();
Serializable typedRelationshipId = parseId(resourceId, idFieldType);
relationshipTypedIds.add(typedRelationshipId);
}
if (relationshipField.hasIdField()) {
relationshipField.getIdAccessor().setValue(newResource, relationshipTypedIds);
}
// TODO batch fetchRelatedObject
if (decideSetRelationObjectsField(relationshipField)) {
List relationshipEntities = new LinkedList<>();
for (int i = 0; i < relationshipIds.size(); i++) {
ResourceIdentifier resourceId = relationshipIds.get(i);
Serializable typedRelationshipId = (Serializable) relationshipTypedIds.get(i);
RegistryEntry entry = resourceRegistry.getEntry(resourceId.getType());
Object relationObject = fetchRelatedObject(entry, typedRelationshipId, parameterProvider, queryAdapter);
relationshipEntities.add(relationObject);
}
relationshipField.getAccessor().setValue(newResource, relationshipEntities);
}
}
}
use of io.crnk.core.engine.registry.RegistryEntry in project crnk-framework by crnk-project.
the class ResourceUpsert method setRelationField.
protected void setRelationField(Object newResource, RegistryEntry registryEntry, String relationshipName, Relationship relationship, QueryAdapter queryAdapter, RepositoryMethodParameterProvider parameterProvider) {
if (relationship.getData().isPresent()) {
ResourceIdentifier relationshipId = (ResourceIdentifier) relationship.getData().get();
ResourceField field = registryEntry.getResourceInformation().findRelationshipFieldByName(relationshipName);
if (field == null) {
throw new ResourceException(String.format("Invalid relationship name: %s", relationshipName));
}
for (ResourceModificationFilter filter : modificationFilters) {
relationshipId = filter.modifyOneRelationship(newResource, field, relationshipId);
}
Object relationObject;
if (relationshipId == null) {
relationObject = null;
field.getAccessor().setValue(newResource, relationObject);
} else {
RegistryEntry entry = resourceRegistry.getEntry(relationshipId.getType());
Class idFieldType = entry.getResourceInformation().getIdField().getType();
Serializable typedRelationshipId = parseId(relationshipId, idFieldType);
if (field.hasIdField()) {
field.getIdAccessor().setValue(newResource, typedRelationshipId);
}
if (decideSetRelationObjectField(entry, typedRelationshipId, field)) {
relationObject = fetchRelatedObject(entry, typedRelationshipId, parameterProvider, queryAdapter);
field.getAccessor().setValue(newResource, relationObject);
}
}
}
}
use of io.crnk.core.engine.registry.RegistryEntry 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;
}
Aggregations