Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
@Service
public class AggregateUserReviews {

UserReviewAggregation userReviewAggregation = new UserReviewAggregation();
public AggregateUserReviews() {}

public UserReviewAggregation execute(List<UserReview> userReviews) {
return UserReviewAggregation.aggregate(userReviews);
return userReviewAggregation.aggregate(userReviews);
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.pakland.mdas.githubstats;
package io.pakland.mdas.githubstats.application;

import io.pakland.mdas.githubstats.application.exceptions.HttpException;
import io.pakland.mdas.githubstats.domain.User;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import io.pakland.mdas.githubstats.application.exceptions.OrganizationNotFound;
import io.pakland.mdas.githubstats.domain.Organization;
import io.pakland.mdas.githubstats.domain.repository.OrganizationRepository;
import org.aspectj.weaver.ast.Or;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -20,13 +19,11 @@ public GetOrganizationFromId(OrganizationRepository organizationRepository) {

// For tests sake, we return boolean to know if the code works properly
@Transactional(readOnly = true)
public boolean execute(Integer id) throws OrganizationNotFound {
public Organization execute(Integer id) throws OrganizationNotFound {
Optional<Organization> org = organizationRepository.findById(id);
if (org.isPresent()) {
return true;
}
else {
if(org.isEmpty()) {
throw new OrganizationNotFound(id);
}
return org.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.pakland.mdas.githubstats.application;

import io.pakland.mdas.githubstats.application.exceptions.OrganizationNotFound;
import io.pakland.mdas.githubstats.application.exceptions.UserLoginNotFound;
import io.pakland.mdas.githubstats.domain.User;
import io.pakland.mdas.githubstats.domain.repository.UserRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

@Service
public class GetUserByLogin {

private final UserRepository userRepository;

public GetUserByLogin(UserRepository userRepository) {
this.userRepository = userRepository;
}

@Transactional(readOnly = true)
public User execute(String login) throws UserLoginNotFound {
Optional<User> user = userRepository.findUserByLogin(login);
if(user.isEmpty()) {
throw new UserLoginNotFound(login);
}
return user.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.pakland.mdas.githubstats.application;

import io.pakland.mdas.githubstats.domain.*;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class OrchestrateAggregators {

// TODO: this class needs a better design

private final AggregateCommits aggregateCommits;
private CommitAggregation commitAggregation;

private final AggregateUserReviews aggregateUserReviews;
private UserReviewAggregation userReviewAggregation;

// private final AggregatePullRequests aggregatePullRequests;
// private PullRequestAggregation pullRequestAggregation;

public OrchestrateAggregators() {
this.aggregateCommits = new AggregateCommits();
this.aggregateUserReviews = new AggregateUserReviews();
// this.aggregatePullRequests = new AggregatePullRequests();
}

public void execute(User user, List<PullRequest> pullRequests) {
pullRequests.forEach(pull -> {
List<Commit> commits = pull.getCommitsByUser(user);

CommitAggregation commitAggregation = new AggregateCommits().execute(commits);
int linesAdded = commitAggregation.getLinesAdded();
int linesRemoved = commitAggregation.getLinesRemoved();
// aggregate additions, deletions

List<UserReview> userReviews = pull.getReviewsFromUser(user);

long numReviewsInsideTeam = userReviews
.stream()
.filter(review -> review.isReviewFromTeam(pull.getRepository().getTeam()))
.count();
long numReviewsOutsideTeam = userReviews.size() - numReviewsInsideTeam;
// aggregate numReviewsInsideTeam, numReviewsOutsideTeam
});
}

public CommitAggregation getCommitAggregation() {
return commitAggregation;
}

public UserReviewAggregation getUserReviewAggregation() {
return userReviewAggregation;
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.pakland.mdas.githubstats.application.exceptions;

public class UserLoginNotFound extends Exception {
public UserLoginNotFound(String login) {
super("UserLogin: " + login + " not found");
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.pakland.mdas.githubstats.application;
package io.pakland.mdas.githubstats.application.unnused;

import io.pakland.mdas.githubstats.application.exceptions.TeamNotFound;
import io.pakland.mdas.githubstats.domain.Organization;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.pakland.mdas.githubstats.application;
package io.pakland.mdas.githubstats.application.unnused;

import io.pakland.mdas.githubstats.domain.Repository;
import io.pakland.mdas.githubstats.domain.Team;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.pakland.mdas.githubstats.application;
package io.pakland.mdas.githubstats.application.unnused;

import io.pakland.mdas.githubstats.domain.Organization;
import io.pakland.mdas.githubstats.domain.Team;
Expand Down
Empty file.
45 changes: 28 additions & 17 deletions src/main/java/io/pakland/mdas/githubstats/domain/PullRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,39 @@ public class PullRequest {
@JsonProperty("state")
private PullRequestState state;

@Column(name = "additions")
@JsonProperty("additions")
private Integer additions;
@ManyToOne(fetch = FetchType.LAZY)
@ToString.Exclude
private Repository repository;

@Column(name = "deletions")
@JsonProperty("deletions")
private Integer deletions;
@ManyToOne(fetch = FetchType.LAZY)
private User user;

@OneToMany(
mappedBy = "pullRequest",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<UserReview> userReviews = new ArrayList<>();
public List<Commit> getCommitsByUser(User user) {
return commits
.stream()
.filter(commit -> commit.getUser().equals(user))
.toList();
}

public boolean isClosed() {
return state.equals(PullRequestState.CLOSED);
}

public boolean isCreatedByUser(User user) {
return this.user.equals(user);
}

public List<UserReview> getReviewsFromUser(User user) {
return userReviews
.stream()
.filter(x -> x.getUser().equals(user))
.toList();
}

@OneToMany(
mappedBy = "pullRequest",
cascade = CascadeType.ALL,
mappedBy = "pullRequest",
orphanRemoval = true
)
private List<Commit> commits = new ArrayList<>();

@ManyToOne(fetch = FetchType.LAZY)
private Repository repository;
private List<UserReview> userReviews = new ArrayList<>();
}
7 changes: 7 additions & 0 deletions src/main/java/io/pakland/mdas/githubstats/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,11 @@ public class User {
orphanRemoval = true
)
private List<Commit> commits = new ArrayList<>();

@OneToMany(
mappedBy = "user",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PullRequest> pullRequests = new ArrayList<>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,8 @@ public int hashCode() {
return getClass().hashCode();
}

public boolean isReviewFromTeam(Team team) {
return pullRequest.getRepository().getTeam().equals(team);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@

public class UserReviewAggregation {

private int commentLengthSum;
private int commentLengthSum = 0;
private int commentCount = 0;

public static UserReviewAggregation aggregate(List<UserReview> userReviews) {
UserReviewAggregation userReviewAggregation = new UserReviewAggregation();
userReviewAggregation.commentLengthSum = userReviews.stream().mapToInt(UserReview::sumCommentLength).sum();
return userReviewAggregation;
public UserReviewAggregation aggregate(List<UserReview> userReviews) {
commentCount = userReviews.size();
commentLengthSum = userReviews.stream().mapToInt(UserReview::sumCommentLength).sum();
return this;
}

public int getCommentLengthSum() {
return commentLengthSum;
public float getCommentLengthAvg() {
if(commentCount == 0) return 0;
return (float) commentLengthSum / commentCount;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

/**
* Add jdoc about the rep
*/

@Repository
public interface UserRepository extends JpaRepository<User,Integer> {

public Optional<User> findUserByLogin(String login);
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.pakland.mdas.githubstats.infrastructure.controller;

import io.pakland.mdas.githubstats.application.FetchAvailableOrganizations;
import io.pakland.mdas.githubstats.application.GetUserByLogin;
import io.pakland.mdas.githubstats.application.OrchestrateAggregators;
import io.pakland.mdas.githubstats.application.exceptions.HttpException;
import io.pakland.mdas.githubstats.application.exceptions.UserLoginNotFound;
import io.pakland.mdas.githubstats.domain.*;
import io.pakland.mdas.githubstats.domain.repository.OrganizationExternalRepository;
import io.pakland.mdas.githubstats.infrastructure.github.repository.OrganizationGitHubRepository;
import io.pakland.mdas.githubstats.infrastructure.github.repository.WebClientConfiguration;
import io.pakland.mdas.githubstats.infrastructure.shell.model.UserOptionRequest;

import java.util.List;

public class UserControllerFromDb {

private final UserOptionRequest userOptionRequest;

private final GetUserByLogin getUserByLogin;

private final OrganizationExternalRepository organizationExternalRepository;

public UserControllerFromDb(UserOptionRequest userOptionRequest, GetUserByLogin getUserByLogin) {
this.userOptionRequest = userOptionRequest;
this.getUserByLogin = getUserByLogin;
WebClientConfiguration webClientConfiguration = new WebClientConfiguration(
"https://api.github.com", userOptionRequest.getApiKey());
this.organizationExternalRepository = new OrganizationGitHubRepository(
webClientConfiguration);
}

public void execute() throws UserLoginNotFound {
List<Organization> orgs;

try {
orgs = new FetchAvailableOrganizations(this.organizationExternalRepository).execute();
} catch (HttpException e) {
throw new RuntimeException(e);
}

User user = getUserByLogin.execute(userOptionRequest.getUserName());

List<PullRequest> pullRequests = orgs.stream()
.flatMap(org -> org.getTeams().stream())
.flatMap(team -> team.getRepositories().stream())
.flatMap(repo -> repo.getPullRequests().stream())
.filter(pull -> pull.isClosed() && pull.isCreatedByUser(user))
.toList();

// TODO: we could have a chain of responsibility instead of a use case orchestrator
OrchestrateAggregators orchestrator = new OrchestrateAggregators();
orchestrator.execute(user, pullRequests);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.pakland.mdas.githubstats.infrastructure.shell.controller;
package io.pakland.mdas.githubstats.infrastructure.controller;

import io.pakland.mdas.githubstats.FetchUsersFromTeam;
import io.pakland.mdas.githubstats.application.*;
import io.pakland.mdas.githubstats.application.exceptions.HttpException;
import io.pakland.mdas.githubstats.domain.*;
Expand All @@ -16,9 +15,9 @@

@Component
@NoArgsConstructor
public class UserOptionController {
public class UserControllerFromGithub {

Logger logger = LoggerFactory.getLogger(UserOptionController.class);
Logger logger = LoggerFactory.getLogger(UserControllerFromGithub.class);
private UserOptionRequest userOptionRequest;
private OrganizationExternalRepository organizationExternalRepository;
private TeamExternalRepository teamExternalRepository;
Expand All @@ -27,7 +26,7 @@ public class UserOptionController {
private PullRequestExternalRepository pullRequestExternalRepository;
private CommitExternalRepository commitExternalRepository;

public UserOptionController(UserOptionRequest userOptionRequest) {
public UserControllerFromGithub(UserOptionRequest userOptionRequest) {
this.userOptionRequest = userOptionRequest;
WebClientConfiguration webClientConfiguration = new WebClientConfiguration(
"https://api.github.com", userOptionRequest.getApiKey());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.pakland.mdas.githubstats.infrastructure.shell.components;

import io.pakland.mdas.githubstats.infrastructure.shell.controller.UserOptionController;
import io.pakland.mdas.githubstats.infrastructure.controller.UserControllerFromGithub;
import io.pakland.mdas.githubstats.infrastructure.shell.model.UserOptionRequest;
import io.pakland.mdas.githubstats.infrastructure.shell.validation.DateValidator;
import io.pakland.mdas.githubstats.infrastructure.shell.validation.UserNameValidator;
Expand Down Expand Up @@ -43,8 +43,8 @@ private boolean user(
throw new RuntimeException(e);
}

UserOptionController userOptionController = new UserOptionController(this.userOptionRequest);
userOptionController.execute();
UserControllerFromGithub userControllerFromGithub = new UserControllerFromGithub(this.userOptionRequest);
userControllerFromGithub.execute();
// ... Perform request ...

return true;
Expand Down
Loading