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: 온보딩 후 기본 용어집을 추가하는 로직 #102

Merged
merged 5 commits into from
Jun 27, 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
65 changes: 59 additions & 6 deletions api/src/main/java/vook/server/api/devhelper/app/InitService.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
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.VocabularyRepository;
import vook.server.api.domain.vocabulary.model.*;
import vook.server.api.domain.vocabulary.service.TemplateVocabularyService;
import vook.server.api.domain.vocabulary.service.data.TemplateVocabularyCreateCommand;
import vook.server.api.infra.search.demo.MeilisearchDemoTermSearchService;

import java.util.Arrays;
import java.util.List;

@Service
Expand All @@ -22,29 +24,55 @@ public class InitService {

private final DemoTermRepository demoTermRepository;
private final DemoTermSynonymRepository demoTermSynonymRepository;
private final TemplateTermRepository templateTermRepository;
private final TemplateVocabularyRepository templateVocabularyRepository;
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 MeilisearchDemoTermSearchService searchService;

private final TemplateVocabularyService templateVocabularyService;

public void init() {
deleteAll();

List<DemoTerm> devTerms = testTermsLoader.getTerms("classpath:init/개발.tsv");
demoTermRepository.saveAll(devTerms);
// 데모 용어집
List<DemoTerm> demoTerms = testTermsLoader.getTerms(
"classpath:init/데모.tsv",
InitService::convertToDemoTerm
);
demoTermRepository.saveAll(demoTerms);

searchService.init();
searchService.addTerms(devTerms);
searchService.addTerms(demoTerms);

// 템플릿 용어집
createTemplateVocabulary(TemplateVocabularyName.DEVELOPMENT, "classpath:init/템플릿용어집-개발.tsv");
createTemplateVocabulary(TemplateVocabularyName.MARKETING, "classpath:init/템플릿용어집-마케팅.tsv");
createTemplateVocabulary(TemplateVocabularyName.DESIGN, "classpath:init/템플릿용어집-디자인.tsv");
createTemplateVocabulary(TemplateVocabularyName.GENERAL_OFFICE, "classpath:init/템플릿용어집-일반사무.tsv");
}

private void createTemplateVocabulary(TemplateVocabularyName name, String location) {
templateVocabularyService.create(new TemplateVocabularyCreateCommand(
name,
testTermsLoader.getTerms(location, InitService::convertToTemplateTerm)
));
}

private void deleteAll() {
// 데모 용어
demoTermSynonymRepository.deleteAllInBatch();
demoTermRepository.deleteAllInBatch();

// 템플릿 용어집
templateTermRepository.deleteAllInBatch();
templateVocabularyRepository.deleteAllInBatch();

// 용어집
termRepository.deleteAllInBatch();
vocabularyRepository.deleteAllInBatch();
Expand All @@ -57,4 +85,29 @@ private void deleteAll() {
// 검색 엔진
searchService.clearAll();
}

public static List<DemoTerm> convertToDemoTerm(List<TestTermsLoader.RawTerm> input) {
return input.stream()
.map(t -> {
DemoTerm term = DemoTerm.forCreateOf(t.getTerm(), t.getMeaning());
String[] synonymArray = t.getSynonyms().split("//n");
Arrays.stream(synonymArray)
.map(String::trim)
.forEach(term::addSynonym);
return term;
})
.toList();
}

public static List<TemplateVocabularyCreateCommand.Term> convertToTemplateTerm(List<TestTermsLoader.RawTerm> input) {
return input.stream()
.map(t -> new TemplateVocabularyCreateCommand.Term(
t.getTerm(),
t.getMeaning(),
Arrays.stream(t.getSynonyms().split(","))
.map(String::trim)
.toList()
))
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package vook.server.api.devhelper.app;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import vook.server.api.devhelper.helper.CsvReader;
import vook.server.api.domain.demo.model.DemoTerm;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;

@Component
Expand All @@ -17,37 +16,27 @@ public class TestTermsLoader {

private final ResourceLoader resourceLoader;

public List<DemoTerm> getTerms(String location) {
public <T> List<T> getTerms(String location, Converter<T> converter) {
try {
// file로 바로 접근 할 경우, IDE에서는 접근 가능하나, jar로 패키징 후 실행 시에는 접근 불가능
// ref) https://velog.io/@haron/트러블슈팅-Spring-IDE-에서-되는데-배포하면-안-돼요
InputStream tsvFileInputStream = resourceLoader.getResource(location).getInputStream();
CsvReader tsvReader = new CsvReader("\t");
List<RawTerm> rawTerms = tsvReader.readValue(tsvFileInputStream, RawTerm.class);
return toTerms(rawTerms);
return converter.convert(rawTerms);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

private static List<DemoTerm> toTerms(List<RawTerm> rawTerms) {
return rawTerms.stream()
.map(RawTerm::toTerm)
.toList();
}

@Getter
public static class RawTerm {
private String term;
private String synonyms;
private String meaning;
}

public DemoTerm toTerm() {
DemoTerm term = DemoTerm.forCreateOf(this.term, this.meaning);
String[] synonymArray = this.synonyms.split("//n");
Arrays.stream(synonymArray)
.map(String::trim)
.forEach(term::addSynonym);
return term;
}
public interface Converter<T> {
List<T> convert(List<RawTerm> rawTerm);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private List<String> getFieldNames(String line) {
}

private <T> T createInstance(Class<T> clazz, List<String> fieldNames, String line) {
String[] values = line.split(DELIMITER);
String[] values = parseLine(line);
T instance;
try {
instance = clazz.getDeclaredConstructor().newInstance();
Expand All @@ -72,4 +72,20 @@ private <T> T createInstance(Class<T> clazz, List<String> fieldNames, String lin
}
return instance;
}

private String[] parseLine(String line) {
return Arrays.stream(line.split(DELIMITER))
.map(String::trim)
.map(v -> processValue(v, v.startsWith("\"") && v.endsWith("\"")))
.toArray(String[]::new);
}

private String processValue(String value, boolean inQuotes) {
if (inQuotes) {
return value
.substring(1, value.length() - 1) //앞 뒤 " 제거
.replaceAll("\\\\n", "\n"); // \n -> 개행문자로 변환
}
return value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package vook.server.api.domain.vocabulary.model;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Getter;

import java.util.Arrays;
import java.util.List;

@Getter
@Entity
@Table(name = "template_term")
public class TemplateTerm {

public static final String SYNONYM_DELIMITER = ":,:";

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

/**
* 용어 이름
*/
@Column(length = 100, nullable = false)
private String term;

/**
* 용어 의미
*/
@Column(length = 2000, nullable = false)
private String meaning;

/**
* 동의어
*/
@Getter(AccessLevel.PRIVATE)
@Column(length = 1100)
private String synonym;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "template_vocabulary_id", nullable = false)
private TemplateVocabulary templateVocabulary;

public static TemplateTerm forCreateOf(
String term,
String meaning,
List<String> synonyms,
TemplateVocabulary templateVocabulary
) {
TemplateTerm result = new TemplateTerm();
result.term = term;
result.meaning = meaning;
result.addAllSynonym(synonyms);
result.templateVocabulary = templateVocabulary;
return result;
}

private void addAllSynonym(List<String> input) {
this.synonym = String.join(SYNONYM_DELIMITER, input);
}

public List<String> getSynonyms() {
if (synonym == null || synonym.isEmpty()) {
return List.of();
}
return Arrays.stream(synonym.split(SYNONYM_DELIMITER)).toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package vook.server.api.domain.vocabulary.model;

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

import java.util.List;

public interface TemplateTermRepository extends JpaRepository<TemplateTerm, Long> {
List<TemplateTerm> findByTemplateVocabulary(TemplateVocabulary templateVocabulary);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package vook.server.api.domain.vocabulary.model;

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

@Getter
@Entity
@Table(name = "template_vocabulary")
public class TemplateVocabulary {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

/**
* 용어집 이름
*/
@Column(length = 20, nullable = false, unique = true)
@Enumerated(EnumType.STRING)
private TemplateVocabularyName name;

public static TemplateVocabulary forCreateOf(
TemplateVocabularyName name
) {
TemplateVocabulary result = new TemplateVocabulary();
result.name = name;
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package vook.server.api.domain.vocabulary.model;

import vook.server.api.domain.user.model.Job;

public enum TemplateVocabularyName {
// 개발 용어집
DEVELOPMENT,

// 마케팅 용어집
MARKETING,

// 디자인 용어집
DESIGN,

// 일반 사무 용어집
GENERAL_OFFICE;

public static TemplateVocabularyName from(Job job) {
return switch (job) {
case PLANNER, DESIGNER -> DEVELOPMENT;
case MARKETER -> MARKETING;
case DEVELOPER -> DESIGN;
case CEO, HR, OTHER -> GENERAL_OFFICE;
case null -> GENERAL_OFFICE;
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package vook.server.api.domain.vocabulary.model;

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

import java.util.Optional;

public interface TemplateVocabularyRepository extends JpaRepository<TemplateVocabulary, Long> {
Optional<TemplateVocabulary> findByName(TemplateVocabularyName name);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
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.model.*;
import vook.server.api.domain.vocabulary.service.data.TemplateVocabularyCreateCommand;

import java.util.List;

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

private final TemplateVocabularyRepository vocabularyRepository;
private final TemplateTermRepository termRepository;

public void create(@Valid TemplateVocabularyCreateCommand command) {
TemplateVocabulary vocabulary = vocabularyRepository.save(command.toVocabulary());
termRepository.saveAll(command.toTerms(vocabulary));
}

public List<TemplateTerm> getTermsByName(@Valid TemplateVocabularyName name) {
TemplateVocabulary vocabulary = vocabularyRepository.findByName(name).orElseThrow();
return termRepository.findByTemplateVocabulary(vocabulary);
}
}
Loading
Loading