Skip to content

Commit

Permalink
feat: 자체 점역 API 호출 (#57)
Browse files Browse the repository at this point in the history
* fix: 저장하는 path 변경

* feat: TranslationEvent 발행

* feat: Translations 객체 초기화 조건 설정

* fix: Latex zip 파일 압축 해제 (#60)

* chore: submodules 최신화

* feat: brf file 경로 저장

* fix: 테스트용 mock 객체 생성
  • Loading branch information
gitchannn authored Feb 27, 2024
1 parent a969385 commit 360ffd8
Show file tree
Hide file tree
Showing 13 changed files with 190 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package sunflower.server.application.event;

import lombok.Getter;
import org.springframework.context.ApplicationEvent;

@Getter
public class BrailleTranslateEvent extends ApplicationEvent {

private final Long id;

public BrailleTranslateEvent(final Object source, final Long id) {
super(source);
this.id = id;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,9 @@
public class OcrStatusEvent extends ApplicationEvent {

private final Long id;
private final String pdfId;

public OcrStatusEvent(final Object source, final Long id, final String pdfId) {
public OcrStatusEvent(final Object source, final Long id) {
super(source);
this.id = id;
this.pdfId = pdfId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package sunflower.server.application.eventlistener;

import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;
import sunflower.server.application.event.BrailleTranslateEvent;
import sunflower.server.client.BrailleTranslationClient;
import sunflower.server.entity.Translations;
import sunflower.server.repository.TranslationsRepository;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

import static org.springframework.transaction.annotation.Propagation.REQUIRES_NEW;

@Slf4j
@NoArgsConstructor
@Component
public class BrailleTranslateEventListener {

private TranslationsRepository translationsRepository;
private BrailleTranslationClient brailleTranslationClient;
private ApplicationEventPublisher eventPublisher;

@Autowired
public BrailleTranslateEventListener(
final TranslationsRepository translationsRepository,
final BrailleTranslationClient brailleTranslationClient,
final ApplicationEventPublisher eventPublisher
) {
this.translationsRepository = translationsRepository;
this.brailleTranslationClient = brailleTranslationClient;
this.eventPublisher = eventPublisher;
}

@Async
@TransactionalEventListener
@Transactional(propagation = REQUIRES_NEW)
public void downloadLatexFile(final BrailleTranslateEvent event) {
final Translations translations = translationsRepository.getById(event.getId());

final String latexPath = translations.getLatexPath();
final File latexFile = Paths.get(latexPath).toFile();

if (!latexFile.exists()) {
throw new RuntimeException("파일이 존재하지 않습니다!");
}

final String brfContent = brailleTranslationClient.translate(latexFile);
final String brfPath = saveBrfFile(brfContent, translations.getOcrPdfId());

translations.registerBrfPath(brfPath);
}

private String saveBrfFile(final String content, final String ocrPdfId) {
final String directory = "src/main/brf";

final String fileName = ocrPdfId + ".brf";
final Path brfPath = Paths.get(directory, fileName);

final File file = brfPath.toFile();
try {
final FileWriter writer = new FileWriter(file);
writer.write(content);
writer.close();
} catch (IOException e) {
throw new RuntimeException(e);
}

return brfPath.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;
import sunflower.server.application.event.BrailleTranslateEvent;
import sunflower.server.application.event.OcrDownloadEvent;
import sunflower.server.client.OcrDownloadClient;
import sunflower.server.entity.Translations;
Expand Down Expand Up @@ -45,8 +46,9 @@ public void downloadLatexFile(final OcrDownloadEvent event) {

final byte[] latex = ocrDownloadClient.download(pdfId);
final String latexPath = saveLatexFile(pdfId, latex);
log.info("Latex File 저장! 경로: {}", latexPath);
translations.registerLatexPath(latexPath);

// TODO: publish event
eventPublisher.publishEvent(new BrailleTranslateEvent(this, event.getId()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ public void registerOcr(final OcrRegisterEvent event) {
final String pdfId = ocrRegisterClient.requestPdfId(file);
translations.registerPdfId(pdfId);

eventPublisher.publishEvent(new OcrStatusEvent(this, id, pdfId));
eventPublisher.publishEvent(new OcrStatusEvent(this, id));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public void checkOcrStatus(final OcrStatusEvent event) {
final Long id = event.getId();
final Translations translations = translationsRepository.getById(id);

final String pdfId = event.getPdfId();
final String pdfId = translations.getOcrPdfId();
final OcrStatusDto status = ocrStatusClient.checkStatus(pdfId);
translations.changeOcrStatus(status);

Expand All @@ -63,6 +63,6 @@ public void checkOcrStatus(final OcrStatusEvent event) {
@Scheduled(fixedDelay = 1000)
private void retryCheckOcrStatus(final Long id, final String pdfId) {
log.info("Cheking OCR status for translations id: {}, pdf id: {}", id, pdfId);
eventPublisher.publishEvent(new OcrStatusEvent(this, id, pdfId));
eventPublisher.publishEvent(new OcrStatusEvent(this, id));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,64 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.File;

import static org.springframework.http.MediaType.MULTIPART_FORM_DATA;

@Slf4j
@Profile("!test")
@Component
public class ApiBrailleTranslationClient implements BrailleTranslationClient {

private final String appURI;
private final String key;
private final String keyName;
private final RestTemplate restTemplate;

public ApiBrailleTranslationClient(
@Value("${braille-translation.url}") String appURI,
@Value("${braille-translation.key-name}") String key,
@Value("${braille-translation.uri}") String appURI,
@Value("${braille-translation.key-name}") String keyName,
RestTemplate restTemplate
) {
this.appURI = appURI;
this.key = key;
this.keyName = keyName;
this.restTemplate = restTemplate;
}

@Override
public File translate(final Long id) {
MultiValueMap<String, Object> requestBody = new LinkedMultiValueMap<>();
public String translate(final File file) {
final HttpHeaders requestHeader = createRequestHeader();
MultiValueMap<String, Object> requestBody = createRequestBody(file);
final HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(requestBody, requestHeader);

log.info("Request URI: {}", appURI);
log.info("Request Headers: {}", requestHeader);
log.info("Request Parameters: {}", requestBody);

final ResponseEntity<String> response = restTemplate.postForEntity(appURI, requestEntity, String.class);

log.info("Response Body: {}", response.getBody());

return null;
return response.getBody();
}

private HttpHeaders createRequestHeader() {
HttpHeaders requestHeader = new HttpHeaders();
requestHeader.setContentType(MULTIPART_FORM_DATA);
return requestHeader;
}

private MultiValueMap<String, Object> createRequestBody(final File file) {
MultiValueMap<String, Object> requestBody = new LinkedMultiValueMap<>();
requestBody.add(keyName, new FileSystemResource(file));
return requestBody;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
Expand All @@ -15,7 +16,6 @@
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import sunflower.server.util.FileUtil;

import java.io.File;
import java.util.Arrays;
Expand Down Expand Up @@ -87,7 +87,7 @@ private HttpHeaders createRequestHeader() {
@Deprecated
private MultiValueMap<String, Object> createRequestBody(final MultipartFile file) {
MultiValueMap<String, Object> requestBody = new LinkedMultiValueMap<>();
requestBody.add("file", FileUtil.convertToFileSystemResource(file));
requestBody.add("file", file.getResource());

Map<String, Object> bodyMap = new HashMap<>();
bodyMap.put("conversion_formats", Map.of("docx", true, "tex.zip", true));
Expand Down Expand Up @@ -136,7 +136,7 @@ public String requestPdfId(final File file) {

private MultiValueMap<String, Object> createRequestBody(final File file) {
MultiValueMap<String, Object> requestBody = new LinkedMultiValueMap<>();
requestBody.add("file", FileUtil.convertToFileSystemResource(file));
requestBody.add("file", new FileSystemResource(file));

Map<String, Object> bodyMap = new HashMap<>();
bodyMap.put("conversion_formats", Map.of("docx", true, "tex.zip", true));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

public interface BrailleTranslationClient {

File translate(final Long id);
String translate(File file);
}
10 changes: 10 additions & 0 deletions server/src/main/java/sunflower/server/entity/Translations.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,17 @@ public class Translations {

public static Translations of(final String pdfPath, final String inputFileName) {
final Translations translations = new Translations();
translations.start();
translations.changePdfPath(pdfPath);
translations.changeInputFileName(inputFileName);
return translations;
}

private void start() {
this.ocrPercentDone = 0;
this.translationPercentDone = 0;
}

private void changePdfPath(final String pdfPath) {
this.pdfPath = pdfPath;
}
Expand All @@ -69,4 +75,8 @@ public void changeOcrStatus(final OcrStatusDto dto) {
public void registerLatexPath(final String latexPath) {
this.latexPath = latexPath;
}

public void registerBrfPath(final String brfPath) {
this.brfPath = brfPath;
}
}
30 changes: 22 additions & 8 deletions server/src/main/java/sunflower/server/util/FileUtil.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
package sunflower.server.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

@Slf4j
public final class FileUtil {

private static final String BASE_PATH = "src/main/latex/";

public static String savePdfFile(final MultipartFile file, String fileName) {
final Path path = Paths.get("src", "main", "pdf", fileName);

try {
Files.copy(file.getInputStream(), path);
Resource resource = new FileSystemResource(path.toFile());
return resource.getURI().getPath();
return resource.getFile().getPath();
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand All @@ -34,13 +40,21 @@ public static FileSystemResource convertToFileSystemResource(final File file) {
}

public static String saveLatexFile(final String pdfId, byte[] content) {
final File file = new File("src/main/latex/" + pdfId + ".zip");

try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(content);
String path = BASE_PATH + pdfId + ".tex";

try (ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(content))) {
ZipEntry entry;
while ((entry = zipInputStream.getNextEntry()) != null) {
if (!entry.isDirectory()) {
Files.copy(zipInputStream, Paths.get(path));
break;
}
}
} catch (IOException e) {
throw new RuntimeException("파일을 읽는데 실패함!");
log.error("Error extracting file from zip: {}", e.getMessage());
throw new RuntimeException(e);
}
return file.getPath();

return path;
}
}
2 changes: 1 addition & 1 deletion server/src/main/resources/security
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package sunflower.server.client;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

import java.io.File;

@Component
@Profile("test")
public class MockBrailleTranslationClient implements BrailleTranslationClient {

@Override
public String translate(final File file) {
return null;
}
}

0 comments on commit 360ffd8

Please sign in to comment.