Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 용어 관리 API #96

Merged
merged 6 commits into from
Jun 25, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import vook.server.api.domain.user.model.SocialUserRepository;
import vook.server.api.domain.user.model.UserInfoRepository;
import vook.server.api.domain.user.model.UserRepository;
import vook.server.api.domain.vocabulary.model.TermRepository;
import vook.server.api.domain.vocabulary.model.TermSynonymRepository;
import vook.server.api.domain.vocabulary.model.VocabularyRepository;
import vook.server.api.infra.search.demo.MeilisearchDemoTermSearchService;

Expand All @@ -21,12 +23,14 @@ public class InitService {

private final DemoTermRepository demoTermRepository;
private final DemoTermSynonymRepository demoTermSynonymRepository;
private final TermRepository termRepository;
private final VocabularyRepository vocabularyRepository;
private final UserInfoRepository userInfoRepository;
private final SocialUserRepository socialUserRepository;
private final UserRepository userRepository;
private final MeilisearchDemoTermSearchService searchService;
private final TestTermsLoader testTermsLoader;
private final TermSynonymRepository termSynonymRepository;

public void init() {
deleteAll();
Expand All @@ -44,6 +48,8 @@ private void deleteAll() {
demoTermRepository.deleteAllInBatch();

// 용어집
termSynonymRepository.deleteAllInBatch();
termRepository.deleteAllInBatch();
vocabularyRepository.deleteAllInBatch();

// 사용자
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package vook.server.api.domain.term.exception;
package vook.server.api.domain.vocabulary.exception;

import vook.server.api.domain.common.exception.DomainException;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package vook.server.api.domain.vocabulary.exception;

import vook.server.api.domain.common.exception.DomainException;

public class TermNotFoundException extends DomainException {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package vook.server.api.domain.vocabulary.exception;

import vook.server.api.domain.common.exception.DomainException;

public class VocabularyTermNotFoundException extends DomainException {
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package vook.server.api.domain.term.model;
package vook.server.api.domain.vocabulary.model;

import jakarta.persistence.*;
import lombok.Getter;
Expand Down Expand Up @@ -31,27 +31,49 @@ public class Term extends BaseEntity {
@Column(length = 2000, nullable = false)
private String meaning;

@Embedded
@AttributeOverride(name = "id", column = @Column(name = "vocabulary_id", nullable = false))
private VocabularyId vocabularyId;

@OneToMany(mappedBy = "term", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private List<TermSynonym> synonyms = new ArrayList<>();

@ManyToOne
@JoinColumn(name = "vocabulary_id", nullable = false)
private Vocabulary vocabulary;

public static Term forCreateOf(
String term,
String meaning,
VocabularyId vocabularyId
List<String> synonyms,
Vocabulary vocabulary
) {
Term result = new Term();
result.uid = UUID.randomUUID().toString();
result.term = term;
result.meaning = meaning;
result.vocabularyId = vocabularyId;
result.addAllSynonym(synonyms);
result.vocabulary = vocabulary;
vocabulary.addTerm(result);
return result;
}

public void addAllSynonym(List<String> synonyms) {
public static Term forUpdateOf(
String term,
String meaning,
List<String> synonyms
) {
Term result = new Term();
result.term = term;
result.meaning = meaning;
result.addAllSynonym(synonyms);
return result;
}

private void addAllSynonym(List<String> synonyms) {
synonyms.forEach(s -> this.synonyms.add(TermSynonym.forCreateOf(s, this)));
}

public void update(Term term) {
this.term = term.getTerm();
this.meaning = term.getMeaning();
this.synonyms.clear();
this.synonyms.addAll(term.getSynonyms());
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package vook.server.api.domain.term.model;
package vook.server.api.domain.vocabulary.model;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface TermRepository extends JpaRepository<Term, Long> {
Optional<Term> findByUid(String uid);

int countByVocabularyId(VocabularyId vocabularyId);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package vook.server.api.domain.term.model;
package vook.server.api.domain.vocabulary.model;

import jakarta.persistence.*;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package vook.server.api.domain.vocabulary.model;

import org.springframework.data.jpa.repository.JpaRepository;

public interface TermSynonymRepository extends JpaRepository<TermSynonym, Long> {
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package vook.server.api.domain.vocabulary.model;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;
import org.hibernate.annotations.Formula;
import vook.server.api.domain.common.model.BaseEntity;

import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

@Getter
Expand All @@ -27,6 +31,13 @@ public class Vocabulary extends BaseEntity {
@AttributeOverride(name = "id", column = @Column(name = "user_id", nullable = false))
private UserId userId;

@OneToMany(mappedBy = "vocabulary", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Set<Term> terms = new HashSet<>();

@Getter(AccessLevel.NONE)
@Formula("(SELECT COUNT(t.id) FROM term t WHERE t.vocabulary_id = id)")
private int termCount;

public static Vocabulary forCreateOf(
String name,
UserId userId
Expand All @@ -45,4 +56,18 @@ public boolean isValidOwner(UserId userId) {
public void update(String name) {
this.name = name;
}

public void addTerm(Term term) {
this.terms.add(term);
termCount++;
}

public int termCount() {
return this.termCount;
}

public void removeTerm(Term term) {
this.terms.remove(term);
termCount--;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package vook.server.api.domain.vocabulary.service;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import vook.server.api.domain.vocabulary.exception.TermLimitExceededException;
import vook.server.api.domain.vocabulary.exception.TermNotFoundException;
import vook.server.api.domain.vocabulary.model.Term;
import vook.server.api.domain.vocabulary.model.TermRepository;
import vook.server.api.domain.vocabulary.model.VocabularyRepository;
import vook.server.api.domain.vocabulary.service.data.TermCreateCommand;
import vook.server.api.domain.vocabulary.service.data.TermUpdateCommand;

@Service
@Validated
@Transactional
@RequiredArgsConstructor
public class TermService {

private final TermRepository termRepository;
private final VocabularyRepository vocabularyRepository;

public Term create(@Valid TermCreateCommand command) {
Term term = command.toEntity(vocabularyRepository::findByUid);
int termCount = term.getVocabulary().termCount();
if (termCount >= 100) {
throw new TermLimitExceededException();
}
return termRepository.save(term);
}

public Term getByUid(String uid) {
return termRepository.findByUid(uid).orElseThrow(TermNotFoundException::new);
}

public void update(TermUpdateCommand serviceCommand) {
Term term = termRepository.findByUid(serviceCommand.getUid()).orElseThrow(TermNotFoundException::new);
Term updateTerm = serviceCommand.toEntity();
term.update(updateTerm);
}

public void delete(String uid) {
Term term = termRepository.findByUid(uid).orElseThrow(TermNotFoundException::new);
term.getVocabulary().removeTerm(term);
termRepository.delete(term);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package vook.server.api.domain.vocabulary.service.data;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Builder;
import lombok.Getter;
import vook.server.api.domain.vocabulary.exception.VocabularyNotFoundException;
import vook.server.api.domain.vocabulary.model.Term;
import vook.server.api.domain.vocabulary.model.Vocabulary;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;

@Getter
public class TermCreateCommand {

@NotNull
private String vocabularyUid;

@NotBlank
@Size(min = 1, max = 100)
private String term;

@NotBlank
@Size(min = 1, max = 2000)
private String meaning;

@NotNull
private List<String> synonyms;

@Builder
private static TermCreateCommand of(String vocabularyUid, String term, String meaning, List<String> synonyms) {
TermCreateCommand command = new TermCreateCommand();
command.vocabularyUid = vocabularyUid;
command.term = term;
command.meaning = meaning;
command.synonyms = synonyms;
return command;
}

public Term toEntity(Function<String, Optional<Vocabulary>> vocabularySupplier) {
return Term.forCreateOf(
term,
meaning,
synonyms,
vocabularySupplier.apply(vocabularyUid).orElseThrow(VocabularyNotFoundException::new)
);
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
package vook.server.api.domain.term.service.data;
package vook.server.api.domain.vocabulary.service.data;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Builder;
import lombok.Getter;
import vook.server.api.domain.term.model.Term;
import vook.server.api.domain.term.model.VocabularyId;
import vook.server.api.domain.vocabulary.model.Term;

import java.util.List;

@Getter
public class TermCreateCommand {
public class TermUpdateCommand {

@NotNull
private VocabularyId vocabularyId;
private String uid;

@NotBlank
@Size(min = 1, max = 100)
Expand All @@ -28,16 +27,16 @@ public class TermCreateCommand {
private List<String> synonyms;

@Builder
private static TermCreateCommand of(VocabularyId vocabularyId, String term, String meaning, List<String> synonyms) {
TermCreateCommand command = new TermCreateCommand();
command.vocabularyId = vocabularyId;
private static TermUpdateCommand of(String uid, String term, String meaning, List<String> synonyms) {
TermUpdateCommand command = new TermUpdateCommand();
command.uid = uid;
command.term = term;
command.meaning = meaning;
command.synonyms = synonyms;
return command;
}

public Term toEntity() {
return Term.forCreateOf(term, meaning, vocabularyId);
return Term.forUpdateOf(term, meaning, synonyms);
}
}
Loading
Loading