Skip to content

Commit

Permalink
Updated link repository and service, controller, added javadoc
Browse files Browse the repository at this point in the history
  • Loading branch information
ArtemPoliakov committed Apr 18, 2024
1 parent b5dd793 commit 3947d0e
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 59 deletions.
3 changes: 2 additions & 1 deletion src/main/java/com/linkurlshorter/urlshortener/link/Link.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class Link {
@Column(name = "statistics")
private int statistics;
@Column(name = "status")
@Builder.Default
@Enumerated(EnumType.STRING)
private LinkStatus status;
private LinkStatus status = LinkStatus.ACTIVE;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
* Controller for Link-related operations such as create, delete, update and get info + statistics
Expand All @@ -33,7 +32,6 @@ public class LinkController {

private final LinkService linkService;
private final UserService userService;
private final EntityManager entityManager;
private final LinkInfoDtoMapper linkDtoMapper;

/**
Expand All @@ -57,15 +55,15 @@ public class LinkController {
@PostMapping("/create")
public ResponseEntity<CreateLinkResponse> createLink(@RequestBody @Valid CreateLinkRequest createRequest) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UUID userId = userService.findByEmail(authentication.getName()).getId();
User user = userService.findByEmail(authentication.getName());
String newShortUrl = generateShortLink();
try {
linkService.save(
Link.builder()
.longLink(createRequest.getLongLink())
.shortLink(newShortUrl)
.expirationTime(LocalDateTime.now().plusDays(SHORT_LINK_LIFETIME_IN_DAYS))
.user(entityManager.getReference(User.class, userId))
.user(user)
.build() //TODO: add validations (short link being unique etc)
);
} catch (Exception e) {
Expand Down Expand Up @@ -137,7 +135,13 @@ public ResponseEntity<LinkModifyingResponse> refreshLink(@RequestParam UUID id)
throw new ForbiddenException(OPERATION_FORBIDDEN_MSG);
}
}
//TODO: for info and all-links-info exclude all results of status DELETED!
/**
* Retrieves information about a link using its short link.
*
* @param shortLink the short link of the link to retrieve information for
* @return a ResponseEntity containing the response object with information about the link
* @throws ForbiddenException if the authenticated user does not have rights to access the link
*/
@GetMapping("/info")
public ResponseEntity<LinkInfoResponse> getInfoByShortLink(@RequestParam String shortLink) {
Link link = linkService.findByShortLink(shortLink);
Expand All @@ -149,37 +153,36 @@ public ResponseEntity<LinkInfoResponse> getInfoByShortLink(@RequestParam String
throw new ForbiddenException(OPERATION_FORBIDDEN_MSG);
}
}

/**
* Retrieves information about all links associated with the authenticated user.
*
* @return a ResponseEntity containing the response object with information about all links for the user
*/
@GetMapping("/all-links-info")
public ResponseEntity<LinkInfoResponse> getAllLinksForUser() {
try {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
User requesterUser = userService.findByEmail(authentication.getName());
List<LinkInfoDto> linksDto = linkService
.findAllByUser(requesterUser)
.stream()
.map(linkDtoMapper::mapLinkToDto)
.sorted(Comparator.comparing(LinkInfoDto::getUsageStatistics).reversed())
.collect(Collectors.toList());
return ResponseEntity.ok(new LinkInfoResponse(linksDto, "ok"));
} catch (Exception e) {
throw new InternalServerLinkException();
}

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UUID requesterUserId = userService.findByEmail(authentication.getName()).getId();
List<LinkInfoDto> linksDto = linkService
.findAllByUserId(requesterUserId)
.stream()
.map(linkDtoMapper::mapLinkToDto)
.sorted(Comparator.comparing(LinkInfoDto::getUsageStatistics).reversed())
.toList();
return ResponseEntity.ok(new LinkInfoResponse(linksDto, "ok"));
}

//TODO: exclude all results of non-Active (or only of DELETED?)
/**
* Retrieves usage statistics for all links associated with the authenticated user.
*
* @return a ResponseEntity containing the response object with usage statistics for all links for the user,
* links are sorted in descending order
*/
@GetMapping("/url-usage-top-for-user")
public ResponseEntity<LinkStatisticsResponse> getLinksStatsForUser() {
try {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
User requesterUser = userService.findByEmail(authentication.getName());
List<LinkStatisticsDto> stats = linkService.getLinkUsageStatsByUserId(requesterUser.getId());
stats.sort(Comparator.comparing(LinkStatisticsDto::getUsageStatistics).reversed());
return ResponseEntity.ok(new LinkStatisticsResponse(stats, "ok"));
} catch (Exception e) {
throw new InternalServerLinkException();
}
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
User requesterUser = userService.findByEmail(authentication.getName());
List<LinkStatisticsDto> stats = linkService.getLinkUsageStatsByUserId(requesterUser.getId());
stats.sort(Comparator.comparing(LinkStatisticsDto::getUsageStatistics).reversed());
return ResponseEntity.ok(new LinkStatisticsResponse(stats, "ok"));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
import lombok.NoArgsConstructor;

import java.util.List;

/**
* Data transfer object (DTO) for representing a response containing link information.
* This class encapsulates a list of {@link LinkInfoDto} objects representing link information,
* along with an optional error message.
*
* @author Artem Poliakov
* @version 1.0
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@
import com.linkurlshorter.urlshortener.user.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
Expand All @@ -34,9 +30,10 @@ public interface LinkRepository extends JpaRepository<Link, UUID> {
*/
Optional<Link> findByShortLink(String shortLink);

List<Link> findAllByUser(User user);
@Query("SELECT l from Link l WHERE l.user.id = :userId AND l.status <> 'DELETED'")
List<Link> findAllByUserId(@Param(value = "userId") UUID userId);

@Query("SELECT new com.linkurlshorter.urlshortener.link.LinkStatisticsDto(l.id, l.shortLink, l.statistics)" +
" FROM Link l WHERE l.user.id = :userId")
" FROM Link l WHERE l.user.id = :userId AND l.status <> 'DELETED'")
List<LinkStatisticsDto> getLinkUsageStatsForUser(@Param(value = "userId") UUID userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ public Link findByShortLink(String shortLink) {
return link;
}

public List<Link> findAllByUser(User user){
if(Objects.isNull(user)){
public List<Link> findAllByUserId(UUID userId){
if(Objects.isNull(userId)){
throw new NullLinkPropertyException();
}
return linkRepository.findAllByUser(user);
return linkRepository.findAllByUserId(userId);
}

public List<LinkStatisticsDto> getLinkUsageStatsByUserId(UUID userId){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@
import lombok.NoArgsConstructor;

import java.util.UUID;

/**
* Data transfer object (DTO) for representing link statistics.
* This class encapsulates information about a link's ID, short link, and usage statistics.
*
* @author Artem Poliakov
* @version 1.0
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@
import lombok.NoArgsConstructor;

import java.util.List;

/**
* Data transfer object (DTO) for representing a response containing statistics of links.
* This class encapsulates a list of {@link LinkStatisticsDto} objects representing link statistics,
* along with an optional error message.
*
* @author Artem Poliakov
* @version 1.0
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/linkurlshorter/urlshortener/user/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ public class User {
private String password;
@Column(name = "role")
@Enumerated(EnumType.STRING)
private UserRole role;
@Builder.Default
private UserRole role = UserRole.USER;
@EqualsAndHashCode.Exclude
@OneToMany(mappedBy = "user", cascade = {CascadeType.MERGE, CascadeType.PERSIST})
private List<Link> links;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@

import com.linkurlshorter.urlshortener.user.User;
import com.linkurlshorter.urlshortener.user.UserRole;
import jakarta.persistence.EntityManager;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalDateTime;
import java.util.*;
Expand Down Expand Up @@ -189,36 +194,31 @@ void findByShortLinkNotFoundTest() {
}

/**
* Test case for the {@link LinkService#findAllByUser(User)} method.
* Test case for the {@link LinkService#findAllByUserId(UUID)} method.
*/
@Test
void findByAllByUserTest() {
User user = User.builder()
.id(UUID.fromString("84991c79-f6a9-4b7b-b1b4-0d66c0b92c81"))
.email("[email protected]")
.password("password1")
.role(UserRole.USER)
.build();

void findByAllByUserIdTest() {
UUID userId = UUID.fromString("84991c79-f6a9-4b7b-b1b4-0d66c0b92c81");
User user = User.builder().id(userId).build();
List<Link> userLinks = Arrays.asList(
Link.builder().id(UUID.randomUUID()).user(user).build(),
Link.builder().id(UUID.randomUUID()).user(user).build(),
Link.builder().id(UUID.randomUUID()).user(user).build()
);

when(linkRepository.findAllByUser(user)).thenReturn(userLinks);
List<Link> foundLinks = linkService.findAllByUser(user);
when(linkRepository.findAllByUserId(userId)).thenReturn(userLinks);
List<Link> foundLinks = linkService.findAllByUserId(userId);

assertThat(foundLinks).isNotNull().isEqualTo(userLinks);
verify(linkRepository, times(1)).findAllByUser(user);
verify(linkRepository, times(1)).findAllByUserId(userId);
}

/**
* Test case for the {@link LinkService#findAllByUser(User)} method when the provided user is null.
* Test case for the {@link LinkService#findAllByUserId(UUID)} method when the provided user is null.
*/
@Test
void findAllByNullUserTest() {
assertThatThrownBy(() -> linkService.findAllByUser(null))
assertThatThrownBy(() -> linkService.findAllByUserId(null))
.isInstanceOf(NullLinkPropertyException.class);
}

Expand Down

0 comments on commit 3947d0e

Please sign in to comment.