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 ddab9cb..dec9e91 100644
--- a/src/main/java/com/skillsync/skillsync/controller/UserController.java
+++ b/src/main/java/com/skillsync/skillsync/controller/UserController.java
@@ -5,15 +5,24 @@
import org.springframework.http.HttpStatus;
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
@@ -58,7 +67,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 f34260f..66a3fe4 100644
--- a/src/main/java/com/skillsync/skillsync/model/Skill.java
+++ b/src/main/java/com/skillsync/skillsync/model/Skill.java
@@ -1,15 +1,33 @@
package com.skillsync.skillsync.model;
import com.fasterxml.jackson.annotation.JsonBackReference;
-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;
@@ -21,47 +39,4 @@ public class Skill {
@JsonBackReference
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 4377f30..4ae6cac 100644
--- a/src/main/java/com/skillsync/skillsync/model/User.java
+++ b/src/main/java/com/skillsync/skillsync/model/User.java
@@ -1,16 +1,39 @@
package com.skillsync.skillsync.model;
import com.fasterxml.jackson.annotation.JsonManagedReference;
-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.GeneratedValue;
+import jakarta.persistence.GenerationType;
+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
@GeneratedValue(strategy = GenerationType.IDENTITY)
- private Long user_id;
+ private Long id;
private String name;
@@ -30,83 +53,5 @@ public class User {
@JsonManagedReference
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;
- }
}
diff --git a/src/main/java/com/skillsync/skillsync/repository/SkillRepository.java b/src/main/java/com/skillsync/skillsync/repository/SkillRepository.java
index e9106e4..f893560 100644
--- a/src/main/java/com/skillsync/skillsync/repository/SkillRepository.java
+++ b/src/main/java/com/skillsync/skillsync/repository/SkillRepository.java
@@ -1,17 +1,14 @@
package com.skillsync.skillsync.repository;
+import com.skillsync.skillsync.model.Skill;
import com.skillsync.skillsync.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
-import com.skillsync.skillsync.model.Skill;
-
import java.util.List;
@Repository
public interface SkillRepository extends JpaRepository {
// Future custom queries like findBySkillName can be added here
-
-
List findByUser(User user);
}
diff --git a/src/main/java/com/skillsync/skillsync/repository/UserRepository.java b/src/main/java/com/skillsync/skillsync/repository/UserRepository.java
index 359b917..6031cd4 100644
--- a/src/main/java/com/skillsync/skillsync/repository/UserRepository.java
+++ b/src/main/java/com/skillsync/skillsync/repository/UserRepository.java
@@ -1,16 +1,12 @@
package com.skillsync.skillsync.repository;
+import com.skillsync.skillsync.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
-import org.springframework.stereotype.Repository;
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 68df387..b88aae5 100644
--- a/src/main/java/com/skillsync/skillsync/service/UserService.java
+++ b/src/main/java/com/skillsync/skillsync/service/UserService.java
@@ -1,11 +1,12 @@
package com.skillsync.skillsync.service;
-import java.util.*;
-
import com.skillsync.skillsync.dto.UserDTO;
+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(UserDTO userDTO);
@@ -14,7 +15,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 8bb24ae..c044dbd 100644
--- a/src/main/java/com/skillsync/skillsync/service/impl/SkillServiceImpl.java
+++ b/src/main/java/com/skillsync/skillsync/service/impl/SkillServiceImpl.java
@@ -1,36 +1,27 @@
package com.skillsync.skillsync.service.impl;
-import java.util.*;
-
import com.skillsync.skillsync.model.Skill;
-import com.skillsync.skillsync.model.User;
import com.skillsync.skillsync.repository.SkillRepository;
import com.skillsync.skillsync.repository.UserRepository;
import com.skillsync.skillsync.service.SkillService;
-import org.springframework.beans.factory.annotation.Autowired;
+import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
+import java.util.Collections;
+import java.util.List;
+
@Service
+@RequiredArgsConstructor
public class SkillServiceImpl implements SkillService {
- final private UserRepository userRepository;
- final private SkillRepository skillRepository;
-
- @Autowired
- public SkillServiceImpl(SkillRepository skillRepository,UserRepository userRepository){
- this.skillRepository=skillRepository;
- this.userRepository=userRepository;
- }
+ private final UserRepository userRepository;
+ private final SkillRepository skillRepository;
@Override
public List getSkillsByUserId(Long userId) {
- Optional userOpt = userRepository.findById(userId);
- if (userOpt.isEmpty()) {
- return List.of();
- }
- User user = userOpt.get();
- List skills = skillRepository.findByUser(user);
- return skills.isEmpty() ? List.of() : skills;
+ return userRepository.findById(userId)
+ .map(skillRepository::findByUser)
+ .orElse(Collections.emptyList());
}
}
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 09e0123..65fb1be 100644
--- a/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java
+++ b/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java
@@ -8,25 +8,30 @@
import com.skillsync.skillsync.dto.UserDTO;
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
-public class UserServiceImpl implements UserService
+@RequiredArgsConstructor
+public class UserServiceImpl implements UserService
{
private final UserRepository userRepository;
-
- //Constructor for Dependency Injection
- @Autowired
- public UserServiceImpl(UserRepository userRepository) {
- this.userRepository = userRepository;
- }
-
+ private final UserMapper userMapper;
+ private final SkillMapper skillMapper;
/**
*
@@ -64,23 +69,42 @@ 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);
+ if (!CollectionUtils.isEmpty(userUpdateDTO.getSkills())) {
+ builder.skills(userUpdateDTO.getSkills());
+ }
+ UserUpdateDTO updateDTO = builder.build();
+ User updatedUser = userMapper.fromDtoToEntity(updateDTO);
+
+ updatedUser.setId(existingUser.getId());
+ if (!CollectionUtils.isEmpty(updateDTO.getSkills())) {
+ updatedUser.getSkills().clear();
+ User finalUpdatedUser = updatedUser;
+ List updatedSkills = updateDTO.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() {
- }
-
-}
diff --git a/src/test/java/com/skillsync/skillsync/service/impl/UserServiceImplTest.java b/src/test/java/com/skillsync/skillsync/service/impl/UserServiceImplTest.java
new file mode 100644
index 0000000..3fb7cab
--- /dev/null
+++ b/src/test/java/com/skillsync/skillsync/service/impl/UserServiceImplTest.java
@@ -0,0 +1,76 @@
+package com.skillsync.skillsync.service.impl;
+
+
+import com.skillsync.skillsync.dto.SkillDTO;
+import com.skillsync.skillsync.dto.SkillMapper;
+import com.skillsync.skillsync.dto.SkillMapperImpl;
+import com.skillsync.skillsync.dto.UserMapper;
+import com.skillsync.skillsync.dto.UserMapperImpl;
+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 org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentMatchers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
+import java.util.Optional;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class UserServiceImplTest {
+
+ @InjectMocks
+ private UserServiceImpl userService;
+
+ @Mock
+ private UserRepository userRepository;
+
+ @Spy
+ private UserMapper userMapper = new UserMapperImpl();
+
+ @Spy
+ private SkillMapper skillMapper = new SkillMapperImpl();
+
+ @Test
+ void testUpdateUser() {
+ // arrange
+ final Long id = 1L;
+ final UserUpdateDTO userUpdateDTO = UserUpdateDTO.builder()
+ .name("Piolo")
+ .skills(List.of(
+ SkillDTO.builder()
+ .name("Java")
+ .build()
+ ))
+ .build();
+ User user = User.builder()
+ .name("Piolo")
+ .skills(List.of(Skill.builder()
+ .name("Java")
+ .build()))
+ .build();
+ when(userRepository.findById(anyLong()))
+ .thenReturn(Optional.of(user));
+ when(userRepository.save(any(User.class))).thenReturn(user);
+
+
+ // act
+ User actual = userService.updateUser(id, userUpdateDTO);
+
+ // assert
+ Assertions.assertNotNull(actual);
+ Assertions.assertFalse(CollectionUtils.isEmpty(actual.getSkills()));
+ }
+}
\ No newline at end of file