/************************************************************ * * @packageName : io.company.localhost.controller.api * @fileName : BoardController.java * @author : 서지희 * @date : 25.01.07 * @description : 게시판 * * =========================================================== * DATE AUTHOR NOTE * ----------------------------------------------------------- * 24.01.02 서지희 최초 생성 * *************************************************************/ package io.company.localhost.controller.api; import java.math.BigInteger; import java.nio.charset.StandardCharsets; import java.sql.Blob; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageSerializable; import io.company.localhost.common.annotation.ReqMap; import io.company.localhost.common.dto.ApiResponse; import io.company.localhost.common.dto.MapDto; import io.company.localhost.service.localbordService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @RestController @RequestMapping("/api/board") @RequiredArgsConstructor @Slf4j public class BoardController { private final localbordService boardService; /** * 공지사항 목록 조회 * @ReqMap map 요청 파라미터 (searchKeyword) * @return 전체 공지사항 목록 */ @GetMapping("/notices") public ApiResponse> getNotices(@ReqMap MapDto map) { List posts = boardService.getNotices(map); // Blob 데이터를 처리 (문자열로 변환) for (MapDto post : posts) { Object content = post.get("content"); if (content instanceof Blob) { Blob blob = (Blob) content; post.put("content", safeBlobToString(blob)); } } return ApiResponse.ok(posts); } /** * 자유/익명 게시판 목록 조회 * @ReqMap map 요청 파라미터 (page, searchKeyword) * @return 페이징된 자유/익명 게시판 목록 */ @GetMapping("/general") public ApiResponse> getGeneralPosts(@ReqMap MapDto map) { PageInfo posts = boardService.getGeneralPosts(map); // Blob 데이터를 처리 (문자열로 변환) for (MapDto post : posts.getList()) { Object content = post.get("content"); if (content instanceof Blob) { Blob blob = (Blob) content; post.put("content", safeBlobToString(blob)); } } return ApiResponse.ok(posts); } /** * 안전하게 Blob 데이터를 문자열로 변환하는 메서드 * @ReqMap * @return 변환된 문자열 또는 null */ private String safeBlobToString(Blob blob) { if (blob == null) { return null; // Blob이 null이면 null 반환 } try { long blobLength = blob.length(); if (blobLength > Integer.MAX_VALUE) { throw new IllegalArgumentException("Blob is too large to process."); } return new String(blob.getBytes(1, (int) blobLength), StandardCharsets.UTF_8); } catch (Exception e) { System.err.println("Failed to convert Blob to String: " + e.getMessage()); e.printStackTrace(); return null; // 변환 실패 시 null 반환 } } /** * 게시물 작성 * @ReqMap map 요청 파라미터 (LOCBRDTTL, LOCBRDCON, MEMBERSEQ, LOCBRDTYP, * LOCBRDPWD(익명일떄에만), LOCBRDCAT(지식커뮤니티만)) * @return 작성된 게시물의 ID */ @PostMapping public ApiResponse createBoard(@ReqMap MapDto map) { BigInteger createdIdx = boardService.createBoard(map); // 작성된 게시물의 idx를 반환 Map responseData = new HashMap<>(); responseData.put("CMNBRDSEQ", createdIdx); responseData.put("message", "게시물이 작성되었습니다."); return ApiResponse.ok(responseData); } /** * 첨부파일 추가 * @ReqMap map 요청 파라미터 (CMNFLEREG, CMNFLESIZ, CMNFLEEXT, CMNFLEORG, CMNFLENAM, CMNFLEPAT, CMNBRDSEQ) * @return 첨부파일 저장 결과 메시지 */ @PostMapping("/{CMNBRDSEQ}/attachments") public ApiResponse uploadAttachment(@ReqMap MapDto map) { // 파일 데이터 저장 boardService.addAttachment(map); return ApiResponse.ok("첨부파일이 저장되었습니다."); } /** * 게시물 상세보기 * @param boardId 게시물 ID * @return 게시물 상세정보, 첨부파일 목록, 댓글 목록 */ @GetMapping("/{boardId}") public ApiResponse getBoardDetail(@PathVariable("boardId") Long boardId) { log.info("Fetching details for board ID: {}", boardId); // 게시물 상세정보 조회 MapDto boardDetail = boardService.getBoardDetail(boardId); if (boardDetail == null) { throw new IllegalArgumentException("Board not found for ID: " + boardId); } // Blob 데이터를 문자열로 변환 if (boardDetail.get("content") instanceof Blob) { try { Blob blob = (Blob) boardDetail.get("content"); String contentString = new String(blob.getBytes(1, (int) blob.length()), StandardCharsets.UTF_8); boardDetail.put("content", contentString); } catch (Exception e) { throw new RuntimeException("Failed to process Blob content", e); } } // 첨부파일 및 댓글 조회 List attachments = boardService.getAttachments(boardId); List comments = boardService.getComments(boardId.intValue()); // 결과 조합 MapDto result = new MapDto(); result.put("boardDetail", boardDetail); result.put("attachments", attachments); result.put("comments", comments); return ApiResponse.ok(result); } /** * 게시물 삭제 * @param boardId 게시물 ID * @return 삭제 결과 메시지 */ @DeleteMapping("/{boardId}") public ApiResponse deleteBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) { map.put("LOCBRDSEQ", boardId); log.info("Deleting board with ID: {}", boardId); boardService.deleteBoard(map); return ApiResponse.ok("게시물이 삭제되었습니다."); } /** * 게시물 수정 * @param boardId 게시물 ID * @ReqMap map 수정 데이터 (LOCBRDTTL, LOCBRDCON) * @return 수정 결과 메시지 */ @PutMapping("/{boardId}") public ApiResponse updateBoard(@PathVariable("boardId") Long boardId,@ReqMap MapDto map) { map.put("LOCBRDSEQ", boardId); boardService.updateBoard(map); return ApiResponse.ok("게시물이 수정되었습니다."); } /** * 게시물,댓글 좋아요/싫어요 추가 * @ReqMap map 데이터 (LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD, LOCBRDSEQ) * @return 반응 추가 결과 메시지 */ @PostMapping("/{LOCBRDSEQ}/{LOCCMTSEQ}/reaction") public ApiResponse reactToBoard(@ReqMap MapDto map) { boardService.reactToBoard(map); return ApiResponse.ok("반응이 추가되었습니다."); } /** * 댓글/대댓글 조회 * @param boardId 게시물 ID * @return 댓글과 대댓글의 계층 구조 데이터 */ @GetMapping("/{boardId}/comments") public ApiResponse> getComments(@PathVariable("boardId") int boardId) { // 모든 댓글과 대댓글 조회 List comments = boardService.getComments(boardId); return ApiResponse.ok(comments); } /** * 댓글/대댓글 작성 * @param boardId 게시물 ID * @ReqMap map 댓글 데이터 (LOCBRDSEQ, LOCCMTRPY, LOCCMTPNT, LOCCMTPWD, MEMBERSEQ 등) * @return 작성 결과 메시지 */ @PostMapping("/{LOCBRDSEQ}/comment") public ApiResponse addCommentOrReply(@ReqMap MapDto map) { // 부모 댓글 확인 boardService.addCommentOrReply(map); return ApiResponse.ok("댓글 또는 대댓글이 작성되었습니다."); } /** * 댓글/대댓글 수정 * @param commentId 댓글 ID * @ReqMap map 수정 데이터 (LOCCMTSEQ, LOCCMTRPY ) * @return 수정 결과 메시지 */ @PutMapping("/comment/{commentId}") public ApiResponse updateComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { // 기존 댓글 조회 MapDto existingComment = boardService.getCommentById(commentId); if (existingComment == null) { throw new IllegalArgumentException("Comment not found for ID: " + commentId); } map.put("LOCCMTSEQ", commentId); boardService.updateComment(map); return ApiResponse.ok("댓글이 수정되었습니다."); } /** * 댓글/대댓글 삭제 * @param commentId 댓글 ID * @return 삭제 결과 메시지 */ @DeleteMapping("/comment/{commentId}") public ApiResponse deleteComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { map.put("LOCCMTSEQ", commentId); boardService.deleteComment(map); return ApiResponse.ok("댓글이 삭제되었습니다."); } /** * 댓글 비밀번호 확인 * @param commentId 댓글 ID * @ReqMap map 비밀번호 데이터 * @return 비밀번호 확인 결과 */ @PostMapping("/comment/{commentId}/password") public ApiResponse checkCommentPassword(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { map.put("LOCCMTSEQ", commentId); return ApiResponse.ok(boardService.checkCommentPassword(map)); } /** * 게시물 비밀번호 확인 * @param boardId 게시물 ID * @ReqMap map 비밀번호 데이터 * @return 비밀번호 확인 결과 */ @PostMapping("/{boardId}/password") public ApiResponse checkBoardPassword(@PathVariable("boardId") int boardId, @ReqMap MapDto map) { map.put("LOCBRDSEQ", boardId); return ApiResponse.ok(boardService.checkBoardPassword(map)); } // /** // * 비밀게시판 여부 확인 // * @param boardId 게시물 ID // * @return 비밀게시판 여부 // */ // @GetMapping("/{boardId}/isSecret") // public ApiResponse isSecretBoard(@PathVariable("boardId") Long boardId) { // log.info("Checking if board ID {} is secret", boardId); // return ApiResponse.ok(boardService.isSecretBoard(boardId)); // } }