package org.resthub.web.controller;
import org.resthub.common.exception.NotFoundException;
import org.resthub.common.service.CrudService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.io.Serializable;
import java.util.Set;
/**
* Abstract REST controller using a service implementation
* <p/>
* <p>You should extend this class when you want to use a 3 layers pattern : Repository, Service and Controller
* If you don't have a real service (also called business layer), consider using RepositoryBasedRestController</p>
* <p/>
* <p>Default implementation uses "id" field (usually a Long) in order to identify resources in web request.
* If your want to identity resources by a slug (human readable identifier), your should override findById() method with for example :
* <p/>
* <pre>
* <code>
* {@literal @}Override
* public Sample findById({@literal @}PathVariable String id) {
* Sample sample = this.service.findByName(id);
* if (sample == null) {
* throw new NotFoundException();
* }
* return sample;
* }
* </code>
* </pre>
*
* @param <T> Your resource class to manage, maybe an entity or DTO class
* @param <ID> Resource id type, usually Long or String
* @param <S> The service class
* @see RepositoryBasedRestController
*/
public abstract class ServiceBasedRestController<T, ID extends Serializable, S extends CrudService> implements
RestController<T, ID> {
protected S service;
/**
* You should override this setter in order to inject your service with @Inject annotation
*
* @param service The service to be injected
*/
public void setService(S service) {
this.service = service;
}
/**
* {@inheritDoc}
*/
@Override
public T create(@RequestBody T resource) {
return (T) this.service.create(resource);
}
/**
* {@inheritDoc}
*/
@Override
public T update(@PathVariable ID id, @RequestBody T resource) {
Assert.notNull(id, "id cannot be null");
T retreivedResource = this.findById(id);
if (retreivedResource == null) {
throw new NotFoundException();
}
return (T) this.service.update(resource);
}
/**
* {@inheritDoc}
*/
@Override
public Iterable<T> findAll() {
return service.findAll();
}
/**
* {@inheritDoc}
*/
@Override
public Page<T> findPaginated(@RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
@RequestParam(value = "size", required = false, defaultValue = "10") Integer size,
@RequestParam(value = "direction", required = false, defaultValue = "") String direction,
@RequestParam(value = "properties", required = false) String properties) {
Assert.isTrue(page > 0, "Page index must be greater than 0");
Assert.isTrue(direction.isEmpty() || direction.equalsIgnoreCase(Sort.Direction.ASC.toString()) || direction.equalsIgnoreCase(Sort.Direction.DESC.toString()), "Direction should be ASC or DESC");
if (direction.isEmpty()) {
return this.service.findAll(new PageRequest(page - 1, size));
} else {
Assert.notNull(properties);
return this.service.findAll(new PageRequest(page - 1, size, new Sort(Sort.Direction.fromString(direction.toUpperCase()), properties.split(","))));
}
}
/**
* {@inheritDoc}
*/
@Override
public T findById(@PathVariable ID id) {
T resource = (T) this.service.findById(id);
if (resource == null) {
throw new NotFoundException();
}
return resource;
}
/**
* {@inheritDoc}
*/
@Override
public Iterable<T> findByIds(@RequestParam(value = "ids[]") Set<ID> ids) {
Assert.notNull(ids, "ids list cannot be null");
return this.service.findByIds(ids);
}
/**
* {@inheritDoc}
*/
@Override
public void delete() {
this.service.deleteAllWithCascade();
}
/**
* {@inheritDoc}
*/
@Override
public void delete(@PathVariable ID id) {
T resource = this.findById(id);
this.service.delete(resource);
}
}