Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docker-compose-db.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: '3.8'
services:
web_db:
image: postgres
container_name: spring_db
environment:
- POSTGRES_DB=localdb
- POSTGRES_PASSWORD=localdb
- POSTGRES_USER=localdb
restart: always
ports:
- '5430:5432'
14 changes: 9 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- <dependency>-->
<!-- <groupId>org.postgresql</groupId>-->
<!-- <artifactId>postgresql</artifactId>-->
<!-- <scope>runtime</scope>-->
<!-- </dependency>-->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
Expand All @@ -62,6 +62,10 @@
<artifactId>tomcat-embed-core</artifactId>
<version>10.1.13</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>

<build>
Expand Down

This file was deleted.

199 changes: 95 additions & 104 deletions src/main/java/com/example/springlabs/controllers/CategoryController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.example.springlabs.controllers.dtos.CategoryDto;
import com.example.springlabs.controllers.dtos.mappers.CategoryDtoMapper;
import com.example.springlabs.exception.CategoryNotFoundException;
import com.example.springlabs.model.Category;
import com.example.springlabs.services.CategoryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
Expand All @@ -11,132 +13,121 @@
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;

import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.*;

import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.experimental.FieldDefaults;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
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.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.HandlerMapping;

@Tag(name = "Category", description = "Operations related to categories")
@RestController
@RequestMapping(value = "/categories", produces = MediaType.APPLICATION_JSON_VALUE)
@RequestMapping(value = "/categories", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class CategoryController {

CategoryService categoryService;
CategoryService categoryService;

CategoryDtoMapper categoryDtoMapper;

CategoryDtoMapper categoryDtoMapper;
String CATEGORY_NAME_NOT_FOUND = "Category with name: %s doesn't exist!";

@Operation(summary = "Get all categories", description = "Returns a list of all categories.", parameters = {
@Parameter(name = "page", description = "Page number starting from 0"),
@Parameter(name = "size", description = "Size of page"),
@Parameter(name = "name", description = "Value for filtering by category name")
})
@ApiResponse(responseCode = "200", description = "Successful given categories",
content = @Content(schema = @Schema(implementation = CategoryDto.class)))
@GetMapping
public Collection<CategoryDto> getAll(@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "size", defaultValue = "0") int size,
@RequestParam(value = "name", defaultValue = "") String name) {
return categoryDtoMapper.createDtosSet(categoryService.getAllCategories(page, size, name));
}
@Operation(summary = "Get all categories", description = "Returns a list of all categories.", parameters = {
@Parameter(name = "page", description = "Page number starting from 0"),
@Parameter(name = "size", description = "Size of page"),
@Parameter(name = "name", description = "Value for filtering by category name")
})
@ApiResponse(responseCode = "200", description = "Successful given categories",
content = @Content(schema = @Schema(implementation = CategoryDto.class)))
@GetMapping
public Collection<CategoryDto> getAll(@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "size", defaultValue = "0") int size,
@RequestParam(value = "name", defaultValue = "") String name) {
return categoryDtoMapper.createDtosSet(categoryService.getAllCategories(page, size, name));
}

@Operation(summary = "Get a category by name", description = "Returns a category by its name.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successful returned category",
content = @Content(schema = @Schema(implementation = CategoryDto.class))),
@ApiResponse(responseCode = "404", description = "Category not found by name", content = @Content)
})
@GetMapping("/**")
public CategoryDto getCategory(HttpServletRequest request) {
List<String> urlComponents = getUrlComponents(request);
return categoryDtoMapper.createDto(categoryService.getCategoryByName(urlComponents));
}
@Operation(summary = "Get a category by name", description = "Returns a category by its name.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successful returned category",
content = @Content(schema = @Schema(implementation = CategoryDto.class))),
@ApiResponse(responseCode = "404", description = "Category not found by name", content = @Content)
})
@GetMapping("/**")
public CategoryDto getCategory(HttpServletRequest request) {
List<String> urlComponents = getUrlComponents(request);
return categoryDtoMapper.createDto(categoryService.getCategoryByName(urlComponents));
}

@Operation(summary = "Add a new category", description = "Creates a new category.")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "A new category created", content = @Content(schema = @Schema(implementation = CategoryDto.class))),
@ApiResponse(responseCode = "400", description = "Invalid request data", content = @Content)
})
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public CategoryDto addCategory(@RequestBody CategoryDto categoryDto) {
return categoryDtoMapper.createDto(
categoryService.addCategory(categoryDtoMapper.createCategoryFromDto(categoryDto)));
}
@Operation(summary = "Add a new category", description = "Creates a new category.")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "A new category created", content = @Content(schema = @Schema(implementation = CategoryDto.class))),
@ApiResponse(responseCode = "400", description = "Invalid request data", content = @Content)
})
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public CategoryDto addCategory(@RequestBody CategoryDto categoryDto) {
return categoryDtoMapper.createDto(
categoryService.addCategory(categoryDtoMapper.createCategoryFromDto(categoryDto)));
}

@Operation(summary = "Add a subcategory to a category", description = "Creates a new subcategory for the specified category.")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "New subcategory for the specified category created",
content = @Content(schema = @Schema(implementation = CategoryDto.class))),
@ApiResponse(responseCode = "400", description = "Invalid request data", content = @Content),
@ApiResponse(responseCode = "404", description = "Parent category is not found by name", content = @Content)
})
@PostMapping("/**")
@ResponseStatus(HttpStatus.CREATED)
public CategoryDto addSubcategory(HttpServletRequest request,
@RequestBody CategoryDto categoryDto) {
List<String> urlComponents = getUrlComponents(request);
return categoryDtoMapper.createDto(
categoryService.addSubcategory(urlComponents,
categoryDtoMapper.createCategoryFromDto(categoryDto)));
}
@Operation(summary = "Add a subcategory to a category", description = "Creates a new subcategory for the specified category.")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "New subcategory for the specified category created",
content = @Content(schema = @Schema(implementation = CategoryDto.class))),
@ApiResponse(responseCode = "400", description = "Invalid request data", content = @Content),
@ApiResponse(responseCode = "404", description = "Parent category is not found by name", content = @Content)
})
@PostMapping("/**")
@ResponseStatus(HttpStatus.CREATED)
public CategoryDto addSubcategory(HttpServletRequest request,
@RequestBody CategoryDto categoryDto) {
List<String> urlComponents = getUrlComponents(request);
return categoryDtoMapper.createDto(categoryService.addCategory(categoryDtoMapper.createCategoryFromDto(categoryDto), urlComponents));
}

@Operation(summary = "Update a category", description = "Updates an existing category.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Category updated",
content = @Content(schema = @Schema(implementation = CategoryDto.class))),
@ApiResponse(responseCode = "400", description = "Invalid category or request data", content = @Content),
@ApiResponse(responseCode = "404", description = "Category is not found by id", content = @Content)
})
@PutMapping("/**")
@ResponseStatus(HttpStatus.OK)
public CategoryDto updateCategory(HttpServletRequest request,
@RequestBody CategoryDto categoryDto) {
List<String> urlComponents = new ArrayList<>(getUrlComponents(request));
String id = urlComponents.remove(urlComponents.size() - 1);
return categoryDtoMapper.createDto(
categoryService.updateCategory(urlComponents, id,
categoryDtoMapper.createCategoryFromDto(categoryDto)));
}
@Operation(summary = "Update a category", description = "Updates an existing category.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Category updated",
content = @Content(schema = @Schema(implementation = CategoryDto.class))),
@ApiResponse(responseCode = "400", description = "Invalid category or request data", content = @Content),
@ApiResponse(responseCode = "404", description = "Category is not found by id", content = @Content)
})
@PutMapping("/**")
@ResponseStatus(HttpStatus.OK)
public CategoryDto updateCategory(HttpServletRequest request,
@RequestBody CategoryDto categoryDto) {
List<String> urlComponents = new ArrayList<>(getUrlComponents(request));
String id = urlComponents.remove(urlComponents.size() - 1);
return categoryDtoMapper.createDto(
categoryService.updateCategory(urlComponents, id,
categoryDtoMapper.createCategoryFromDto(categoryDto)));
}

@Operation(summary = "Delete a category", description = "Deletes an existing category.")
@ApiResponses({
@ApiResponse(responseCode = "204", description = "Category was successfully deleted"),
@ApiResponse(responseCode = "404", description = "Category is not found by id")})
@DeleteMapping("/**")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteCategory(HttpServletRequest request) {
List<String> urlComponents = new ArrayList<>(getUrlComponents(request));
String id = urlComponents.remove(urlComponents.size() - 1);
categoryService.deleteCategory(urlComponents, id);
}
@Operation(summary = "Delete a category", description = "Deletes an existing category.")
@ApiResponses({
@ApiResponse(responseCode = "204", description = "Category was successfully deleted"),
@ApiResponse(responseCode = "404", description = "Category is not found by id")})
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void deleteCategory(@PathVariable long id) {
categoryService.deleteCategory(id);
}

private List<String> getUrlComponents(HttpServletRequest request) {
return Arrays.stream(new AntPathMatcher().extractPathWithinPattern(
request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString(),
URLDecoder.decode(
request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).toString(),
Charset.defaultCharset()))
.split("/"))
.toList();
}
private List<String> getUrlComponents(HttpServletRequest request) {
return Arrays.stream(new AntPathMatcher().extractPathWithinPattern(
request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString(),
URLDecoder.decode(
request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).toString(),
Charset.defaultCharset()))
.split("/"))
.toList();
}
}
24 changes: 14 additions & 10 deletions src/main/java/com/example/springlabs/model/Category.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,28 @@
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

import jakarta.persistence.*;
import lombok.*;

@Entity(name = "categories")
@NamedQuery(name = "Categories.getCategoryById",
query = "SELECT u FROM categories u WHERE u.id = :id")
@Getter
@Setter
@ToString
@EqualsAndHashCode
@NoArgsConstructor

public class Category implements Comparable<Category> {
private static long nextId = 10; // temporary solution for id generation
private long id = nextId++;
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
private long id;
@Column(nullable = false)
private String name;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<Category> subCategories = new TreeSet<>();
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private List<Product> products = new ArrayList<>();

public Category(String name, Set<Category> subCategories, List<Product> products) {
Expand All @@ -29,10 +35,8 @@ public Category(String name, Set<Category> subCategories, List<Product> products
this.products = products;
}


@Override
public int compareTo(Category o) {
return this.name.compareTo(o.name);
}
}

}
Loading