From 193ceb88ae1ceaee7e20ee2488c9080c0101d592 Mon Sep 17 00:00:00 2001 From: NyorJa Date: Thu, 23 Oct 2025 23:09:03 +0800 Subject: [PATCH 1/2] Initial implementation --- pom.xml | 34 +++- .../skillsync/controller/UserController.java | 20 +- .../com/skillsync/skillsync/dto/SkillDTO.java | 23 ++- .../skillsync/skillsync/dto/SkillMapper.java | 10 + .../skillsync/skillsync/dto/UserMapper.java | 11 ++ .../skillsync/dto/UserSearchResponseDTO.java | 1 + .../skillsync/dto/UserUpdateDTO.java | 20 +- .../com/skillsync/skillsync/model/Skill.java | 67 ++----- .../com/skillsync/skillsync/model/User.java | 187 ++++++++++-------- .../skillsync/repository/SkillRepository.java | 3 +- .../skillsync/repository/UserRepository.java | 7 +- .../skillsync/service/SkillService.java | 4 +- .../skillsync/service/UserService.java | 7 +- .../service/impl/SkillServiceImpl.java | 5 +- .../service/impl/UserServiceImpl.java | 66 ++++--- .../skillsync/SkillsyncApplicationTests.java | 13 -- 16 files changed, 278 insertions(+), 200 deletions(-) create mode 100644 src/main/java/com/skillsync/skillsync/dto/SkillMapper.java create mode 100644 src/main/java/com/skillsync/skillsync/dto/UserMapper.java delete mode 100644 src/test/java/com/skillsync/skillsync/SkillsyncApplicationTests.java diff --git a/pom.xml b/pom.xml index 51f7bca..ec8d1a3 100644 --- a/pom.xml +++ b/pom.xml @@ -28,13 +28,35 @@ 21 - + 1.6.2 + org.springframework.boot spring-boot-starter-web + + + + org.mapstruct + mapstruct + ${mapstruct.version} + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + provided + + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + provided + + org.springframework.boot spring-boot-devtools @@ -71,6 +93,16 @@ maven-compiler-plugin + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + org.projectlombok lombok diff --git a/src/main/java/com/skillsync/skillsync/controller/UserController.java b/src/main/java/com/skillsync/skillsync/controller/UserController.java index d6d979e..584ce13 100644 --- a/src/main/java/com/skillsync/skillsync/controller/UserController.java +++ b/src/main/java/com/skillsync/skillsync/controller/UserController.java @@ -1,17 +1,23 @@ package com.skillsync.skillsync.controller; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - +import com.skillsync.skillsync.dto.UserSearchResponseDTO; import com.skillsync.skillsync.dto.UserUpdateDTO; import com.skillsync.skillsync.model.Skill; import com.skillsync.skillsync.model.User; import com.skillsync.skillsync.service.SkillService; import com.skillsync.skillsync.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; -import com.skillsync.skillsync.dto.UserSearchResponseDTO; - -import java.util.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; import java.util.stream.Collectors; @RestController @@ -57,7 +63,7 @@ public List getUserSkills(@PathVariable Long id) { @PutMapping("/update/{id}") public User updateUser(@PathVariable Long id, @RequestBody UserUpdateDTO user) { // TODO: Implement update user logic (call service layer) - return null; + return userService.updateUser(id, user); } diff --git a/src/main/java/com/skillsync/skillsync/dto/SkillDTO.java b/src/main/java/com/skillsync/skillsync/dto/SkillDTO.java index 79f22c1..4bdfe38 100644 --- a/src/main/java/com/skillsync/skillsync/dto/SkillDTO.java +++ b/src/main/java/com/skillsync/skillsync/dto/SkillDTO.java @@ -1,27 +1,30 @@ package com.skillsync.skillsync.dto; import com.skillsync.skillsync.model.Skill; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +@AllArgsConstructor +@NoArgsConstructor +@Data +@Builder +@Setter +@Getter public class SkillDTO { private Long id; private String name; private String description; - // Static mapper to convert Entity to DTO public static SkillDTO fromEntity(Skill skill) { SkillDTO dto = new SkillDTO(); // Assuming Skill.getId() maps to skill_id, and so on - dto.id = skill.getId(); + dto.id = skill.getId(); dto.name = skill.getName(); dto.description = skill.getDescription(); return dto; } - - // Getters and Setters - public Long getId() { return id; } - public void setId(Long id) { this.id = id; } - public String getName() { return name; } - public void setName(String name) { this.name = name; } - public String getDescription() { return description; } - public void setDescription(String description) { this.description = description; } } \ No newline at end of file diff --git a/src/main/java/com/skillsync/skillsync/dto/SkillMapper.java b/src/main/java/com/skillsync/skillsync/dto/SkillMapper.java new file mode 100644 index 0000000..a5a4318 --- /dev/null +++ b/src/main/java/com/skillsync/skillsync/dto/SkillMapper.java @@ -0,0 +1,10 @@ +package com.skillsync.skillsync.dto; + +import com.skillsync.skillsync.model.Skill; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface SkillMapper { + SkillDTO fromEntityToDto(Skill skill); + Skill fromDtoToEntity(SkillDTO skillDTO); +} diff --git a/src/main/java/com/skillsync/skillsync/dto/UserMapper.java b/src/main/java/com/skillsync/skillsync/dto/UserMapper.java new file mode 100644 index 0000000..13ec9bd --- /dev/null +++ b/src/main/java/com/skillsync/skillsync/dto/UserMapper.java @@ -0,0 +1,11 @@ +package com.skillsync.skillsync.dto; + +import com.skillsync.skillsync.model.User; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface UserMapper { + + User fromDtoToEntity(UserUpdateDTO userUpdateDTO); + UserUpdateDTO fromEntityToDto(User user); +} diff --git a/src/main/java/com/skillsync/skillsync/dto/UserSearchResponseDTO.java b/src/main/java/com/skillsync/skillsync/dto/UserSearchResponseDTO.java index c8e8474..325ff42 100644 --- a/src/main/java/com/skillsync/skillsync/dto/UserSearchResponseDTO.java +++ b/src/main/java/com/skillsync/skillsync/dto/UserSearchResponseDTO.java @@ -1,6 +1,7 @@ package com.skillsync.skillsync.dto; import com.skillsync.skillsync.model.User; + import java.util.List; import java.util.stream.Collectors; diff --git a/src/main/java/com/skillsync/skillsync/dto/UserUpdateDTO.java b/src/main/java/com/skillsync/skillsync/dto/UserUpdateDTO.java index 4d14986..f68f861 100644 --- a/src/main/java/com/skillsync/skillsync/dto/UserUpdateDTO.java +++ b/src/main/java/com/skillsync/skillsync/dto/UserUpdateDTO.java @@ -1,8 +1,22 @@ package com.skillsync.skillsync.dto; -public class UserUpdateDTO { +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; - // Add feilds to update user - // this file helps not to senf all the fields of user entity to update +import java.util.List; +@AllArgsConstructor +@NoArgsConstructor +@Data +@Setter +@Getter +@Builder +public class UserUpdateDTO { + private String name; + private String bio; + private List skills; } diff --git a/src/main/java/com/skillsync/skillsync/model/Skill.java b/src/main/java/com/skillsync/skillsync/model/Skill.java index 93fb97f..607f797 100644 --- a/src/main/java/com/skillsync/skillsync/model/Skill.java +++ b/src/main/java/com/skillsync/skillsync/model/Skill.java @@ -1,14 +1,32 @@ package com.skillsync.skillsync.model; -import jakarta.persistence.*; - +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Builder +@Setter +@Getter @Entity @Table(name = "skills") public class Skill { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long skill_id; + private Long id; private String name; @@ -19,47 +37,4 @@ public class Skill { @JoinColumn(name = "user_id") private User user; - // Constructors - public Skill() { - } - - public Skill(String name, String description, User user) { - this.name = name; - this.description = description; - this.user = user; - } - - // Getters and Setters - public Long getId() { - return skill_id; - } - - public void setId(Long id) { - this.skill_id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - } diff --git a/src/main/java/com/skillsync/skillsync/model/User.java b/src/main/java/com/skillsync/skillsync/model/User.java index a6aed7c..0d4778a 100644 --- a/src/main/java/com/skillsync/skillsync/model/User.java +++ b/src/main/java/com/skillsync/skillsync/model/User.java @@ -1,14 +1,35 @@ package com.skillsync.skillsync.model; -import jakarta.persistence.*; -import java.util.*; - +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Builder +@Setter +@Getter @Entity @Table(name = "users") public class User { @Id - private Long user_id; + private Long id; private String name; @@ -28,82 +49,86 @@ public class User { private List skills = new ArrayList<>(); // Constructors - public User() { - } - - public User(String name, String email, String password, String bio, RoleType roleType, - boolean availableForMentorship) { - this.name = name; - this.email = email; - this.password = password; - this.bio = bio; - this.roleType = roleType; - this.availableForMentorship = availableForMentorship; - } - - // Getters and Setters - public Long getId() { - return user_id; - } - - public void setId(Long id) { - this.user_id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getBio() { - return bio; - } - - public void setBio(String bio) { - this.bio = bio; - } - - public RoleType getRoleType() { - return roleType; - } - - public void setRoleType(RoleType roleType) { - this.roleType = roleType; - } - - public boolean isAvailableForMentorship() { - return availableForMentorship; - } - - public void setAvailableForMentorship(boolean availableForMentorship) { - this.availableForMentorship = availableForMentorship; - } - - public List getSkills() { - return skills; - } - - public void setSkills(List skills) { - this.skills = skills; - } +// public User() { +// } + +// // Constructors +// public User() { +// } +// +// public User(String name, String email, String password, String bio, RoleType roleType, +// boolean availableForMentorship) { +// this.name = name; +// this.email = email; +// this.password = password; +// this.bio = bio; +// this.roleType = roleType; +// this.availableForMentorship = availableForMentorship; +// } +// +// // Getters and Setters +// public Long getId() { +// return user_id; +// } +// +// public void setId(Long id) { +// this.user_id = id; +// } +// +// public String getName() { +// return name; +// } +// +// public void setName(String name) { +// this.name = name; +// } +// +// public String getEmail() { +// return email; +// } +// +// public void setEmail(String email) { +// this.email = email; +// } +// +// public String getPassword() { +// return password; +// } +// +// public void setPassword(String password) { +// this.password = password; +// } +// +// public String getBio() { +// return bio; +// } +// +// public void setBio(String bio) { +// this.bio = bio; +// } +// +// public RoleType getRoleType() { +// return roleType; +// } +// +// public void setRoleType(RoleType roleType) { +// this.roleType = roleType; +// } +// +// public boolean isAvailableForMentorship() { +// return availableForMentorship; +// } +// +// public void setAvailableForMentorship(boolean availableForMentorship) { +// this.availableForMentorship = availableForMentorship; +// } +// +// public List getSkills() { +// return skills; +// } +// +// public void setSkills(List skills) { +// this.skills = skills; +// } } diff --git a/src/main/java/com/skillsync/skillsync/repository/SkillRepository.java b/src/main/java/com/skillsync/skillsync/repository/SkillRepository.java index 23b25ea..8b682d8 100644 --- a/src/main/java/com/skillsync/skillsync/repository/SkillRepository.java +++ b/src/main/java/com/skillsync/skillsync/repository/SkillRepository.java @@ -1,10 +1,9 @@ package com.skillsync.skillsync.repository; +import com.skillsync.skillsync.model.Skill; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import com.skillsync.skillsync.model.Skill; - @Repository public interface SkillRepository extends JpaRepository { // Future custom queries like findBySkillName can be added here diff --git a/src/main/java/com/skillsync/skillsync/repository/UserRepository.java b/src/main/java/com/skillsync/skillsync/repository/UserRepository.java index fa876aa..6031cd4 100644 --- a/src/main/java/com/skillsync/skillsync/repository/UserRepository.java +++ b/src/main/java/com/skillsync/skillsync/repository/UserRepository.java @@ -1,13 +1,12 @@ package com.skillsync.skillsync.repository; +import com.skillsync.skillsync.model.User; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; -import com.skillsync.skillsync.model.User; +import java.util.List; -@Repository public interface UserRepository extends JpaRepository { // Custom query methods can be added later, e.g. findByEmail, findBySkillName, // etc. diff --git a/src/main/java/com/skillsync/skillsync/service/SkillService.java b/src/main/java/com/skillsync/skillsync/service/SkillService.java index 2b7b882..0866dc5 100644 --- a/src/main/java/com/skillsync/skillsync/service/SkillService.java +++ b/src/main/java/com/skillsync/skillsync/service/SkillService.java @@ -1,9 +1,9 @@ package com.skillsync.skillsync.service; -import java.util.List; - import com.skillsync.skillsync.model.Skill; +import java.util.List; + public interface SkillService { List getSkillsByUserId(Long userId); diff --git a/src/main/java/com/skillsync/skillsync/service/UserService.java b/src/main/java/com/skillsync/skillsync/service/UserService.java index 1fe2574..edbd004 100644 --- a/src/main/java/com/skillsync/skillsync/service/UserService.java +++ b/src/main/java/com/skillsync/skillsync/service/UserService.java @@ -1,10 +1,11 @@ package com.skillsync.skillsync.service; -import java.util.*; - +import com.skillsync.skillsync.dto.UserUpdateDTO; import com.skillsync.skillsync.model.Skill; import com.skillsync.skillsync.model.User; +import java.util.List; + public interface UserService { User saveUser(User user); @@ -13,7 +14,7 @@ public interface UserService { User getUserById(Long id); // Update User - User updateUser(Long id, User user); + User updateUser(Long id, UserUpdateDTO user); // Add Skill to existing User User addSkillToUser(Long userId, Skill skill); diff --git a/src/main/java/com/skillsync/skillsync/service/impl/SkillServiceImpl.java b/src/main/java/com/skillsync/skillsync/service/impl/SkillServiceImpl.java index 8fb0048..24752f3 100644 --- a/src/main/java/com/skillsync/skillsync/service/impl/SkillServiceImpl.java +++ b/src/main/java/com/skillsync/skillsync/service/impl/SkillServiceImpl.java @@ -1,10 +1,11 @@ package com.skillsync.skillsync.service.impl; -import java.util.*; - import com.skillsync.skillsync.model.Skill; import com.skillsync.skillsync.service.SkillService; +import java.util.ArrayList; +import java.util.List; + public class SkillServiceImpl implements SkillService { @Override diff --git a/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java b/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java index 15cf8b8..e9afdc9 100644 --- a/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java +++ b/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java @@ -1,32 +1,29 @@ package com.skillsync.skillsync.service.impl; -import java.util.*; - -import javax.management.RuntimeErrorException; - -import org.springframework.beans.factory.annotation.Autowired; - +import com.skillsync.skillsync.dto.SkillMapper; +import com.skillsync.skillsync.dto.UserMapper; +import com.skillsync.skillsync.dto.UserUpdateDTO; import com.skillsync.skillsync.model.Skill; import com.skillsync.skillsync.model.User; import com.skillsync.skillsync.repository.UserRepository; import com.skillsync.skillsync.service.UserService; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import com.skillsync.skillsync.repository.UserRepository; +import org.springframework.util.CollectionUtils; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import static java.util.Optional.ofNullable; @Service +@RequiredArgsConstructor public class UserServiceImpl implements UserService { private final UserRepository userRepository; - - //Constructor for Dependency Injection - @Autowired - public UserServiceImpl(UserRepository userRepository) { - this.userRepository = userRepository; - } - - @Autowired - private UserRepository userRepository; + private final UserMapper userMapper; + private final SkillMapper skillMapper; @Override public User saveUser(User user) { @@ -41,23 +38,40 @@ public List getAllUsers() { @Override public User getUserById(Long id) { - Optional userOptional = userRepository.findById(id); - - if(!userOptional.isPresent()) - { - throw new RuntimeException("User Not Found"); - } - return userOptional.get(); + return userRepository.findById(id) + .orElseThrow(() -> new RuntimeException("User Not Found")); } // Update User @Override - public User updateUser(Long id, User user) { + public User updateUser(Long id, UserUpdateDTO userUpdateDTO) { // TODO: Fetch existing user by ID // TODO: Update only provided fields // TODO: Save and return updated user - return null; + User existingUser = getUserById(id); + + UserUpdateDTO existingDto = userMapper.fromEntityToDto(existingUser); + + UserUpdateDTO.UserUpdateDTOBuilder builder = UserUpdateDTO.builder(); + ofNullable(existingDto.getBio()).ifPresent(builder::bio); + ofNullable(existingDto.getName()).ifPresent(builder::name); + + UserUpdateDTO updateDTO = builder.build(); + User updatedUser = userMapper.fromDtoToEntity(updateDTO); + + updatedUser.setId(existingUser.getId()); + if (!CollectionUtils.isEmpty(userUpdateDTO.getSkills())) { + updatedUser.getSkills().clear(); + User finalUpdatedUser = updatedUser; + List updatedSkills = userUpdateDTO.getSkills().stream() + .map(skillMapper::fromDtoToEntity) + .peek(skill -> skill.setUser(finalUpdatedUser)) + .toList(); + updatedUser.setSkills(updatedSkills); + } + updatedUser = userRepository.save(updatedUser); + return updatedUser; } diff --git a/src/test/java/com/skillsync/skillsync/SkillsyncApplicationTests.java b/src/test/java/com/skillsync/skillsync/SkillsyncApplicationTests.java deleted file mode 100644 index e5ea664..0000000 --- a/src/test/java/com/skillsync/skillsync/SkillsyncApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.skillsync.skillsync; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class SkillsyncApplicationTests { - - @Test - void contextLoads() { - } - -} From 1fa9aa1057b4f35b0d32ad1c25864831e2c63a55 Mon Sep 17 00:00:00 2001 From: NyorJa Date: Fri, 24 Oct 2025 00:06:02 +0800 Subject: [PATCH 2/2] Implement update user skills --- pom.xml | 13 +++++++++++++ .../java/com/skillsync/skillsync/model/Skill.java | 2 ++ .../skillsync/service/impl/UserServiceImpl.java | 9 ++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index ec8d1a3..999f0ce 100644 --- a/pom.xml +++ b/pom.xml @@ -80,6 +80,19 @@ runtime + + + jakarta.validation + jakarta.validation-api + 3.0.2 + + + + + org.hibernate.validator + hibernate-validator + + org.springframework.boot spring-boot-starter-data-jpa diff --git a/src/main/java/com/skillsync/skillsync/model/Skill.java b/src/main/java/com/skillsync/skillsync/model/Skill.java index 607f797..d73b78a 100644 --- a/src/main/java/com/skillsync/skillsync/model/Skill.java +++ b/src/main/java/com/skillsync/skillsync/model/Skill.java @@ -7,6 +7,7 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; +import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -28,6 +29,7 @@ public class Skill { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @NotNull(message = "name is required") private String name; diff --git a/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java b/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java index e9afdc9..129e7b6 100644 --- a/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java +++ b/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -82,7 +83,13 @@ public User addSkillToUser(Long userId, Skill skill) { // TODO: Add skill to user’s skill list // TODO: Save updated user // TODO: Return updated user - return null; + User existingUser = getUserById(userId); + if (CollectionUtils.isEmpty(existingUser.getSkills())) { + existingUser.getSkills().add(skill); + } else { + existingUser.setSkills(List.of(skill)); + } + return userRepository.save(existingUser); }