package io.kaif.web.v1; import static java.util.stream.Collectors.*; import java.util.List; import javax.validation.Valid; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import io.swagger.annotations.Api; import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiOperation; import io.kaif.flake.FlakeId; import io.kaif.model.clientapp.ClientAppScope; import io.kaif.model.clientapp.ClientAppUserAccessToken; import io.kaif.model.debate.Debate; import io.kaif.model.zone.Zone; import io.kaif.service.ArticleService; import io.kaif.web.v1.dto.V1DebateDto; import io.kaif.web.v1.dto.V1DebateNodeDto; @Api(tags = "debate", description = "Debates on articles") @RestController @RequestMapping(value = "/v1/debate", produces = MediaType.APPLICATION_JSON_VALUE) public class V1DebateResource { static class CreateDebateEntry { @NotNull @ApiModelProperty(required = true) public FlakeId articleId; @ApiModelProperty(value = "debateId reply to. null if reply to article", required = false) public FlakeId parentDebateId; @Size(min = Debate.CONTENT_MIN, max = Debate.CONTENT_MAX) @NotNull @ApiModelProperty(value = "content of debate, min 5 chars", required = true) public String content; } static class UpdateDebateEntry { @Size(min = Debate.CONTENT_MIN, max = Debate.CONTENT_MAX) @NotNull @ApiModelProperty(value = "content of debate, min 5 chars", required = true) public String content; } @Autowired private ArticleService articleService; @ApiOperation(value = "[public] Get a debate", notes = "Get a debate by debateId") @RequiredScope(ClientAppScope.PUBLIC) @RequestMapping(value = "/{debateId}", method = RequestMethod.GET) public V1DebateDto debate(ClientAppUserAccessToken accessToken, @PathVariable("debateId") FlakeId debateId) { return articleService.loadDebateWithCache(debateId).toV1Dto(); } @ApiOperation(value = "[public] Load all debates for an article", notes = "Load all debates (in tree structure) for an article. Note that result may be a big json.") @RequiredScope(ClientAppScope.PUBLIC) @RequestMapping(value = "/article/{articleId}/tree", method = RequestMethod.GET) public V1DebateNodeDto debateTreeOfArticle(ClientAppUserAccessToken accessToken, @PathVariable("articleId") FlakeId articleId) { return articleService.listBestDebates(articleId, null).toV1Dto(); } @ApiOperation(value = "[public] List latest debates of all zones", notes = "List latest debates of all zones, 25 debates a page. " + "To retrieve next page, passing last debate id of previous page in parameter start-debate-id.") @RequiredScope(ClientAppScope.PUBLIC) @RequestMapping(value = "/latest", method = RequestMethod.GET) public List<V1DebateDto> latest(ClientAppUserAccessToken accessToken, @RequestParam(value = "start-debate-id", required = false) FlakeId startDebateId) { return toDtos(articleService.listLatestDebates(startDebateId)); } private List<V1DebateDto> toDtos(List<Debate> debates) { return debates.stream().map(Debate::toV1Dto).collect(toList()); } @ApiOperation(value = "[public] List latest debates for a zone", notes = "List latest debates for a zone, 25 debates a page. " + "To retrieve next page, passing last debate id of previous page in parameter start-debate-id") @RequiredScope(ClientAppScope.PUBLIC) @RequestMapping(value = "/zone/{zone}/latest", method = RequestMethod.GET) public List<V1DebateDto> latestByZone(ClientAppUserAccessToken accessToken, @PathVariable("zone") String zone, @RequestParam(value = "start-debate-id", required = false) FlakeId startDebateId) { return toDtos(articleService.listLatestZoneDebates(Zone.valueOf(zone), startDebateId)); } @ApiOperation(value = "[debate] List submitted debates of the user", notes = "List submitted debates of the user, 25 debates a page. " + "To retrieve next page, passing last debate id of previous page in parameter start-debate-id") @RequiredScope(ClientAppScope.DEBATE) @RequestMapping(value = "/user/{username}/submitted", method = RequestMethod.GET) public List<V1DebateDto> userSubmitted(ClientAppUserAccessToken accessToken, @PathVariable("username") String username, @RequestParam(value = "start-debate-id", required = false) FlakeId startDebateId) { return toDtos(articleService.listDebatesByDebater(username, startDebateId)); } @ApiOperation(value = "[debate] Create a debate in the article", notes = "Create a debate in the article. If reply to a debate, " + "it should be specified in the field: parentDebateId.") @ResponseStatus(HttpStatus.CREATED) @RequiredScope(ClientAppScope.DEBATE) @RequestMapping(value = "", method = RequestMethod.PUT, consumes = { MediaType.APPLICATION_JSON_VALUE }) public V1DebateDto create(ClientAppUserAccessToken accessToken, @Valid @RequestBody CreateDebateEntry entry) { return articleService.debate(entry.articleId, entry.parentDebateId, accessToken, entry.content.trim()).toV1Dto(); } @ApiOperation(value = "[debate] Edit content of a debate", notes = "Edit content of a debate that user created.") @RequiredScope(ClientAppScope.DEBATE) @RequestMapping(value = "/{debateId}/content", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE }) public String updateDebateContent(ClientAppUserAccessToken accessToken, @PathVariable("debateId") FlakeId debateId, @Valid @RequestBody UpdateDebateEntry entry) { return articleService.updateDebateContent(debateId, accessToken, entry.content.trim()); } }