diff --git a/build.gradle b/build.gradle index d1f7789..c66e483 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ plugins { id 'java' - id 'org.springframework.boot' version '3.3.1' - id 'io.spring.dependency-management' version '1.1.5' + id 'org.springframework.boot' version '3.4.1' + id 'io.spring.dependency-management' version '1.1.7' } group = 'com.example' diff --git a/src/main/java/com/booleanuk/api/Main.java b/src/main/java/com/booleanuk/api/Main.java new file mode 100644 index 0000000..4e437d6 --- /dev/null +++ b/src/main/java/com/booleanuk/api/Main.java @@ -0,0 +1,11 @@ +package com.booleanuk.api; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Main { + public static void main(String[] args) { + SpringApplication.run(Main.class, args); + } +} \ No newline at end of file diff --git a/src/main/java/com/booleanuk/api/products/Product.java b/src/main/java/com/booleanuk/api/products/Product.java new file mode 100644 index 0000000..df095bb --- /dev/null +++ b/src/main/java/com/booleanuk/api/products/Product.java @@ -0,0 +1,43 @@ +package com.booleanuk.api.products; + +public class Product { + private int id; + private String name; + private String category; + private int price; + + public Product(int id, String name, String category, int price) { + this.id = id; + this.name = name; + this.category = category; + this.price = price; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public String getCategory() { + return category; + } + + public int getPrice() { + return price; + } + + public void setName(String name) { + this.name = name; + } + + public void setCategory(String category) { + this.category = category; + } + + public void setPrice(int price) { + this.price = price; + } +} diff --git a/src/main/java/com/booleanuk/api/products/ProductController.java b/src/main/java/com/booleanuk/api/products/ProductController.java new file mode 100644 index 0000000..96a4a23 --- /dev/null +++ b/src/main/java/com/booleanuk/api/products/ProductController.java @@ -0,0 +1,80 @@ +package com.booleanuk.api.products; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.server.ResponseStatusException; + +import java.util.List; +import java.util.NoSuchElementException; + +@RestController +@RequestMapping("/products") +public class ProductController { + ProductRepository repository; + + public ProductController(ProductRepository repository) { + this.repository = repository; + } + + public ProductController() { + this.repository = new ProductRepository(); + } + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public Product create(@RequestBody Product product) { + Product p = repository.create(product); + if (p == null) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Product with provided name already exists."); + } + return p; + } + + @GetMapping + @ResponseStatus(HttpStatus.OK) + public List getAll(@RequestParam(name="category", required=false) String category) { + List products; + if (category != null) + products = this.repository.findAll(category); + else + products = this.repository.findAll(); + if (products.isEmpty()) + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "No products of the provided category were found."); + return products; + } + + @GetMapping("/{id}") + @ResponseStatus(HttpStatus.OK) + public Product getOne(@PathVariable(name="id") int id) { + try { + return repository.find(id); + } catch (NoSuchElementException e) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Product not found."); + } + } + + @PutMapping("/{id}") + @ResponseStatus(HttpStatus.CREATED) + public Product update(@PathVariable(name="id") int id, @RequestBody Product product) { + Product updatedProduct; + try { + updatedProduct = repository.update(id, product); + } catch (NoSuchElementException e) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Product not found."); + } + if (updatedProduct == null) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Product with provided name already exists."); + } + return updatedProduct; + } + + @DeleteMapping("/{id}") + @ResponseStatus(HttpStatus.OK) + public Product delete(@PathVariable(name="id") int id) { + try { + return repository.delete(id); + } catch (NoSuchElementException e) { + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Product not found."); + } + } +} diff --git a/src/main/java/com/booleanuk/api/products/ProductRepository.java b/src/main/java/com/booleanuk/api/products/ProductRepository.java new file mode 100644 index 0000000..7138220 --- /dev/null +++ b/src/main/java/com/booleanuk/api/products/ProductRepository.java @@ -0,0 +1,74 @@ +package com.booleanuk.api.products; + +import java.util.ArrayList; +import java.util.List; + +public class ProductRepository { + private int idCounter = 1; + private List data; + + public ProductRepository() { + data = new ArrayList<>(); + create("Bagel", "Food", 12); + create("Apple", "Food", 7); + } + + public Product create(String name, String category, int price) { + Product product = new Product(this.idCounter++, name, category, price); + this.data.add(product); + return product; + } + + public Product create(Product product) { + if (!nameExists(product.getName())) { + return this.create(product.getName(), product.getCategory(), product.getPrice()); + } + return null; + } + + public List findAll(String category) { + return this.data.stream() + .filter(p -> p.getCategory().equals(category)) + .toList(); + } + + public List findAll() { + return this.data; + } + + public Product find(int id) { + return this.data.stream() + .filter(product -> product.getId() == id) + .findFirst() + .orElseThrow(); + } + + public Product update(int id, Product product) { + if (nameExists(product.getName(), id)) { + return null; + } + Product productToUpdate = find(id); + productToUpdate.setName(product.getName()); + productToUpdate.setCategory(product.getCategory()); + productToUpdate.setPrice(product.getPrice()); + return productToUpdate; + } + + public Product delete(int id) { + Product productToDelete = find(id); + data.remove(productToDelete); + return productToDelete; + } + + private boolean nameExists(String name) { + return !this.data.stream() + .filter(p -> p.getName().equals(name)) + .toList().isEmpty(); + } + + private boolean nameExists(String name, int excludeId) { + return !this.data.stream() + .filter(p -> p.getName().equals(name) && p.getId() != excludeId) + .toList().isEmpty(); + } +}