localhost-back/src/main/java/io/company/localhost/service/localbordService.java
2025-02-24 16:10:05 +09:00

336 lines
12 KiB
Java

package io.company.localhost.service;
import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.company.localhost.common.dto.MapDto;
import io.company.localhost.mapper.localbordMapper;
import io.company.localhost.utils.AuthUtil;
import io.company.localhost.utils.PageUtil;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
public class localbordService {
private final localbordMapper boardMapper;
private static final long MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
public List<MapDto> selectNotices(MapDto map) {
List<MapDto> posts = boardMapper.selectNotices(map);
enrichPostsWithAdditionalData(posts);
return posts;
}
public PageInfo<MapDto> selectGeneralPosts(MapDto map) {
System.out.println(map);
int page = map.getString("page") != null ? Integer.parseInt(map.getString("page")) : 1;
int size = map.getString("size") != null ? Integer.parseInt(map.getString("size")) : 10;
String orderBy = map.getString("orderBy");
if (orderBy == null || (!orderBy.equals("date") && !orderBy.equals("views"))) {
map.put("orderBy", "date");
}
PageHelper.startPage(page, size);
List<MapDto> result = boardMapper.selectGeneralPosts(map);
enrichPostsWithAdditionalData(result);
return PageUtil.redefineNavigation(new PageInfo<>(result, size));
}
public void updateIncrementViewCount(Long boardId) {
boardMapper.updateIncrementViewCount(boardId);
}
public BigInteger insertBoard(MapDto map) {
// 익명게시판이면 회원 정보를 null로 설정
if ("300102".equals(String.valueOf(map.get("LOCBRDTYP")))) {
map.put("MEMBERSEQ", null);
}else {
Long userId = AuthUtil.getUser().getId();
map.put("MEMBERSEQ", userId);
}
boardMapper.insertBoard(map);
return (BigInteger) map.get("LOCBRDSEQ");
}
public void insertAttachment(MapDto map) {
String boardSeqStr = (String) map.get("CMNBRDSEQ");
Long boardSeq = Long.parseLong(boardSeqStr);
map.put("CMNBRDSEQ", boardSeq);
String newFilename = UUID.randomUUID().toString();
map.put("CMNFLENAM", newFilename);
boardMapper.insertAttachment(map);
}
public void validateAttachmentsSize(List<MapDto> attachments) {
long totalSize = attachments.stream()
.mapToLong(attachment -> (Long) attachment.get("size"))
.sum();
if (totalSize > MAX_FILE_SIZE) {
throw new IllegalArgumentException("첨부파일의 총 용량이 5MB를 초과합니다.");
}
}
public MapDto selectBoardDetail(Long boardId) {
updateIncrementViewCount(boardId);
MapDto boardDetail = boardMapper.selectBoardDetail(boardId);
enrichBoardDetail(boardDetail);
return boardDetail;
}
public List<MapDto> selectAttachments(Long boardId) {
return boardMapper.selectAttachments(boardId);
}
public void deleteBoard(MapDto map) {
boardMapper.deleteCommentsByBoardId(map);
boardMapper.deleteBoard(map);
}
public void updateBoard(MapDto map) {
boardMapper.updateBoard(map);
}
public void procReactToBoard(MapDto map) {
MapDto existingReaction = boardMapper.selectReaction(map);
if (existingReaction != null) {
boardMapper.updateReaction(map);
} else {
boardMapper.insertReaction(map);
}
}
public PageInfo<MapDto> selectComments(MapDto map) {
int page = map.getString("page") != null ? Integer.parseInt(map.getString("page")) : 1;
int size = map.getString("size") != null ? Integer.parseInt(map.getString("size")) : 10;
PageHelper.startPage(page, size);
List<MapDto> result = boardMapper.selectComments(map);
enrichCommentsWithAdditionalData(result); // 댓글 데이터 보강
return PageUtil.redefineNavigation(new PageInfo<>(result, size));
}
public List<MapDto> selectReply(MapDto map) {
return boardMapper.selectReply(map);
}
public void insertCommentOrReply(MapDto map) {
if ("300102".equals(String.valueOf(map.get("LOCBRDTYP")))) {
map.put("MEMBERSEQ", null);
}else {
Long userId = AuthUtil.getUser().getId();
map.put("MEMBERSEQ", userId);
}
boardMapper.insertCommentOrReply(map);
}
public void updateComment(MapDto map) {
boardMapper.updateComment(map);
}
public void deleteComment(MapDto map) {
boolean isReply = boardMapper.selectIsReply(map);
if (isReply) {
boardMapper.deleteReply(map);
} else {
boolean hasReplies = boardMapper.selectHasReplies(map);
if (hasReplies) {
boardMapper.updateSoftDeleteComment(map);
} else {
boardMapper.deleteComment(map);
}
}
}
public String selectCommentPassword(int commentId) {
return boardMapper.selectCommentPassword(commentId);
}
public String selectBoardPassword(int boardId) {
return boardMapper.selectBoardPassword(boardId);
}
public MapDto selectCommentById(int commentId) {
return boardMapper.selectCommentById(commentId);
}
public int selectCountComments(Long boardId) {
return boardMapper.selectCountComments(boardId);
}
public boolean selectIsAttachments(Long boardId) {
int count = boardMapper.selectIsAttachments(boardId);
return count > 0;
}
public MapDto selectCountBoardReactions(Long boardId) {
return boardMapper.selectCountBoardReactions(boardId);
}
public MapDto selectCountCommentReactions(Long boardId) {
return boardMapper.selectCountCommentReactions(boardId);
}
private String procBlobToString(Object blob) {
try {
if (blob instanceof String) {
return (String) blob; // 이미 문자열이면 그대로 반환
} else if (blob instanceof java.sql.Blob) {
java.sql.Blob sqlBlob = (java.sql.Blob) blob;
long blobLength = sqlBlob.length();
byte[] blobBytes = sqlBlob.getBytes(1, (int) blobLength);
return new String(blobBytes, StandardCharsets.UTF_8); // SQL BLOB → 바이트 배열 → 문자열 변환
} else {
throw new UnsupportedOperationException("Unsupported blob type: " + blob.getClass()); // 지원되지 않는 타입이면 예외 발생
}
} catch (Exception e) {
throw new RuntimeException("Failed to convert Blob to String: " + e.getMessage(), e); // 변환 실패 시 예외 처리
}
}
private String procFirstImageUrl(String jsonContent) {
try {
// JSON 유효성 검사
if (!procIsValidJson(jsonContent)) {
throw new IllegalArgumentException("Invalid JSON content: " + jsonContent);
}
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(jsonContent);
// JSON 배열 순회
for (JsonNode node : rootNode) {
JsonNode insertNode = node.get("insert");
if (insertNode != null && insertNode.has("image")) {
return insertNode.get("image").asText(); // 첫 번째 이미지 URL 반환
}
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Failed to extract first image URL: " + e.getMessage(), e);
}
return null; // 이미지가 없는 경우
}
private boolean procIsValidJson(String json) {
try {
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.readTree(json); // JSON 파싱 시도
return true; // JSON이 유효하면 true 반환
} catch (Exception e) {
return false; // 유효하지 않은 경우 false 반환
}
}
private String procPlainTextFromJson(String jsonContent) {
StringBuilder plainTextBuilder = new StringBuilder();
try {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(jsonContent);
// JSON 배열인지 확인
if (!rootNode.isArray()) {
System.err.println("JSON content is not an array");
return "";
}
// JSON 노드 순회
for (JsonNode node : rootNode) {
JsonNode insertNode = node.get("insert");
// insert 노드가 텍스트인지 확인
if (insertNode != null && insertNode.isTextual()) {
String text = insertNode.asText();
// '\n' 제거하고 순수 텍스트만 추가
if (!text.trim().isEmpty() && !text.trim().equals("\n")) {
plainTextBuilder.append(text.trim());
}
}
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Failed to extract plain text: " + e.getMessage(), e);
}
return plainTextBuilder.toString();
}
private void enrichBoardDetail(MapDto boardDetail) {
long boardId = ((Number) boardDetail.get("id")).longValue();
boardDetail.put("hasAttachment", selectIsAttachments(boardId));
boardDetail.put("commentCount", selectCountComments(boardId));
MapDto reactions = selectCountBoardReactions(boardId);
boardDetail.put("likeCount", reactions.getOrDefault("likeCount", 0));
boardDetail.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0));
// Blob 데이터를 문자열로 변환
Object content = boardDetail.get("content");
if (content != null) {
String contentString = procBlobToString(content); // Blob을 문자열로 변환
boardDetail.put("content", contentString); // JSON 변환 가능
}
}
private void enrichPostsWithAdditionalData(List<MapDto> posts) {
for (MapDto post : posts) {
Object idObject = post.get("id");
if (idObject instanceof Number) {
long postId = ((Number) idObject).longValue();
post.put("commentCount", selectCountComments(postId));
post.put("hasAttachment", selectAttachments(postId));
MapDto reactions = selectCountBoardReactions(postId);
post.put("likeCount", reactions.getOrDefault("likeCount", 0));
post.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0));
Object content = post.get("content");
String contentString = procBlobToString(content);
post.put("content", contentString);
String firstImageUrl = procFirstImageUrl(contentString);
post.put("firstImageUrl", firstImageUrl);
String plainContent = procPlainTextFromJson(contentString);
post.put("plainContent", plainContent);
}
}
}
private void enrichCommentsWithAdditionalData(List<MapDto> comments) {
for (MapDto comment : comments) {
Object idObject = comment.get("LOCCMTSEQ");
if (idObject instanceof Number) {
long commentId = ((Number) idObject).longValue();
MapDto reactions = boardMapper.selectCountCommentReactions(commentId);
comment.put("likeCount", reactions != null ? reactions.getOrDefault("likeCount", 0) : 0);
comment.put("dislikeCount", reactions != null ? reactions.getOrDefault("dislikeCount", 0) : 0);
Object content = comment.get("content");
comment.put("content", content);
}
}
}
}