MessageServiceImpl.java
package com.newbit.coffeeletter.service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
import org.modelmapper.ModelMapper;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.newbit.coffeeletter.domain.chat.ChatMessage;
import com.newbit.coffeeletter.domain.chat.CoffeeLetterRoom;
import com.newbit.coffeeletter.domain.chat.MessageType;
import com.newbit.coffeeletter.dto.ChatMessageDTO;
import com.newbit.coffeeletter.repository.ChatMessageRepository;
import com.newbit.coffeeletter.repository.CoffeeLetterRoomRepository;
import com.newbit.coffeeletter.util.RoomUtils;
import com.newbit.notification.command.application.dto.request.NotificationSendRequest;
import com.newbit.notification.command.application.service.NotificationCommandService;
import com.newbit.user.service.MentorService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class MessageServiceImpl implements MessageService {
private final ChatMessageRepository messageRepository;
private final CoffeeLetterRoomRepository roomRepository;
private final SimpMessagingTemplate messagingTemplate;
private final ModelMapper modelMapper;
private final NotificationCommandService notificationCommandService;
private final MentorService mentorService;
public MessageServiceImpl(
ChatMessageRepository messageRepository,
CoffeeLetterRoomRepository roomRepository,
SimpMessagingTemplate messagingTemplate,
ModelMapper modelMapper,
NotificationCommandService notificationCommandService, MentorService mentorService) {
this.messageRepository = messageRepository;
this.roomRepository = roomRepository;
this.messagingTemplate = messagingTemplate;
this.modelMapper = modelMapper;
this.notificationCommandService = notificationCommandService;
this.mentorService = mentorService;
}
@Override
@Transactional
public ChatMessageDTO sendMessage(ChatMessageDTO messageDto) {
ChatMessage message = modelMapper.map(messageDto, ChatMessage.class);
message.setTimestamp(LocalDateTime.now());
CoffeeLetterRoom room = RoomUtils.getRoomById(roomRepository, message.getRoomId());
if (message.getSenderId().equals(room.getMentorId())) {
message.setReadByMentor(true);
}
else if (message.getSenderId().equals(room.getMenteeId())) {
message.setReadByMentee(true);
}
ChatMessage savedMessage = messageRepository.save(message);
ChatMessageDTO savedMessageDto = modelMapper.map(savedMessage, ChatMessageDTO.class);
room.setLastMessageContent(message.getContent());
room.setLastMessageTime(message.getTimestamp());
room.setLastMessageType(message.getType());
room.setLastMessageSenderId(message.getSenderId());
if (!message.isReadByMentor()) {
room.setUnreadCountMentor(room.getUnreadCountMentor() + 1);
}
if (!message.isReadByMentee()) {
room.setUnreadCountMentee(room.getUnreadCountMentee() + 1);
}
roomRepository.save(room);
messagingTemplate.convertAndSend("/topic/chat/room/" + message.getRoomId(), savedMessageDto);
Long receiverId = message.getSenderId().equals(room.getMentorId())
? room.getMenteeId()
: mentorService.getUserIdByMentorId(room.getMentorId());
notificationCommandService.sendNotification(
new NotificationSendRequest(
receiverId,
8L,
room.getCoffeeChatId(),
message.getContent()
)
);
return savedMessageDto;
}
@Override
@Transactional
public ChatMessageDTO sendSystemMessage(String roomId, String content) {
CoffeeLetterRoom room = RoomUtils.getRoomById(roomRepository, roomId);
ChatMessage systemMessage = ChatMessage.builder()
.roomId(roomId)
.type(MessageType.SYSTEM)
.content(content)
.senderId(0L)
.senderName("System")
.timestamp(LocalDateTime.now())
.readByMentor(false)
.readByMentee(false)
.build();
ChatMessage savedMessage = messageRepository.save(systemMessage);
ChatMessageDTO savedMessageDto = modelMapper.map(savedMessage, ChatMessageDTO.class);
room.setLastMessageContent(systemMessage.getContent());
room.setLastMessageTime(systemMessage.getTimestamp());
room.setLastMessageType(systemMessage.getType());
room.setLastMessageSenderId(systemMessage.getSenderId());
if (!systemMessage.isReadByMentor()) {
room.setUnreadCountMentor(room.getUnreadCountMentor() + 1);
}
if (!systemMessage.isReadByMentee()) {
room.setUnreadCountMentee(room.getUnreadCountMentee() + 1);
}
roomRepository.save(room);
messagingTemplate.convertAndSend("/topic/chat/room/" + roomId, savedMessageDto);
return savedMessageDto;
}
@Override
public List<ChatMessageDTO> getMessagesByRoomId(String roomId) {
RoomUtils.getRoomById(roomRepository, roomId);
return messageRepository.findByRoomIdOrderByTimestampAsc(roomId).stream()
.map(message -> modelMapper.map(message, ChatMessageDTO.class))
.collect(Collectors.toList());
}
@Override
public Page<ChatMessageDTO> getMessagesByRoomId(String roomId, Pageable pageable) {
RoomUtils.getRoomById(roomRepository, roomId);
return messageRepository.findByRoomId(roomId, pageable)
.map(message -> modelMapper.map(message, ChatMessageDTO.class));
}
@Override
public List<ChatMessageDTO> getUnreadMessages(String roomId, Long userId) {
CoffeeLetterRoom room = RoomUtils.getRoomById(roomRepository, roomId);
RoomUtils.isParticipant(room, userId);
List<ChatMessage> unreadMessages;
if (userId.equals(room.getMentorId())) {
unreadMessages = messageRepository.findByRoomIdAndReadByMentorFalseOrderByTimestampAsc(roomId);
} else {
unreadMessages = messageRepository.findByRoomIdAndReadByMenteeFalseOrderByTimestampAsc(roomId);
}
return unreadMessages.stream()
.map(message -> modelMapper.map(message, ChatMessageDTO.class))
.collect(Collectors.toList());
}
@Override
@Transactional
public void markAsRead(String roomId, Long userId) {
CoffeeLetterRoom room = RoomUtils.getRoomById(roomRepository, roomId);
RoomUtils.isParticipant(room, userId);
int updatedCount = 0;
if (userId.equals(room.getMentorId())) {
updatedCount = messageRepository.updateReadByMentorByRoomId(roomId);
room.setUnreadCountMentor(0);
} else {
updatedCount = messageRepository.updateReadByMenteeByRoomId(roomId);
room.setUnreadCountMentee(0);
}
roomRepository.save(room);
}
@Override
public int getUnreadMessageCount(String roomId, Long userId) {
CoffeeLetterRoom room = RoomUtils.getRoomById(roomRepository, roomId);
RoomUtils.isParticipant(room, userId);
if (userId.equals(room.getMentorId())) {
return messageRepository.countByRoomIdAndReadByMentorFalse(roomId);
} else {
return messageRepository.countByRoomIdAndReadByMenteeFalse(roomId);
}
}
@Override
public ChatMessageDTO getLastMessage(String roomId) {
ChatMessage lastMessage = messageRepository.findTopByRoomIdOrderByTimestampDesc(roomId);
if (lastMessage == null) {
return null;
}
return modelMapper.map(lastMessage, ChatMessageDTO.class);
}
}