From eed3b226abee511f72ce8ea94f109a6cea2c4f74 Mon Sep 17 00:00:00 2001 From: MannyMb Date: Tue, 17 Aug 2021 23:28:43 -0400 Subject: [PATCH] saving progress --- README.md | 16 ++-- pom.xml | 2 +- .../java/dtos/ComputeResultController.java | 31 ++++++++ src/main/java/dtos/OptionCount.java | 22 ++++++ src/main/java/dtos/VoteResult.java | 23 ++++++ .../controller/PollController.java | 72 ++++++++++++++++++ .../controller/VoteController.java | 43 +++++++++++ .../domain/Option.java | 34 +++++++++ .../domain/Poll.java | 54 ++++++++++++++ .../domain/Vote.java | 38 ++++++++++ .../error/ErrorDetail.java | 73 +++++++++++++++++++ .../error/ValidationError.java | 25 +++++++ .../exception/ResourceNotFoundException.java | 20 +++++ .../exception/RestExceptionHandler.java | 67 +++++++++++++++++ .../repositories/OptionRepository.java | 10 +++ .../repositories/PollRepository.java | 9 +++ .../repositories/VoteRepository.java | 16 ++++ src/main/resources/import.sql | 3 + src/main/resources/messages.properties | 2 + 19 files changed, 551 insertions(+), 9 deletions(-) create mode 100644 src/main/java/dtos/ComputeResultController.java create mode 100644 src/main/java/dtos/OptionCount.java create mode 100644 src/main/java/dtos/VoteResult.java create mode 100644 src/main/java/io/zipcoder/tc_spring_poll_application/controller/PollController.java create mode 100644 src/main/java/io/zipcoder/tc_spring_poll_application/controller/VoteController.java create mode 100644 src/main/java/io/zipcoder/tc_spring_poll_application/domain/Option.java create mode 100644 src/main/java/io/zipcoder/tc_spring_poll_application/domain/Poll.java create mode 100644 src/main/java/io/zipcoder/tc_spring_poll_application/domain/Vote.java create mode 100644 src/main/java/io/zipcoder/tc_spring_poll_application/error/ErrorDetail.java create mode 100644 src/main/java/io/zipcoder/tc_spring_poll_application/error/ValidationError.java create mode 100644 src/main/java/io/zipcoder/tc_spring_poll_application/exception/ResourceNotFoundException.java create mode 100644 src/main/java/io/zipcoder/tc_spring_poll_application/exception/RestExceptionHandler.java create mode 100644 src/main/java/io/zipcoder/tc_spring_poll_application/repositories/OptionRepository.java create mode 100644 src/main/java/io/zipcoder/tc_spring_poll_application/repositories/PollRepository.java create mode 100644 src/main/java/io/zipcoder/tc_spring_poll_application/repositories/VoteRepository.java create mode 100644 src/main/resources/import.sql create mode 100644 src/main/resources/messages.properties diff --git a/README.md b/README.md index 2c6950e..f452352 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,12 @@ # Part 1 - Domain Implementation * _Domain objects_ are the backbone for an application and contain the [business logic](https://en.wikipedia.org/wiki/Business_logic). -* Create a sub package of `io.zipcoder.tc_spring_poll_application` named `domain`. +* Create a sub package of `io.zipcoder.tc_spring_poll_application` named `io.zipcoder.tc_spring_poll_application.domain`. ## Part 1.1 - Create class `Option` -* Create an `Option` class in the `domain` sub-package. +* Create an `Option` class in the `io.zipcoder.tc_spring_poll_application.domain` sub-package. * `Option` class signature is annotated with `@Entity` * `Option` has an `id` instance variable of type `Long` * `id` should be `annotated` with @@ -32,7 +32,7 @@ ## Part 1.2 - Create class `Poll` -* Create a `Poll` class in the `domain` sub-package. +* Create a `Poll` class in the `io.zipcoder.tc_spring_poll_application.domain` sub-package. * `Poll` class signature is annotated with `@Entity` * `Poll` has an `id` instance variable of type `Long` * `id` should be `annotated` with @@ -55,7 +55,7 @@ ## Part 1.3 - Create class `Vote` -* Create a `Vote` class in the `domain` sub-package. +* Create a `Vote` class in the `io.zipcoder.tc_spring_poll_application.domain` sub-package. * `Vote` class signature is annotated with `@Entity` * `Vote` has an `id` instance variable of type `Long` * `id` should be `annotated` with @@ -75,7 +75,7 @@ * _Repositories_ or [Data Access Objects (DAO)](https://en.wikipedia.org/wiki/Data_access_object), provide an abstraction for interacting with _datastores_. * Typically DAOs include an interface that provides a set of finder methods such as `findById`, `findAll`, for retrieving data, and methods to persist and delete data. -* It is customary to have one `Repository` per `domain` object. +* It is customary to have one `Repository` per `io.zipcoder.tc_spring_poll_application.domain` object. * Create a sub-package of `io.zipcoder.tc_spring_poll_application` named `repositories`. @@ -98,7 +98,7 @@ # Part 3 - Controller Implementation -* _Controllers_ provides all of the necessary [endpoints](https://en.wikipedia.org/wiki/Web_API#Endpoints) to access and manipulate respective domain objects. +* _Controllers_ provides all of the necessary [endpoints](https://en.wikipedia.org/wiki/Web_API#Endpoints) to access and manipulate respective io.zipcoder.tc_spring_poll_application.domain objects. * REST resources are identified using URI endpoints. * Create a sub package of `io.zipcoder.tc_spring_poll_application` named `controller`. @@ -357,7 +357,7 @@ public Iterable getVote(@PathVariable Long pollId) { # Part 4 - Data Transfer Object (DTO) Implementation * The final piece remaining for us is the implementation of the ComputeResult resource. -* Because we don’t have any domain objects that can directly help generate this resource representation, we implement two Data Transfer Objects or DTOs—OptionCount and VoteResult +* Because we don’t have any io.zipcoder.tc_spring_poll_application.domain objects that can directly help generate this resource representation, we implement two Data Transfer Objects or DTOs—OptionCount and VoteResult * Create a sub package of `java` named `dtos` @@ -506,7 +506,7 @@ public ResponseEntity handleResourceNotFoundException(ResourceNotFoundExcepti -## Part 5.4 - Validating domain entities +## Part 5.4 - Validating io.zipcoder.tc_spring_poll_application.domain entities Now it's time to make sure that all objects persisted to the database actually contain valid values. Use the `org.hibernate.validator.constraints.NotEmpty` and `javax.validation.constraints.Size` and `javax.validation.Valid` annotations for validation. diff --git a/pom.xml b/pom.xml index ed84c9b..7202189 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,7 @@ 1.5.3.RELEASE + UTF-8 io.zipcoder.tc_spring_poll_application.QuickPollApplication @@ -45,5 +46,4 @@ - diff --git a/src/main/java/dtos/ComputeResultController.java b/src/main/java/dtos/ComputeResultController.java new file mode 100644 index 0000000..0138700 --- /dev/null +++ b/src/main/java/dtos/ComputeResultController.java @@ -0,0 +1,31 @@ +package dtos; + +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.HttpStatus; +import org.springframework.http.ResponseEntity; +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.RestController; + +@RestController +public class ComputeResultController { + + private VoteRepository voteRepository; + + @Autowired + public ComputeResultController(VoteRepository voteRepository) { + this.voteRepository = voteRepository; + } + + @RequestMapping(value = "/computeresult", method = RequestMethod.GET) + public ResponseEntity computeResult(@RequestParam Long pollId) { + VoteResult voteResult = new VoteResult(); + Iterable allVotes = voteRepository.findVotesByPoll(pollId); + + //TODO: Implement algorithm to count votes + return new ResponseEntity(voteResult, HttpStatus.OK); + } +} \ No newline at end of file diff --git a/src/main/java/dtos/OptionCount.java b/src/main/java/dtos/OptionCount.java new file mode 100644 index 0000000..5965d67 --- /dev/null +++ b/src/main/java/dtos/OptionCount.java @@ -0,0 +1,22 @@ +package dtos; + +public class OptionCount { + private Long optionId; + private int 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..a42030c --- /dev/null +++ b/src/main/java/dtos/VoteResult.java @@ -0,0 +1,23 @@ +package dtos; + +import java.util.Collection; +public class VoteResult { + private int totalVotes; + private Collection 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/PollController.java b/src/main/java/io/zipcoder/tc_spring_poll_application/controller/PollController.java new file mode 100644 index 0000000..1e85c41 --- /dev/null +++ b/src/main/java/io/zipcoder/tc_spring_poll_application/controller/PollController.java @@ -0,0 +1,72 @@ +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.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; + +import javax.validation.Valid; +import java.net.URI; + +@RestController +public class PollController { + + PollRepository pollRepository; + + @Autowired + public PollController(PollRepository pollRepository) { + this.pollRepository = pollRepository; + } + + @RequestMapping(value="/polls", method= RequestMethod.GET) + public ResponseEntity> getAllPolls() { + Iterable allPolls = pollRepository.findAll(); + return new ResponseEntity<>(allPolls, HttpStatus.OK); + } + + + @RequestMapping(value="/polls", method=RequestMethod.POST) + public ResponseEntity createPoll(@Valid @RequestBody Poll poll) { + poll = pollRepository.save(poll); + + URI newPollUri = ServletUriComponentsBuilder + .fromCurrentRequest() + .path("/{id}") + .buildAndExpand(poll.getId()) + .toUri(); + + return new ResponseEntity<>(newPollUri, HttpStatus.CREATED); + } + + @RequestMapping(value="/polls/{pollId}", method=RequestMethod.GET) + public ResponseEntity getPoll(@PathVariable Long pollId) { + Poll p = pollRepository.findOne(pollId); + return new ResponseEntity<> (p, HttpStatus.OK); + } + + @RequestMapping(value="/polls/{pollId}", method=RequestMethod.PUT) + public ResponseEntity updatePoll(@Valid @RequestBody Poll poll, @PathVariable Long pollId) { + // Save the entity + Poll p = pollRepository.save(poll); + return new ResponseEntity<>(HttpStatus.OK); + } + + @RequestMapping(value="/polls/{pollId}", method=RequestMethod.DELETE) + public ResponseEntity deletePoll(@PathVariable Long pollId) { + pollRepository.delete(pollId); + return new ResponseEntity<>(HttpStatus.OK); + } + + void verifyPoll(@PathVariable Long pollId) { + if (pollRepository.findOne(pollId) == null) { + 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..d5caf8f --- /dev/null +++ b/src/main/java/io/zipcoder/tc_spring_poll_application/controller/VoteController.java @@ -0,0 +1,43 @@ +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.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; + } + + @RequestMapping(value = "/polls/{pollId}/votes", method = RequestMethod.POST) + 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); + } + + @RequestMapping(value="/polls/votes", method=RequestMethod.GET) + public Iterable getAllVotes() { + return voteRepository.findAll(); + } + + @RequestMapping(value="/polls/{pollId}/votes", method=RequestMethod.GET) + public Iterable getVote(@PathVariable Long pollId) { + return (Iterable) voteRepository.findOne(pollId); + } + +} 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..73bcd97 --- /dev/null +++ b/src/main/java/io/zipcoder/tc_spring_poll_application/domain/Option.java @@ -0,0 +1,34 @@ +package io.zipcoder.tc_spring_poll_application.domain; + +import javax.persistence.*; + +@Entity +public class Option { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "OPTION_ID") + Long id; + + @Column(name = "OPTION_VALUE") + String value; + + public Option() { + } + + 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..36c15fe --- /dev/null +++ b/src/main/java/io/zipcoder/tc_spring_poll_application/domain/Poll.java @@ -0,0 +1,54 @@ +package io.zipcoder.tc_spring_poll_application.domain; + +import org.hibernate.validator.constraints.NotEmpty; +import org.springframework.core.annotation.Order; + +import javax.persistence.*; +import javax.validation.constraints.Size; +import java.util.Set; + +@Entity +public class Poll { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @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