-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add the ability to delete unused category
- Loading branch information
1 parent
fefc605
commit fe1df66
Showing
18 changed files
with
355 additions
and
9 deletions.
There are no files selected for viewing
40 changes: 40 additions & 0 deletions
40
src/main/java/me/ezzedine/mohammed/personalspace/DataBackwardsCompatibilityEnabler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package me.ezzedine.mohammed.personalspace; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import me.ezzedine.mohammed.personalspace.article.infra.ArticleEntity; | ||
import me.ezzedine.mohammed.personalspace.article.infra.ArticleMongoRepository; | ||
import org.springframework.boot.CommandLineRunner; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
|
||
@Slf4j | ||
@Component | ||
@RequiredArgsConstructor | ||
public class DataBackwardsCompatibilityEnabler implements CommandLineRunner { | ||
|
||
private final ArticleMongoRepository articleMongoRepository; | ||
|
||
@Override | ||
public void run(String... args) { | ||
List<ArticleEntity> articles = articleMongoRepository.findAll(); | ||
for (ArticleEntity article : articles) { | ||
|
||
if (article.getCreatedDate() == null) { | ||
article.setCreatedDate(LocalDateTime.now()); | ||
} | ||
|
||
if (article.getLastModifiedDate() == null) { | ||
article.setLastModifiedDate(LocalDateTime.now()); | ||
} | ||
|
||
if (article.getVersion() == null) { | ||
articleMongoRepository.deleteById(article.getId()); | ||
} | ||
|
||
articleMongoRepository.save(article); | ||
} | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
.../java/me/ezzedine/mohammed/personalspace/article/core/ArticleCategoryDeletionAdvisor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package me.ezzedine.mohammed.personalspace.article.core; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import me.ezzedine.mohammed.personalspace.category.core.deletion.CategoryDeletionPermission; | ||
import me.ezzedine.mohammed.personalspace.category.core.deletion.CategoryDeletionPermissionGranter; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.util.List; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class ArticleCategoryDeletionAdvisor implements CategoryDeletionPermissionGranter { | ||
|
||
private final ArticleStorage articleStorage; | ||
|
||
@Override | ||
public CategoryDeletionPermission canDeleteCategory(String categoryId) { | ||
List<Article> articles = articleStorage.fetchByCategory(categoryId); | ||
if (articles.isEmpty()) { | ||
return CategoryDeletionPermission.allowed(); | ||
} | ||
|
||
return CategoryDeletionPermission.notAllowed(getReasonMessage(articles)); | ||
} | ||
|
||
private String getReasonMessage(List<Article> articles) { | ||
String commaSeparatedArticleIds = articles.stream().map(Article::getId).reduce((id1, id2) -> id1 + ", " + id2).orElse(""); | ||
return "Category cannot be deleted since it is linked to the following articles: [" + commaSeparatedArticleIds + "]"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
...e/ezzedine/mohammed/personalspace/category/api/advice/CategoryDeletionRejectedAdvice.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package me.ezzedine.mohammed.personalspace.category.api.advice; | ||
|
||
import me.ezzedine.mohammed.personalspace.category.core.deletion.CategoryDeletionRejectedException; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.ControllerAdvice; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import org.springframework.web.context.request.WebRequest; | ||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; | ||
|
||
@ControllerAdvice | ||
public class CategoryDeletionRejectedAdvice extends ResponseEntityExceptionHandler { | ||
|
||
@ExceptionHandler(CategoryDeletionRejectedException.class) | ||
protected ResponseEntity<Object> handle(CategoryDeletionRejectedException exception, WebRequest request) { | ||
return handleExceptionInternal(exception, exception.getMessage(), new HttpHeaders(), HttpStatus.BAD_REQUEST, request); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/me/ezzedine/mohammed/personalspace/category/core/CategoryDeleter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package me.ezzedine.mohammed.personalspace.category.core; | ||
|
||
import me.ezzedine.mohammed.personalspace.category.core.deletion.CategoryDeletionRejectedException; | ||
|
||
public interface CategoryDeleter { | ||
void delete(String id) throws CategoryNotFoundException, CategoryDeletionRejectedException; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
...me/ezzedine/mohammed/personalspace/category/core/deletion/CategoryDeletionPermission.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package me.ezzedine.mohammed.personalspace.category.core.deletion; | ||
|
||
import lombok.Builder; | ||
import lombok.Data; | ||
|
||
import java.util.Optional; | ||
|
||
@Data | ||
@Builder | ||
public class CategoryDeletionPermission { | ||
private boolean allowed; | ||
private String message; | ||
|
||
public Optional<String> getMessage() { | ||
return Optional.ofNullable(message); | ||
} | ||
|
||
public static CategoryDeletionPermission allowed() { | ||
return CategoryDeletionPermission.builder().allowed(true).build(); | ||
} | ||
|
||
public static CategoryDeletionPermission notAllowed(String reason) { | ||
return CategoryDeletionPermission.builder().allowed(false).message(reason).build(); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
...dine/mohammed/personalspace/category/core/deletion/CategoryDeletionPermissionGranter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package me.ezzedine.mohammed.personalspace.category.core.deletion; | ||
|
||
public interface CategoryDeletionPermissionGranter { | ||
CategoryDeletionPermission canDeleteCategory(String categoryId); | ||
} |
7 changes: 7 additions & 0 deletions
7
...dine/mohammed/personalspace/category/core/deletion/CategoryDeletionRejectedException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package me.ezzedine.mohammed.personalspace.category.core.deletion; | ||
|
||
public class CategoryDeletionRejectedException extends Exception { | ||
public CategoryDeletionRejectedException(String message) { | ||
super(message); | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
...a/me/ezzedine/mohammed/personalspace/article/core/ArticleCategoryDeletionAdvisorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package me.ezzedine.mohammed.personalspace.article.core; | ||
|
||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
import static org.junit.jupiter.api.Assertions.*; | ||
import static org.mockito.Mockito.mock; | ||
import static org.mockito.Mockito.when; | ||
|
||
class ArticleCategoryDeletionAdvisorTest { | ||
|
||
public static final String CATEGORY_ID = UUID.randomUUID().toString(); | ||
private ArticleStorage articleStorage; | ||
private ArticleCategoryDeletionAdvisor deletionAdvisor; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
articleStorage = mock(ArticleStorage.class); | ||
deletionAdvisor = new ArticleCategoryDeletionAdvisor(articleStorage); | ||
} | ||
|
||
@Test | ||
@DisplayName("the user should not be able to delete a category that has at least one article linked to it") | ||
void the_user_should_not_be_able_to_delete_a_category_that_has_at_least_one_article_linked_to_it() { | ||
Article article = getArticleMock(UUID.randomUUID().toString()); | ||
when(articleStorage.fetchByCategory(CATEGORY_ID)).thenReturn(List.of(article)); | ||
assertFalse(deletionAdvisor.canDeleteCategory(CATEGORY_ID).isAllowed()); | ||
} | ||
|
||
@Test | ||
@DisplayName("the user should get a message including the list of conflicting articles IDs when the deletion is rejected") | ||
void the_user_should_get_a_message_including_the_list_of_conflicting_articles_IDs_when_the_deletion_is_rejected() { | ||
String firstArticleId = UUID.randomUUID().toString(); | ||
Article firstArticle = getArticleMock(firstArticleId); | ||
String secondArticleId = UUID.randomUUID().toString(); | ||
Article secondArticle = getArticleMock(secondArticleId); | ||
|
||
when(articleStorage.fetchByCategory(CATEGORY_ID)).thenReturn(List.of(firstArticle, secondArticle)); | ||
assertTrue(deletionAdvisor.canDeleteCategory(CATEGORY_ID).getMessage().isPresent()); | ||
String message = "Category cannot be deleted since it is linked to the following articles: [" + firstArticleId + ", " + secondArticleId + "]"; | ||
assertEquals(message, deletionAdvisor.canDeleteCategory(CATEGORY_ID).getMessage().get()); | ||
} | ||
|
||
@Test | ||
@DisplayName("the user should be able to delete a category that is not linked to any article") | ||
void the_user_should_be_able_to_delete_a_category_that_is_not_linked_to_any_article() { | ||
when(articleStorage.fetchByCategory(CATEGORY_ID)).thenReturn(Collections.emptyList()); | ||
assertTrue(deletionAdvisor.canDeleteCategory(CATEGORY_ID).isAllowed()); | ||
} | ||
|
||
private Article getArticleMock(String id) { | ||
Article article = mock(Article.class); | ||
when(article.getId()).thenReturn(id); | ||
return article; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.