diff --git a/src/main/java/callhub/connect/data_access/EmailDataAccessObject.java b/src/main/java/callhub/connect/data_access/EmailDataAccessObject.java new file mode 100644 index 0000000..2290d53 --- /dev/null +++ b/src/main/java/callhub/connect/data_access/EmailDataAccessObject.java @@ -0,0 +1,75 @@ +package callhub.connect.data_access; + +import callhub.connect.entities.Message; +import callhub.connect.entities.Session; +import callhub.connect.entities.exceptions.NoMessagesException; +import callhub.connect.entities.exceptions.SessionNotFoundException; +import callhub.connect.use_case.email.EmailDataAccessInterface; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; + +@Service +public class EmailDataAccessObject implements EmailDataAccessInterface { + private final SessionRepository sessionRepository; + + public EmailDataAccessObject(SessionRepository sessionRepository) { + this.sessionRepository = sessionRepository; + } + + /** + * Retrieves the transcript of messages for a given session code. + * + * @param id The session code to identify the session. + * @return A ResponseEntity containing the transcript of messages as a String. + * @throws NullPointerException if there is no session with the id in the sessionRepository. + */ + @Override + public String getTranscript(String id) { + boolean sessionExists = sessionRepository.existsById(id); + if (!sessionExists) { + throw new SessionNotFoundException("Session not found."); + } + + Session session = sessionRepository.getSessionById(id); + ArrayList messagesList = session.getMessages(); + + if (!(messagesList.isEmpty())) { + StringBuilder transcript = new StringBuilder(); + for (Message message : messagesList) { + transcript.append(message.formattedMessage()).append("\n"); + } + return transcript.toString(); + } + else{ + throw new NoMessagesException("No messages found."); + } + } + + /** + * Retrieves the date messages were sent for a given session code, assuming all messages + * were sent on the same day as the first message. + * + * @param id The session code to identify the session. + * @return A ResponseEntity containing the date of messages as a String. + * @throws NullPointerException if there is no session with the id in the sessionRepository. + */ + @Override + public String getDate(String id) { + boolean sessionExists = sessionRepository.existsById(id); + if (!sessionExists) { + throw new SessionNotFoundException("Session not found."); + } + + Session session = sessionRepository.getSessionById(id); + ArrayList messagesList = session.getMessages(); + + if (!(messagesList.isEmpty())) { + Message firstMessage = messagesList.get(0); + return firstMessage.getDateString(); + } + else { + throw new NoMessagesException("No messages found."); + } + } +} diff --git a/src/main/java/callhub/connect/entities/Session.java b/src/main/java/callhub/connect/entities/Session.java index 1b70bed..bd5bc68 100644 --- a/src/main/java/callhub/connect/entities/Session.java +++ b/src/main/java/callhub/connect/entities/Session.java @@ -34,6 +34,13 @@ public Session(boolean active, String code){ this.documents = new ArrayList(); } + /** + * Sets the unique identifier (ID) of the session for testing purposes. + */ + public void setId(String id) { + this.id = id; + } + /** * Gets the unique identifier (ID) associated with the session. * diff --git a/src/main/java/callhub/connect/entities/exceptions/NoMessagesException.java b/src/main/java/callhub/connect/entities/exceptions/NoMessagesException.java new file mode 100644 index 0000000..f1aca23 --- /dev/null +++ b/src/main/java/callhub/connect/entities/exceptions/NoMessagesException.java @@ -0,0 +1,7 @@ +package callhub.connect.entities.exceptions; + +public class NoMessagesException extends RuntimeException { + public NoMessagesException(String message) { + super(message); + } +} diff --git a/src/main/java/callhub/connect/entities/exceptions/SessionNotFoundException.java b/src/main/java/callhub/connect/entities/exceptions/SessionNotFoundException.java new file mode 100644 index 0000000..2c40f00 --- /dev/null +++ b/src/main/java/callhub/connect/entities/exceptions/SessionNotFoundException.java @@ -0,0 +1,7 @@ +package callhub.connect.entities.exceptions; + +public class SessionNotFoundException extends RuntimeException { + public SessionNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/callhub/connect/interface_adapter/email/EmailController.java b/src/main/java/callhub/connect/interface_adapter/email/EmailController.java new file mode 100644 index 0000000..90f88e4 --- /dev/null +++ b/src/main/java/callhub/connect/interface_adapter/email/EmailController.java @@ -0,0 +1,30 @@ +package callhub.connect.interface_adapter.email; + +import callhub.connect.use_case.email.EmailInputBoundary; +import callhub.connect.use_case.email.EmailInputData; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/email") +public class EmailController { + + @Autowired + private EmailInputBoundary emailInteractor; + + @GetMapping("/transcript/{id}") + public ResponseEntity getTranscript(@PathVariable String id) { + EmailInputData inputData = new EmailInputData(id); + return emailInteractor.getTranscript(inputData); + } + + @GetMapping("/date/{id}") + public ResponseEntity getCode(@PathVariable String id) { + EmailInputData inputData = new EmailInputData(id); + return emailInteractor.getDate(inputData); + } +} diff --git a/src/main/java/callhub/connect/interface_adapter/email/EmailPresenter.java b/src/main/java/callhub/connect/interface_adapter/email/EmailPresenter.java new file mode 100644 index 0000000..18b4601 --- /dev/null +++ b/src/main/java/callhub/connect/interface_adapter/email/EmailPresenter.java @@ -0,0 +1,14 @@ +package callhub.connect.interface_adapter.email; + +import callhub.connect.use_case.email.EmailOutputBoundary; +import callhub.connect.use_case.email.EmailOutputData; +import org.springframework.stereotype.Service; + +@Service +public class EmailPresenter implements EmailOutputBoundary { + + @Override + public String getResponse(EmailOutputData outputData) { + return outputData.getResponseBody(); + } +} diff --git a/src/main/java/callhub/connect/use_case/EmailController.java b/src/main/java/callhub/connect/use_case/EmailController.java deleted file mode 100644 index d82671c..0000000 --- a/src/main/java/callhub/connect/use_case/EmailController.java +++ /dev/null @@ -1,81 +0,0 @@ -package callhub.connect.use_case; - -import callhub.connect.data_access.SessionRepository; -import callhub.connect.entities.Message; -import callhub.connect.entities.Session; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.ArrayList; - -@RestController -@RequestMapping("/email") -public class EmailController { - - public SessionRepository sessionRepository; - - public EmailController(SessionRepository sessionRepository) { - this.sessionRepository = sessionRepository; - } - - /** - * Retrieves the transcript of messages for a given session code. - * - * @param id The session code to identify the session. - * @return A ResponseEntity containing the transcript of messages as a String. - * If the session is not found, an error occurs. - */ - @GetMapping("/transcript/{id}") - public ResponseEntity getTranscript(@PathVariable String id) { - HttpHeaders headers = new HttpHeaders(); - boolean sessionExists = sessionRepository.existsById(id); - if (!sessionExists) { - return new ResponseEntity<>("This session is inactive or does not exist.", headers, HttpStatus.NOT_FOUND); - } - - try { - Session session = sessionRepository.getSessionById(id); - ArrayList messagesList = session.getMessages(); - - StringBuilder transcript = new StringBuilder(); - for (Message message : messagesList) { - transcript.append(message.formattedMessage()).append("\n"); - } - return new ResponseEntity<>(transcript.toString(), headers, HttpStatus.OK); - } catch (Exception e) { - return new ResponseEntity<>(e.getMessage(), headers, HttpStatus.BAD_REQUEST); - } - } - - /** - * Retrieves the date messages were sent for a given session code, assuming all messages - * were sent on the same day as the first message. - * - * @param id The session code to identify the session. - * @return A ResponseEntity containing the date of messages as a String. - * If the session is not found, an error occurs. - */ - @GetMapping("/date/{id}") - public ResponseEntity getDate(@PathVariable String id) { - HttpHeaders headers = new HttpHeaders(); - boolean sessionExists = sessionRepository.existsById(id); - if (!sessionExists) { - new ResponseEntity<>("This session is inactive or does not exist.", headers, HttpStatus.NOT_FOUND); - } - - try { - Session session = sessionRepository.getSessionById(id); - ArrayList messagesList = session.getMessages(); - - Message firstMessage = messagesList.get(0); - return new ResponseEntity<>(firstMessage.getDateString(), headers, HttpStatus.OK); - } catch (Exception e) { - return new ResponseEntity<>(e.getMessage(), headers, HttpStatus.BAD_REQUEST); - } - } -} \ No newline at end of file diff --git a/src/main/java/callhub/connect/use_case/email/EmailDataAccessInterface.java b/src/main/java/callhub/connect/use_case/email/EmailDataAccessInterface.java new file mode 100644 index 0000000..e19c82a --- /dev/null +++ b/src/main/java/callhub/connect/use_case/email/EmailDataAccessInterface.java @@ -0,0 +1,14 @@ +package callhub.connect.use_case.email; + +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import java.util.HashMap; + +@Service +public interface EmailDataAccessInterface { + + String getTranscript(String id); + + String getDate(String id); +} diff --git a/src/main/java/callhub/connect/use_case/email/EmailInputBoundary.java b/src/main/java/callhub/connect/use_case/email/EmailInputBoundary.java new file mode 100644 index 0000000..397b574 --- /dev/null +++ b/src/main/java/callhub/connect/use_case/email/EmailInputBoundary.java @@ -0,0 +1,11 @@ +package callhub.connect.use_case.email; + +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +@Service +public interface EmailInputBoundary { + ResponseEntity getTranscript(EmailInputData inputData); + + ResponseEntity getDate(EmailInputData inputData); +} diff --git a/src/main/java/callhub/connect/use_case/email/EmailInputData.java b/src/main/java/callhub/connect/use_case/email/EmailInputData.java new file mode 100644 index 0000000..27b6c3d --- /dev/null +++ b/src/main/java/callhub/connect/use_case/email/EmailInputData.java @@ -0,0 +1,11 @@ +package callhub.connect.use_case.email; + +public class EmailInputData { + private final String id; + public EmailInputData(String id) { + this.id = id; + } + public String getId() { + return this.id; + } +} diff --git a/src/main/java/callhub/connect/use_case/email/EmailInteractor.java b/src/main/java/callhub/connect/use_case/email/EmailInteractor.java new file mode 100644 index 0000000..d8c579d --- /dev/null +++ b/src/main/java/callhub/connect/use_case/email/EmailInteractor.java @@ -0,0 +1,53 @@ +package callhub.connect.use_case.email; + +import callhub.connect.entities.exceptions.NoMessagesException; +import callhub.connect.entities.exceptions.SessionNotFoundException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class EmailInteractor implements EmailInputBoundary { + + @Autowired + final EmailDataAccessInterface emailDataAccessObject; + + @Autowired + final EmailOutputBoundary emailPresenter; + + public EmailInteractor(EmailDataAccessInterface emailDataAccessObject, EmailOutputBoundary emailPresenter) { + this.emailDataAccessObject = emailDataAccessObject; + this.emailPresenter = emailPresenter; + } + + @Override + public ResponseEntity getTranscript(EmailInputData inputData) { + HttpHeaders headers = new HttpHeaders(); + try { + String transcript = emailDataAccessObject.getTranscript(inputData.getId()); + EmailOutputData outputData = new EmailOutputData(transcript); + return new ResponseEntity<>(emailPresenter.getResponse(outputData), headers, HttpStatus.OK); + } catch (SessionNotFoundException e) { + return new ResponseEntity<>("This session is inactive or does not exist.", headers, HttpStatus.NOT_FOUND); + } catch (NoMessagesException e) { + return new ResponseEntity<>("This session has no messages.", headers, HttpStatus.NOT_FOUND); + } + } + + + @Override + public ResponseEntity getDate(EmailInputData inputData) { + HttpHeaders headers = new HttpHeaders(); + try { + String date = emailDataAccessObject.getDate(inputData.getId()); + EmailOutputData outputData = new EmailOutputData(date); + return new ResponseEntity<>(emailPresenter.getResponse(outputData), headers, HttpStatus.OK); + } catch (SessionNotFoundException e) { + return new ResponseEntity<>("This session is inactive or does not exist.", headers, HttpStatus.NOT_FOUND); + } catch (NoMessagesException e) { + return new ResponseEntity<>("This session has no messages.", headers, HttpStatus.NOT_FOUND); + } + } +} diff --git a/src/main/java/callhub/connect/use_case/email/EmailOutputBoundary.java b/src/main/java/callhub/connect/use_case/email/EmailOutputBoundary.java new file mode 100644 index 0000000..7f54a97 --- /dev/null +++ b/src/main/java/callhub/connect/use_case/email/EmailOutputBoundary.java @@ -0,0 +1,8 @@ +package callhub.connect.use_case.email; + +import org.springframework.stereotype.Service; + +@Service +public interface EmailOutputBoundary { + String getResponse(EmailOutputData outputData); +} diff --git a/src/main/java/callhub/connect/use_case/email/EmailOutputData.java b/src/main/java/callhub/connect/use_case/email/EmailOutputData.java new file mode 100644 index 0000000..f0be694 --- /dev/null +++ b/src/main/java/callhub/connect/use_case/email/EmailOutputData.java @@ -0,0 +1,11 @@ +package callhub.connect.use_case.email; + +public class EmailOutputData { + private final String responseBody; + public EmailOutputData(String responseBody) { + this.responseBody = responseBody; + } + public String getResponseBody() { + return this.responseBody; + } +} diff --git a/src/test/java/callhub/connect/EmailTests.java b/src/test/java/callhub/connect/EmailTests.java new file mode 100644 index 0000000..95dfdab --- /dev/null +++ b/src/test/java/callhub/connect/EmailTests.java @@ -0,0 +1,130 @@ +package callhub.connect; + +import callhub.connect.data_access.SessionRepository; +import callhub.connect.entities.Message; +import callhub.connect.entities.Session; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; + +import java.time.LocalDateTime; +import java.time.Month; + +import static callhub.connect.entities.Sender.CUSTOMER; +import static callhub.connect.entities.Sender.EMPLOYEE; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +class EmailTests { + + @MockBean + public SessionRepository sessionRepository; + + @Autowired + MockMvc mockMvc; + + @Test + void getTranscriptSuccess() throws Exception { + Session mockSession = new Session(true, "ABCDEF"); + mockSession.setId("abc123adsbksdhlsad"); + LocalDateTime timeStamp = LocalDateTime.of(2023, Month.DECEMBER, 3, 17, 9, 48); + LocalDateTime timeStamp2 = LocalDateTime.of(2023, Month.DECEMBER, 3, 17, 11, 12); + Message message1 = new Message("Test Message", timeStamp, mockSession.getId(), CUSTOMER); + Message message2 = new Message("Reply Message", timeStamp2, mockSession.getId(), EMPLOYEE); + mockSession.addMessage(message1); + mockSession.addMessage(message2); + when(sessionRepository.existsById(anyString())).thenReturn(true); + when(sessionRepository.getSessionById(anyString())).thenReturn(mockSession); + String expected = "17:09:48 CUSTOMER: Test Message\n17:11:12 EMPLOYEE: Reply Message\n"; + + String Url = "/email/transcript/" + mockSession.getId(); + mockMvc.perform(get(Url)).andExpect(status().isOk()).andExpect(content().string(expected)); + } + + @Test + void getTranscriptEmpty() throws Exception { + Session mockSession = new Session(true, "ABCDEF"); + mockSession.setId("abc123adsbksdhlsad"); + + when(sessionRepository.existsById(anyString())).thenReturn(true); + when(sessionRepository.getSessionById(anyString())).thenReturn(mockSession); + + String Url = "/email/transcript/" + mockSession.getId(); + mockMvc.perform(get(Url)) .andExpect(status().isNotFound()) + .andExpect(content().string("This session has no messages.")); + } + + + @Test + void getTranscriptDNE() throws Exception { + Session mockSession = new Session(true, "ABCDEF"); + mockSession.setId("abc123adsbksdhlsad"); + LocalDateTime timeStamp = LocalDateTime.of(2023, Month.DECEMBER, 3, 17, 9, 48); + LocalDateTime timeStamp2 = LocalDateTime.of(2023, Month.DECEMBER, 3, 17, 11, 12); + Message message1 = new Message("Test Message", timeStamp, mockSession.getId(), CUSTOMER); + Message message2 = new Message("Reply Message", timeStamp2, mockSession.getId(), EMPLOYEE); + mockSession.addMessage(message1); + mockSession.addMessage(message2); + when(sessionRepository.existsById(anyString())).thenReturn(false); + + String Url = "/email/transcript/" + mockSession.getId(); + mockMvc.perform(get(Url)).andExpect(status().isNotFound()) + .andExpect(content().string("This session is inactive or does not exist.")); + } + + @Test + void getDateSuccess() throws Exception { + Session mockSession = new Session(true, "ABCDEF"); + mockSession.setId("abc123adsbksdhlsad"); + LocalDateTime timeStamp = LocalDateTime.of(2023, Month.DECEMBER, 3, 17, 9, 48); + LocalDateTime timeStamp2 = LocalDateTime.of(2023, Month.DECEMBER, 3, 17, 11, 12); + Message message1 = new Message("Test Message", timeStamp, mockSession.getId(), CUSTOMER); + Message message2 = new Message("Reply Message", timeStamp2, mockSession.getId(), EMPLOYEE); + mockSession.addMessage(message1); + mockSession.addMessage(message2); + when(sessionRepository.existsById(anyString())).thenReturn(true); + when(sessionRepository.getSessionById(anyString())).thenReturn(mockSession); + String expected = "December 03, 2023"; + + String Url = "/email/date/" + mockSession.getId(); + mockMvc.perform(get(Url)).andExpect(status().isOk()).andExpect(content().string(expected)); + } + + @Test + void getDateEmpty() throws Exception { + Session mockSession = new Session(true, "ABCDEF"); + mockSession.setId("abc123adsbksdhlsad"); + + when(sessionRepository.existsById(anyString())).thenReturn(true); + when(sessionRepository.getSessionById(anyString())).thenReturn(mockSession); + + String Url = "/email/date/" + mockSession.getId(); + mockMvc.perform(get(Url)) .andExpect(status().isNotFound()) + .andExpect(content().string("This session has no messages.")); + } + + @Test + void getDateDNE() throws Exception { + Session mockSession = new Session(true, "ABCDEF"); + mockSession.setId("abc123adsbksdhlsad"); + LocalDateTime timeStamp = LocalDateTime.of(2023, Month.DECEMBER, 3, 17, 9, 48); + LocalDateTime timeStamp2 = LocalDateTime.of(2023, Month.DECEMBER, 3, 17, 11, 12); + Message message1 = new Message("Test Message", timeStamp, mockSession.getId(), CUSTOMER); + Message message2 = new Message("Reply Message", timeStamp2, mockSession.getId(), EMPLOYEE); + mockSession.addMessage(message1); + mockSession.addMessage(message2); + when(sessionRepository.existsById(anyString())).thenReturn(false); + + String Url = "/email/date/" + mockSession.getId(); + mockMvc.perform(get(Url)).andExpect(status().isNotFound()) + .andExpect(content().string("This session is inactive or does not exist.")); + } +} \ No newline at end of file