use of io.crnk.core.engine.document.Resource in project crnk-framework by crnk-project.
the class ResourceUpsert method getRequestBody.
protected Resource getRequestBody(Document requestDocument, JsonPath path, HttpMethod method) {
String resourceType = path.getResourceType();
assertRequestDocument(requestDocument, method, resourceType);
if (!requestDocument.getData().isPresent() || requestDocument.getData().get() == null) {
throw new RequestBodyException(method, resourceType, "No data field in the body.");
}
if (requestDocument.getData().get() instanceof Collection) {
throw new RequestBodyException(method, resourceType, "Multiple data in body");
}
Resource resourceBody = (Resource) requestDocument.getData().get();
RegistryEntry bodyRegistryEntry = resourceRegistry.getEntry(resourceBody.getType());
if (bodyRegistryEntry == null) {
throw new RepositoryNotFoundException(resourceBody.getType());
}
return resourceBody;
}
use of io.crnk.core.engine.document.Resource in project crnk-framework by crnk-project.
the class IncludeLookupSetter method setupRelation.
private List<Resource> setupRelation(Resource sourceResource, ResourceField relationshipField, Object targetEntity, QueryAdapter queryAdapter, Map<ResourceIdentifier, Resource> resourceMap, Map<ResourceIdentifier, Object> entityMap, ResourceMappingConfig resourceMappingConfig) {
// set the relation
String relationshipName = relationshipField.getJsonName();
Map<String, Relationship> relationships = sourceResource.getRelationships();
Relationship relationship = relationships.get(relationshipName);
if (targetEntity instanceof Iterable) {
List<Resource> targets = new ArrayList<>();
for (Object targetElement : (Iterable<?>) targetEntity) {
Resource targetResource = mergeResource(targetElement, queryAdapter, resourceMap, entityMap, resourceMappingConfig);
targets.add(targetResource);
}
relationship.setData(Nullable.of((Object) util.toIds(targets)));
return targets;
} else {
Resource targetResource = mergeResource(targetEntity, queryAdapter, resourceMap, entityMap, resourceMappingConfig);
relationship.setData(Nullable.of((Object) targetResource.toIdentifier()));
return Collections.singletonList(targetResource);
}
}
use of io.crnk.core.engine.document.Resource in project crnk-framework by crnk-project.
the class IncludeLookupSetter method lookupRelatedResourceWithRelationship.
private Set<Resource> lookupRelatedResourceWithRelationship(Collection<Resource> sourceResources, ResourceField relationshipField, QueryAdapter queryAdapter, RepositoryMethodParameterProvider parameterProvider, Map<ResourceIdentifier, Resource> resourceMap, Map<ResourceIdentifier, Object> entityMap, ResourceMappingConfig resourceMappingConfig) {
ResourceInformation resourceInformation = relationshipField.getParentResourceInformation();
RegistryEntry registyEntry = resourceRegistry.getEntry(resourceInformation.getResourceType());
List<Serializable> resourceIds = getIds(sourceResources, resourceInformation);
boolean isMany = Iterable.class.isAssignableFrom(relationshipField.getType());
Set<Resource> loadedTargets = new HashSet<>();
@SuppressWarnings("rawtypes") RelationshipRepositoryAdapter relationshipRepository = registyEntry.getRelationshipRepository(relationshipField, parameterProvider);
if (relationshipRepository != null) {
Map<Object, JsonApiResponse> responseMap;
if (isMany) {
responseMap = relationshipRepository.findBulkManyTargets(resourceIds, relationshipField, queryAdapter);
} else {
responseMap = relationshipRepository.findBulkOneTargets(resourceIds, relationshipField, queryAdapter);
}
for (Resource sourceResource : sourceResources) {
Serializable sourceId = resourceInformation.parseIdString(sourceResource.getId());
JsonApiResponse targetResponse = responseMap.get(sourceId);
if (targetResponse != null && targetResponse.getEntity() != null) {
Object targetEntity = targetResponse.getEntity();
List<Resource> targets = setupRelation(sourceResource, relationshipField, targetEntity, queryAdapter, resourceMap, entityMap, resourceMappingConfig);
loadedTargets.addAll(targets);
} else {
Nullable<Object> emptyData = (Nullable) Nullable.of(Iterable.class.isAssignableFrom(relationshipField.getType()) ? Collections.emptyList() : null);
Relationship relationship = sourceResource.getRelationships().get(relationshipField.getJsonName());
relationship.setData(emptyData);
}
}
} else {
throw new RepositoryNotFoundException("no relationship repository found for " + resourceInformation.getResourceType() + "." + relationshipField.getUnderlyingName());
}
return loadedTargets;
}
use of io.crnk.core.engine.document.Resource in project crnk-framework by crnk-project.
the class IncludeLookupSetter method populateField.
private void populateField(ResourceField resourceField, QueryAdapter queryAdapter, List<ResourceField> fieldPath, PopulatedCache populatedCache, Collection<Resource> resourceList, Set<String> fieldsWithEnforceIdSerialization, RepositoryMethodParameterProvider parameterProvider, Map<ResourceIdentifier, Resource> resourceMap, Map<ResourceIdentifier, Object> entityMap, Set<ResourceIdentifier> inclusions, ResourceMappingConfig resourceMappingConfig) {
ResourceInformation resourceInformation = resourceField.getParentResourceInformation();
boolean includeRequested = util.isInclusionRequested(queryAdapter, fieldPath);
boolean includeResources = includeRequested || resourceField.getSerializeType() == SerializeType.EAGER;
boolean includeRelationId = resourceField.getSerializeType() != SerializeType.LAZY || fieldsWithEnforceIdSerialization.contains(resourceField.getJsonName());
boolean includeRelationshipData = includeRelationId || includeResources;
if (includeRelationshipData) {
Collection<Resource> unpopulatedResourceList = populatedCache.filterProcessed(resourceList, resourceField);
if (!unpopulatedResourceList.isEmpty()) {
// only handle resources from the proper subtype where the
// relationship is desired to be loaded
List<Resource> resourcesByType = util.filterByType(unpopulatedResourceList, resourceInformation);
List<Resource> resourcesWithField = util.filterByLoadedRelationship(resourcesByType, resourceField);
// lookup resources by inspecting the POJOs in entityMap
LookupIncludeBehavior fieldLookupIncludeBehavior = resourceField.getLookupIncludeAutomatically();
Set<Resource> populatedResources;
if (!includeResources && resourceField.hasIdField()) {
// fill in @JsonApiRelationId into Relationship where possible
fetchRelationFromEntity(resourcesWithField, resourceField, queryAdapter, resourceMap, entityMap, false, false, includeResources, resourceMappingConfig);
// only ID is required and no lookup must take place
// nothing to do
populatedResources = Collections.emptySet();
} else if (fieldLookupIncludeBehavior == LookupIncludeBehavior.AUTOMATICALLY_ALWAYS) {
// fill in @JsonApiRelationId into Relationship where possible
fetchRelationFromEntity(resourcesWithField, resourceField, queryAdapter, resourceMap, entityMap, false, false, includeResources, resourceMappingConfig);
// lookup resources by making repository calls
populatedResources = lookupRelatedResource(resourcesWithField, resourceField, queryAdapter, parameterProvider, resourceMap, entityMap, resourceMappingConfig);
} else if (fieldLookupIncludeBehavior == LookupIncludeBehavior.AUTOMATICALLY_WHEN_NULL) {
// try to populate from entities
Set<Resource> extractedResources = fetchRelationFromEntity(resourcesWithField, resourceField, queryAdapter, resourceMap, entityMap, true, true, includeResources, resourceMappingConfig);
// do lookups where relationship data is null
Collection<Resource> resourcesForLookup = util.findResourcesWithoutRelationshipToLoad(resourcesWithField, resourceField, resourceMap);
Collection<Resource> lookedupResources = lookupRelatedResource(resourcesForLookup, resourceField, queryAdapter, parameterProvider, resourceMap, entityMap, resourceMappingConfig);
populatedResources = util.union(lookedupResources, extractedResources);
} else {
// do not do any lookups
populatedResources = fetchRelationFromEntity(resourcesWithField, resourceField, queryAdapter, resourceMap, entityMap, false, true, includeResources, resourceMappingConfig);
// and be sure.
if (!Iterable.class.isAssignableFrom(resourceField.getType())) {
Nullable<Object> emptyData = Nullable.nullValue();
for (Resource resourceWithField : resourcesWithField) {
Relationship relationship = resourceWithField.getRelationships().get(resourceField.getJsonName());
if (!relationship.getData().isPresent()) {
relationship.setData(emptyData);
}
}
}
}
// such
if (includeResources && !populatedResources.isEmpty()) {
inclusions.addAll(util.toIds(populatedResources));
Set<String> additionalEagerLoadedNestedRelations = Collections.emptySet();
populate(populatedResources, inclusions, resourceMap, entityMap, fieldPath, queryAdapter, parameterProvider, additionalEagerLoadedNestedRelations, populatedCache, resourceMappingConfig);
}
}
}
}
use of io.crnk.core.engine.document.Resource in project crnk-framework by crnk-project.
the class IncludeLookupSetter method fetchRelationFromEntity.
/**
* No lookup specified for the field. Attempt to load relationship from
* original POJOs. Throw an InternalServerErrorException if the field is an
* Iterable and null.
*/
private Set<Resource> fetchRelationFromEntity(List<Resource> sourceResources, ResourceField relationshipField, QueryAdapter queryAdapter, Map<ResourceIdentifier, Resource> resourceMap, Map<ResourceIdentifier, Object> entityMap, boolean allowLookup, boolean fetchRelatedEntity, boolean mustInclude, ResourceMappingConfig resourceMappingConfig) {
Set<Resource> loadedResources = new HashSet<>();
for (Resource sourceResource : sourceResources) {
ResourceIdentifier id = sourceResource.toIdentifier();
Object sourceEntity = entityMap.get(id);
if (sourceEntity != null && !(sourceEntity instanceof Resource)) {
Object relatedEntity = null;
if (fetchRelatedEntity) {
relatedEntity = relationshipField.getAccessor().getValue(sourceEntity);
if (!allowLookup && Iterable.class.isAssignableFrom(relationshipField.getType()) && relatedEntity == null) {
// note that single-valued relations are allowed to be null
throw new InternalServerErrorException(id + " relationship field collection '" + relationshipField.getJsonName() + "' can not be null. Either set the relationship as an empty " + Iterable.class.getCanonicalName() + " or add annotation @" + JsonApiLookupIncludeAutomatically.class.getCanonicalName());
}
}
// attempt to work with full relationship and fallback to relationshipId where possible
if (relatedEntity != null) {
List<Resource> relatedResources = setupRelation(sourceResource, relationshipField, relatedEntity, queryAdapter, resourceMap, entityMap, resourceMappingConfig);
loadedResources.addAll(relatedResources);
} else if (relationshipField.hasIdField()) {
Object relatedEntityID = relationshipField.getIdAccessor().getValue(sourceEntity);
setupRelationId(sourceResource, relationshipField, relatedEntityID);
if (fetchRelatedEntity && relatedEntityID != null && !allowLookup && mustInclude) {
throw new IllegalStateException("inconsistent relationship '" + relationshipField.getUnderlyingName() + "' for " + id + ", id " + "set to " + relatedEntityID + ", but related object is null and lookup disabled");
}
}
}
}
return loadedResources;
}
Aggregations