io.katharsis.dispatcher.controller.resource.RelationshipsResourceUpsert Maven / Gradle / Ivy
package io.katharsis.dispatcher.controller.resource;
import io.katharsis.dispatcher.controller.BaseController;
import io.katharsis.dispatcher.controller.HttpMethod;
import io.katharsis.queryParams.QueryParams;
import io.katharsis.repository.RepositoryMethodParameterProvider;
import io.katharsis.request.dto.DataBody;
import io.katharsis.request.dto.RequestBody;
import io.katharsis.request.path.JsonPath;
import io.katharsis.request.path.PathIds;
import io.katharsis.request.path.RelationshipsPath;
import io.katharsis.resource.exception.RequestBodyException;
import io.katharsis.resource.exception.RequestBodyNotFoundException;
import io.katharsis.resource.exception.ResourceFieldNotFoundException;
import io.katharsis.resource.exception.ResourceNotFoundException;
import io.katharsis.resource.field.ResourceField;
import io.katharsis.resource.registry.RegistryEntry;
import io.katharsis.resource.registry.ResourceRegistry;
import io.katharsis.resource.registry.responseRepository.RelationshipRepositoryAdapter;
import io.katharsis.resource.registry.responseRepository.ResourceRepositoryAdapter;
import io.katharsis.response.BaseResponseContext;
import io.katharsis.response.HttpStatus;
import io.katharsis.response.JsonApiResponse;
import io.katharsis.response.ResourceResponseContext;
import io.katharsis.utils.Generics;
import io.katharsis.utils.parser.TypeParser;
import java.io.Serializable;
public abstract class RelationshipsResourceUpsert extends BaseController {
private final ResourceRegistry resourceRegistry;
final TypeParser typeParser;
RelationshipsResourceUpsert(ResourceRegistry resourceRegistry, TypeParser typeParser) {
this.resourceRegistry = resourceRegistry;
this.typeParser = typeParser;
}
/**
* HTTP method name
*
* @return HTTP method name
*/
protected abstract HttpMethod method();
/**
* Processes To-Many field
*
* @param resource source resource
* @param relationshipIdType {@link Class} class of the relationship's id field
* @param elementName field's name
* @param dataBodies Data bodies with relationships
* @param queryParams query params
* @param relationshipRepositoryForClass Relationship repository
*/
protected abstract void processToManyRelationship(Object resource, Class extends Serializable> relationshipIdType,
String elementName, Iterable dataBodies, QueryParams queryParams,
RelationshipRepositoryAdapter relationshipRepositoryForClass);
/**
* Processes To-One field
*
* @param resource source resource
* @param relationshipIdType {@link Class} class of the relationship's id field
* @param elementName field's name
* @param dataBody Data body with a relationship
* @param queryParams query params
* @param relationshipRepositoryForClass Relationship repository
*/
protected abstract void processToOneRelationship(Object resource, Class extends Serializable> relationshipIdType,
String elementName, DataBody dataBody, QueryParams queryParams,
RelationshipRepositoryAdapter relationshipRepositoryForClass);
@Override
public final boolean isAcceptable(JsonPath jsonPath, String requestType) {
return !jsonPath.isCollection()
&& RelationshipsPath.class.equals(jsonPath.getClass())
&& method().name().equals(requestType);
}
@Override
public final BaseResponseContext handle(JsonPath jsonPath, QueryParams queryParams,
RepositoryMethodParameterProvider parameterProvider, RequestBody requestBody) {
String resourceName = jsonPath.getResourceName();
PathIds resourceIds = jsonPath.getIds();
RegistryEntry registryEntry = resourceRegistry.getEntry(resourceName);
if (registryEntry == null) {
throw new ResourceNotFoundException(resourceName);
}
if (requestBody == null) {
throw new RequestBodyNotFoundException(HttpMethod.POST, resourceName);
}
Serializable castedResourceId = getResourceId(resourceIds, registryEntry);
ResourceField relationshipField = registryEntry.getResourceInformation().findRelationshipFieldByName(jsonPath
.getElementName());
if (relationshipField == null) {
throw new ResourceFieldNotFoundException(jsonPath.getElementName());
}
ResourceRepositoryAdapter resourceRepository = registryEntry.getResourceRepository(parameterProvider);
@SuppressWarnings("unchecked")
JsonApiResponse response = resourceRepository.findOne(castedResourceId, queryParams);
Object resource = extractResource(response);
Class> baseRelationshipFieldClass = relationshipField.getType();
Class> relationshipFieldClass = Generics
.getResourceClass(relationshipField.getGenericType(), baseRelationshipFieldClass);
@SuppressWarnings("unchecked") Class extends Serializable> relationshipIdType = (Class extends Serializable>) resourceRegistry
.getEntry(relationshipFieldClass).getResourceInformation().getIdField().getType();
@SuppressWarnings("unchecked")
RelationshipRepositoryAdapter relationshipRepositoryForClass = registryEntry
.getRelationshipRepositoryForClass(relationshipFieldClass, parameterProvider);
if (Iterable.class.isAssignableFrom(baseRelationshipFieldClass)) {
if (!requestBody.isMultiple()) {
throw new RequestBodyException(HttpMethod.POST, resourceName, "Non-multiple data in body");
}
Iterable dataBodies = requestBody.getMultipleData();
processToManyRelationship(resource, relationshipIdType, jsonPath.getElementName(), dataBodies, queryParams,
relationshipRepositoryForClass);
} else {
if (requestBody.isMultiple()) {
throw new RequestBodyException(HttpMethod.POST, resourceName, "Multiple data in body");
}
DataBody dataBody = requestBody.getSingleData();
processToOneRelationship(resource, relationshipIdType, jsonPath.getElementName(), dataBody, queryParams,
relationshipRepositoryForClass);
}
return new ResourceResponseContext(response, HttpStatus.NO_CONTENT_204);
}
private Serializable getResourceId(PathIds resourceIds, RegistryEntry> registryEntry) {
String resourceId = resourceIds.getIds().get(0);
@SuppressWarnings("unchecked") Class extends Serializable> idClass = (Class extends Serializable>) registryEntry
.getResourceInformation()
.getIdField()
.getType();
return typeParser.parse(resourceId, idClass);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy