VoteService.java
/*
* Copyright © 2025 The CTAN Team and individual authors
*
* This file is distributed under the 3-clause BSD license.
* See file LICENSE for details.
*/
package org.ctan.site.services.catalogue;
import java.util.List;
import java.util.stream.Collectors;
import org.ctan.site.domain.account.User;
import org.ctan.site.domain.account.User.PrintableUser;
import org.ctan.site.domain.catalogue.Pkg;
import org.ctan.site.domain.site.Vote;
import org.ctan.site.stores.VoteStore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;
/**
* This service deals with votes.
*
* @author <a href="mailto:gene@ctan.org">Gerd Neugebauer</a>
*/
public final class VoteService {
/**
* The class <code>VoteSummaryTo</code> contains the transport object for
* the vote resource in the summary list.
*/
@Getter
@Builder
@AllArgsConstructor
@JsonInclude(Include.NON_NULL)
@SuppressFBWarnings(value = {"EI_EXPOSE_REP", "EI_EXPOSE_REP2"})
public static class VoteSummaryTo {
private int[] ratings;
private List<VoteTo> list;
private int count;
}
/**
* The class <code>VoteTo</code> contains the transport object for the vote.
*/
@Getter
@Builder
@AllArgsConstructor
@JsonInclude(Include.NON_NULL)
@SuppressFBWarnings(value = "EI_EXPOSE_REP")
public static class VoteTo {
private String pkg;
private int rating;
private int expertise;
private String comment;
private String account;
private String user;
private String date;
}
/**
* The field <code>voteStore</code> contains the vote store.
*/
private VoteStore voteStore;
/**
* This is the constructor for <code>VoteService</code>.
*
* @param voteStore the vote store
*/
@SuppressFBWarnings(value = "EI_EXPOSE_REP2")
public VoteService(@NonNull VoteStore voteStore) {
this.voteStore = voteStore;
}
/**
* The method <code>find</code> provides means to retrieve the votes for a
* user.
*
* @param pkg the user
* @param page the current page to retrieve
* @param size the page size
* @return the list and rating summary
*/
public VoteSummaryTo find(Pkg pkg, long page, long size) {
List<Vote> votes = voteStore.findByPkg(pkg);
return prepareVotes(votes, page, size);
}
/**
* The method <code>find</code> provides means to retrieve the votes for a
* package.
*
* @param user the package
* @param page the current page to retrieve
* @param size the page size
* @return the list and rating summary
*/
public VoteSummaryTo find(User user, long page, long size) {
List<Vote> votes = voteStore.findByAccount(user);
return prepareVotes(votes, page, size);
}
/**
* The method <code>prepareVotes</code> provides means to prepare a list of
* votes.
*
* @param votes the list of all votes
* @param page the current page
* @param size the page size
*
* @return the vote summary
*/
private VoteSummaryTo prepareVotes(List<Vote> votes, long page, long size) {
int length = votes.size();
int[] ratings = new int[]{0, 0, 0, 0, 0, 0};
for (var it : votes) {
ratings[it.getRating()]++;
}
List<VoteTo> list = votes
.stream()
.sorted(
(a, b) -> a.getLastModified().compareTo(b.getLastModified()))
.skip(page * size)
.limit(size)
.map((Vote a) -> {
PrintableUser printable = a.getUser().getPrintable();
return VoteTo.builder()
.account(printable.getAccount())
.comment(a.getComment())
.date(a.getDate())
.expertise(a.getExpertise())
.pkg(a.getPkg().getKey())
.rating(a.getRating())
.user(printable.getName())
.build();
})
.collect(Collectors.toList());
return VoteSummaryTo.builder()
.ratings(ratings)
.list(list)
.count(length)
.build();
}
}