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..a049d53 --- /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); + } +} diff --git a/src/main/java/com/booleanuk/api/product/controller/ProductController.java b/src/main/java/com/booleanuk/api/product/controller/ProductController.java new file mode 100644 index 0000000..e7409a7 --- /dev/null +++ b/src/main/java/com/booleanuk/api/product/controller/ProductController.java @@ -0,0 +1,71 @@ +package com.booleanuk.api.product.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.booleanuk.api.product.service.ProductService; + +import java.util.List; +import com.booleanuk.api.product.model.Product; +import com.booleanuk.api.product.model.ProductCreateDto; + +@RestController +@RequestMapping("/products") +public class ProductController{ + private ProductService productService; + + public ProductController(ProductService productService){ + this.productService = productService; + } + + // @GetMapping + // public ResponseEntity> getAllProduct(){ + // List prods = this.productService.getAllProduct(); + // return ResponseEntity.ok(prods); + // } + + @GetMapping + public ResponseEntity> getAllProduct(@RequestParam (required = false) String category){ + List prods; + if(category == null) + prods = this.productService.getAllProduct(); + else + prods = this.productService.getAllProduct(category); + + return ResponseEntity.ok(prods); + } + + @GetMapping("/{id}") + public ResponseEntity getProduct(@PathVariable int id){ + Product res = this.productService.getProduct(id); + return ResponseEntity.ok(res); + } + + @PostMapping + public ResponseEntity createProduct(@RequestBody ProductCreateDto productDto){ + Product res = this.productService.createProduct(productDto.getName(), productDto.getCategory(), productDto.getPrice()); + return ResponseEntity.status(HttpStatus.CREATED).body(res); + } + + @PutMapping("/{id}") + public ResponseEntity putProduct(@PathVariable int id, @RequestBody ProductCreateDto productDto){ + Product res = this.productService.putProduct(id, productDto.getName(), productDto.getCategory(), productDto.getPrice()); + return ResponseEntity.ok(res); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteProduct(@PathVariable int id){ + Product res = this.productService.deleteProduct(id); + return ResponseEntity.ok(res); + } + +} diff --git a/src/main/java/com/booleanuk/api/product/exeption/AlreadyExistsException.java b/src/main/java/com/booleanuk/api/product/exeption/AlreadyExistsException.java new file mode 100644 index 0000000..da9cfab --- /dev/null +++ b/src/main/java/com/booleanuk/api/product/exeption/AlreadyExistsException.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.product.exeption; + +public class AlreadyExistsException extends RuntimeException{ + public AlreadyExistsException(String message){ + super(message); + } +} diff --git a/src/main/java/com/booleanuk/api/product/exeption/InputNotValidException.java b/src/main/java/com/booleanuk/api/product/exeption/InputNotValidException.java new file mode 100644 index 0000000..130733f --- /dev/null +++ b/src/main/java/com/booleanuk/api/product/exeption/InputNotValidException.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.product.exeption; + +public class InputNotValidException extends RuntimeException{ + public InputNotValidException(String message){ + super(message); + } +} diff --git a/src/main/java/com/booleanuk/api/product/exeption/ProductExeptionHandler.java b/src/main/java/com/booleanuk/api/product/exeption/ProductExeptionHandler.java new file mode 100644 index 0000000..a574402 --- /dev/null +++ b/src/main/java/com/booleanuk/api/product/exeption/ProductExeptionHandler.java @@ -0,0 +1,25 @@ +package com.booleanuk.api.product.exeption; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class ProductExeptionHandler{ + + @ExceptionHandler(ResourceNotFoundException.class) + public ResponseEntity handleNotFound(ResourceNotFoundException ex){ + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage()); + } + + @ExceptionHandler(AlreadyExistsException.class) + public ResponseEntity handleInvalidRequest(AlreadyExistsException ex){ + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.getMessage()); + } + + @ExceptionHandler(InputNotValidException.class) + public ResponseEntity handleInvelidArgs(InputNotValidException ex){ + return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body(ex.getMessage()); + } +} diff --git a/src/main/java/com/booleanuk/api/product/exeption/ResourceNotFoundException.java b/src/main/java/com/booleanuk/api/product/exeption/ResourceNotFoundException.java new file mode 100644 index 0000000..8f43b75 --- /dev/null +++ b/src/main/java/com/booleanuk/api/product/exeption/ResourceNotFoundException.java @@ -0,0 +1,7 @@ +package com.booleanuk.api.product.exeption; + +public class ResourceNotFoundException extends RuntimeException{ + public ResourceNotFoundException(String message){ + super(message); + } +} \ No newline at end of file diff --git a/src/main/java/com/booleanuk/api/product/model/Product.java b/src/main/java/com/booleanuk/api/product/model/Product.java new file mode 100644 index 0000000..7c81460 --- /dev/null +++ b/src/main/java/com/booleanuk/api/product/model/Product.java @@ -0,0 +1,55 @@ +package com.booleanuk.api.product.model; + +public class Product { + + private static int nextId = 0; + + private int id; + private String name; + private String category; + private int price; + + public Product(String name, String category, int price){ + setId(++nextId); + setName(name); + setCategory(category); + setPrice(price); + } + + public int getId(){ + return this.id; + } + + public void setId(int id){ + this.id = id; + } + + public String getName(){ + return this.name; + } + + public void setName(String name){ + this.name = name; + } + + public String getCategory(){ + return this.category; + } + + public void setCategory(String category){ + this.category = category; + } + + public int getPrice(){ + return this.price; + } + + public void setPrice(int price){ + this.price = price; + } + + public static int getCurrentId(){ + return nextId; + } + +} diff --git a/src/main/java/com/booleanuk/api/product/model/ProductCreateDto.java b/src/main/java/com/booleanuk/api/product/model/ProductCreateDto.java new file mode 100644 index 0000000..612349f --- /dev/null +++ b/src/main/java/com/booleanuk/api/product/model/ProductCreateDto.java @@ -0,0 +1,40 @@ +package com.booleanuk.api.product.model; + +public class ProductCreateDto { + + + private String name; + private String category; + private int price; + + public ProductCreateDto(String name, String category, int price){ + setName(name); + setCategory(category); + setPrice(price); + } + + public String getName(){ + return this.name; + } + + public void setName(String name){ + this.name = name; + } + + public String getCategory(){ + return this.category; + } + + public void setCategory(String category){ + this.category = category; + } + + public int getPrice(){ + return this.price; + } + + public void setPrice(int price){ + this.price = price; + } + +} diff --git a/src/main/java/com/booleanuk/api/product/repo/ProductRepository.java b/src/main/java/com/booleanuk/api/product/repo/ProductRepository.java new file mode 100644 index 0000000..982ecb6 --- /dev/null +++ b/src/main/java/com/booleanuk/api/product/repo/ProductRepository.java @@ -0,0 +1,79 @@ +package com.booleanuk.api.product.repo; + +import java.util.List; +import java.util.Optional; +import java.util.ArrayList; + +import org.springframework.stereotype.Repository; + +import com.booleanuk.api.product.model.Product; + +@Repository +public class ProductRepository{ + private List products; + + public ProductRepository(){ + this.products = new ArrayList(); + this.products.add(new Product("How to build APIs", "Book", 1500)); + this.products.add(new Product("Get good at vim", "Paper", 100)); + } + + public List getAll(){ + return this.products; + } + + public Optional> getAll(String category){ + List tmp = new ArrayList(); + for (Product p : this.products){ + if(p.getCategory().equals(category)) + tmp.add(p); + } + if(tmp.isEmpty()) + return Optional.empty(); + return Optional.of(tmp); + } + + public Product createProduct(String name, String category, int price){ + Product product = new Product(name, category, price); + this.products.add(product); + return product; + } + + public Optional getOne(int id){ + for (Product p : this.products){ + if(p.getId() == id) + return Optional.of(p); + } + return Optional.empty(); + } + + public Optional putOne(int id, String name, String category, int price){ + for (int i = 0; i < Product.getCurrentId()-1; i++){ + Product p = this.products.get(i); + if(p.getId() == id){ + p.setName(name); + p.setCategory(category); + p.setPrice(price); + return Optional.of(this.products.set(i, p)); + } + } + return Optional.empty(); + } + + public Optional deleteOne(int id){ + for (int i = 0; i < Product.getCurrentId()-1; i++){ + Product p = this.products.get(i); + if(p.getId() == id){ + Product removed = this.products.remove(i); + return Optional.of(removed); + } + } + return Optional.empty(); + } + + public boolean isProduct(String name){ + boolean cond = this.products.stream().anyMatch(product -> product.getName().equals(name)); + return cond; + } + +} diff --git a/src/main/java/com/booleanuk/api/product/service/ProductService.java b/src/main/java/com/booleanuk/api/product/service/ProductService.java new file mode 100644 index 0000000..5c369ed --- /dev/null +++ b/src/main/java/com/booleanuk/api/product/service/ProductService.java @@ -0,0 +1,83 @@ +package com.booleanuk.api.product.service; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import com.booleanuk.api.product.repo.ProductRepository; +import com.booleanuk.api.product.exeption.ResourceNotFoundException; +import com.booleanuk.api.product.exeption.InputNotValidException; +import com.booleanuk.api.product.exeption.AlreadyExistsException; + + +import java.util.List; +import java.util.Optional; + +import com.booleanuk.api.product.model.Product; + +@Service +public class ProductService{ + + private ProductRepository productRepo; + + public ProductService(ProductRepository productRepo){ + this.productRepo = productRepo; + } + + public List getAllProduct(){ + return this.productRepo.getAll(); + } + + public List getAllProduct(String category){ + Optional> res = this.productRepo.getAll(category); + if(res.isEmpty()) + throw new ResourceNotFoundException("No category called \"" + category + "\""); + + return res.get(); + } + + public Product createProduct(String name, String category, int price){ + if(price < 0) + throw new InputNotValidException("Price cannot be negative"); + else if(name.isBlank() || category.isBlank()) + throw new InputNotValidException("Cannot be empty or blank"); + else if(this.productRepo.isProduct(name)) + throw new AlreadyExistsException("Product with name allready exists"); + + Product prod = this.productRepo.createProduct(name, category, price); + + return prod; + } + + public Product getProduct(int id){ + Optional optionalProd = this.productRepo.getOne(id); + if(optionalProd.isEmpty()) + throw new ResourceNotFoundException("Product not found"); + + return optionalProd.get(); + } + + public Product putProduct(int id, String name, String category, int price){ + if(price < 0) + throw new InputNotValidException("Price cannot be negative"); + else if(name.isBlank() || category.isBlank()) + throw new InputNotValidException("Cannot be empty or blank"); + else if(this.productRepo.isProduct(name)) + throw new AlreadyExistsException("Product with name allready exists"); + + Optional optionalProd = this.productRepo.putOne(id, name, category, price); + if(optionalProd.isEmpty()) + throw new ResourceNotFoundException("Product not found"); + + return optionalProd.get(); + } + + public Product deleteProduct(int id){ + Optional optionalProd = this.productRepo.deleteOne(id); + if(optionalProd.isEmpty()) + throw new ResourceNotFoundException("Product not found"); + + return optionalProd.get(); + } + +}