diff --git a/pom.xml b/pom.xml index ed84c9b..1b6e6cf 100644 --- a/pom.xml +++ b/pom.xml @@ -7,10 +7,22 @@ io.zipcoder spring-demo 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + + + + org.springframework.boot spring-boot-starter-parent - 1.5.3.RELEASE + 2.1.2.RELEASE diff --git a/src/main/java/dtos/OptionCount.java b/src/main/java/dtos/OptionCount.java new file mode 100644 index 0000000..8180316 --- /dev/null +++ b/src/main/java/dtos/OptionCount.java @@ -0,0 +1,28 @@ +package dtos; + +public class OptionCount { + + private Long optionId; + private int count; + + public OptionCount(Long optionId, int count) { + this.optionId = optionId; + this.count = count; + } + + public Long getOptionId() { + return optionId; + } + + public void setOptionId(Long optionId) { + this.optionId = optionId; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } +} diff --git a/src/main/java/dtos/VoteResult.java b/src/main/java/dtos/VoteResult.java new file mode 100644 index 0000000..04a0e7b --- /dev/null +++ b/src/main/java/dtos/VoteResult.java @@ -0,0 +1,30 @@ +package dtos; + +import java.util.Collection; + +public class VoteResult { + + private int totalVotes; + private Collection results; + + public VoteResult(int totalVotes, Collection results) { + this.totalVotes = totalVotes; + this.results = results; + } + + public int getTotalVotes() { + return totalVotes; + } + + public void setTotalVotes(int totalVotes) { + this.totalVotes = totalVotes; + } + + public Collection getResults() { + return results; + } + + public void setResults(Collection results) { + this.results = results; + } +} diff --git a/src/main/java/io/zipcoder/tc_spring_poll_application/controller/ComputeResultController.java b/src/main/java/io/zipcoder/tc_spring_poll_application/controller/ComputeResultController.java new file mode 100644 index 0000000..e04b383 --- /dev/null +++ b/src/main/java/io/zipcoder/tc_spring_poll_application/controller/ComputeResultController.java @@ -0,0 +1,63 @@ +package io.zipcoder.tc_spring_poll_application.controller; + +import dtos.OptionCount; +import dtos.VoteResult; +import io.zipcoder.tc_spring_poll_application.domain.Option; +import io.zipcoder.tc_spring_poll_application.domain.Poll; +import io.zipcoder.tc_spring_poll_application.domain.Vote; +import io.zipcoder.tc_spring_poll_application.repositories.OptionRepository; +import io.zipcoder.tc_spring_poll_application.repositories.PollRepository; +import io.zipcoder.tc_spring_poll_application.repositories.VoteRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +@RestController +public class ComputeResultController { + private VoteRepository voteRepository; + + @Autowired + public ComputeResultController(VoteRepository voteRepository) { + this.voteRepository = voteRepository; + } + + @GetMapping("/computeresult") + public ResponseEntity computeResult(@RequestParam Long pollId) { + List optionsCountList = new ArrayList<>(); + Map optionCounts; + Iterable allVotes; + + allVotes = voteRepository.findVotesByPoll(pollId); + optionCounts= StreamSupport.stream(allVotes.spliterator(), false) + .collect(Collectors.groupingBy(v -> v.getOption().getId(), Collectors.counting())); + ArrayList keys = new ArrayList(optionCounts.keySet()); + for (int i = 0; i < optionCounts.size(); i++) { + optionsCountList.add(new OptionCount(keys.get(i), optionCounts.get(keys.get(i)).intValue())); + } + + VoteResult voteResult = new VoteResult(countAllVotes(allVotes), optionsCountList); + //TODO: Implement algorithm to count votes + return new ResponseEntity(voteResult, HttpStatus.OK); + } + + public Integer countAllVotes (Iterable allVotes){ + Long count = StreamSupport.stream(allVotes.spliterator(), false).count(); + return count.intValue(); + } + +} + + + + + diff --git a/src/main/java/io/zipcoder/tc_spring_poll_application/controller/PollController.java b/src/main/java/io/zipcoder/tc_spring_poll_application/controller/PollController.java new file mode 100644 index 0000000..9e25547 --- /dev/null +++ b/src/main/java/io/zipcoder/tc_spring_poll_application/controller/PollController.java @@ -0,0 +1,76 @@ +package io.zipcoder.tc_spring_poll_application.controller; + +import io.zipcoder.tc_spring_poll_application.domain.Poll; +import io.zipcoder.tc_spring_poll_application.exception.ResourceNotFoundException; +import io.zipcoder.tc_spring_poll_application.repositories.PollRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties; +import org.springframework.data.domain.Page; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; +import org.springframework.data.domain.Pageable; +import javax.validation.Valid; + +import java.net.URI; + +@RestController +public class PollController { + + private PollRepository pollRepository; + + @Autowired + public PollController(PollRepository pollRepository){ + this.pollRepository = pollRepository; + } + + @GetMapping("/polls") + public ResponseEntity> getAllPolls(Pageable pageable) { + Page allPolls = pollRepository.findAll(pageable); + return new ResponseEntity<>(allPolls, HttpStatus.OK); + } + + @PostMapping("/polls") + public ResponseEntity createPoll(@RequestBody @Valid Poll poll) { + pollRepository.save(poll); + URI newPollUri = ServletUriComponentsBuilder + .fromCurrentRequest() + .path("/{id}") + .buildAndExpand(poll.getId()) + .toUri(); + HttpHeaders header = new HttpHeaders(); + header.setLocation(newPollUri); + return new ResponseEntity<>(header, HttpStatus.CREATED); + } + + @GetMapping("/polls/{pollId}") + public ResponseEntity getPoll(@PathVariable Long pollId) { + if (pollRepository.findById(pollId).isPresent()) { + Poll p = pollRepository.findById(pollId).get(); + return new ResponseEntity<>(p, HttpStatus.OK); + } + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + + @PutMapping("/polls/{pollId}") + public ResponseEntity updatePoll(@RequestBody @Valid Poll poll, @PathVariable Long pollId) { + // Save the entity + verifyPoll(pollId); + Poll p = pollRepository.save(poll); + return new ResponseEntity<>(HttpStatus.OK); + } + + @DeleteMapping("/polls/{pollId}") + public ResponseEntity deletePoll(@PathVariable Long pollId) { + verifyPoll(pollId); + pollRepository.deleteById(pollId); + return new ResponseEntity<>(HttpStatus.OK); + } + + public void verifyPoll (Long pollId) throws ResourceNotFoundException { + if(!pollRepository.findById(pollId).isPresent()) throw new ResourceNotFoundException(); + } +} + diff --git a/src/main/java/io/zipcoder/tc_spring_poll_application/controller/VoteController.java b/src/main/java/io/zipcoder/tc_spring_poll_application/controller/VoteController.java new file mode 100644 index 0000000..7d51aab --- /dev/null +++ b/src/main/java/io/zipcoder/tc_spring_poll_application/controller/VoteController.java @@ -0,0 +1,41 @@ +package io.zipcoder.tc_spring_poll_application.controller; + +import io.zipcoder.tc_spring_poll_application.domain.Vote; +import io.zipcoder.tc_spring_poll_application.repositories.VoteRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +@RestController +public class VoteController { + + private VoteRepository voteRepository; + + @Autowired + public VoteController(VoteRepository voteRepository) { + this.voteRepository = voteRepository; + } + + @PostMapping("/polls/{pollId}/votes") + public ResponseEntity createVote(@PathVariable Long pollId, @RequestBody Vote + vote) { + vote = voteRepository.save(vote); + // Set the headers for the newly created resource + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders. + setLocation(ServletUriComponentsBuilder + .fromCurrentRequest() + .path("/{id}"). + buildAndExpand(vote.getId()).toUri()); + return new ResponseEntity<>(null, responseHeaders, HttpStatus.CREATED); + } + + @GetMapping("/polls/{pollId}/votes") + public ResponseEntity> getVote(@PathVariable Long pollId) { + return new ResponseEntity<>(voteRepository.findVotesByPoll(pollId), HttpStatus.OK); + } +} diff --git a/src/main/java/io/zipcoder/tc_spring_poll_application/domain/Option.java b/src/main/java/io/zipcoder/tc_spring_poll_application/domain/Option.java new file mode 100644 index 0000000..bfead6e --- /dev/null +++ b/src/main/java/io/zipcoder/tc_spring_poll_application/domain/Option.java @@ -0,0 +1,44 @@ +package io.zipcoder.tc_spring_poll_application.domain; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Option { + @Id + @GeneratedValue + @Column(name="OPTION_ID") + Long id; + + @Column(name = "OPTION_VALUE") + String value; + + public Option () {} + + public Option(Long id, String value) { + this.id = id; + this.value = value; + } + + public Option(String value) { + this.value = value; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/src/main/java/io/zipcoder/tc_spring_poll_application/domain/Poll.java b/src/main/java/io/zipcoder/tc_spring_poll_application/domain/Poll.java new file mode 100644 index 0000000..511c200 --- /dev/null +++ b/src/main/java/io/zipcoder/tc_spring_poll_application/domain/Poll.java @@ -0,0 +1,64 @@ +package io.zipcoder.tc_spring_poll_application.domain; + +import javax.persistence.*; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; +import java.util.Set; + +@Entity +public class Poll { + + @Id + @GeneratedValue + @Column(name = "POLL_ID") + Long id; + + @Column(name = "QUESTION") + @NotEmpty + String question; + + @OneToMany(cascade = CascadeType.ALL) + @JoinColumn(name = "POLL_ID") + @OrderBy + @Size(min = 2, max = 6) + Set