diff --git a/src/main/java/org/wikitolearn/wikirating/exception/RevisionNotFoundException.java b/src/main/java/org/wikitolearn/wikirating/exception/RevisionNotFoundException.java new file mode 100644 index 0000000..b66c773 --- /dev/null +++ b/src/main/java/org/wikitolearn/wikirating/exception/RevisionNotFoundException.java @@ -0,0 +1,21 @@ +/** + * + */ +package org.wikitolearn.wikirating.exception; + +/** + * @author aletundo + * + */ +public class RevisionNotFoundException extends RuntimeException { + + private static final long serialVersionUID = -5894333501939857908L; + + public RevisionNotFoundException(){ + super("Revision not found."); + } + + public RevisionNotFoundException(String message){ + super(message); + } +} diff --git a/src/main/java/org/wikitolearn/wikirating/exception/TemporaryVoteValidationException.java b/src/main/java/org/wikitolearn/wikirating/exception/TemporaryVoteValidationException.java new file mode 100644 index 0000000..ac3211d --- /dev/null +++ b/src/main/java/org/wikitolearn/wikirating/exception/TemporaryVoteValidationException.java @@ -0,0 +1,22 @@ +/** + * + */ +package org.wikitolearn.wikirating.exception; + +/** + * @author aletundo + * + */ +public class TemporaryVoteValidationException extends RuntimeException { + + private static final long serialVersionUID = 3942868822128902263L; + + public TemporaryVoteValidationException(){ + super(); + } + + public TemporaryVoteValidationException(String message){ + super("An error occurs during temporary votes validation. " + message); + } + +} diff --git a/src/main/java/org/wikitolearn/wikirating/exception/UpdateGraphException.java b/src/main/java/org/wikitolearn/wikirating/exception/UpdateGraphException.java new file mode 100644 index 0000000..e38e83f --- /dev/null +++ b/src/main/java/org/wikitolearn/wikirating/exception/UpdateGraphException.java @@ -0,0 +1,21 @@ +/** + * + */ +package org.wikitolearn.wikirating.exception; + +/** + * @author aletundo + * + */ +public class UpdateGraphException extends RuntimeException { + + private static final long serialVersionUID = -6040367633687463024L; + + public UpdateGraphException(){ + super("Update graph procedure fails"); + } + + public UpdateGraphException(String message){ + super(message); + } +} diff --git a/src/main/java/org/wikitolearn/wikirating/exception/UserNotFoundException.java b/src/main/java/org/wikitolearn/wikirating/exception/UserNotFoundException.java new file mode 100644 index 0000000..9b375f3 --- /dev/null +++ b/src/main/java/org/wikitolearn/wikirating/exception/UserNotFoundException.java @@ -0,0 +1,21 @@ +/** + * + */ +package org.wikitolearn.wikirating.exception; + +/** + * @author aletundo + * + */ +public class UserNotFoundException extends RuntimeException { + + private static final long serialVersionUID = 5153683580236807114L; + + public UserNotFoundException(){ + super("User not found."); + } + + public UserNotFoundException(String message){ + super(message); + } +} diff --git a/src/main/java/org/wikitolearn/wikirating/model/Revision.java b/src/main/java/org/wikitolearn/wikirating/model/Revision.java index 279bec8..9db807b 100644 --- a/src/main/java/org/wikitolearn/wikirating/model/Revision.java +++ b/src/main/java/org/wikitolearn/wikirating/model/Revision.java @@ -1,356 +1,364 @@ package org.wikitolearn.wikirating.model; import org.neo4j.ogm.annotation.GraphId; import org.neo4j.ogm.annotation.Index; import org.neo4j.ogm.annotation.NodeEntity; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.neo4j.ogm.annotation.Relationship; import org.neo4j.ogm.annotation.typeconversion.DateLong; import java.util.Date; import java.util.Set; /** * This class handles the data of the Revision of a page. * Created by valsdav on 14/03/17. */ @JsonIgnoreProperties(ignoreUnknown = true) @NodeEntity( label = "Revision" ) public class Revision { @GraphId private Long graphId; private int revid; private String lang; private int userid; private int parentid; @DateLong private Date timestamp; private long length; private double changeCoefficient; private double currentMeanVote; private double currentVotesReliability; private double currentNormalisesVotesReliability; private double totalMeanVote; private double totalVotesReliability; private double totalNormalisesVotesReliability; private boolean validated; @Index(unique = true, primary=true) private String langRevId; @Relationship(type="PREVIOUS_REVISION", direction = Relationship.OUTGOING) private Revision previousRevision; @Relationship(type="VOTE", direction = Relationship.INCOMING) private Set votes; @Relationship( type="AUTHOR", direction = Relationship.INCOMING) private User author; /** * */ public Revision() {} /** * @param revid * @param userid * @param parentid * @param length * @param lang * @param timestamp */ public Revision(int revid, String lang, int userid, int parentid, long length, Date timestamp) { this.revid = revid; this.langRevId = lang +"_"+revid; this.userid = userid; this.parentid = parentid; this.length = length; this.lang = lang; this.timestamp = timestamp; this.validated = false; } /** * @return the revid */ public int getRevid() { return revid; } /** * @param revid the revid to set */ public void setRevid(int revid) { this.revid = revid; } /** * @return the userid */ public int getUserid() { return userid; } /** * @param userid the userid to set */ public void setUserid(int userid) { this.userid = userid; } /** * @return the parentid */ public int getParentid() { return parentid; } /** * @param parentid the parentid to set */ public void setParentid(int parentid) { this.parentid = parentid; } /** * @return the length */ public long getLength() { return length; } /** * @param length the length to set */ public void setLength(long length) { this.length = length; } /** * @return the changeCoefficient */ public double getChangeCoefficient() { return changeCoefficient; } /** * @param changeCoefficient the changeCoefficient to set */ public void setChangeCoefficient(double changeCoefficient) { this.changeCoefficient = changeCoefficient; } /** * @return the currentMeanVote */ public double getCurrentMeanVote() { return currentMeanVote; } /** * @param currentMeanVote the currentMeanVote to set */ public void setCurrentMeanVote(double currentMeanVote) { this.currentMeanVote = currentMeanVote; } /** * @return the currentVotesReliability */ public double getCurrentVotesReliability() { return currentVotesReliability; } /** * @param currentVotesReliability the currentVotesReliability to set */ public void setCurrentVotesReliability(double currentVotesReliability) { this.currentVotesReliability = currentVotesReliability; } /** * @return the currentNormalisesVotesReliability */ public double getCurrentNormalisesVotesReliability() { return currentNormalisesVotesReliability; } /** * @param currentNormalisesVotesReliability the currentNormalisesVotesReliability to set */ public void setCurrentNormalisesVotesReliability(double currentNormalisesVotesReliability) { this.currentNormalisesVotesReliability = currentNormalisesVotesReliability; } /** * @return the totalMeanVote */ public double getTotalMeanVote() { return totalMeanVote; } /** * @param totalMeanVote the totalMeanVote to set */ public void setTotalMeanVote(double totalMeanVote) { this.totalMeanVote = totalMeanVote; } /** * @return the totalVotesReliability */ public double getTotalVotesReliability() { return totalVotesReliability; } /** * @param totalVotesReliability the totalVotesReliability to set */ public void setTotalVotesReliability(double totalVotesReliability) { this.totalVotesReliability = totalVotesReliability; } /** * @return the totalNormalisesVotesReliability */ public double getTotalNormalisesVotesReliability() { return totalNormalisesVotesReliability; } /** * @param totalNormalisesVotesReliability the totalNormalisesVotesReliability to set */ public void setTotalNormalisesVotesReliability(double totalNormalisesVotesReliability) { this.totalNormalisesVotesReliability = totalNormalisesVotesReliability; } /** * @return the validated */ public boolean isValidated() { return validated; } /** * @param validated the validated to set */ public void setValidated(boolean validated) { this.validated = validated; } /** * @return the lang */ public String getLang() { return lang; } /** * @param lang the lang to set */ public void setLang(String lang) { this.lang = lang; } /** * @return the langRevId */ public String getLangRevId() { return langRevId; } /** * @param langRevId the langRevId to set */ public void setLangRevId(String langRevId) { this.langRevId = langRevId; } /** * @return the graphId */ public Long getGraphId() { return graphId; } /** * @param graphId the graphId to set */ public void setGraphId(Long graphId) { this.graphId = graphId; } /** * @return the timestamp */ public Date getTimestamp() { return timestamp; } /** * @param timestamp the timestamp to set */ public void setTimestamp(Date timestamp) { this.timestamp = timestamp; } /** * @return the previousRevision */ public Revision getPreviousRevision() { return previousRevision; } /** * @param previousRevision the previousRevision to set */ public void setPreviousRevision(Revision previousRevision) { this.previousRevision = previousRevision; } /** * @return the votes */ public Set getVotes() { return votes; } /** * @param votes the votes to set */ public void setVotes(Set votes) { this.votes = votes; } /** * @return the author */ public User getAuthor() { return author; } /** * @param author the author to set */ public void setAuthor(User author) { this.author = author; } + + /** + * + * @param vote the vote to set + */ + public void addVote(Vote vote){ + this.votes.add(vote); + } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "Revision{" + "graphId=" + graphId + ", revid=" + revid + ", lang='" + lang + '\'' + ", userid=" + userid + ", parentid=" + parentid + ", timestamp=" + timestamp + ", length=" + length + ", changeCoefficient=" + changeCoefficient + ", validated=" + validated + ", langRevId='" + langRevId + '\'' + ", author=" + author + '}'; } } \ No newline at end of file diff --git a/src/main/java/org/wikitolearn/wikirating/model/Vote.java b/src/main/java/org/wikitolearn/wikirating/model/Vote.java index a9c0669..62a0a88 100644 --- a/src/main/java/org/wikitolearn/wikirating/model/Vote.java +++ b/src/main/java/org/wikitolearn/wikirating/model/Vote.java @@ -1,119 +1,121 @@ /** * */ package org.wikitolearn.wikirating.model; import org.neo4j.ogm.annotation.*; import org.neo4j.ogm.annotation.typeconversion.DateLong; import java.util.Date; /** * @author aletundo, valsdav * */ @RelationshipEntity( type = "VOTE") public class Vote { @GraphId private Long graphId; private double value; private double reliability; @DateLong private Date timestamp; @StartNode private User user; @EndNode private Revision revision; /** * */ public Vote() {} /** * @param value * @param reliability * @param timestamp */ public Vote(double value, double reliability, Date timestamp) { this.value = value; this.reliability = reliability; this.timestamp = timestamp; } /** * @return the value */ public double getValue() { return value; } /** * @param value the value to set */ public void setValue(double value) { this.value = value; } /** * @return the reliability */ public double getReliability() { return reliability; } /** * @param reliability the reliability to set */ public void setReliability(double reliability) { this.reliability = reliability; } /** * - * @return + * @return the user */ public User getUser() { return user; } /** * - * @param user + * @param user the user to set */ public void setUser(User user) { this.user = user; } /** * - * @return + * @return the revision */ public Revision getRevision() { return revision; } /** * - * @param revision + * @param revision the revision to set */ public void setRevision(Revision revision) { this.revision = revision; } /** * - * @return + * @return the timestamp */ public Date getTimestamp() { return timestamp; } /** * - * @param timestamp + * @param timestamp the timestamp to set */ public void setTimestamp(Date timestamp) { this.timestamp = timestamp; } + + /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "Vote [value=" + value + ", reliability=" + reliability + "]"; } } diff --git a/src/main/java/org/wikitolearn/wikirating/repository/TemporaryVoteRepository.java b/src/main/java/org/wikitolearn/wikirating/repository/TemporaryVoteRepository.java index 7bf9719..92b01e5 100644 --- a/src/main/java/org/wikitolearn/wikirating/repository/TemporaryVoteRepository.java +++ b/src/main/java/org/wikitolearn/wikirating/repository/TemporaryVoteRepository.java @@ -1,12 +1,25 @@ package org.wikitolearn.wikirating.repository; +import java.util.Date; +import java.util.List; + +import org.springframework.data.neo4j.annotation.Query; import org.springframework.data.neo4j.repository.GraphRepository; +import org.springframework.data.repository.query.Param; import org.wikitolearn.wikirating.model.TemporaryVote; /** * Created by valsdav on 24/03/17. */ public interface TemporaryVoteRepository extends GraphRepository { TemporaryVote findByLangRevId(String langRevId); + + /** + * Find temporary votes with added before the given timestamp + * @param timestamp + * @return the temporary votes list + */ + @Query("MATCH (n:TemporaryVote) WHERE n.timestamp < {timestamp} RETURN n") + List findByTimestamp(@Param("timestamp") Date timestamp); } diff --git a/src/main/java/org/wikitolearn/wikirating/service/RevisionService.java b/src/main/java/org/wikitolearn/wikirating/service/RevisionService.java index a011a92..ffac117 100644 --- a/src/main/java/org/wikitolearn/wikirating/service/RevisionService.java +++ b/src/main/java/org/wikitolearn/wikirating/service/RevisionService.java @@ -1,96 +1,122 @@ /** * */ package org.wikitolearn.wikirating.service; import java.util.Date; import java.util.List; import java.util.ListIterator; import java.util.Set; import java.util.concurrent.CompletableFuture; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; +import org.wikitolearn.wikirating.exception.RevisionNotFoundException; import org.wikitolearn.wikirating.model.Page; import org.wikitolearn.wikirating.model.Revision; import org.wikitolearn.wikirating.repository.PageRepository; import org.wikitolearn.wikirating.repository.RevisionRepository; import org.wikitolearn.wikirating.service.mediawiki.RevisionMediaWikiService; /** * * @author aletundo, valsdav * */ @Service public class RevisionService { private static final Logger LOG = LoggerFactory.getLogger(RevisionService.class); @Autowired private RevisionMediaWikiService revisionMediaWikiService; @Autowired private RevisionRepository revisionRepository; @Autowired private PageRepository pageRepository; /** * Initialize the revisions for the first time querying the MediaWiki API. * This method adds the revisions and sets the FIRST_REVISION, * LAST_REVISION and PREVIOUS_REVISION relationships. * @param lang the domain language * @param apiUrl the MediaWiki API url * @return CompletableFuture */ @Async public CompletableFuture initRevisions(String lang, String apiUrl) { Iterable pages = pageRepository.findAll(); pages.forEach(page -> { List revisions = revisionMediaWikiService.getAllRevisionByPageId(apiUrl, page.getPageid()); // Set the first and the last revisions for the current page page.setFistRevision(revisions.get(0)); page.setLastRevision(revisions.get(revisions.size() - 1)); ListIterator it = revisions.listIterator(); while(it.hasNext()){ Revision rev = it.next(); rev.setLangRevId(lang + "_" + rev.getRevid()); rev.setLang(lang); if (it.previousIndex() != 0){ rev.setPreviousRevision(revisions.get(it.previousIndex()-1)); } } // Saving all the revisions node and the page node revisionRepository.save(revisions); pageRepository.save(page); LOG.info("Inserted revisions for page {}", page.getLangPageId()); }); return CompletableFuture.completedFuture(true); } /** * Add a new Revision to the graph * @param revid * @param lang * @param userid * @param parentid * @param length * @param timestamp * @return */ public Revision addRevision(int revid, String lang, int userid, int parentid, int length, Date timestamp){ Revision rev = new Revision(revid, lang,userid, parentid, length, timestamp); revisionRepository.save(rev); return rev; } /** * Delete a revision given its langPageId * @param langPageId the langPageId of the revision */ public void deleteRevisionsOfPage(String langPageId){ Set revisions = revisionRepository.findAllRevisionOfPage(langPageId); revisionRepository.delete(revisions); //TODO throw exceptions } + + /** + * Get the requested revision + * @param langRevId + * @return + * @throws RevisionNotFoundException + */ + public Revision getRevision(String langRevId) throws RevisionNotFoundException{ + Revision revision = revisionRepository.findByLangRevId(langRevId); + if(revision == null){ + LOG.error("Revision {} not found", langRevId); + throw new RevisionNotFoundException(); + } + return revision; + } + + /** + * Update the given revision + * @param revision + * @return the updated revision + */ + public Revision updateRevision(Revision revision){ + revisionRepository.save(revision); + return revision; + } } diff --git a/src/main/java/org/wikitolearn/wikirating/service/UpdateService.java b/src/main/java/org/wikitolearn/wikirating/service/UpdateService.java index fd31c0a..96b6701 100644 --- a/src/main/java/org/wikitolearn/wikirating/service/UpdateService.java +++ b/src/main/java/org/wikitolearn/wikirating/service/UpdateService.java @@ -1,135 +1,172 @@ package org.wikitolearn.wikirating.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; +import org.wikitolearn.wikirating.exception.RevisionNotFoundException; +import org.wikitolearn.wikirating.exception.TemporaryVoteValidationException; +import org.wikitolearn.wikirating.exception.UpdateGraphException; +import org.wikitolearn.wikirating.exception.UserNotFoundException; import org.wikitolearn.wikirating.model.Process; import org.wikitolearn.wikirating.model.Revision; +import org.wikitolearn.wikirating.model.TemporaryVote; import org.wikitolearn.wikirating.model.UpdateInfo; import org.wikitolearn.wikirating.model.User; +import org.wikitolearn.wikirating.model.Vote; +import org.wikitolearn.wikirating.repository.TemporaryVoteRepository; import org.wikitolearn.wikirating.service.mediawiki.UpdateMediaWikiService; import org.wikitolearn.wikirating.util.enums.ProcessStatus; import org.wikitolearn.wikirating.util.enums.ProcessType; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * Created by valsdav on 29/03/17. */ @Service public class UpdateService { private static final Logger LOG = LoggerFactory.getLogger(UpdateService.class); @Autowired private UserService userService; @Autowired private PageService pageService; @Autowired private RevisionService revisionService; @Autowired private ProcessService processService; @Autowired private UpdateMediaWikiService updateMediaWikiService; + @Autowired + private TemporaryVoteRepository temporaryVoteRepository; @Value("#{'${mediawiki.langs}'.split(',')}") private List langs; @Value("${mediawiki.protocol}") private String protocol; @Value("${mediawiki.api.url}") private String apiUrl; @Value("${mediawiki.namespace}") private String namespace; /** * Entry point for the scheduled graph updated * @return true if the update succeed */ @Scheduled(cron = "${maintenance.update.cron}") public boolean updateGraph() { // Get start timestamp of the latest FETCH Process before opening a new process Date startTimestampLatestFetch = processService.getLastProcessStartDateByType(ProcessType.FETCH); // Create a new FETCH process Process currentFetchProcess = processService.createNewProcess(ProcessType.FETCH); LOG.info("Created new fetch process {}", currentFetchProcess.toString()); Date startTimestampCurrentFetch = currentFetchProcess.getStartOfProcess(); - updateUsers(startTimestampLatestFetch, startTimestampCurrentFetch); - updatePagesAndRevisions(startTimestampLatestFetch, startTimestampCurrentFetch); + try{ + updateUsers(startTimestampLatestFetch, startTimestampCurrentFetch); + updatePagesAndRevisions(startTimestampLatestFetch, startTimestampCurrentFetch); + validateTemporaryVotes(startTimestampCurrentFetch); + }catch(TemporaryVoteValidationException e){ + LOG.error("An error occurred during a scheduled graph update procedure"); + throw new UpdateGraphException(); + } // Save the result of the process, closing the current one processService.closeCurrentProcess(ProcessStatus.DONE); return true; } /** * Update the users querying the MediaWiki API * @param start * @param end */ private void updateUsers(Date start, Date end) { String url = protocol + langs.get(0) + "." + apiUrl; List usersUpdateInfo = updateMediaWikiService.getNewUsers(url, start, end); List newUsers = new ArrayList<>(); // Build a list with new users to be added to the graph for(UpdateInfo updateInfo : usersUpdateInfo){ User user = new User(); user.setUserId(updateInfo.getUserid()); user.setUsername(updateInfo.getUser()); newUsers.add(user); } userService.addUsers(newUsers); } /** * Update the pages and the revisions querying the MediaWiki API * @param start * @param end */ private void updatePagesAndRevisions(Date start, Date end) { // First of all, get the RecentChangeEvents from MediaWiki API for (String lang : langs) { String url = protocol + lang + "." + apiUrl; // Fetching pages updates List updates = updateMediaWikiService.getPagesUpdateInfo(url, namespace, start, end); for(UpdateInfo update : updates){ switch (update.getType()) { case NEW: // Create the new revision Revision newRev = revisionService.addRevision(update.getRevid(), lang, update.getUserid(), update.getOld_revid(), update.getNewlen(), update.getTimestamp()); // Then create a new Page and link it with the revision pageService.addPage(update.getPageid(), update.getTitle(), lang, newRev); userService.setAuthorship(newRev); break; case EDIT: // Create a new revision Revision updateRev = revisionService.addRevision(update.getRevid(), lang, update.getUserid(), update.getOld_revid(), update.getNewlen(), update.getTimestamp()); // Then add it to the page pageService.addRevisionToPage(lang + "_" + update.getPageid(), updateRev); userService.setAuthorship(updateRev); break; case MOVE: // Move the page to the new title pageService.movePage(update.getTitle(), update.getNewTitle(), lang); break; case DELETE: // Delete the page and all its revisions pageService.deletePage(update.getTitle(), lang); break; default: break; } } } } + /** + * Validate temporary votes added before the given timestamp + * @param timestamp the timestamp used for comparison + */ + private void validateTemporaryVotes(Date timestamp) throws TemporaryVoteValidationException{ + List temporaryVotes = temporaryVoteRepository.findByTimestamp(timestamp); + for(TemporaryVote temporaryVote: temporaryVotes){ + try{ + User user = userService.getUser(temporaryVote.getUserid()); + Revision revision = revisionService.getRevision(temporaryVote.getLangRevId()); + Vote vote = new Vote(temporaryVote.getValue(), temporaryVote.getReliability(), temporaryVote.getTimestamp()); + vote.setRevision(revision); + vote.setUser(user); + revision.addVote(vote); + revisionService.updateRevision(revision); + }catch(UserNotFoundException | RevisionNotFoundException e){ + LOG.error("An error occurred during temporary vote validation: {}", temporaryVote); + throw new TemporaryVoteValidationException(e.getMessage()); + } + } + } + } diff --git a/src/main/java/org/wikitolearn/wikirating/service/UserService.java b/src/main/java/org/wikitolearn/wikirating/service/UserService.java index 2c6c33b..2a696cc 100644 --- a/src/main/java/org/wikitolearn/wikirating/service/UserService.java +++ b/src/main/java/org/wikitolearn/wikirating/service/UserService.java @@ -1,104 +1,120 @@ /** * */ package org.wikitolearn.wikirating.service; import java.util.List; import java.util.Set; import java.util.concurrent.CompletableFuture; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; +import org.wikitolearn.wikirating.exception.UserNotFoundException; import org.wikitolearn.wikirating.model.Revision; import org.wikitolearn.wikirating.model.User; import org.wikitolearn.wikirating.repository.RevisionRepository; import org.wikitolearn.wikirating.repository.UserRepository; import org.wikitolearn.wikirating.service.mediawiki.UserMediaWikiService; /** * * @author aletundo, valsdav * */ @Service public class UserService { private static final Logger LOG = LoggerFactory.getLogger(UserService.class); @Autowired private UserMediaWikiService userMediaWikiService; @Autowired private UserRepository userRepository; @Autowired private RevisionRepository revisionRepository; /** * Initialize the graph for the first time querying the MediaWiki API * to get the all the users and then insert them. * @param apiUrl the MediaWiki API url * @return CompletableFuture */ @Async public CompletableFuture initUsers(String apiUrl){ List users = userMediaWikiService.getAll(apiUrl); addUsers(users); return CompletableFuture.completedFuture(true); } /** * Initialize relationships between users and their created revisions for the first time * @return CompletableFuture */ @Async public CompletableFuture initAuthorship(){ Iterable users = userRepository.findAll(); for(User user : users){ Set revisions = revisionRepository.findByUserid(user.getUserid()); user.setRevisionsAuthored(revisions); userRepository.save(user); LOG.info("Set revisions authorship for user {}", user.getUserid()); } // Get revisions with userid = 0 (anonymous authors) Set anonRevisions = revisionRepository.findByUserid(0); User anonymousUser = new User("AnonymousUser", 0, 0.0, 0.0, 0.0); anonymousUser.setRevisionsAuthored(anonRevisions); userRepository.save(anonymousUser); LOG.info("Set revisions authorship for anonymous revisions"); return CompletableFuture.completedFuture(true); } /** * Insert users into the graph * @param users the list of users to be inserted * @return the list of inserted users */ public List addUsers(List users){ userRepository.save(users); LOG.info("Inserted users: {}", users); return users; //TODO handle exceptions } /** * Set the authorship for a revision * @param revision the revision */ public void setAuthorship(Revision revision){ User user = userRepository.findByUserId(revision.getUserid()); user.setRevisionAuthored(revision); } /** * Set the authorship for a list of revisions * @param revisions the list of revisions */ public void setAuthorship(List revisions){ for(Revision revision : revisions){ setAuthorship(revision); } } + + /** + * Get the requested user. + * @param userId the user id + * @return the requested user if is found + * @throws UserNotFoundException + */ + public User getUser(int userId) throws UserNotFoundException{ + User user = userRepository.findByUserId(userId); + if(user == null){ + LOG.error("User {} not found", userId); + throw new UserNotFoundException(); + } + return user; + } }