content: package com.codesoom.demo.application;
  
  import com.codesoom.demo.domain.Role;
  import com.codesoom.demo.domain.RoleRepository;
  import com.codesoom.demo.domain.User;
  import com.codesoom.demo.domain.UserRepository;
  import com.codesoom.demo.dto.UserModificationData;
  import com.codesoom.demo.dto.UserRegistrationData;
  import com.codesoom.demo.errors.UserEmailDuplicationException;
  import com.codesoom.demo.errors.UserNotFoundException;
  import com.github.dozermapper.core.Mapper;
  import org.springframework.stereotype.Service;
  
  import javax.transaction.Transactional;
  import java.nio.file.AccessDeniedException;
  
  @Service
  @Transactional
  public class UserService {
      private final Mapper mapper;
      private final UserRepository userRepository;
      private final RoleRepository roleRepository;
  
      public UserService(Mapper dozerMapper,
                         UserRepository userRepository,
                         RoleRepository roleRepository) {
          this.mapper = dozerMapper;
          this.userRepository = userRepository;
          this.roleRepository = roleRepository;
      }
  
      public User registerUser(UserRegistrationData registrationData) {
          String email = registrationData.getEmail();
          if (userRepository.existsByEmail(email)) {
              throw new UserEmailDuplicationException(email);
          }
  
          User user = userRepository.save(
                  mapper.map(registrationData, User.class));
          roleRepository.save(new Role(user.getId(), "USER"));
  
          return user;
      }
  
      public User updateUser(Long id, UserModificationData modificationData,
                             Long userId) throws AccessDeniedException {
          if (id != userId) {
              throw new AccessDeniedException("Access denied");
          }
  
          User user = findUser(id);
  
          User source = mapper.map(modificationData, User.class);
          user.changeWith(source);
  
          return user;
      }
  
      public User deleteUser(Long id) {
          User user = findUser(id);
          user.destroy();
          return user;
      }
  
      private User findUser(Long id) {
          return userRepository.findByIdAndDeletedIsFalse(id)
                  .orElseThrow(() -> new UserNotFoundException(id));
      }
  }
  