diff --git a/data/channels.ser b/data/channels.ser new file mode 100644 index 000000000..665a8492e Binary files /dev/null and b/data/channels.ser differ diff --git a/data/messages.ser b/data/messages.ser new file mode 100644 index 000000000..665a8492e Binary files /dev/null and b/data/messages.ser differ diff --git a/data/users.ser b/data/users.ser new file mode 100644 index 000000000..665a8492e Binary files /dev/null and b/data/users.ser differ diff --git a/src/main/java/com/sprint/mission/discodeit/JavaApplication.java b/src/main/java/com/sprint/mission/discodeit/JavaApplication.java index 545bfba2d..cd015b6ea 100644 --- a/src/main/java/com/sprint/mission/discodeit/JavaApplication.java +++ b/src/main/java/com/sprint/mission/discodeit/JavaApplication.java @@ -3,32 +3,73 @@ import com.sprint.mission.discodeit.entity.Channel; import com.sprint.mission.discodeit.entity.Message; import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.repository.file.FileChannelRepository; +import com.sprint.mission.discodeit.repository.file.FileMessageRepository; +import com.sprint.mission.discodeit.repository.file.FileUserRepository; +import com.sprint.mission.discodeit.repository.jcf.JCFChannelRepository; +import com.sprint.mission.discodeit.repository.jcf.JCFMessageRepository; +import com.sprint.mission.discodeit.repository.jcf.JCFUserRepository; import com.sprint.mission.discodeit.service.ChannelService; import com.sprint.mission.discodeit.service.MessageService; import com.sprint.mission.discodeit.service.UserService; +import com.sprint.mission.discodeit.service.basic.BasicChannelService; +import com.sprint.mission.discodeit.service.basic.BasicMessageService; +import com.sprint.mission.discodeit.service.basic.BasicUserService; +import com.sprint.mission.discodeit.service.file.FileChannelService; +import com.sprint.mission.discodeit.service.file.FileMessageService; +import com.sprint.mission.discodeit.service.file.FileUserService; +import com.sprint.mission.discodeit.service.jcf.JCFListChannelService; import com.sprint.mission.discodeit.service.jcf.JCFMapUserService; import com.sprint.mission.discodeit.factory.ServiceFactory; import com.sprint.mission.discodeit.factory.ServiceType; import java.util.*; +import static com.sprint.mission.discodeit.factory.ServiceType.JCF_LIST; + public class JavaApplication { public static void main(String[] args) { -// channelServiceTest(); -// messageServiceTest(); - userServiceTest(); + // ====================== JCF/File 기반 저장소로 서비스 초기화 ====================== +// ChannelService channelService = ServiceFactory.createChannelService( "JCF", new JCFChannelRepository()); + ChannelService channelService = ServiceFactory.createChannelService("File", new FileChannelRepository()); + channelService.clearChannels(); + +// MessageService messageService = ServiceFactory.createMessageService("JCF", new JCFMessageRepository(), new JCFChannelRepository(), new JCFUserRepository()); + MessageService messageService = ServiceFactory.createMessageService("File", new FileMessageRepository(), new FileChannelRepository(), new FileUserRepository()); + messageService.clearMessages(); + +// UserService userService = ServiceFactory.createUserService("JCF", new JCFUserRepository()); + UserService userService = ServiceFactory.createUserService("File", new FileUserRepository()); + userService.clearUsers(); + + // =============================== 서비스 테스팅 =============================== + channelServiceTest(channelService, messageService, userService); +// messageServiceTest(channelService, messageService, userService); +// userServiceTest(channelService, messageService, userService); // 따로 테스팅 필요 -> 채널은 userList, messageList 를 따로 관리 / 유저는 channelList, messageList 를 따로 관리 -// entityTest(); +// entityTest(channelService, messageService, userService); - // factory pattern 테스트 -// ServiceFactory serviceFactory = new ServiceFactory(ServiceType.JCF_LIST); -// ChannelService channelService = serviceFactory.createChannelService(); -// MessageService messageService = serviceFactory.createMessageService(); -// UserService userService = serviceFactory.createUserService(); + // ====================== (심화) BasicService 테스팅 ====================== + +// UserService userService = new BasicUserService(new JCFUserRepository()); +// UserService userService = new BasicUserService(new FileUserRepository()); + +// ChannelService channelService = new BasicChannelService(new JCFChannelRepository()); +// ChannelService channelService = new BasicChannelService(new FileChannelRepository()); + +// MessageService messageService = new BasicMessageService(new JCFMessageRepository(), new JCFChannelRepository(), new JCFUserRepository()); +// MessageService messageService = new BasicMessageService(new FileMessageRepository(), new FileChannelRepository(), new FileUserRepository()); + + +// // 셋업 +// User user = setupUser(userService); +// Channel channel = setupChannel(channelService); +// // 테스트 +// messageCreateTest(messageService, channel, user); } @@ -36,11 +77,7 @@ public static void main(String[] args) { * ChannelService 기능을 테스트하는 메서드입니다. * 채널 생성, 조회, 수정, 삭제, 유저 입장/퇴장 등을 검증합니다. */ - public static void channelServiceTest() { - -// ServiceFactory serviceFactory = new ServiceFactory(ServiceType.JCF_LIST); - ServiceFactory serviceFactory = new ServiceFactory(ServiceType.JCF_MAP); - ChannelService channelService = serviceFactory.createChannelService(); + public static void channelServiceTest(ChannelService channelService, MessageService messageService, UserService userService) { // 등록 System.out.println("\n[CREATE] Channels created:"); @@ -49,9 +86,12 @@ public static void channelServiceTest() { Channel foodChannel = channelService.createChannel("food-channel"); System.out.println("See all channels: " + channelService.getChannels()); + // 조회(단건, 다건) System.out.println("[READ] Read one channel (study channel): "); - System.out.println(channelService.getChannel(studyChannel.getId())); + UUID id = studyChannel.getId(); + System.out.println("Id to check: " + id); +// System.out.println(channelService.deleteById(id)); System.out.println("\n[READ] Read all channels:"); System.out.println("See all channels: " + channelService.getChannels()); @@ -60,7 +100,7 @@ public static void channelServiceTest() { // 수정된 데이터 조회 System.out.println("\n[Update] Update individual channel (study channel):"); System.out.println("Read study channel name: " - + channelService.getChannel(studyChannel.getId())); + + channelService.findVerifiedChannel(studyChannel.getId())); System.out.println("Read updated study channel name: " + channelService.updateChannel(studyChannel.getId(), "study-channel-edited")); @@ -74,27 +114,25 @@ public static void channelServiceTest() { channelService.clearChannels(); System.out.println("See all channels" + channelService.getChannels()); - - // 삭제를 한 후 read, update, delete 진행할때 - System.out.println("Read study channel name (deleted): " - + channelService.getChannel(studyChannel.getId())); - System.out.println("Update study channel name (deleted): " - + channelService.updateChannel(studyChannel.getId(), "study-channel-edited")); - System.out.println("Delete channel (deleted): " + channelService.deleteChannel(studyChannel.getId())); +// +// // 삭제를 한 후 read, update, delete 진행할때 -> throws Error +// System.out.println("Read study channel name (deleted): " +// + channelService.getChannel(studyChannel.getId())); +// System.out.println("Update study channel name (deleted): " +// + channelService.updateChannel(studyChannel.getId(), "study-channel-edited")); +// +// channelService.deleteChannel(studyChannel.getId()); +// System.out.println("Delete channel (deleted): " + channelService.getChannels()); } /** * MessageService 기능을 테스트하는 메서드입니다. * 메시지 생성, 조회, 수정, 삭제 기능을 검증합니다. */ - public static void messageServiceTest() { - -// ServiceFactory serviceFactory = new ServiceFactory(ServiceType.JCF_LIST); - ServiceFactory serviceFactory = new ServiceFactory(ServiceType.JCF_MAP); - MessageService messageService = serviceFactory.createMessageService(); - + public static void messageServiceTest(ChannelService channelService, MessageService messageService, UserService userService) { User newUser = new User("newUser", "test@gmail.com", "pw1"); + System.out.println("\n[CREATE] New user: " + newUser); Channel newChannel = new Channel("newChannel1"); Channel newChannel2 = new Channel("newChannel2"); @@ -106,7 +144,7 @@ public static void messageServiceTest() { // 조회(단건, 다건) System.out.println("\n[READ] Read one message (test1):"); - System.out.println(messageService.getMessage(test1.getId())); + System.out.println(messageService.findVerifiedMessage(test1.getId())); System.out.println("\n[READ] Read all messages:"); System.out.println("See all messages: " + messageService.getMessages()); @@ -114,7 +152,7 @@ public static void messageServiceTest() { // 수정된 데이터 조회 System.out.println("\n[Update] Update individual message (test2):"); System.out.println("Read test2 message: " - + messageService.getMessage(test2.getId())); + + messageService.findVerifiedMessage(test2.getId())); System.out.println("Read updated test2 message: " + messageService.updateMessage(test2.getId(), "testmessage2 updated!!")); @@ -131,12 +169,13 @@ public static void messageServiceTest() { System.out.println("See all messages: " + messageService.getMessages()); - // 삭제를 한 후 read, update, delete 진행할때 - System.out.println("Read test1 (deleted): " - + messageService.getMessage(test1.getId())); - System.out.println("Update test1 username (deleted): " - + messageService.updateMessage(test1.getId(), "study-channel-edited")); - System.out.println("Delete channel (deleted): " + messageService.deleteMessage(test1.getId())); + // 삭제를 한 후 read, update, delete 진행할때 -> throws error +// System.out.println("Read test1 (deleted): " +// + messageService.findById(test1.getId())); +// System.out.println("Update test1 username (deleted): " +// + messageService.updateMessage(test1.getId(), "study-channel-edited")); +// messageService.deleteById(test1.getId()); +// System.out.println("Delete channel (deleted): " + messageService.getMessages()); } @@ -144,11 +183,7 @@ public static void messageServiceTest() { * UserService 기능을 테스트하는 메서드입니다. * 유저 생성, 조회, 수정, 삭제 등의 기능을 검증합니다. */ - public static void userServiceTest() { -// ServiceFactory serviceFactory = new ServiceFactory(ServiceType.JCF_LIST); - ServiceFactory serviceFactory = new ServiceFactory(ServiceType.JCF_MAP); - UserService userService = serviceFactory.createUserService(); - + public static void userServiceTest(ChannelService channelService, MessageService messageService, UserService userService) { //등록 System.out.println("\n[CREATE] Users created:"); @@ -157,9 +192,14 @@ public static void userServiceTest() { System.out.println("See all users: " + userService.getUsers()); + System.out.println("See all users2: " + userService.getUsers()); + + // 조회(단건, 다건) + System.out.println("\n[DEBUG] About to search for ID: " + newUser1.getId()); System.out.println("\n[READ] Read one user (newUser1):"); - System.out.println(userService.getUser(newUser1.getId())); + System.out.println("\n[DEBUG] About to search for ID (again): " + newUser1.getId()); + System.out.println(userService.findVerifiedUser(newUser1.getId())); System.out.println("\n[READ] Read all users:"); System.out.println("See all users: " + userService.getUsers()); @@ -167,10 +207,10 @@ public static void userServiceTest() { // 수정된 데이터 조회 System.out.println("\n[Update] Update (newUser2):"); System.out.println("Read newUser2: " - + userService.getUser(newUser2.getId())); - User userInfo = new User(null, "CHANGED EMAIL!!", "CHANGED PASSWORD!!"); - System.out.println("Read updated newUser2 (new email and pw): " + - userService.updateUser(newUser2.getId(), userInfo)); + + userService.findVerifiedUser(newUser2.getId())); + User userInfo = new User(null, "testchanged@gmail.com", "CHANGED PASSWORD!!"); + userService.updateUser(newUser2.getId(), userInfo); + System.out.println("Read updated newUser2 (new email and pw): " + newUser2); // 삭제 // 조회를 통해 삭제되었는지 확인 @@ -187,13 +227,15 @@ public static void userServiceTest() { System.out.println("See all users: " + userService.getUsers()); - // 삭제를 한 후 read, update, delete 진행할때 - System.out.println("Read newUser1 (deleted): " - + userService.getUser(newUser1.getId())); - User userInfoTest = new User(null, "CHANGED EMAIL AGAIN!!", "CHANGED PASSWORD AGAIN!!"); - System.out.println("Update test1 username (deleted): " - + userService.updateUser(newUser1.getId(), userInfoTest)); - System.out.println("Delete channel (deleted): " + userService.deleteUser(newUser1.getId())); + // 삭제를 한 후 read, update, delete 진행할때 -> throws Error +// System.out.println("Read newUser1 (deleted): " +// + userService.getUser(newUser1.getId())); +// User userInfoTest = new User(null, "CHANGED EMAIL AGAIN!!", "CHANGED PASSWORD AGAIN!!"); +// System.out.println("Update test1 username (deleted): " +// + userService.updateUser(newUser1.getId(), userInfoTest)); +// userService.deleteUser(newUser1.getId()); +// System.out.println("Delete channel (deleted): "); +// userService.getUsers(); } @@ -201,10 +243,7 @@ public static void userServiceTest() { * Entity 클래스들(User, Channel, Message)의 기본 동작을 테스트하는 메서드입니다. * 각 엔티티의 관계 연결 등을 검증합니다. */ - public static void entityTest() { -// ServiceFactory serviceFactory = new ServiceFactory(ServiceType.JCF_LIST); - ServiceFactory serviceFactory = new ServiceFactory(ServiceType.JCF_MAP); - ChannelService channelService = serviceFactory.createChannelService(); + public static void entityTest(ChannelService channelService, MessageService messageService, UserService userService) { // memberIds 확인 System.out.println("\n========== Channel's user Test =========="); @@ -212,7 +251,6 @@ public static void entityTest() { System.out.println("Created channel: " + testChannel); // 멤버 생성 + 추가 - UserService userService = new JCFMapUserService(); System.out.println("\n[CREATE] Users created:"); User newUser1 = userService.createUser("newUser1", "test@gmail.com", "pw1"); User newUser2 = userService.createUser("newUser1", "test2@gmail.com", "pw2"); @@ -248,4 +286,26 @@ public static void entityTest() { System.out.println("MessageList of newUser1: " + newUser2.getMessagesList()); } + + + static User setupUser(UserService userService) { + User user = userService.createUser("woody", "woody@codeit.com", "woody1234"); + System.out.println("유저 생성: " + user); + return user; + } + + static Channel setupChannel(ChannelService channelService) { + Channel channel = channelService.createChannel( "공지"); + System.out.println("채널 생성: " + channel); + return channel; + } + + static void messageCreateTest(MessageService messageService, Channel channel, User author) { + Message message = messageService.createMessage( + new User("woody", "woody@codeit.com", "woody1234"), + "안녕하세요.", + new Channel("testChannel") + ); + System.out.println("메시지 생성: " + message); + } } diff --git a/src/main/java/com/sprint/mission/discodeit/entity/BaseEntity.java b/src/main/java/com/sprint/mission/discodeit/entity/BaseEntity.java index 9928a5e58..cb25f88aa 100644 --- a/src/main/java/com/sprint/mission/discodeit/entity/BaseEntity.java +++ b/src/main/java/com/sprint/mission/discodeit/entity/BaseEntity.java @@ -1,13 +1,18 @@ package com.sprint.mission.discodeit.entity; +import java.io.Serial; +import java.io.Serializable; import java.util.UUID; -public class BaseEntity { +public class BaseEntity implements Serializable { private UUID id; - private long createdAt; + private final long createdAt; private long updatedAt; + @Serial + private static final long serialVersionUID = 1L; // base entity's version + public BaseEntity() { this.id = UUID.randomUUID(); this.createdAt = System.currentTimeMillis(); @@ -22,11 +27,16 @@ public long getCreatedAt() { return createdAt; } - public void setUpdatedAt() { + public void updateTimeStamp() { this.updatedAt = System.currentTimeMillis(); } public long getUpdatedAt() { return updatedAt; } + + // used only when we want to update user + public void setId(UUID id) { + this.id = id; + } } diff --git a/src/main/java/com/sprint/mission/discodeit/entity/Channel.java b/src/main/java/com/sprint/mission/discodeit/entity/Channel.java index 8e322d43f..1e96da7a8 100644 --- a/src/main/java/com/sprint/mission/discodeit/entity/Channel.java +++ b/src/main/java/com/sprint/mission/discodeit/entity/Channel.java @@ -1,5 +1,7 @@ package com.sprint.mission.discodeit.entity; +import java.io.Serial; +import java.io.Serializable; import java.util.*; public class Channel extends BaseEntity { @@ -8,9 +10,11 @@ public class Channel extends BaseEntity { private String channelName; // extra fields - private List users; + private final List users; private List messages; + @Serial + private static final long serialVersionUID = 1L; // channel's version public Channel(String channelName) { super(); @@ -25,9 +29,14 @@ public Channel(String channelName) { // utility methods + private boolean containsUser(User user) { + return users.contains(user); + } + + public void addUser(User user) { - if (!users.contains(user)) { + if (!containsUser(user)) { users.add(user); // extra safe checking @@ -39,7 +48,8 @@ public void addUser(User user) { public void deleteUser(User user) { - if (users.contains(user)) { + if (containsUser(user)) { + users.remove(user); if (user.getChannels().contains(this)) { user.deleteChannel(this); diff --git a/src/main/java/com/sprint/mission/discodeit/entity/Message.java b/src/main/java/com/sprint/mission/discodeit/entity/Message.java index 99fa4ee84..125c3c1b5 100644 --- a/src/main/java/com/sprint/mission/discodeit/entity/Message.java +++ b/src/main/java/com/sprint/mission/discodeit/entity/Message.java @@ -1,14 +1,20 @@ package com.sprint.mission.discodeit.entity; +import java.io.Serial; +import java.io.Serializable; import java.util.UUID; public class Message extends BaseEntity { + // new fields private User user; private String message; private Channel channel; + @Serial + private static final long serialVersionUID = 1L; // message's version + public Message(User user, String message, Channel channel) { super(); diff --git a/src/main/java/com/sprint/mission/discodeit/entity/User.java b/src/main/java/com/sprint/mission/discodeit/entity/User.java index fb27f091f..2d350d2ac 100644 --- a/src/main/java/com/sprint/mission/discodeit/entity/User.java +++ b/src/main/java/com/sprint/mission/discodeit/entity/User.java @@ -1,8 +1,11 @@ package com.sprint.mission.discodeit.entity; +import java.io.Serial; +import java.io.Serializable; import java.util.*; +import java.util.regex.Pattern; -public class User extends BaseEntity { +public class User extends BaseEntity implements Serializable { // new fields private String email; @@ -11,8 +14,11 @@ public class User extends BaseEntity { // extra fields private UserStatus userStatus; - private List channels; - private List messages; + private final List channels; + private final List messages; + + @Serial + private static final long serialVersionUID = 1L; // user's version /** * member status (user statuc -> enum @@ -126,7 +132,24 @@ public String getEmail() { } public void setEmail(String email) { - this.email = email; + if (email == null || email.isBlank()) { + throw new IllegalArgumentException("Email is null or blank"); + } + + // validating the format + // https://stackoverflow.com/questions/66934141/how-can-i-check-email-address-in-java + String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\."+ + "[a-zA-Z0-9_+&*-]+)*@" + + "(?:[a-zA-Z0-9-]+\\.)+[a-z" + + "A-Z]{2,7}$"; + + Pattern pat = Pattern.compile(emailRegex); + if (pat.matcher(email).matches()) { + this.email = email; + } else { + // ✅ ADD THIS LINE + throw new IllegalArgumentException("Invalid email format: " + email); + } } public String getPassword() { @@ -141,6 +164,8 @@ public String getUserName() { return userName; } + + public void setUserName(String userName) { this.userName = userName; } @@ -154,6 +179,7 @@ public String toString() { " email = " + this.email + ",\n" + " password = " + this.password + "\n" + " updatedAt = " + this.getUpdatedAt() + "\n" + + " channels = " + this.getChannels() + ",\n" + "}"; } diff --git a/src/main/java/com/sprint/mission/discodeit/factory/ServiceFactory.java b/src/main/java/com/sprint/mission/discodeit/factory/ServiceFactory.java index b7db6bfd9..5250704fa 100644 --- a/src/main/java/com/sprint/mission/discodeit/factory/ServiceFactory.java +++ b/src/main/java/com/sprint/mission/discodeit/factory/ServiceFactory.java @@ -1,60 +1,67 @@ package com.sprint.mission.discodeit.factory; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import com.sprint.mission.discodeit.repository.MessageRepository; +import com.sprint.mission.discodeit.repository.UserRepository; +import com.sprint.mission.discodeit.repository.file.FileMessageRepository; import com.sprint.mission.discodeit.service.ChannelService; import com.sprint.mission.discodeit.service.MessageService; import com.sprint.mission.discodeit.service.UserService; +import com.sprint.mission.discodeit.service.file.FileChannelService; +import com.sprint.mission.discodeit.service.file.FileMessageService; +import com.sprint.mission.discodeit.service.file.FileUserService; import com.sprint.mission.discodeit.service.jcf.*; public class ServiceFactory { - // 사용할 서비스 타입 (JCF_LIST 또는 JCF_MAP) - private final ServiceType type; - /** - * 생성자: 서비스 타입을 지정합니다. - * - * @param type 사용할 구현 방식 (JCF_LIST 또는 JCF_MAP) + * 이 클래스는 인스턴스화될 필요가 없습니다. 모든 서비스 생성 메서드는 static으로 제공됩니다. */ - public ServiceFactory(ServiceType type) { - this.type = type; + public ServiceFactory() { } + // MAP은 잠시 보류 /** * 지정된 타입에 따라 UserService 인스턴스를 생성합니다. * + * @param type 사용할 구현 방식 (JCF_LIST 또는 JCF_MAP) * @return UserService 객체 */ - - public UserService createUserService() { + public static UserService createUserService(String type, UserRepository repository) { return switch (type) { - case JCF_LIST -> new JCFListUserService(); - case JCF_MAP -> new JCFMapUserService(); + case "JCF" -> new JCFListUserService(repository); + case "File" -> new FileUserService(repository); + default -> null; }; } + /** * 지정된 타입에 따라 ChannelService 인스턴스를 생성합니다. * + * @param type 사용할 구현 방식 (JCF_LIST 또는 JCF_MAP) * @return ChannelService 객체 */ - - public ChannelService createChannelService() { + public static ChannelService createChannelService(String type, ChannelRepository repository) { return switch (type) { - case JCF_LIST -> new JCFListChannelService(); - case JCF_MAP -> new JCFMapChannelService(); + case "JCF" -> new JCFListChannelService(repository); + case "File" -> new FileChannelService(repository); + default -> null; }; } /** * 지정된 타입에 따라 MessageService 인스턴스를 생성합니다. * + * @param type 사용할 구현 방식 (JCF_LIST 또는 JCF_MAP) * @return MessageService 객체 */ - public MessageService createMessageService() { + public static MessageService createMessageService(String type, MessageRepository messageRepository, ChannelRepository channelRepository, UserRepository userRepository ) { return switch (type) { - case JCF_LIST -> new JCFListMessageService(); - case JCF_MAP -> new JCFMapMessageService(); + case "JCF" -> new JCFListMessageService(messageRepository, channelRepository, userRepository); + case "File" -> new FileMessageService(messageRepository, channelRepository, userRepository); + default -> null; }; } -} +} \ No newline at end of file diff --git a/src/main/java/com/sprint/mission/discodeit/repository/ChannelRepository.java b/src/main/java/com/sprint/mission/discodeit/repository/ChannelRepository.java new file mode 100644 index 000000000..cdb5839a6 --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/repository/ChannelRepository.java @@ -0,0 +1,45 @@ +package com.sprint.mission.discodeit.repository; + +import com.sprint.mission.discodeit.entity.Channel; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface ChannelRepository { + + /** + * 채널 목록 전체를 저장합니다. + * + * @param channels 저장할 채널 목록 + */ + void saveAll(List channels); + + /** + * 채널 목록 전체를 반환합니다. + * + * @return 전체 채널 목록 + */ + List findAll(); + + /** + * 주어진 ID에 해당하는 채널을 조회합니다. + * + * @param id 조회할 채널의 ID + * @return 해당 채널이 존재하면 Optional에 담아 반환, 없으면 빈 Optional 반환 + */ + Optional findVerifiedChannel(UUID id); + + /** + * 채널을 저장합니다. + * + * @param channel 저장할 채널 + */ + void save(Channel channel); + + /** + * 채널을 삭제합니다. + * + * @param id 삭제할 채널의 ID + */ + void deleteChannel(UUID id); +} diff --git a/src/main/java/com/sprint/mission/discodeit/repository/MessageRepository.java b/src/main/java/com/sprint/mission/discodeit/repository/MessageRepository.java new file mode 100644 index 000000000..5beda6545 --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/repository/MessageRepository.java @@ -0,0 +1,47 @@ +package com.sprint.mission.discodeit.repository; + +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.entity.Message; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface MessageRepository { + + /** + * 메시지 목록 전체를 저장합니다. + * + * @param messages 저장할 메시지 목록 + */ + void saveAll(List messages); + + /** + * 모든 메시지를 반환합니다. + * + * @return 전체 메시지 목록 + */ + List findAll(); + + /** + * 주어진 ID에 해당하는 메시지를 조회합니다. + * + * @param id 조회할 메시지의 ID + * @return 해당 ID의 메시지가 존재하면 Optional에 담아 반환, 없으면 빈 Optional 반환 + */ + Optional findVerifiedMessage(UUID id); + + /** + * 메세지를 저장합니다. + * + * @param message 저장할 채널 + */ + void save(Message message); + + /** + * 메세지를 삭제합니다. + * + * @param id 삭제할 메세지의 ID + */ + void deleteMessage(UUID id); +} diff --git a/src/main/java/com/sprint/mission/discodeit/repository/UserRepository.java b/src/main/java/com/sprint/mission/discodeit/repository/UserRepository.java new file mode 100644 index 000000000..fc20424a8 --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/repository/UserRepository.java @@ -0,0 +1,48 @@ +package com.sprint.mission.discodeit.repository; + +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.entity.User; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface UserRepository { + + /** + * 사용자 목록 전체를 저장합니다. + * + * @param users 저장할 사용자 목록 + */ + void saveAll(List users); + + /** + * 모든 사용자를 반환합니다. + * + * @return 전체 사용자 목록 + */ + List findAll(); + + /** + * 주어진 ID에 해당하는 사용자를 조회합니다. + * + * @param id 조회할 사용자의 ID + * @return 해당 ID의 사용자가 존재하면 Optional에 담아 반환, 없으면 빈 Optional 반환 + */ + Optional findVerifiedUser(UUID id); + + /** + * 유저를 저장합니다. + * 등록되지 않은 유저면 새로 저장이 되고, 등록되어 있다면 정보를 갱신합니다. + * @param user 저장할 유저 객체 + */ + void save(User user); + + /** + * 유저를 삭제합니다. + * + * @param id 삭제할 유저의 ID + */ + void deleteUser(UUID id); +} diff --git a/src/main/java/com/sprint/mission/discodeit/repository/file/FileChannelRepository.java b/src/main/java/com/sprint/mission/discodeit/repository/file/FileChannelRepository.java new file mode 100644 index 000000000..42603fb44 --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/repository/file/FileChannelRepository.java @@ -0,0 +1,75 @@ +package com.sprint.mission.discodeit.repository.file; +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public class FileChannelRepository implements ChannelRepository { + + private static final String FILE_PATH = "data/channels.ser"; + + @Override + public void saveAll(List channels) { + try { + FileOutputStream fos = new FileOutputStream(FILE_PATH); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(channels); + } catch (IOException e) { + System.out.println("Error saving channels: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + @Override + public List findAll() { + List channels = null; + try { + FileInputStream fis = new FileInputStream(FILE_PATH); + ObjectInputStream ois = new ObjectInputStream(fis); + channels = (List) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + System.err.println("Error reading channels: " + e.getMessage()); + return new ArrayList<>(); // fallback + } + return channels; + } + + @Override + public Optional findVerifiedChannel(UUID id) { + return findAll().stream() + .filter(c -> c.getId().equals(id)) + .findFirst(); + } + + @Override + public void save(Channel channel) { + List channels = findAll(); + + // replace if same ID, add if none + boolean updated = false; + + for (int i = 0; i < channels.size(); i++) { + if (channels.get(i).getId().equals(channel.getId())) { + channels.set(i, channel); + updated = true; + break; + } + } + + if (!updated) { + channels.add(channel); + } + + saveAll(channels); + } + + @Override + public void deleteChannel(UUID id) { + List channels = findAll(); + channels.removeIf(c -> c.getId().equals(id)); + saveAll(channels); + } +} diff --git a/src/main/java/com/sprint/mission/discodeit/repository/file/FileMessageRepository.java b/src/main/java/com/sprint/mission/discodeit/repository/file/FileMessageRepository.java new file mode 100644 index 000000000..8b0595041 --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/repository/file/FileMessageRepository.java @@ -0,0 +1,78 @@ +package com.sprint.mission.discodeit.repository.file; +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.repository.MessageRepository; +import java.io.*; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public class FileMessageRepository implements MessageRepository { + + private static final String FILE_PATH = "data/messages.ser"; + + @Override + public void saveAll(List messages) { + try (FileOutputStream fos = new FileOutputStream(FILE_PATH); + ObjectOutputStream oos = new ObjectOutputStream(fos)) { + oos.writeObject(messages); + } catch (IOException e) { + System.out.println("Error saving channels: " + e.getMessage()); + } + } + + @Override + public List findAll() { + List messages = null; + + try { + FileInputStream fis = new FileInputStream(FILE_PATH); + ObjectInputStream ois = new ObjectInputStream(fis); + messages = (List) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + System.out.println("Error reading channels: " + e.getMessage()); + throw new RuntimeException(e); + } + + return messages; + } + + @Override + public Optional findVerifiedMessage(UUID id) { + return findAll().stream() + .filter(m -> m.getId().equals(id)) + .findFirst(); + + } + + @Override + public void save(Message message) { + List messages = findAll(); + + // replace if same ID, add if none + boolean updated = false; + + for (int i = 0; i < messages.size(); i++) { + if (messages.get(i).getId().equals(message.getId())) { + messages.set(i, message); + updated = true; + break; + } + } + + if (!updated) { + messages.add(message); + } + + saveAll(messages); + + } + + @Override + public void deleteMessage(UUID id) { + List messages = findAll(); + messages.removeIf(m -> m.getId().equals(id)); + saveAll(messages); + } + +} diff --git a/src/main/java/com/sprint/mission/discodeit/repository/file/FileUserRepository.java b/src/main/java/com/sprint/mission/discodeit/repository/file/FileUserRepository.java new file mode 100644 index 000000000..5bccfb7de --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/repository/file/FileUserRepository.java @@ -0,0 +1,76 @@ +package com.sprint.mission.discodeit.repository.file; +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.repository.UserRepository; +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public class FileUserRepository implements UserRepository { + private static final String FILE_PATH = "data/users.ser"; + + @Override + public void saveAll(List users) { + try { + FileOutputStream fos = new FileOutputStream(FILE_PATH); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(users); + } catch (IOException e) { + System.out.println("Error saving users: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + @Override + public List findAll() { + List users = null; + try { + FileInputStream fis = new FileInputStream(FILE_PATH); + ObjectInputStream ois = new ObjectInputStream(fis); + users = (List) ois.readObject(); + } catch (IOException | ClassNotFoundException e) { + System.err.println("Error reading users: " + e.getMessage()); + return new ArrayList<>(); // fallback + } + return users; + } + + @Override + public Optional findVerifiedUser(UUID id) { + List users = findAll(); + return users.stream() + .filter(u -> u.getId().equals(id)) + .findFirst(); + } + + @Override + public void save(User user) { + + List users = findAll(); + + // replace if same ID, add if none + boolean updated = false; + + for (int i = 0; i < users.size(); i++) { + if (users.get(i).getId().equals(user.getId())) { + users.set(i, user); + updated = true; + break; + } + } + + if (!updated) { + users.add(user); + } + + saveAll(users); + } + + @Override + public void deleteUser(UUID id) { + List users = findAll(); + users.removeIf(u -> u.getId().equals(id)); + saveAll(users); + }} diff --git a/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFChannelRepository.java b/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFChannelRepository.java new file mode 100644 index 000000000..2aaeda398 --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFChannelRepository.java @@ -0,0 +1,62 @@ +package com.sprint.mission.discodeit.repository.jcf; + +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.repository.ChannelRepository; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public class JCFChannelRepository implements ChannelRepository { + + public List data = new ArrayList<>(); + + public JCFChannelRepository() { + data = new ArrayList<>(); + } + + @Override + public void saveAll(List channels) { + data = channels; + } + + @Override + public List findAll() { + return data; + } + + @Override + public Optional findVerifiedChannel(UUID id) { + return findAll().stream() + .filter(c -> c.getId().equals(id)) + .findFirst(); + } + + @Override + public void save(Channel channel) { + + // replace if same ID, add if none + boolean updated = false; + + for (int i = 0; i < data.size(); i++) { + if (data.get(i).getId().equals(channel.getId())) { + data.set(i, channel); + updated = true; + break; + } + } + + if (!updated) { + data.add(channel); + } + + saveAll(data); + } + + @Override + public void deleteChannel(UUID id) { + data.removeIf(c -> c.getId().equals(id)); + } +} diff --git a/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFMessageRepository.java b/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFMessageRepository.java new file mode 100644 index 000000000..186142232 --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFMessageRepository.java @@ -0,0 +1,57 @@ +package com.sprint.mission.discodeit.repository.jcf; +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.repository.MessageRepository; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public class JCFMessageRepository implements MessageRepository { + private List data = new ArrayList<>(); + + @Override + public void saveAll(List messages) { + data = messages; + } + + @Override + public List findAll() { + return data; + } + + @Override + public Optional findVerifiedMessage(UUID id) { + return findAll().stream() + .filter(m -> m.getId().equals(id)) + .findFirst(); + } + + @Override + public void save(Message message) { + + // replace if same ID, add if none + boolean updated = false; + + for (int i = 0; i < data.size(); i++) { + if (data.get(i).getId().equals(message.getId())) { + data.set(i, message); + updated = true; + break; + } + } + + if (!updated) { + data.add(message); + } + + saveAll(data); + + } + + @Override + public void deleteMessage(UUID id) { + data.removeIf(m -> m.getId().equals(id)); + } +} diff --git a/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFUserRepository.java b/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFUserRepository.java new file mode 100644 index 000000000..2612d86eb --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/repository/jcf/JCFUserRepository.java @@ -0,0 +1,63 @@ +package com.sprint.mission.discodeit.repository.jcf; +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.entity.UserStatus; +import com.sprint.mission.discodeit.repository.UserRepository; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +public class JCFUserRepository implements UserRepository { + List data = new ArrayList<>(); + + @Override + public void saveAll(List users) { + data = users; + } + + @Override + public List findAll() { + return data.stream() + .filter(u -> u.getUserStatus() == (UserStatus.ACTIVE)) + .collect(Collectors.toList()); + } + + @Override + public Optional findVerifiedUser(UUID id) { + System.out.println(findAll()); + return findAll().stream() + .filter(u -> u.getId().equals(id)) + .findFirst(); + } + + @Override + public void save(User user) { + + List users = findAll(); + + // replace if same ID, add if none + boolean updated = false; + + for (int i = 0; i < users.size(); i++) { + if (users.get(i).getId().equals(user.getId())) { + users.set(i, user); + updated = true; + break; + } + } + + if (!updated) { + users.add(user); + } + + saveAll(users); + } + + @Override + public void deleteUser(UUID id) { + data.removeIf(u -> u.getId().equals(id)); + } +} diff --git a/src/main/java/com/sprint/mission/discodeit/service/ChannelService.java b/src/main/java/com/sprint/mission/discodeit/service/ChannelService.java index 2906f2662..fe3033d71 100644 --- a/src/main/java/com/sprint/mission/discodeit/service/ChannelService.java +++ b/src/main/java/com/sprint/mission/discodeit/service/ChannelService.java @@ -4,6 +4,7 @@ import com.sprint.mission.discodeit.entity.User; import java.util.ArrayList; +import java.util.List; import java.util.UUID; public interface ChannelService { @@ -23,14 +24,14 @@ public interface ChannelService { * @param id 채널의 UUID * @return 조회된 채널 (없으면 null) */ - Channel getChannel(UUID id); + Channel findVerifiedChannel(UUID id); /** * 모든 채널 목록을 반환합니다. * * @return 전체 채널 리스트 */ - ArrayList getChannels(); + List getChannels(); // 수정(Update) /** @@ -49,7 +50,7 @@ public interface ChannelService { * @param id 삭제할 채널의 UUID * @return 삭제 성공 여부 */ - boolean deleteChannel(UUID id); + void deleteChannel(UUID id); // ------- 따로 추가 ------- /** @@ -77,4 +78,6 @@ public interface ChannelService { void clearChannels(); + + } diff --git a/src/main/java/com/sprint/mission/discodeit/service/MessageService.java b/src/main/java/com/sprint/mission/discodeit/service/MessageService.java index 4286c6eca..9bab778c1 100644 --- a/src/main/java/com/sprint/mission/discodeit/service/MessageService.java +++ b/src/main/java/com/sprint/mission/discodeit/service/MessageService.java @@ -4,6 +4,7 @@ import com.sprint.mission.discodeit.entity.User; import java.util.ArrayList; +import java.util.List; import java.util.UUID; public interface MessageService { @@ -27,14 +28,14 @@ public interface MessageService { * @param id 메시지 UUID * @return 메시지 객체 (없으면 null 반환) */ - Message getMessage(UUID id); + Message findVerifiedMessage(UUID id); /** * 저장된 모든 메시지를 리스트로 반환합니다. * * @return 전체 메시지 리스트 */ - ArrayList getMessages(); + List getMessages(); // 수정(Update) /** @@ -51,9 +52,8 @@ public interface MessageService { * 메시지를 삭제합니다. * * @param id 삭제할 메시지의 UUID - * @return 삭제 성공 여부 */ - boolean deleteMessage(UUID id); + void deleteMessage(UUID id); // ------- 따로 추가 ------- diff --git a/src/main/java/com/sprint/mission/discodeit/service/UserService.java b/src/main/java/com/sprint/mission/discodeit/service/UserService.java index e8a40bf6e..ef26eece0 100644 --- a/src/main/java/com/sprint/mission/discodeit/service/UserService.java +++ b/src/main/java/com/sprint/mission/discodeit/service/UserService.java @@ -23,7 +23,7 @@ public interface UserService { * @param userId 유저의 UUID * @return 조회된 유저 객체 (없을 경우 null) */ - User getUser(UUID userId); + User findVerifiedUser(UUID userId); /** * 전체 유저 목록을 반환합니다. @@ -39,17 +39,16 @@ public interface UserService { // 수정(Update) /** - * 주어진 UUID를 가진 유저 정보를 수정합니다. + * 주어진 UUID를 가진 유저 정보를 수정거나, 존재하지 않을경우 추가합니다. * * 전달된 partialUser 객체는 수정하고자 하는 필드만 값을 가지며, * 그 외의 필드는 null일 수 있습니다. * 기존 유저 객체의 해당 필드만 업데이트됩니다. * 수정 가능한 필드는 userName, email, password, userStatus 입니다. - * @param userId 유저의 UUID - * @param partialUser 새로운 유저 - * @return 수정된 유저 객체 (없을 경우 null) + * @param id 수정할 경우, 새로운 정보를 갱신할 유저의 id + * @param user 새로운 유저 정보 */ - User updateUser(UUID userId, User partialUser); + void updateUser(UUID id, User user); // User updateUserStatus(UUID id, UserStatus userStatus); @@ -61,7 +60,7 @@ public interface UserService { * @param id 유저의 UUID * @return Status 변환 성공 여부 */ - boolean deleteUser(UUID id); + void deleteUser(UUID id); // ------- 따로 추가 ------- diff --git a/src/main/java/com/sprint/mission/discodeit/service/basic/BasicChannelService.java b/src/main/java/com/sprint/mission/discodeit/service/basic/BasicChannelService.java new file mode 100644 index 000000000..61f5a8ff8 --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/service/basic/BasicChannelService.java @@ -0,0 +1,98 @@ +package com.sprint.mission.discodeit.service.basic; +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.entity.UserStatus; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import com.sprint.mission.discodeit.service.ChannelService; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; + +public class BasicChannelService implements ChannelService { + private final ChannelRepository channelRepository; + + public BasicChannelService(ChannelRepository channelRepository) { + this.channelRepository = channelRepository; + } + + @Override + public Channel createChannel(String channelName) { + if (channelName == null || channelName.isBlank()) { + throw new IllegalArgumentException("Channel name cannot be empty!"); + } + + Channel channel = new Channel(channelName); + + channelRepository.save(channel); + return channel; + } + + @Override + public void joinChannel(Channel channel, User user) { + findVerifiedChannel(channel.getId()); + isValidActiveUser(user); + channel.addUser(user); + channelRepository.save(channel); + } + + @Override + public void leaveChannel(Channel channel, User user) { + findVerifiedChannel(channel.getId()); + isValidActiveUser(user); + channel.deleteUser(user); + channelRepository.save(channel); + } + + @Override + public Channel findVerifiedChannel(UUID id) { + return channelRepository.findVerifiedChannel(id) + .orElseThrow(() -> new RuntimeException("Channel not found with id: " + id)); + } + + @Override + public Channel updateChannel(UUID id, String channelName) { + Channel channel = findVerifiedChannel(id); + + channel.setChannelName(channelName); + channelRepository.save(channel); + return channel; + } + + + @Override + public void deleteChannel(UUID id) { + channelRepository.deleteChannel(id); + } + + + @Override + public List getChannels() { + return channelRepository.findAll(); + } + + + @Override + public void clearChannels() { + List channels = new ArrayList<>(); + channelRepository.saveAll(channels); + } + + // =========== utility methods =========== + /** + * 사용자가 유효한 활성 사용자인지 검증합니다. + * + * @param user 검증할 사용자 객체 + * @throws NoSuchElementException 다음 경우에 예외를 발생시킵니다: + * - user가 null인 경우 + * - user의 상태가 null인 경우 + * - user의 상태가 WITHDRAWN(탈퇴)인 경우 + */ + + private void isValidActiveUser(User user) { + if (user == null || user.getUserStatus() == null || user.getUserStatus() == UserStatus.WITHDRAWN) { + throw new NoSuchElementException("Not a valid user"); + } + } +} diff --git a/src/main/java/com/sprint/mission/discodeit/service/basic/BasicMessageService.java b/src/main/java/com/sprint/mission/discodeit/service/basic/BasicMessageService.java new file mode 100644 index 000000000..c459a422c --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/service/basic/BasicMessageService.java @@ -0,0 +1,75 @@ +package com.sprint.mission.discodeit.service.basic; + +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.entity.UserStatus; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import com.sprint.mission.discodeit.repository.MessageRepository; +import com.sprint.mission.discodeit.repository.UserRepository; +import com.sprint.mission.discodeit.service.MessageService; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class BasicMessageService implements MessageService { + private final MessageRepository messageRepository; + private final ChannelRepository channelRepository; + private final UserRepository userRepository; + + public BasicMessageService(MessageRepository messageRepository, ChannelRepository channelRepository, UserRepository userRepository) { + + this.messageRepository = messageRepository; + this.channelRepository = channelRepository; + this.userRepository = userRepository; + } + @Override + public Message createMessage(User user, String message, Channel channel) { + if (user.getUserStatus() == UserStatus.WITHDRAWN) { + return null; + } + Message msg = new Message(user, message, channel); + + user.addMessage(msg); + channel.addMessage(msg); + + channelRepository.save(channel); + userRepository.save(user); + + messageRepository.save(msg); + return msg; + } + + @Override + public Message findVerifiedMessage(UUID id) { + return messageRepository.findVerifiedMessage(id) + .orElseThrow(() -> new RuntimeException("Channel not found with id: " + id)); + } + + @Override + public Message updateMessage(UUID id, String message) { + findVerifiedMessage(id); + + Message msg = findVerifiedMessage(id); + msg.setMessage(message); + messageRepository.save(msg); + return msg; + } + + @Override + public void deleteMessage(UUID id) { + messageRepository.deleteMessage(id); + } + + @Override + public List getMessages() { + return messageRepository.findAll(); + } + + @Override + public void clearMessages() { + List messages = new ArrayList<>(); + messageRepository.saveAll(messages); + } +} diff --git a/src/main/java/com/sprint/mission/discodeit/service/basic/BasicUserService.java b/src/main/java/com/sprint/mission/discodeit/service/basic/BasicUserService.java new file mode 100644 index 000000000..7309b3c87 --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/service/basic/BasicUserService.java @@ -0,0 +1,90 @@ +package com.sprint.mission.discodeit.service.basic; + +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.entity.UserStatus; +import com.sprint.mission.discodeit.repository.UserRepository; +import com.sprint.mission.discodeit.service.UserService; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +public class BasicUserService implements UserService { + private final UserRepository userRepository; + + public BasicUserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + + @Override + public User createUser(String userName, String email, String pw) { + User newUser = new User(userName, email, pw); + userRepository.save(newUser); + return newUser; + } + + @Override + public User findVerifiedUser(UUID id) { + return userRepository.findVerifiedUser(id) + .orElseThrow(() -> new RuntimeException("User not found with id: " + id)); + } + + + @Override + public List getUsersByStatus(UserStatus userStatus) { + List users = getUsers(); + + return users.stream() + .filter(u -> u.getUserStatus() == userStatus) + .collect(Collectors.toList()); + } + + // update user 합침 + @Override + public void updateUser(UUID id, User partialUser) { + User user = findVerifiedUser(id); + + // replace if same ID, add if none + Optional.ofNullable(partialUser.getUserName()) + .ifPresent(name -> user.setUserName(partialUser.getUserName())); + + // setting email + Optional.ofNullable(partialUser.getEmail()) + .ifPresent(email -> user.setEmail(partialUser.getEmail())); + + // setting password + Optional.ofNullable(partialUser.getPassword()) + .ifPresent(pw -> user.setPassword(partialUser.getPassword())); + + // setting status + Optional.ofNullable(partialUser.getUserStatus()) + .ifPresent(status -> user.setUserStatus(partialUser.getUserStatus())); + + //partialUser updatedAt + user.updateTimeStamp(); + + userRepository.save(user); + } + + @Override + public void deleteUser(UUID id) { + userRepository.deleteUser(id); + } + + @Override + public List getUsers() { + return userRepository.findAll(); + } + + @Override + public void clearUsers() { + List users = new ArrayList<>(); + userRepository.saveAll(users); + + } + +} diff --git a/src/main/java/com/sprint/mission/discodeit/service/file/FileChannelService.java b/src/main/java/com/sprint/mission/discodeit/service/file/FileChannelService.java new file mode 100644 index 000000000..05dada501 --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/service/file/FileChannelService.java @@ -0,0 +1,98 @@ +package com.sprint.mission.discodeit.service.file; +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.entity.UserStatus; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import com.sprint.mission.discodeit.service.ChannelService; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; + +public class FileChannelService implements ChannelService { + + private final ChannelRepository channelRepository; + + public FileChannelService(ChannelRepository channelRepository) { + this.channelRepository = channelRepository; + } + + @Override + public Channel createChannel(String channelName) { + if (channelName == null || channelName.isBlank()) { + throw new IllegalArgumentException("Channel name cannot be empty!"); + } + + Channel channel = new Channel(channelName); + + channelRepository.save(channel); + return channel; + } + + @Override + public void joinChannel(Channel channel, User user) { + findVerifiedChannel(channel.getId()); + isValidActiveUser(user); + + channel.addUser(user); + channelRepository.save(channel); + } + + @Override + public void leaveChannel(Channel channel, User user) { + findVerifiedChannel(channel.getId()); + isValidActiveUser(user); + + channel.deleteUser(user); + channelRepository.save(channel); + } + + @Override + public Channel findVerifiedChannel(UUID id) { + return channelRepository.findVerifiedChannel(id) + .orElseThrow(() -> new RuntimeException("Channel not found with id: " + id)); + } + + @Override + public Channel updateChannel(UUID id, String channelName) { + Channel channel = findVerifiedChannel(id); + + channel.setChannelName(channelName); + channelRepository.save(channel); + return channel; + } + + @Override + public void deleteChannel(UUID id) { + channelRepository.deleteChannel(id); + } + + @Override + public List getChannels() { + return channelRepository.findAll(); + } + + @Override + public void clearChannels() { + List channels = new ArrayList<>(); + channelRepository.saveAll(channels); + } + + // =========== utility methods =========== + + /** + * 사용자가 유효한 활성 사용자인지 검증합니다. + * + * @param user 검증할 사용자 객체 + * @throws NoSuchElementException 다음 경우에 예외를 발생시킵니다: + * - user가 null인 경우 + * - user의 상태가 null인 경우 + * - user의 상태가 WITHDRAWN(탈퇴)인 경우 + */ + + private void isValidActiveUser(User user) { + if (user == null || user.getUserStatus() == null || user.getUserStatus() == UserStatus.WITHDRAWN) { + throw new NoSuchElementException("Not a valid user"); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/sprint/mission/discodeit/service/file/FileMessageService.java b/src/main/java/com/sprint/mission/discodeit/service/file/FileMessageService.java new file mode 100644 index 000000000..402da880d --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/service/file/FileMessageService.java @@ -0,0 +1,75 @@ +package com.sprint.mission.discodeit.service.file; +import com.sprint.mission.discodeit.entity.Channel; +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.entity.UserStatus; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import com.sprint.mission.discodeit.repository.MessageRepository; +import com.sprint.mission.discodeit.repository.UserRepository; +import com.sprint.mission.discodeit.service.MessageService; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class FileMessageService implements MessageService { + + private final MessageRepository messageRepository; + private final ChannelRepository channelRepository; + private final UserRepository userRepository; + + public FileMessageService(MessageRepository messageRepository, ChannelRepository channelRepository, UserRepository userRepository) { + + this.messageRepository = messageRepository; + this.channelRepository = channelRepository; + this.userRepository = userRepository; + } + + @Override + public Message createMessage(User user, String message, Channel channel) { + if (user.getUserStatus() == UserStatus.WITHDRAWN) { + return null; + } + Message msg = new Message(user, message, channel); + + user.addMessage(msg); + channel.addMessage(msg); + + channelRepository.save(channel); + userRepository.save(user); + + messageRepository.save(msg); + return msg; + } + + @Override + public Message findVerifiedMessage(UUID id) { + return messageRepository.findVerifiedMessage(id) + .orElseThrow(() -> new RuntimeException("Message not found with id: " + id)); + } + + @Override + public Message updateMessage(UUID id, String message) { + findVerifiedMessage(id); + + Message msg = findVerifiedMessage(id); + msg.setMessage(message); + messageRepository.save(msg); + return msg; + } + + @Override + public void deleteMessage(UUID id) { + messageRepository.deleteMessage(id); + } + + @Override + public List getMessages() { + return messageRepository.findAll(); + } + + @Override + public void clearMessages() { + List messages = new ArrayList<>(); + messageRepository.saveAll(messages); + } +} diff --git a/src/main/java/com/sprint/mission/discodeit/service/file/FileUserService.java b/src/main/java/com/sprint/mission/discodeit/service/file/FileUserService.java new file mode 100644 index 000000000..c59c77bbc --- /dev/null +++ b/src/main/java/com/sprint/mission/discodeit/service/file/FileUserService.java @@ -0,0 +1,88 @@ +package com.sprint.mission.discodeit.service.file; +import com.sprint.mission.discodeit.entity.Message; +import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.entity.UserStatus; +import com.sprint.mission.discodeit.repository.UserRepository; +import com.sprint.mission.discodeit.service.UserService; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; + +public class FileUserService implements UserService { + + private final UserRepository userRepository; + + public FileUserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + + @Override + public User createUser(String userName, String email, String password) { + User newUser = new User(userName, email, password); + userRepository.save(newUser); + return newUser; + } + + @Override + public User findVerifiedUser(UUID id) { + return userRepository.findVerifiedUser(id) + .orElseThrow(() -> new RuntimeException("User not found with id: " + id)); + } + + @Override + public List getUsersByStatus(UserStatus userStatus) { + List users = getUsers(); + + return users.stream() + .filter(u -> u.getUserStatus() == userStatus) + .collect(Collectors.toList()); + } + + @Override + public void updateUser(UUID id, User partialUser) { + User user = findVerifiedUser(id); + + // replace if same ID, add if none + Optional.ofNullable(partialUser.getUserName()) + .ifPresent(name -> user.setUserName(partialUser.getUserName())); + + // setting email + Optional.ofNullable(partialUser.getEmail()) + .ifPresent(email -> user.setEmail(partialUser.getEmail())); + + // setting password + Optional.ofNullable(partialUser.getPassword()) + .ifPresent(pw -> user.setPassword(partialUser.getPassword())); + + // setting status + Optional.ofNullable(partialUser.getUserStatus()) + .ifPresent(status -> user.setUserStatus(partialUser.getUserStatus())); + + //partialUser updatedAt + user.updateTimeStamp(); + + userRepository.save(user); + + } + + @Override + public void deleteUser(UUID id) { + userRepository.deleteUser(id); + } + + @Override + public List getUsers() { + return userRepository.findAll(); + } + + + @Override + public void clearUsers() { + List users = new ArrayList<>(); + userRepository.saveAll(users); + } + +} diff --git a/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFListChannelService.java b/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFListChannelService.java index 37265832e..ab1ef8c9a 100644 --- a/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFListChannelService.java +++ b/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFListChannelService.java @@ -3,6 +3,9 @@ import com.sprint.mission.discodeit.entity.UserStatus; import com.sprint.mission.discodeit.entity.Channel; import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import com.sprint.mission.discodeit.repository.file.FileChannelRepository; +import com.sprint.mission.discodeit.repository.jcf.JCFChannelRepository; import com.sprint.mission.discodeit.service.ChannelService; @@ -10,77 +13,89 @@ public class JCFListChannelService implements ChannelService { - public final ArrayList data; // contains channels + private final ChannelRepository channelRepository; - public JCFListChannelService() { - data = new ArrayList<>(); + public JCFListChannelService(ChannelRepository channelRepository) { + this.channelRepository = channelRepository; } - @Override public Channel createChannel(String channelName) { + if (channelName == null || channelName.isBlank()) { + throw new IllegalArgumentException("Channel name cannot be empty!"); + } + Channel channel = new Channel(channelName); - data.add(channel); + + channelRepository.save(channel); return channel; } @Override public void joinChannel(Channel channel, User user) { - if (user.getUserStatus() != (UserStatus.WITHDRAWN)) { - channel.addUser(user); - } + findVerifiedChannel(channel.getId()); + isValidActiveUser(user); + channel.addUser(user); + channelRepository.save(channel); } @Override public void leaveChannel(Channel channel, User user) { + findVerifiedChannel(channel.getId()); + isValidActiveUser(user); channel.deleteUser(user); - + channelRepository.save(channel); } @Override - public Channel getChannel(UUID id) { - for (Channel c : data) { - if (c.getId().equals(id)) { - return c; - } - } - return null; + public Channel findVerifiedChannel(UUID id) { + return channelRepository.findVerifiedChannel(id) + .orElseThrow(() -> new RuntimeException("Channel not found with id: " + id)); } @Override - public Channel updateChannel(UUID channelId, String channelName) { - // update in data (channel list) - for (Channel c : data) { - if (c.getId().equals(channelId)) { - c.setChannelName(channelName); - return c; - } - } - return null; + public Channel updateChannel(UUID id, String channelName) { + Channel channel = findVerifiedChannel(id); + + channel.setChannelName(channelName); + channelRepository.save(channel); + return channel; } @Override - public boolean deleteChannel(UUID id) { - Channel c = getChannel(id); - if (c == null) return false; - - data.remove(c); - return true; + public void deleteChannel(UUID id) { + channelRepository.deleteChannel(id); } @Override - public ArrayList getChannels() - { - return data; + public List getChannels() { + return channelRepository.findAll(); } @Override public void clearChannels() { - data.clear(); + List channels = new ArrayList<>(); + channelRepository.saveAll(channels); + } + + // =========== utility methods =========== + /** + * 사용자가 유효한 활성 사용자인지 검증합니다. + * + * @param user 검증할 사용자 객체 + * @throws NoSuchElementException 다음 경우에 예외를 발생시킵니다: + * - user가 null인 경우 + * - user의 상태가 null인 경우 + * - user의 상태가 WITHDRAWN(탈퇴)인 경우 + */ + private void isValidActiveUser(User user) { + if (user == null || user.getUserStatus() == null || user.getUserStatus() == UserStatus.WITHDRAWN) { + throw new NoSuchElementException("Not a valid user"); + } } } diff --git a/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFListMessageService.java b/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFListMessageService.java index 131bae6c2..ffb4cce32 100644 --- a/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFListMessageService.java +++ b/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFListMessageService.java @@ -4,19 +4,27 @@ import com.sprint.mission.discodeit.entity.Channel; import com.sprint.mission.discodeit.entity.Message; import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.repository.ChannelRepository; +import com.sprint.mission.discodeit.repository.MessageRepository; +import com.sprint.mission.discodeit.repository.UserRepository; import com.sprint.mission.discodeit.service.MessageService; import java.util.ArrayList; +import java.util.List; import java.util.UUID; public class JCFListMessageService implements MessageService { - public final ArrayList data; - public JCFListMessageService() { - data = new ArrayList<>(); - } + private final MessageRepository messageRepository; + private final ChannelRepository channelRepository; + private final UserRepository userRepository; + public JCFListMessageService(MessageRepository messageRepository, ChannelRepository channelRepository, UserRepository userRepository) { + this.messageRepository = messageRepository; + this.channelRepository = channelRepository; + this.userRepository = userRepository; + } @Override public Message createMessage(User user, String message, Channel channel) { if (user.getUserStatus() == UserStatus.WITHDRAWN) { @@ -27,59 +35,47 @@ public Message createMessage(User user, String message, Channel channel) { user.addMessage(msg); channel.addMessage(msg); - data.add(msg); + channelRepository.save(channel); + userRepository.save(user); + + messageRepository.save(msg); return msg; } @Override - public Message getMessage(UUID id) { - return data.stream() - .filter(m -> m.getId().equals(id)) - .findFirst() - .orElse(null); + public Message findVerifiedMessage(UUID id) { + return messageRepository.findVerifiedMessage(id) + .orElseThrow(() -> new RuntimeException("Channel not found with id: " + id)); } @Override - public Message updateMessage(UUID msgUUID, String message) { - if (getMessage(msgUUID).getUser().getUserStatus() == UserStatus.WITHDRAWN) { - return null; - } - - for (Message m : data) { - if (m.getId().equals(msgUUID)) { - m.setMessage(message); - return m; - } - } + public Message updateMessage(UUID id, String message) { + findVerifiedMessage(id); - return null; + Message msg = findVerifiedMessage(id); + msg.setMessage(message); + messageRepository.save(msg); + return msg; } @Override - public boolean deleteMessage(UUID id) { - Message m = getMessage(id); - - if (!data.contains(m) || m.getUser().getUserStatus() == UserStatus.WITHDRAWN ) { - return false; - } - - data.remove(m); - return true; + public void deleteMessage(UUID id) { + messageRepository.deleteMessage(id); } @Override - public ArrayList getMessages() - { - return data; + public List getMessages() { + return messageRepository.findAll(); } @Override - public void clearMessages() - { - data.clear(); + public void clearMessages() { + List messages = new ArrayList<>(); + messageRepository.saveAll(messages); + } } \ No newline at end of file diff --git a/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFListUserService.java b/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFListUserService.java index c4b08b175..145bd87c7 100644 --- a/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFListUserService.java +++ b/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFListUserService.java @@ -1,6 +1,7 @@ package com.sprint.mission.discodeit.service.jcf; import com.sprint.mission.discodeit.entity.UserStatus; import com.sprint.mission.discodeit.entity.User; +import com.sprint.mission.discodeit.repository.UserRepository; import com.sprint.mission.discodeit.service.UserService; import java.util.ArrayList; @@ -10,95 +11,75 @@ import java.util.stream.Collectors; public class JCFListUserService implements UserService { - public final ArrayList data; - public JCFListUserService() { - data = new ArrayList<>(); + private final UserRepository userRepository; + + public JCFListUserService(UserRepository userRepository) { + this.userRepository = userRepository; } @Override public User createUser(String userName, String email, String pw) { User newUser = new User(userName, email, pw); - data.add(newUser); + userRepository.save(newUser); return newUser; } @Override - public User getUser(UUID id) { - - return data.stream() - .filter(u -> - u.getUserStatus() == (UserStatus.ACTIVE) && u.getId().equals(id)) - .findFirst() - .orElse(null); - } - - @Override - public List getUsers() { - - return getUsersByStatus(UserStatus.ACTIVE); + public User findVerifiedUser(UUID id) { + return userRepository.findVerifiedUser(id) + .orElseThrow(() -> new RuntimeException("User not found with id: " + id)); } @Override public List getUsersByStatus(UserStatus userStatus) { - return data.stream() - .filter(u -> u.getUserStatus() == (userStatus)) + List users = getUsers(); + + return users.stream() + .filter(u -> u.getUserStatus() == userStatus) .collect(Collectors.toList()); } - // update user 합침 @Override - public User updateUser(UUID id, User userInfo) { - User updatedUser = data.stream() - .filter(u -> u.getId().equals(id)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다!")); - - if (updatedUser.getUserStatus() == (UserStatus.WITHDRAWN)) { - throw new IllegalArgumentException("탈퇴한 유저입니다!"); + public void updateUser(UUID id, User partialUser) { + User user = findVerifiedUser(id); - } - - // setting username - Optional.ofNullable(userInfo.getUserName()) - .ifPresent(name -> updatedUser.setUserName(name)); + // replace if same ID, add if none + Optional.ofNullable(partialUser.getUserName()) + .ifPresent(name -> user.setUserName(partialUser.getUserName())); // setting email - Optional.ofNullable(userInfo.getEmail()) - .ifPresent(email -> updatedUser.setEmail(email)); + Optional.ofNullable(partialUser.getEmail()) + .ifPresent(email -> user.setEmail(partialUser.getEmail())); // setting password - Optional.ofNullable(userInfo.getPassword()) - .ifPresent(pw -> updatedUser.setPassword(pw)); + Optional.ofNullable(partialUser.getPassword()) + .ifPresent(pw -> user.setPassword(partialUser.getPassword())); // setting status - Optional.ofNullable(userInfo.getUserStatus()) - .ifPresent(status -> updatedUser.setUserStatus(status)); - - //setting updatedAt - updatedUser.setUpdatedAt(); - - return updatedUser; - } + Optional.ofNullable(partialUser.getUserStatus()) + .ifPresent(status -> user.setUserStatus(partialUser.getUserStatus())); + //partialUser updatedAt + user.updateTimeStamp(); + userRepository.save(user); } @Override - public boolean deleteUser(UUID id) { - User user = getUser(id); - if (user == null) return false; - - user.setUserStatus(UserStatus.WITHDRAWN); - user.setUpdatedAt(); - user.deleteChannels(); - return true; + public void deleteUser(UUID id) { + userRepository.deleteUser(id); } + @Override + public List getUsers() { + return userRepository.findAll(); + } @Override - public void clearUsers() - { - data.clear(); + public void clearUsers() { + List users = new ArrayList<>(); + userRepository.saveAll(users); + } } diff --git a/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFMapChannelService.java b/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFMapChannelService.java index ea55c664c..4852ca961 100644 --- a/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFMapChannelService.java +++ b/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFMapChannelService.java @@ -37,7 +37,7 @@ public void leaveChannel(Channel channel, User user) { } @Override - public Channel getChannel(UUID id) { + public Channel findVerifiedChannel(UUID id) { if(!data.containsKey(id)) { return null; } @@ -63,14 +63,9 @@ public Channel updateChannel(UUID channelId, String channelName) { @Override - public boolean deleteChannel(UUID id) { - // update in list - if (!data.containsKey(id)) { - return false; - } - + public void deleteChannel(UUID id) { data.remove(id); - return true; + } @Override diff --git a/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFMapMessageService.java b/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFMapMessageService.java index 9517989ce..49a42c23b 100644 --- a/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFMapMessageService.java +++ b/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFMapMessageService.java @@ -33,7 +33,7 @@ public Message createMessage(User user, String message, Channel channel) { } @Override - public Message getMessage(UUID id) { + public Message findVerifiedMessage(UUID id) { List msgList = new ArrayList<>(data.values()); return msgList.stream() @@ -44,7 +44,7 @@ public Message getMessage(UUID id) { @Override public Message updateMessage(UUID msgUUID, String message) { - if (getMessage(msgUUID).getUser().getUserStatus() == (UserStatus.WITHDRAWN)) { + if (findVerifiedMessage(msgUUID).getUser().getUserStatus() == (UserStatus.WITHDRAWN)) { return null; } @@ -62,15 +62,14 @@ public Message updateMessage(UUID msgUUID, String message) { } @Override - public boolean deleteMessage(UUID id) { - Message m = getMessage(id); + public void deleteMessage(UUID id) { + Message m = findVerifiedMessage(id); if (!data.containsKey(id) || m.getUser().getUserStatus() == (UserStatus.WITHDRAWN)) { - return false; + return; } data.remove(id); - return true; } @Override diff --git a/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFMapUserService.java b/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFMapUserService.java index 0a2cfd4fa..416478a0b 100644 --- a/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFMapUserService.java +++ b/src/main/java/com/sprint/mission/discodeit/service/jcf/JCFMapUserService.java @@ -22,7 +22,7 @@ public User createUser(String userName, String email, String pw) { } @Override - public User getUser(UUID id) { + public User findVerifiedUser(UUID id) { List users = new ArrayList<>(data.values()); @@ -51,7 +51,7 @@ public List getUsersByStatus(UserStatus userStatus) { // update user 합침 @Override - public User updateUser(UUID id, User userInfo) { + public void updateUser(UUID id, User userInfo) { User updatedUser = Optional.ofNullable(data.get(id)) .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다!")); @@ -78,25 +78,21 @@ public User updateUser(UUID id, User userInfo) { .ifPresent(status -> updatedUser.setUserStatus(status)); //setting updatedAt - updatedUser.setUpdatedAt(); - - return updatedUser; - + updatedUser.updateTimeStamp(); } @Override - public boolean deleteUser(UUID id) { + public void deleteUser(UUID id) { if (!data.containsKey(id)) { - return false; + return; } User user = data.get(id); user.setUserStatus(UserStatus.WITHDRAWN); - user.setUpdatedAt(); + user.updateTimeStamp(); user.deleteChannels(); - return true; }