1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| package com.example.demo.product;
import org.springframework.http.HttpHeaders; 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.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicLong;
@RestController @RequestMapping("/api/v1/products") public class ProductController { private final List<Product> store = new CopyOnWriteArrayList<>(); private final AtomicLong idGen = new AtomicLong(0);
public record Product(Long id, String description, BigDecimal price, int stock) {} public record CreateProductRequest(String description, BigDecimal price, Integer stock) {} public record PatchProductRequest(String description, BigDecimal price, Integer stock) {}
public ProductController() { store.add(new Product(idGen.incrementAndGet(), "Demo A", new BigDecimal("99.90"), 10)); store.add(new Product(idGen.incrementAndGet(), "Demo B", new BigDecimal("199.00"), 5)); }
@GetMapping public List<Product> list() { return store; }
@GetMapping("/{id}") public ResponseEntity<Product> getById(@PathVariable Long id) { int idx = indexOfId(id); if (idx < 0) { return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); } return ResponseEntity.ok(store.get(idx)); }
@PostMapping public ResponseEntity<Product> create(@RequestBody CreateProductRequest req) { if (!isValidCreate(req)) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); } long id = idGen.incrementAndGet(); Product product = new Product(id, req.description(), req.price(), req.stock()); store.add(product); return ResponseEntity .status(HttpStatus.CREATED) .header(HttpHeaders.LOCATION, "/api/v1/products/" + id) .body(product); }
@PatchMapping("/{id}") public ResponseEntity<Product> patch(@PathVariable Long id, @RequestBody PatchProductRequest req) { int idx = indexOfId(id); if (idx < 0) { return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); } Product old = store.get(idx);
String newDescription = req != null && req.description() != null ? req.description() : old.description(); BigDecimal newPrice = req != null && req.price() != null ? req.price() : old.price(); Integer newStockBoxed = req != null && req.stock() != null ? req.stock() : old.stock();
if (!isValidFields(newDescription, newPrice, newStockBoxed)) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); }
Product updated = new Product(id, newDescription, newPrice, newStockBoxed); store.set(idx, updated); return ResponseEntity.ok(updated); }
@DeleteMapping("/{id}") public ResponseEntity<Void> delete(@PathVariable Long id) { boolean removed = store.removeIf(p -> p.id().equals(id)); return removed ? ResponseEntity.noContent().build() : ResponseEntity.status(HttpStatus.NOT_FOUND).build(); }
private int indexOfId(Long id) { for (int i = 0; i < store.size(); i++) { if (store.get(i).id().equals(id)) { return i; } } return -1; }
private boolean isValidCreate(CreateProductRequest req) { if (req == null || req.description() == null || req.description().isBlank()) return false; if (req.price() == null || req.price().compareTo(BigDecimal.ZERO) < 0) return false; if (req.stock() == null || req.stock() < 0) return false; return true; }
private boolean isValidFields(String description, BigDecimal price, Integer stock) { if (description == null || description.isBlank()) return false; if (price == null || price.compareTo(BigDecimal.ZERO) < 0) return false; if (stock == null || stock < 0) return false; return true; } }
|