TSK-373: list resources according to HAL format.

This commit is contained in:
Holger Hagen 2018-03-07 15:18:19 +01:00 committed by Martin Rojas Miguel Angel
parent c958e8f1d4
commit 4c8b29bcec
10 changed files with 179 additions and 146 deletions

View File

@ -3,9 +3,9 @@ package pro.taskana.rest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.Resources;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
import org.springframework.http.HttpStatus;
@ -36,14 +36,15 @@ import pro.taskana.exceptions.InvalidWorkbasketException;
import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.exceptions.WorkbasketInUseException;
import pro.taskana.exceptions.WorkbasketNotFoundException;
import pro.taskana.rest.resource.DistributionTargetResource;
import pro.taskana.rest.resource.WorkbasketAccessItemResource;
import pro.taskana.rest.resource.WorkbasketListResource;
import pro.taskana.rest.resource.WorkbasketResource;
import pro.taskana.rest.resource.WorkbasketSummaryResource;
import pro.taskana.rest.resource.mapper.DistributionTargetListMapper;
import pro.taskana.rest.resource.mapper.WorkbasketAccessItemListMapper;
import pro.taskana.rest.resource.mapper.WorkbasketAccessItemMapper;
import pro.taskana.rest.resource.mapper.WorkbasketListMapper;
import pro.taskana.rest.resource.mapper.WorkbasketMapper;
import pro.taskana.rest.resource.mapper.WorkbasketSummaryMapper;
/**
* Controller for all {@link Workbasket} related endpoints.
@ -64,21 +65,24 @@ public class WorkbasketController {
@Autowired
private WorkbasketService workbasketService;
@Autowired
private WorkbasketSummaryMapper workbasketSummaryMapper;
@Autowired
private WorkbasketMapper workbasketMapper;
@Autowired
private WorkbasketListMapper workbasketListMapper;
@Autowired
private DistributionTargetListMapper distributionTargetListMapper;
@Autowired
private WorkbasketAccessItemListMapper accessItemListMapper;
@Autowired
private WorkbasketAccessItemMapper workbasketAccessItemMapper;
@GetMapping
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<WorkbasketListResource> getWorkbaskets(
public ResponseEntity<Resources<WorkbasketSummaryResource>> getWorkbaskets(
@RequestParam(value = "sortBy", defaultValue = "name", required = false) String sortBy,
@RequestParam(value = "order", defaultValue = "asc", required = false) String order,
@RequestParam(value = "name", required = false) String name,
@ -96,7 +100,8 @@ public class WorkbasketController {
addAttributeFilter(query, name, nameLike, key, keyLike, descLike, owner, ownerLike, type);
addAuthorizationFilter(query, requiredPermission);
List<WorkbasketSummary> workbasketSummaries = query.list();
WorkbasketListResource workbasketListResource = workbasketListMapper.toResource(workbasketSummaries);
Resources<WorkbasketSummaryResource> workbasketListResource = workbasketListMapper
.toResource(workbasketSummaries);
return new ResponseEntity<>(workbasketListResource, HttpStatus.OK);
} catch (InvalidArgumentException ex) {
return new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
@ -189,25 +194,19 @@ public class WorkbasketController {
@GetMapping(path = "/{workbasketId}/workbasketAccessItems")
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<List<WorkbasketAccessItemResource>> getWorkbasketAccessItems(
public ResponseEntity<Resources<WorkbasketAccessItemResource>> getWorkbasketAccessItems(
@PathVariable(value = "workbasketId") String workbasketId) {
List<WorkbasketAccessItem> wbAuthorizations;
List<WorkbasketAccessItemResource> result = new ArrayList<>();
ResponseEntity<Resources<WorkbasketAccessItemResource>> result;
try {
wbAuthorizations = workbasketService.getWorkbasketAccessItems(workbasketId);
} catch (NotAuthorizedException e1) {
TransactionInterceptor.currentTransactionStatus().setRollbackOnly();
return new ResponseEntity<>(result, HttpStatus.UNAUTHORIZED);
List<WorkbasketAccessItem> accessItems = workbasketService.getWorkbasketAccessItems(workbasketId);
Resources<WorkbasketAccessItemResource> accessItemListResource = accessItemListMapper
.toResource(workbasketId, accessItems);
result = new ResponseEntity<>(accessItemListResource, HttpStatus.OK);
} catch (NotAuthorizedException e) {
result = new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
wbAuthorizations
.forEach(accItem -> {
try {
result.add(workbasketAccessItemMapper.toResource(accItem));
} catch (NotAuthorizedException e) {
e.printStackTrace();
}
});
return new ResponseEntity<>(result, HttpStatus.OK);
return result;
}
@PostMapping(path = "/workbasketAccessItems")
@ -271,16 +270,15 @@ public class WorkbasketController {
@GetMapping(path = "/{workbasketId}/distributiontargets")
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<List<WorkbasketSummaryResource>> getDistributionTargetsForWorkbasketId(
public ResponseEntity<Resources<DistributionTargetResource>> getDistributionTargets(
@PathVariable(value = "workbasketId") String workbasketId) {
ResponseEntity<List<WorkbasketSummaryResource>> result;
List<WorkbasketSummary> distributionTargets;
ResponseEntity<Resources<DistributionTargetResource>> result;
try {
distributionTargets = workbasketService.getDistributionTargets(workbasketId);
result = new ResponseEntity<>(distributionTargets.stream()
.map(workbasket -> workbasketSummaryMapper.toResource(workbasket))
.collect(Collectors.toList()), HttpStatus.OK);
List<WorkbasketSummary> distributionTargets = workbasketService.getDistributionTargets(workbasketId);
Resources<DistributionTargetResource> distributionTargetListResource = distributionTargetListMapper
.toResource(workbasketId, distributionTargets);
result = new ResponseEntity<>(distributionTargetListResource, HttpStatus.OK);
} catch (WorkbasketNotFoundException e) {
result = new ResponseEntity<>(HttpStatus.NOT_FOUND);
} catch (NotAuthorizedException e) {

View File

@ -1,62 +0,0 @@
package pro.taskana.rest.resource;
import org.springframework.hateoas.ResourceSupport;
/**
* Base class for page list resources.
*/
public class AbstractPageableListResource extends ResourceSupport {
private final int pageNumber;
private final int pageSize;
private final int totalPages;
private final long totalElements;
/**
* Creates new instance of {@link AbstractPageableListResource}.
*
* @param pageNumber
* actual page of the collection.
* @param pageSize
* number of elements per pages of the collection.
* @param totalPages
* total number of pages of the collection.
* @param totalElements
* total number of elements of the collection.
*/
public AbstractPageableListResource(int pageNumber, int pageSize, int totalPages, long totalElements) {
this.pageNumber = pageNumber;
this.pageSize = pageSize;
this.totalPages = totalPages;
this.totalElements = totalElements;
}
/**
* Default constructor for a list without paging.
*/
public AbstractPageableListResource() {
this.pageNumber = -1;
this.pageSize = -1;
this.totalPages = -1;
this.totalElements = -1;
}
public int getPageNumber() {
return pageNumber;
}
public int getPageSize() {
return pageSize;
}
public int getTotalPages() {
return totalPages;
}
public long getTotalElements() {
return totalElements;
}
}

View File

@ -0,0 +1,8 @@
package pro.taskana.rest.resource;
/**
* Resource class for a distribution target based on {@link pro.taskana.WorkbasketSummary}.
*/
public class DistributionTargetResource extends WorkbasketSummaryResource {
}

View File

@ -1,47 +0,0 @@
package pro.taskana.rest.resource;
import java.util.Collection;
/**
* Resource for workbasket lists.
*/
public class WorkbasketListResource extends AbstractPageableListResource {
private final Collection<WorkbasketSummaryResource> workbasketSummaries;
/**
* Create a paged list of workbaskets.
*
* @param workbasketSummaries
* the workbasket summaries
* @param pageNumber
* the current page number
* @param pageSize
* the size of the pages
* @param totalPages
* the total number of pages
* @param totalElements
* the total number of elements
*/
public WorkbasketListResource(Collection<WorkbasketSummaryResource> workbasketSummaries, int pageNumber,
int pageSize,
int totalPages, long totalElements) {
super(pageNumber, pageSize, totalPages, totalElements);
this.workbasketSummaries = workbasketSummaries;
}
/**
* Create a unpaged list of workbaskets.
*
* @param workbasketSummaries
* the workbasket summaries
*/
public WorkbasketListResource(Collection<WorkbasketSummaryResource> workbasketSummaries) {
this.workbasketSummaries = workbasketSummaries;
}
public Collection<WorkbasketSummaryResource> getWorkbasketSummaries() {
return workbasketSummaries;
}
}

View File

@ -0,0 +1,47 @@
package pro.taskana.rest.resource.mapper;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.Resources;
import org.springframework.stereotype.Component;
import pro.taskana.WorkbasketSummary;
import pro.taskana.rest.WorkbasketController;
import pro.taskana.rest.resource.DistributionTargetResource;
/**
* Mapper to convert from a list of WorkbasketSummary to a workbasket list resource.
*/
@Component
public class DistributionTargetListMapper {
@Autowired
private DistributionTargetMapper distributionTargetMapper;
public Resources<DistributionTargetResource> toResource(String workbasketId,
Collection<WorkbasketSummary> distributionTargets) {
List<DistributionTargetResource> resourceList = distributionTargets.stream()
.map(workbasket -> distributionTargetMapper.toResource(workbasket))
.collect(Collectors.toList());
Resources<DistributionTargetResource> distributionTargetListResource = new Resources<>(resourceList);
distributionTargetListResource
.add(linkTo(methodOn(WorkbasketController.class).getDistributionTargets(workbasketId))
.withSelfRel());
distributionTargetListResource
.add(linkTo(methodOn(WorkbasketController.class).getDistributionTargets(workbasketId))
.withRel("distributionTargetResourceList"));
distributionTargetListResource
.add(linkTo(methodOn(WorkbasketController.class).getWorkbasket(workbasketId))
.withRel("workbasket"));
return distributionTargetListResource;
}
}

View File

@ -0,0 +1,32 @@
package pro.taskana.rest.resource.mapper;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import pro.taskana.WorkbasketSummary;
import pro.taskana.rest.WorkbasketController;
import pro.taskana.rest.resource.DistributionTargetResource;
/**
* Transforms WorkbasketSummary to its resource counterpart DistributionTargerResource and vice versa.
*/
@Component
public class DistributionTargetMapper {
public DistributionTargetResource toResource(WorkbasketSummary summary) {
DistributionTargetResource resource = new DistributionTargetResource();
BeanUtils.copyProperties(summary, resource);
// named different so needs to be set by hand
resource.setWorkbasketId(summary.getId());
return addLinks(resource, summary);
}
private DistributionTargetResource addLinks(DistributionTargetResource resource, WorkbasketSummary summary) {
resource.add(linkTo(methodOn(WorkbasketController.class).getWorkbasket(summary.getId())).withSelfRel());
return resource;
}
}

View File

@ -0,0 +1,54 @@
package pro.taskana.rest.resource.mapper;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.Resources;
import org.springframework.stereotype.Component;
import pro.taskana.WorkbasketAccessItem;
import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.rest.WorkbasketController;
import pro.taskana.rest.resource.WorkbasketAccessItemResource;
/**
* Mapper to convert from a list of WorkbasketAccessItem to a WorkbasketAccessItemResource.
*/
@Component
public class WorkbasketAccessItemListMapper {
@Autowired
private WorkbasketAccessItemMapper workbasketAccessItemMapper;
public Resources<WorkbasketAccessItemResource> toResource(String workbasketId,
Collection<WorkbasketAccessItem> accessItems) {
List<WorkbasketAccessItemResource> resourceList = accessItems.stream()
.map(accessItem -> {
try {
return workbasketAccessItemMapper.toResource(accessItem);
} catch (NotAuthorizedException e) {
return null;
}
})
.collect(Collectors.toList());
Resources<WorkbasketAccessItemResource> accessItemListResource = new Resources<>(resourceList);
accessItemListResource
.add(linkTo(methodOn(WorkbasketController.class).getWorkbasketAccessItems(workbasketId))
.withSelfRel());
accessItemListResource
.add(linkTo(methodOn(WorkbasketController.class).getWorkbasketAccessItems(workbasketId))
.withRel("setWorkbasketAccessItemResourceList"));
accessItemListResource
.add(linkTo(methodOn(WorkbasketController.class).getWorkbasket(workbasketId))
.withRel("workbasket"));
return accessItemListResource;
}
}

View File

@ -3,17 +3,19 @@ package pro.taskana.rest.resource.mapper;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.Resources;
import org.springframework.stereotype.Component;
import pro.taskana.WorkbasketSummary;
import pro.taskana.rest.WorkbasketController;
import pro.taskana.rest.resource.WorkbasketListResource;
import pro.taskana.rest.resource.WorkbasketSummaryResource;
/**
* Mapper to convert from {@link Collection WorkbasketSummary} to {@link WorkbasketListResource}.
* Mapper to convert from a list of WorkbasketSummary to a workbasket list resource.
*/
@Component
public class WorkbasketListMapper {
@ -21,10 +23,11 @@ public class WorkbasketListMapper {
@Autowired
private WorkbasketSummaryMapper workbasketSummaryMapper;
public WorkbasketListResource toResource(Collection<WorkbasketSummary> workbasketSummaries) {
WorkbasketListResource workbasketListResource = new WorkbasketListResource(workbasketSummaries.stream()
public Resources<WorkbasketSummaryResource> toResource(Collection<WorkbasketSummary> workbasketSummaries) {
List<WorkbasketSummaryResource> resourceList = workbasketSummaries.stream()
.map(workbasket -> workbasketSummaryMapper.toResource(workbasket))
.collect(Collectors.toList()));
.collect(Collectors.toList());
Resources<WorkbasketSummaryResource> workbasketListResource = new Resources<>(resourceList);
workbasketListResource.add(linkTo(WorkbasketController.class).withSelfRel());

View File

@ -48,7 +48,7 @@ public class WorkbasketMapper {
private WorkbasketResource addLinks(WorkbasketResource resource, Workbasket wb) throws NotAuthorizedException {
resource.add(linkTo(methodOn(WorkbasketController.class).getWorkbasket(wb.getId())).withSelfRel());
resource.add(linkTo(methodOn(WorkbasketController.class).getDistributionTargetsForWorkbasketId(wb.getId()))
resource.add(linkTo(methodOn(WorkbasketController.class).getDistributionTargets(wb.getId()))
.withRel("distributionTargets"));
resource.add(linkTo(methodOn(WorkbasketController.class).getWorkbasketAccessItems(wb.getId()))
.withRel("accessItems"));