Skip to content

Commit

Permalink
refactor: refactored and optimized request to get all topics
Browse files Browse the repository at this point in the history
  • Loading branch information
Troha7 committed Mar 28, 2024
1 parent e5c6366 commit 1abe15d
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.chat.yourway.dto.request.TopicRequestDto;
import com.chat.yourway.dto.response.ApiErrorResponseDto;
import com.chat.yourway.dto.response.ContactResponseDto;
import com.chat.yourway.dto.response.TopicInfoResponseDto;
import com.chat.yourway.dto.response.TopicResponseDto;
import com.chat.yourway.service.interfaces.TopicService;
import com.chat.yourway.service.interfaces.TopicSubscriberService;
Expand Down Expand Up @@ -149,7 +150,7 @@ public TopicResponseDto findById(@PathVariable Integer id) {
content = @Content(schema = @Schema(implementation = ApiErrorResponseDto.class)))
})
@GetMapping(path = "/all", produces = APPLICATION_JSON_VALUE)
public List<TopicResponseDto> findAllPublic() {
public List<TopicInfoResponseDto> findAllPublic() {
return topicService.findAllPublic();
}

Expand Down Expand Up @@ -322,7 +323,7 @@ public void removeToFavouriteTopic(
content = @Content(schema = @Schema(implementation = ApiErrorResponseDto.class)))
})
@GetMapping(path = "/favourite", produces = APPLICATION_JSON_VALUE)
public List<TopicResponseDto> findAllFavouriteTopics(
public List<TopicInfoResponseDto> findAllFavouriteTopics(
@AuthenticationPrincipal UserDetails userDetails) {
return topicService.findAllFavouriteTopics(userDetails);
}
Expand All @@ -333,7 +334,7 @@ public List<TopicResponseDto> findAllFavouriteTopics(
@ApiResponse(responseCode = "200", description = SUCCESSFULLY_FOUND_TOPIC)
})
@GetMapping(path = "/popular/public", produces = APPLICATION_JSON_VALUE)
public List<TopicResponseDto> findAllPopularPublicTopics() {
public List<TopicInfoResponseDto> findAllPopularPublicTopics() {
return topicService.findPopularPublicTopics();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.chat.yourway.dto.response;

import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@ToString
public class TopicInfoResponseDto {
@Schema(description = "ID", example = "1")
private Integer id;
@Schema(description = "New Topic name", example = "My programming topic")
private String topicName;
@Schema(description = "Email of Topic creator", example = "[email protected]")
private String createdBy;
@Schema(description = "Created time")
private LocalDateTime createdAt;

}
3 changes: 3 additions & 0 deletions src/main/java/com/chat/yourway/mapper/TopicMapper.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.chat.yourway.mapper;

import com.chat.yourway.dto.response.TopicInfoResponseDto;
import com.chat.yourway.dto.response.TopicResponseDto;
import com.chat.yourway.model.Topic;
import java.util.List;
Expand All @@ -12,6 +13,8 @@ public interface TopicMapper {
TopicResponseDto toResponseDto(Topic topic);
List<TopicResponseDto> toListResponseDto(List<Topic> topics);

List<TopicInfoResponseDto> toListInfoResponseDto(List<Topic> topics);

@Mapping(target = "messages", ignore = true)
Topic toEntity(TopicResponseDto topicResponseDto);

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/chat/yourway/model/Topic.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ public class Topic {
@Column(name = "created_at", nullable = false)
private LocalDateTime createdAt;

@ManyToMany(fetch = FetchType.EAGER)
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
schema = "chat",
name = "topic_tag",
joinColumns = @JoinColumn(name = "topic_id"),
inverseJoinColumns = @JoinColumn(name = "tag_id"))
private Set<Tag> tags;

@OneToMany(mappedBy = "topic", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@OneToMany(mappedBy = "topic", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<TopicSubscriber> topicSubscribers;

@OneToMany(mappedBy = "topic", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
Expand Down
26 changes: 12 additions & 14 deletions src/main/java/com/chat/yourway/repository/TopicRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ public interface TopicRepository extends JpaRepository<Topic, Integer> {
@Query(
value =
"""
SELECT *
FROM chat.topic t
WHERE to_tsvector('english', t.topic_name) @@ to_tsquery('english', :query)
""",
SELECT *
FROM chat.topic t
WHERE to_tsvector('english', t.topic_name) @@ to_tsquery('english', :query)
""",
nativeQuery = true)
List<Topic> findAllByTopicName(String query);

Expand All @@ -31,18 +31,16 @@ WHERE to_tsvector('english', t.topic_name) @@ to_tsquery('english', :query)

@Query(
"select t from Topic t join fetch t.topicSubscribers ts "
+ "where ts.contact.email = :contactEmail and ts.isFavouriteTopic = true")
+ "where ts.contact.email = :contactEmail and ts.isFavouriteTopic = true")
List<Topic> findAllFavouriteTopicsByContactEmail(String contactEmail);

boolean existsByIdAndIsPublic(int topicId, boolean isPublic);

@Query(nativeQuery = true, value =
"SELECT t.*, COUNT(ts.id) AS ts_count, COUNT(m.id) AS m_count " +
"FROM chat.topic t " +
"JOIN chat.topic_subscriber ts ON t.id = ts.topic_id " +
"JOIN chat.message m ON t.id = m.topic_id " +
"WHERE t.is_public = true " +
"GROUP BY t.id " +
"ORDER BY ts_count DESC, m_count DESC")
"SELECT t.*, COUNT(ts.id) AS ts_count, COUNT(m.id) AS m_count " +
"FROM chat.topic t " +
"JOIN chat.topic_subscriber ts ON t.id = ts.topic_id " +
"JOIN chat.message m ON t.id = m.topic_id " +
"WHERE t.is_public = true " +
"GROUP BY t.id " +
"ORDER BY ts_count DESC, m_count DESC")
List<Topic> findPopularPublicTopics();
}
13 changes: 7 additions & 6 deletions src/main/java/com/chat/yourway/service/TopicServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.chat.yourway.dto.request.TagRequestDto;
import com.chat.yourway.dto.request.TopicPrivateRequestDto;
import com.chat.yourway.dto.request.TopicRequestDto;
import com.chat.yourway.dto.response.TopicInfoResponseDto;
import com.chat.yourway.dto.response.TopicResponseDto;
import com.chat.yourway.exception.ContactEmailNotExist;
import com.chat.yourway.exception.TopicAccessException;
Expand Down Expand Up @@ -100,13 +101,13 @@ public TopicResponseDto findByName(String name) {
}

@Override
public List<TopicResponseDto> findAllPublic() {
public List<TopicInfoResponseDto> findAllPublic() {
log.trace("Started findAllPublic");

List<Topic> topics = topicRepository.findAllByIsPublicIsTrue();

log.trace("All public topics was found");
return topicMapper.toListResponseDto(topics);
return topicMapper.toListInfoResponseDto(topics);
}

@Override
Expand Down Expand Up @@ -173,15 +174,15 @@ public String generatePrivateName(String sendTo, String email) {
}

@Override
public List<TopicResponseDto> findAllFavouriteTopics(UserDetails userDetails) {
public List<TopicInfoResponseDto> findAllFavouriteTopics(UserDetails userDetails) {
String contactEmail = userDetails.getUsername();
return topicMapper.toListResponseDto(
return topicMapper.toListInfoResponseDto(
topicRepository.findAllFavouriteTopicsByContactEmail(contactEmail));
}

@Override
public List<TopicResponseDto> findPopularPublicTopics() {
return topicMapper.toListResponseDto(topicRepository.findPopularPublicTopics());
public List<TopicInfoResponseDto> findPopularPublicTopics() {
return topicMapper.toListInfoResponseDto(topicRepository.findPopularPublicTopics());
}

private Topic createOrUpdateTopic(Topic topic, TopicRequestDto topicRequestDto, String email) {
Expand Down
35 changes: 17 additions & 18 deletions src/main/java/com/chat/yourway/service/interfaces/TopicService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,23 @@
import com.chat.yourway.dto.request.TagRequestDto;
import com.chat.yourway.dto.request.TopicPrivateRequestDto;
import com.chat.yourway.dto.request.TopicRequestDto;
import com.chat.yourway.dto.response.TopicInfoResponseDto;
import com.chat.yourway.dto.response.TopicResponseDto;
import com.chat.yourway.exception.TopicAccessException;
import com.chat.yourway.exception.TopicNotFoundException;
import com.chat.yourway.exception.ValueNotUniqException;
import com.chat.yourway.model.Tag;
import com.chat.yourway.model.Topic;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.List;
import java.util.Set;
import org.springframework.security.core.userdetails.UserDetails;

public interface TopicService {

/**
* Creates a new topic with the specified email of the creator.
*
* @param topicRequestDto Request object for creating topic.
* @param email The email of the creator.
* @param email The email of the creator.
* @return Created topic.
* @throws ValueNotUniqException If the topic name already in use.
*/
Expand All @@ -31,7 +30,7 @@ public interface TopicService {
* contacts.
*
* @param topicPrivateDto Request object for creating topic.
* @param email The email of the creator.
* @param email The email of the creator.
* @return Created private topic.
* @throws ValueNotUniqException If the topic name already in use.
*/
Expand All @@ -40,12 +39,12 @@ public interface TopicService {
/**
* Update an existing topic with the specified email of the creator.
*
* @param topicId The ID of the topic to find.
* @param topicId The ID of the topic to find.
* @param topicRequestDto Request object for creating topic.
* @param email The email of the creator.
* @param email The email of the creator.
* @return Updated topic.
* @throws ValueNotUniqException If the topic name already in use.
* @throws TopicAccessException if the email is not the creator of the topic.
* @throws TopicAccessException if the email is not the creator of the topic.
*/
TopicResponseDto update(Integer topicId, TopicRequestDto topicRequestDto, String email);

Expand All @@ -72,12 +71,12 @@ public interface TopicService {
*
* @return A list of public topics.
*/
List<TopicResponseDto> findAllPublic();
List<TopicInfoResponseDto> findAllPublic();

/**
* Deletes a topic by ID if the specified email is the creator of the topic.
*
* @param id The ID of the topic to delete.
* @param id The ID of the topic to delete.
* @param email The email of the user.
* @throws TopicAccessException if the email is not the creator of the topic.
*/
Expand All @@ -88,7 +87,7 @@ public interface TopicService {
*
* @param tagName The unique name of the tag for which topics are to be retrieved.
* @return A list of {@link TopicResponseDto} objects associated with the given tag. An empty list
* is returned if no topics are found for the specified tag.
* is returned if no topics are found for the specified tag.
*/
List<TopicResponseDto> findTopicsByTagName(String tagName);

Expand Down Expand Up @@ -116,7 +115,7 @@ public interface TopicService {
* separated by "<->" symbol.
*
* @param sendTo Email address of the receiver.
* @param email Email address of the sender.
* @param email Email address of the sender.
* @return Unique private topic name.
*/
String generatePrivateName(String sendTo, String email);
Expand All @@ -125,20 +124,20 @@ public interface TopicService {
* Retrieves a list of favorite topics for the specified user.
*
* @param userDetails The details of the user for whom favorite topics are to be retrieved.
* @return A list of {@code TopicResponseDto} objects representing the user's favorite topics.
* @return A list of {@code TopicInfoResponseDto} objects representing the user's favorite topics.
*/
List<TopicResponseDto> findAllFavouriteTopics(UserDetails userDetails);
List<TopicInfoResponseDto> findAllFavouriteTopics(UserDetails userDetails);


/**
* Retrieves a list of popular public topics.
* <p>
* This method returns a list of {@code TopicResponseDto} objects representing popular topics
* that are marked as public. The popularity is determined by the number of subscribers and messages
* This method returns a list of {@code TopicResponseDto} objects representing popular topics that
* are marked as public. The popularity is determined by the number of subscribers and messages
* associated with each topic.
*
* @return A list of {@code TopicResponseDto} objects representing popular public topics.
* @return A list of {@code TopicInfoResponseDto} objects representing popular public topics.
* @see TopicResponseDto
*/
List<TopicResponseDto> findPopularPublicTopics();
List<TopicInfoResponseDto> findPopularPublicTopics();
}
Original file line number Diff line number Diff line change
Expand Up @@ -515,11 +515,7 @@ public void findAllPublic_shouldReturnListOfAllPublicTopics() throws Exception {
.andExpect(jsonPath("$[0].createdBy").value(savedTopics.get(0).getCreatedBy()))
.andExpect(jsonPath("$[1].topicName").value(savedTopics.get(1).getTopicName()))
.andExpect(jsonPath("$[1].createdBy").value(savedTopics.get(1).getCreatedBy()))
.andExpect(jsonPath("$[*].createdAt").isNotEmpty())
.andExpect(jsonPath("$[0].isPublic").value(true))
.andExpect(jsonPath("$[1].isPublic").value(true))
.andExpect(jsonPath("$[*].tags").isArray())
.andExpect(jsonPath("$[*].topicSubscribers").isArray());
.andExpect(jsonPath("$[*].createdAt").isNotEmpty());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.chat.yourway.dto.request.TopicPrivateRequestDto;
import com.chat.yourway.dto.request.TopicRequestDto;
import com.chat.yourway.dto.response.TagResponseDto;
import com.chat.yourway.dto.response.TopicInfoResponseDto;
import com.chat.yourway.dto.response.TopicResponseDto;
import com.chat.yourway.exception.TopicAccessException;
import com.chat.yourway.exception.TopicNotFoundException;
Expand Down Expand Up @@ -351,7 +352,7 @@ public void findAllPublic_shouldReturnListOfTopicResponseDto() {
when(topicRepository.findAllByIsPublicIsTrue()).thenReturn(topics);

// When
List<TopicResponseDto> topicResponseDtos = topicService.findAllPublic();
List<TopicInfoResponseDto> topicResponseDtos = topicService.findAllPublic();

// Then
assertThat(topicResponseDtos).isNotNull();
Expand All @@ -369,7 +370,7 @@ public void findAllPublic_shouldReturnEmptyListOfTopicResponseDto() {
when(topicRepository.findAllByIsPublicIsTrue()).thenReturn(emptyList);

// When
List<TopicResponseDto> topicResponseDtos = topicService.findAllPublic();
List<TopicInfoResponseDto> topicResponseDtos = topicService.findAllPublic();

// Then
assertThat(topicResponseDtos).isNotNull();
Expand Down Expand Up @@ -486,4 +487,10 @@ private void assertTopicEquals(Topic topic, TopicResponseDto topicResponseDto) {
assertThat(topicResponseDto.getTopicSubscribers()).isNull();
}

private void assertTopicEquals(Topic topic, TopicInfoResponseDto topicResponseDto) {
assertThat(topicResponseDto.getTopicName()).isEqualTo(topic.getTopicName());
assertThat(topicResponseDto.getCreatedBy()).isEqualTo(topic.getCreatedBy());
assertThat(topicResponseDto.getCreatedAt()).isEqualTo(topic.getCreatedAt());
}

}

0 comments on commit 1abe15d

Please sign in to comment.