smartGeoinfoOriginal/src/main/java/sgis/board/controller/BoardRestController.java

290 lines
12 KiB
Java

package sgis.board.controller;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.time.OffsetDateTime; // OffsetDateTime import 추가
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute; // ModelAttribute import는 다른 메서드를 위해 유지
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import egovframework.com.cmm.util.EgovUserDetailsHelper;
import sgis.board.entity.Board;
import sgis.board.entity.Member;
import sgis.board.entity.Post; // Post entity import
import sgis.board.mapper.BoardMapper;
import sgis.board.mapper.MemberMapper;
import sgis.board.mapper.PostMapper;
import sgis.board.service.PostService;
import sgis.com.vo.SessionVO;
import sgis.com.web.BaseController;
@RestController // @ResponseBody(JSON)응답
public class BoardRestController extends BaseController {
@Autowired
BoardMapper boardMapper; // 기존 Board 관련 로직을 사용하지 않는다면 제거 고려
@Autowired
PostService postService;
@Autowired
MemberMapper memberMapper;
// ObjectMapper 인스턴스 생성
private final ObjectMapper objectMapper = new ObjectMapper();
public BoardRestController() {
// OffsetDateTime을 ISO 8601 형식으로 직렬화하기 위한 설정
objectMapper.findAndRegisterModules(); // Java 8 date/time modules 등록
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
/**
* @Method_Name : getSessionInfo
* @Date : 2022. 5. 10.
* @Creator : ICTWAY KIM Yoon-Su
* @Method_Discription : 세션정보 가져오기
* @return
* @throws Exception
*/
public SessionVO getSessionInfo() throws Exception {
return (SessionVO) EgovUserDetailsHelper.getAuthenticatedUser();
}
// Post 객체를 Board 객체로 변환하는 헬퍼 메서드
private Board postToBoard(Post post) {
Board board = new Board();
if( post == null ) {
return board;
}
board.setIdx(post.getPostId() != null ? post.getPostId().intValue() : 0);
board.setUserId(post.getUserNo() != null ? String.valueOf(post.getUserNo()) : null);
// 답변글 제목 형식 변경 로직
if (post.getParentPostId() != null && post.getParentPostId() != 0) {
// 부모 게시글 정보 조회 (부모 게시글의 제목을 가져오기 위함)
Post parentPost = postService.getPostById(post.getParentPostId());
if (parentPost != null) {
board.setTitle("" + parentPost.getTitle()); // "<상위글 제목>" 형식으로 설정
} else {
board.setTitle(post.getTitle()); // 부모 게시글을 찾을 수 없으면 원본 제목 사용
}
} else {
board.setTitle(post.getTitle()); // 답변글이 아니면 원본 제목 사용
}
board.setBoardContent(post.getContent());
board.setWriter(post.getUserNo() != null ? "User " + post.getUserNo() : "Unknown"); // 실제 사용자 이름을 가져오는 로직 필요
// Handle dates: OffsetDateTime to String (assuming 'yyyy-MM-dd HH:mm:ss' format for indate)
if (post.getCreatedAt() != null) { // Checks if createdAt is not null
board.setIndate(post.getCreatedAt().toLocalDateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); // Formats createdAt to String
} else {
board.setIndate(null); // Sets indate to null if createdAt is null
}
board.setCount(post.getViewCount() != null ? post.getViewCount() : 0); // Maps viewCount to count, handling potential null
// JSP의 Kendo Grid가 기대하는 project 관련 필드들 (Post 데이터에서 매핑 필요)
board.setProjectName(post.getTitle()); // 예시: Post의 title을 projectName으로 매핑
board.setProjectHarborName(""); // Post에 직접적인 매핑이 없다면 빈 문자열 또는 다른 로직으로 채움
board.setProjectOrderingName("");
board.setProjectAffiliatedName("");
board.setProjectInputId(post.getUserNo() != null ? String.valueOf(post.getUserNo()) : null); // 예시: Post의 userId를 projectInputId로 매핑
// projectStartDate, projectEndDate도 Post의 createdAt, updatedAt에서 매핑
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
if (post.getCreatedAt() != null) {
board.setProjectStartDate(post.getCreatedAt().format(formatter));
} else {
board.setProjectStartDate(null);
}
if (post.getUpdatedAt() != null) {
board.setProjectEndDate(post.getUpdatedAt().format(formatter));
} else {
board.setProjectEndDate(null);
}
board.setUserNm(post.getUserNo() != null ? "User" + post.getUserNo() : "Unknown"); // userNm 매핑 (예시)
board.setParentPostId(post.getParentPostId()); // parentPostId 매핑 추가
return board;
}
// @ResponseBody->jackson-databind(객체를->JSON 데이터포멧으로 변환)
@RequestMapping(value = "/sgis/portal/board/all.do", produces = "application/json;charset=UTF-8")
public String boardList(@RequestParam HashMap<String,Object> params, ModelMap model, Member m, HttpSession session) throws JsonProcessingException {
String boardCategoryIdParam = (String) params.get("boardCategoryId"); // Get the parameter as String
List<Post> posts;
// 게시글 조회
if ("all".equalsIgnoreCase(boardCategoryIdParam) || boardCategoryIdParam == null || boardCategoryIdParam.isEmpty()) {
posts = postService.getAllPosts(); // If "all" or null/empty, get all posts
} else {
try {
Integer boardCategoryId = Integer.valueOf(boardCategoryIdParam); // Try to convert to Integer
posts = postService.getPostsByBoardCategoryId(boardCategoryId); // Get posts by specific category
} catch (NumberFormatException e) {
System.err.println("Invalid boardCategoryId format: " + boardCategoryIdParam + ". Fetching all posts instead.");
posts = postService.getAllPosts(); // Fallback to all posts if conversion fails
}
}
// 게시글 정렬 로직 (부모-자식 관계에 따라 정렬)
List<Board> boardListForJsp = new ArrayList<>();
// 1. 부모 게시글과 답변 게시글을 분리
Map<Long, List<Post>> repliesMap = posts.stream()
.filter(post -> post.getParentPostId() != null)
.collect(Collectors.groupingBy(Post::getParentPostId, Collectors.toCollection(ArrayList::new)));
List<Post> topLevelPosts = posts.stream()
.filter(post -> post.getParentPostId() == null)
.sorted(Comparator.comparing(Post::getCreatedAt).reversed()) // 최신글이 위로 오도록 정렬
.collect(Collectors.toList());
// 2. 부모 게시글 아래에 답변 게시글을 삽입하여 최종 정렬된 리스트 생성
for (Post topPost : topLevelPosts) {
boardListForJsp.add(postToBoard(topPost)); // 부모 게시글 추가
// 해당 부모 게시글의 답변들을 가져와서 정렬 (예: 오래된 답변이 먼저 오도록)
List<Post> currentReplies = repliesMap.get(topPost.getPostId());
if (currentReplies != null && !currentReplies.isEmpty()) {
currentReplies.sort(Comparator.comparing(Post::getCreatedAt)); // 답변은 오래된 순서로
for (Post reply : currentReplies) {
boardListForJsp.add(postToBoard(reply)); // 답변 게시글 추가
}
}
}
HashMap<String, Object> responseMap = new HashMap<>();
responseMap.put("dataList1", boardListForJsp);
return objectMapper.writeValueAsString(responseMap); // Returns the list of Board objects as JSON data
}
@PostMapping("/sgis/portal/board/new.do")
@ResponseBody
public Post createNewPost(
@RequestParam("boardCategoryId") Integer boardCategoryId,
@RequestParam("title") String title,
@RequestParam("boardContent") String content,
// Using @RequestParam(value = "parentPostId", required = false) for optionality.
// If it comes as an empty string, it will be null.
@RequestParam(value = "parentPostId", required = false) Long parentPostId // This is good
) {
Post newPost = new Post();
newPost.setBoardCategoryId(boardCategoryId);
newPost.setTitle(title);
newPost.setContent(content);
// parentPostId를 Post 객체에 설정합니다. (null일 수도 있음)
newPost.setParentPostId(parentPostId);
// userId를 세션에서 직접 가져와 Post 객체에 설정합니다.
try {
SessionVO sessionVO = getSessionInfo();
String userId = sessionVO.getsUserId();
if (sessionVO != null && sessionVO.getsUserId() != null) {
Member m = memberMapper.registerCheck(userId);
if( m!=null ) {
newPost.setUserNo(m.getUserNo()); // userId는 String 타입으로 직접 설정
}
} else {
System.err.println("User ID not found in session for Post creation or session is null.");
throw new IllegalStateException("User ID is required for post creation.");
}
} catch (Exception e) {
System.err.println("Error getting session info for Post creation: " + e.getMessage());
throw new RuntimeException("Failed to get session user info.", e);
}
// 그 외 필드 (기본값 설정)
newPost.setViewCount(0); // 새 글이므로 0
newPost.setStatus("active"); // 기본 상태
newPost.setCreatedAt(OffsetDateTime.now()); // 현재 시간으로 설정
newPost.setUpdatedAt(OffsetDateTime.now()); // 현재 시간으로 설정
// PostService를 통해 게시글 생성
Post createdPost = postService.createPost(newPost);
// 생성된 Post 객체 반환 (클라이언트에게 성공 여부 및 생성된 게시글 정보 전달)
return createdPost;
}
@DeleteMapping("/sgis/portal/board/delete{idx}.do")
public void boardDelete(@PathVariable("idx") int idx) {
postService.deletePost(Long.valueOf(idx)); // PostService의 deletePost 호출
}
@PutMapping("/sgis/portal/board/update.do")
public void boardUpdate(@RequestBody Board vo) {
// 1. Get the postId from the incoming Board object
Long postId = Long.valueOf(vo.getIdx());
// 2. Fetch the existing Post from the database
Post existingPost = postService.getPostById(postId);
if (existingPost == null) {
// Handle case where the post to update is not found.
// You might want to throw a specific exception or return an error response.
System.err.println("Post with ID " + postId + " not found for update.");
// Example: throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Post not found");
return; // Or return an appropriate ResponseEntity
}
// 3. Update only the fields that are provided in the request body
// The JSP sends title and boardContent, which map to title and content in Post.
existingPost.setTitle(vo.getTitle());
existingPost.setContent(vo.getBoardContent());
existingPost.setUpdatedAt(OffsetDateTime.now()); // Update the modification timestamp
// Other fields like boardCategoryId, parentPostId, userNo, viewCount, status
// will retain their original values from 'existingPost' as they are not
// explicitly updated from the 'Board vo' in this method.
// 4. Call PostService to update the post with the modified existingPost object
postService.updatePost(existingPost);
}
@GetMapping("/sgis/portal/board/{idx}.do")
public Board boardContent(@RequestParam HashMap<String,Object> params, @PathVariable("idx") int idx) {
Post post = postService.getPostById(Long.valueOf(idx) ); // PostService를 통해 Post 조회
Board vo = postToBoard(post); // Post 객체를 Board 객체로 변환
return vo;
}
@PutMapping("/sgis/portal/board/count/{idx}.do")
public Board boardCount(@PathVariable("idx") int idx) {
Post post = postService.getPostById(Long.valueOf(idx)); // getPostById 호출 시 조회수 자동 증가
Board vo = postToBoard(post);
return vo;
}
}