diff --git a/build.gradle b/build.gradle index 1d713ee..a94560f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,3 @@ -/* - * Copyright (C) 2021 Anton Romanov - All Rights Reserved - * You may use, distribute and modify this code, please write to: romanov73@gmail.com. - */ - buildscript { ext { versionSpringBoot = '2.3.9.RELEASE' @@ -53,6 +48,9 @@ dependencies { implementation group: 'org.springframework.boot', name: 'spring-boot-starter-jetty' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf' implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa' + implementation group: 'org.springframework.boot', name: 'spring-boot-starter-webflux' + implementation group: 'org.json', name: 'json', version: '20220320' + implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect' implementation group: 'com.fasterxml.jackson.module', name: 'jackson-module-afterburner' implementation group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-hibernate5' @@ -61,6 +59,7 @@ dependencies { implementation group: 'commons-io', name: 'commons-io', version: '2.6' implementation group: 'net.sourceforge.htmlunit', name: 'htmlunit', version: '2.35.0' implementation group: 'com.github.javaparser', name: 'javaparser-core', version: '3.20.2' + implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0' implementation group: 'io.springfox', name: 'springfox-boot-starter', version: '3.0.0' diff --git a/src/main/java/ru/ulstu/extractor/GitExtractorApplication.java b/src/main/java/ru/ulstu/extractor/GitExtractorApplication.java index 425424f..f9a272d 100644 --- a/src/main/java/ru/ulstu/extractor/GitExtractorApplication.java +++ b/src/main/java/ru/ulstu/extractor/GitExtractorApplication.java @@ -2,8 +2,10 @@ package ru.ulstu.extractor; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication +@EnableScheduling public class GitExtractorApplication { public static void main(String[] args) { SpringApplication.run(GitExtractorApplication.class, args); diff --git a/src/main/java/ru/ulstu/extractor/controller/BranchController.java b/src/main/java/ru/ulstu/extractor/branch/controller/BranchController.java similarity index 60% rename from src/main/java/ru/ulstu/extractor/controller/BranchController.java rename to src/main/java/ru/ulstu/extractor/branch/controller/BranchController.java index 5e0f845..22432bd 100644 --- a/src/main/java/ru/ulstu/extractor/controller/BranchController.java +++ b/src/main/java/ru/ulstu/extractor/branch/controller/BranchController.java @@ -3,14 +3,14 @@ * You may use, distribute and modify this code, please write to: romanov73@gmail.com. */ -package ru.ulstu.extractor.controller; +package ru.ulstu.extractor.branch.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; -import ru.ulstu.extractor.repository.BranchRepository; -import ru.ulstu.extractor.repository.RepositoryRepository; +import ru.ulstu.extractor.branch.repository.BranchRepository; +import ru.ulstu.extractor.gitrepository.GitRepositoryRepository; import springfox.documentation.annotations.ApiIgnore; import static ru.ulstu.extractor.controller.Route.DELETE_BRANCH; @@ -19,11 +19,11 @@ import static ru.ulstu.extractor.controller.Route.LIST_REPOSITORY_BRANCHES; @Controller @ApiIgnore public class BranchController { - private final RepositoryRepository repositoryRepository; + private final GitRepositoryRepository gitRepositoryRepository; private final BranchRepository branchRepository; - public BranchController(RepositoryRepository repositoryRepository, BranchRepository branchRepository) { - this.repositoryRepository = repositoryRepository; + public BranchController(GitRepositoryRepository gitRepositoryRepository, BranchRepository branchRepository) { + this.gitRepositoryRepository = gitRepositoryRepository; this.branchRepository = branchRepository; } @@ -31,8 +31,8 @@ public class BranchController { public String indexBranch( Model model, @RequestParam int repositoryId) { - model.addAttribute("branches", branchRepository.findByRepositoryId(repositoryId)); - model.addAttribute("repository", repositoryRepository.findById(repositoryId).get()); + model.addAttribute("branches", branchRepository.findByGitRepositoryId(repositoryId)); + model.addAttribute("repository", gitRepositoryRepository.findById(repositoryId).get()); return LIST_REPOSITORY_BRANCHES; } @@ -41,8 +41,8 @@ public class BranchController { @RequestParam int repositoryId, @RequestParam Integer id) { branchRepository.deleteById(id); - model.addAttribute("branches", branchRepository.findByRepositoryId(repositoryId)); - model.addAttribute("repository", repositoryRepository.findById(repositoryId).get()); + model.addAttribute("branches", branchRepository.findByGitRepositoryId(repositoryId)); + model.addAttribute("repository", gitRepositoryRepository.findById(repositoryId).get()); return LIST_REPOSITORY_BRANCHES; } } diff --git a/src/main/java/ru/ulstu/extractor/model/Branch.java b/src/main/java/ru/ulstu/extractor/branch/model/Branch.java similarity index 70% rename from src/main/java/ru/ulstu/extractor/model/Branch.java rename to src/main/java/ru/ulstu/extractor/branch/model/Branch.java index 30c30dd..6837771 100644 --- a/src/main/java/ru/ulstu/extractor/model/Branch.java +++ b/src/main/java/ru/ulstu/extractor/branch/model/Branch.java @@ -3,10 +3,13 @@ * You may use, distribute and modify this code, please write to: romanov73@gmail.com. */ -package ru.ulstu.extractor.model; +package ru.ulstu.extractor.branch.model; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; +import ru.ulstu.extractor.gitrepository.model.GitRepository; +import ru.ulstu.extractor.model.BaseEntity; +import ru.ulstu.extractor.model.Commit; import javax.persistence.CascadeType; import javax.persistence.Entity; @@ -22,7 +25,7 @@ public class Branch extends BaseEntity { private String name; @ManyToOne - private Repository repository; + private GitRepository gitRepository; @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "branch_id") @@ -36,8 +39,8 @@ public class Branch extends BaseEntity { this.name = name; } - public Branch(Repository repository, String branchName) { - this.repository = repository; + public Branch(GitRepository gitRepository, String branchName) { + this.gitRepository = gitRepository; this.name = branchName; } @@ -49,12 +52,12 @@ public class Branch extends BaseEntity { this.name = name; } - public Repository getRepository() { - return repository; + public GitRepository getGitRepository() { + return gitRepository; } - public void setRepository(Repository repository) { - this.repository = repository; + public void setGitRepository(GitRepository gitRepository) { + this.gitRepository = gitRepository; } public List getCommits() { diff --git a/src/main/java/ru/ulstu/extractor/branch/repository/BranchRepository.java b/src/main/java/ru/ulstu/extractor/branch/repository/BranchRepository.java new file mode 100644 index 0000000..af14f53 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/branch/repository/BranchRepository.java @@ -0,0 +1,21 @@ +package ru.ulstu.extractor.branch.repository; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import ru.ulstu.extractor.branch.model.Branch; +import ru.ulstu.extractor.gitrepository.model.GitRepository; + +import java.util.List; + +public interface BranchRepository extends JpaRepository { + Branch findByGitRepositoryAndName(GitRepository gitRepository, String name); + + @Query("select count(c) from Commit c LEFT JOIN c.branch b LEFT JOIN GitRepository r where r.id = ?1 AND b.name = ?2") + int getCommitsCount(Integer repositoryId, String name); + + List findByGitRepositoryId(Integer repositoryId); + + Page findByGitRepository(GitRepository gitRepository, Pageable pageable); +} diff --git a/src/main/java/ru/ulstu/extractor/service/BranchService.java b/src/main/java/ru/ulstu/extractor/branch/service/BranchService.java similarity index 77% rename from src/main/java/ru/ulstu/extractor/service/BranchService.java rename to src/main/java/ru/ulstu/extractor/branch/service/BranchService.java index 8ce9353..3d6fd28 100644 --- a/src/main/java/ru/ulstu/extractor/service/BranchService.java +++ b/src/main/java/ru/ulstu/extractor/branch/service/BranchService.java @@ -3,16 +3,18 @@ * You may use, distribute and modify this code, please write to: romanov73@gmail.com. */ -package ru.ulstu.extractor.service; +package ru.ulstu.extractor.branch.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.ulstu.extractor.branch.model.Branch; +import ru.ulstu.extractor.branch.repository.BranchRepository; +import ru.ulstu.extractor.commit.service.CommitService; +import ru.ulstu.extractor.gitrepository.model.GitRepository; import ru.ulstu.extractor.model.BaseEntity; -import ru.ulstu.extractor.model.Branch; import ru.ulstu.extractor.model.Commit; -import ru.ulstu.extractor.model.Repository; -import ru.ulstu.extractor.repository.BranchRepository; import java.util.List; import java.util.stream.Collectors; @@ -29,6 +31,7 @@ public class BranchService { this.commitService = commitService; } + @Transactional public Branch save(Branch branch, List commits) { LOG.debug("Start save {} branch with {} commits ", branch.getName(), commits.size()); List commitsToRemoveIds = branch.getCommits().stream().map(BaseEntity::getId).collect(Collectors.toList()); @@ -48,8 +51,8 @@ public class BranchService { return branch; } - public Branch findByRepositoryAndName(Repository repository, String branchName) { - return branchRepository.findByRepositoryAndName(repository, branchName); + public Branch findByRepositoryAndName(GitRepository gitRepository, String branchName) { + return branchRepository.findByGitRepositoryAndName(gitRepository, branchName); } public List findAll() { diff --git a/src/main/java/ru/ulstu/extractor/model/Commit.java b/src/main/java/ru/ulstu/extractor/commit/model/Commit.java similarity index 98% rename from src/main/java/ru/ulstu/extractor/model/Commit.java rename to src/main/java/ru/ulstu/extractor/commit/model/Commit.java index daf9087..699ff94 100644 --- a/src/main/java/ru/ulstu/extractor/model/Commit.java +++ b/src/main/java/ru/ulstu/extractor/commit/model/Commit.java @@ -7,6 +7,7 @@ package ru.ulstu.extractor.model; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; +import ru.ulstu.extractor.branch.model.Branch; import javax.persistence.CascadeType; import javax.persistence.Entity; diff --git a/src/main/java/ru/ulstu/extractor/model/CommitAuthorStatistic.java b/src/main/java/ru/ulstu/extractor/commit/model/CommitAuthorStatistic.java similarity index 90% rename from src/main/java/ru/ulstu/extractor/model/CommitAuthorStatistic.java rename to src/main/java/ru/ulstu/extractor/commit/model/CommitAuthorStatistic.java index 5587cb2..c3d98f4 100644 --- a/src/main/java/ru/ulstu/extractor/model/CommitAuthorStatistic.java +++ b/src/main/java/ru/ulstu/extractor/commit/model/CommitAuthorStatistic.java @@ -1,4 +1,4 @@ -package ru.ulstu.extractor.model; +package ru.ulstu.extractor.commit.model; public class CommitAuthorStatistic { private String author; diff --git a/src/main/java/ru/ulstu/extractor/model/CommitEntityStatistic.java b/src/main/java/ru/ulstu/extractor/commit/model/CommitEntityStatistic.java similarity index 90% rename from src/main/java/ru/ulstu/extractor/model/CommitEntityStatistic.java rename to src/main/java/ru/ulstu/extractor/commit/model/CommitEntityStatistic.java index 61dc428..2a1a677 100644 --- a/src/main/java/ru/ulstu/extractor/model/CommitEntityStatistic.java +++ b/src/main/java/ru/ulstu/extractor/commit/model/CommitEntityStatistic.java @@ -1,4 +1,4 @@ -package ru.ulstu.extractor.model; +package ru.ulstu.extractor.commit.model; public class CommitEntityStatistic { private Boolean entity; diff --git a/src/main/java/ru/ulstu/extractor/model/CommitTimeStatistic.java b/src/main/java/ru/ulstu/extractor/commit/model/CommitTimeStatistic.java similarity index 92% rename from src/main/java/ru/ulstu/extractor/model/CommitTimeStatistic.java rename to src/main/java/ru/ulstu/extractor/commit/model/CommitTimeStatistic.java index a9ca75c..4cdb369 100644 --- a/src/main/java/ru/ulstu/extractor/model/CommitTimeStatistic.java +++ b/src/main/java/ru/ulstu/extractor/commit/model/CommitTimeStatistic.java @@ -1,4 +1,4 @@ -package ru.ulstu.extractor.model; +package ru.ulstu.extractor.commit.model; public class CommitTimeStatistic { private final static String DATE_TEMPLATE = "%s.%s"; diff --git a/src/main/java/ru/ulstu/extractor/model/CommitUrlStatistic.java b/src/main/java/ru/ulstu/extractor/commit/model/CommitUrlStatistic.java similarity index 89% rename from src/main/java/ru/ulstu/extractor/model/CommitUrlStatistic.java rename to src/main/java/ru/ulstu/extractor/commit/model/CommitUrlStatistic.java index 3eb4b37..c075074 100644 --- a/src/main/java/ru/ulstu/extractor/model/CommitUrlStatistic.java +++ b/src/main/java/ru/ulstu/extractor/commit/model/CommitUrlStatistic.java @@ -1,4 +1,4 @@ -package ru.ulstu.extractor.model; +package ru.ulstu.extractor.commit.model; public class CommitUrlStatistic { private String url; diff --git a/src/main/java/ru/ulstu/extractor/commit/repository/CommitRepository.java b/src/main/java/ru/ulstu/extractor/commit/repository/CommitRepository.java new file mode 100644 index 0000000..d0558d8 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/commit/repository/CommitRepository.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2021 Anton Romanov - All Rights Reserved + * You may use, distribute and modify this code, please write to: romanov73@gmail.com. + */ + +package ru.ulstu.extractor.commit.repository; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import ru.ulstu.extractor.commit.model.CommitAuthorStatistic; +import ru.ulstu.extractor.commit.model.CommitEntityStatistic; +import ru.ulstu.extractor.commit.model.CommitTimeStatistic; +import ru.ulstu.extractor.commit.model.CommitUrlStatistic; +import ru.ulstu.extractor.gitrepository.model.GitRepository; +import ru.ulstu.extractor.model.Commit; + +import java.util.List; + +public interface CommitRepository extends JpaRepository { + @Query("SELECT DISTINCT c FROM Commit c LEFT JOIN c.branch b LEFT JOIN c.fileChanges f LEFT JOIN c.author a LEFT JOIN b.gitRepository r WHERE r = :repository AND b.name = :branchName AND (:author IS NULL OR :author = '' OR a.name = :author) AND (:filter IS NULL OR :filter = '' OR lower(c.message) LIKE lower(concat('%', :filter,'%'))) AND (:entity IS NULL OR f.containsEntity = :entity)") + Page findByRepositoryAndBranch(Pageable pageable, @Param("repository") GitRepository gitRepository, @Param("branchName") String branchName, @Param("author") String author, @Param("filter") String filter, @Param("entity") Boolean entity); + + @Query("SELECT new ru.ulstu.extractor.commit.model.CommitAuthorStatistic(c.author.name, COUNT(DISTINCT c.hash)) FROM Commit c LEFT JOIN c.branch LEFT JOIN c.author a WHERE (:branchId IS NULL OR c.branch.id = :branchId) AND (:author IS NULL OR :author = '' OR a.name = :author) GROUP by c.author.name") + List getCommitAuthorStatistic(@Param("branchId") Integer branchId, @Param("author") String author); + + @Query("SELECT new ru.ulstu.extractor.commit.model.CommitUrlStatistic(c.branch.gitRepository.url, COUNT(DISTINCT c.hash)) FROM Commit c GROUP by c.branch.gitRepository.url") + List getCommitUrlStatistic(); + + @Query("SELECT new ru.ulstu.extractor.commit.model.CommitTimeStatistic(extract(month FROM c.date) as month, extract(year FROM c.date) as year, COUNT(DISTINCT c.hash)) FROM Commit c LEFT JOIN c.branch LEFT JOIN c.author a WHERE (:branchId IS NULL OR c.branch.id = :branchId) AND (:author IS NULL OR :author = '' OR a.name = :author) GROUP by extract(month from c.date), extract(year from c.date) ORDER by extract(year from c.date), extract(month from c.date)") + List getCommitTimeStatistic(@Param("branchId") Integer branchId, @Param("author") String author); + + @Query("SELECT new ru.ulstu.extractor.commit.model.CommitEntityStatistic(f.containsEntity, COUNT(DISTINCT c.hash)) FROM Commit c LEFT JOIN c.branch LEFT JOIN c.author a LEFT JOIN c.fileChanges f WHERE (:branchId IS NULL OR c.branch.id = :branchId) AND (:author IS NULL OR :author = '' OR a.name = :author) GROUP by f.containsEntity") + List getCommitEntityStatistic(@Param("branchId") Integer branchId, @Param("author") String author); + + @Query("SELECT new ru.ulstu.extractor.commit.model.CommitTimeStatistic(EXTRACT(MONTH FROM c.date), EXTRACT(YEAR FROM c.date), COUNT(DISTINCT c.hash)) FROM Commit c LEFT JOIN c.branch LEFT JOIN c.author a LEFT JOIN c.fileChanges f WHERE f.containsEntity = true AND (:branchId IS NULL OR c.branch.id = :branchId) AND (:author IS NULL OR :author = '' OR a.name = :author) GROUP by extract(month from c.date), extract(year from c.date) ORDER by extract(year from c.date), extract(month from c.date)") + List getCommitTimeEntityStatistic(@Param("branchId") Integer branchId, @Param("author") String author); + + void deleteByBranchIsNull(); + + @Query("SELECT b.commits FROM Branch b WHERE b.name = ?2 and b.gitRepository.id = ?1") + List findByRepositoryIdAndBranchName(Integer repositoryId, String name); +} diff --git a/src/main/java/ru/ulstu/extractor/service/CommitService.java b/src/main/java/ru/ulstu/extractor/commit/service/CommitService.java similarity index 83% rename from src/main/java/ru/ulstu/extractor/service/CommitService.java rename to src/main/java/ru/ulstu/extractor/commit/service/CommitService.java index ed75ee1..fd1c449 100644 --- a/src/main/java/ru/ulstu/extractor/service/CommitService.java +++ b/src/main/java/ru/ulstu/extractor/commit/service/CommitService.java @@ -3,12 +3,13 @@ * You may use, distribute and modify this code, please write to: romanov73@gmail.com. */ -package ru.ulstu.extractor.service; +package ru.ulstu.extractor.commit.service; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; +import ru.ulstu.extractor.commit.repository.CommitRepository; import ru.ulstu.extractor.model.Commit; -import ru.ulstu.extractor.repository.CommitRepository; +import ru.ulstu.extractor.service.AuthorService; import java.util.List; import java.util.stream.Collectors; @@ -49,6 +50,11 @@ public class CommitService { updateQuery = String.format(updateQuery, String.join(",", commitIds)); jdbcTemplate.update(updateQuery, branchId); } + + + public List findByRepositoryIdAndName(Integer repositoryId, String branchName) { + return commitRepository.findByRepositoryIdAndBranchName(repositoryId, branchName); + } } diff --git a/src/main/java/ru/ulstu/extractor/config/WebClientConfiguration.java b/src/main/java/ru/ulstu/extractor/config/WebClientConfiguration.java new file mode 100644 index 0000000..473a544 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/config/WebClientConfiguration.java @@ -0,0 +1,13 @@ +package ru.ulstu.extractor.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.client.WebClient; + +@Configuration +public class WebClientConfiguration { + @Bean + public WebClient webClient(WebClient.Builder webClientBuilder) { + return webClientBuilder.build(); + } +} diff --git a/src/main/java/ru/ulstu/extractor/controller/GitIndexingController.java b/src/main/java/ru/ulstu/extractor/controller/GitIndexingController.java index ce2433f..7708a1f 100644 --- a/src/main/java/ru/ulstu/extractor/controller/GitIndexingController.java +++ b/src/main/java/ru/ulstu/extractor/controller/GitIndexingController.java @@ -15,10 +15,10 @@ import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.mvc.support.RedirectAttributes; -import ru.ulstu.extractor.model.Branch; +import ru.ulstu.extractor.branch.model.Branch; +import ru.ulstu.extractor.gitrepository.GitRepositoryService; import ru.ulstu.extractor.model.mvc.FilterForm; import ru.ulstu.extractor.model.mvc.RepoForm; -import ru.ulstu.extractor.service.GitRepositoryService; import ru.ulstu.extractor.service.IndexService; import springfox.documentation.annotations.ApiIgnore; diff --git a/src/main/java/ru/ulstu/extractor/controller/RepoController.java b/src/main/java/ru/ulstu/extractor/controller/RepoController.java index 9be6c93..847003d 100644 --- a/src/main/java/ru/ulstu/extractor/controller/RepoController.java +++ b/src/main/java/ru/ulstu/extractor/controller/RepoController.java @@ -12,8 +12,8 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import ru.ulstu.extractor.gitrepository.GitRepositoryService; import ru.ulstu.extractor.model.Commit; -import ru.ulstu.extractor.service.GitRepositoryService; import ru.ulstu.extractor.service.IndexService; import ru.ulstu.extractor.util.HttpUtils; diff --git a/src/main/java/ru/ulstu/extractor/controller/RepositoryController.java b/src/main/java/ru/ulstu/extractor/controller/RepositoryController.java index dd58781..ee5de82 100644 --- a/src/main/java/ru/ulstu/extractor/controller/RepositoryController.java +++ b/src/main/java/ru/ulstu/extractor/controller/RepositoryController.java @@ -9,7 +9,7 @@ import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; -import ru.ulstu.extractor.repository.RepositoryRepository; +import ru.ulstu.extractor.gitrepository.GitRepositoryRepository; import springfox.documentation.annotations.ApiIgnore; import static ru.ulstu.extractor.controller.Route.DELETE_INDEXED_REPOSITORY; @@ -18,23 +18,23 @@ import static ru.ulstu.extractor.controller.Route.LIST_INDEXED_REPOSITORIES; @Controller @ApiIgnore public class RepositoryController { - private final RepositoryRepository repositoryRepository; + private final GitRepositoryRepository gitRepositoryRepository; - public RepositoryController(RepositoryRepository repositoryRepository) { - this.repositoryRepository = repositoryRepository; + public RepositoryController(GitRepositoryRepository gitRepositoryRepository) { + this.gitRepositoryRepository = gitRepositoryRepository; } @GetMapping(LIST_INDEXED_REPOSITORIES) public String indexNewRepo(Model model) { - model.addAttribute("repositories", repositoryRepository.findAll()); + model.addAttribute("repositories", gitRepositoryRepository.findAll()); return LIST_INDEXED_REPOSITORIES; } @GetMapping(DELETE_INDEXED_REPOSITORY) public String deleteRepo(Model model, @RequestParam Integer id) { - repositoryRepository.deleteById(id); - model.addAttribute("repositories", repositoryRepository.findAll()); + gitRepositoryRepository.deleteById(id); + model.addAttribute("repositories", gitRepositoryRepository.findAll()); return "redirect:/" + LIST_INDEXED_REPOSITORIES; } } diff --git a/src/main/java/ru/ulstu/extractor/controller/StatisticController.java b/src/main/java/ru/ulstu/extractor/controller/StatisticController.java index e522c04..771a5a0 100644 --- a/src/main/java/ru/ulstu/extractor/controller/StatisticController.java +++ b/src/main/java/ru/ulstu/extractor/controller/StatisticController.java @@ -9,9 +9,9 @@ import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; +import ru.ulstu.extractor.branch.service.BranchService; +import ru.ulstu.extractor.commit.repository.CommitRepository; import ru.ulstu.extractor.model.mvc.FilterForm; -import ru.ulstu.extractor.repository.CommitRepository; -import ru.ulstu.extractor.service.BranchService; import ru.ulstu.extractor.service.FilteringService; import springfox.documentation.annotations.ApiIgnore; diff --git a/src/main/java/ru/ulstu/extractor/gitrepository/GitRepositoryRepository.java b/src/main/java/ru/ulstu/extractor/gitrepository/GitRepositoryRepository.java new file mode 100644 index 0000000..ae9e821 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/gitrepository/GitRepositoryRepository.java @@ -0,0 +1,8 @@ +package ru.ulstu.extractor.gitrepository; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.ulstu.extractor.gitrepository.model.GitRepository; + +public interface GitRepositoryRepository extends JpaRepository { + GitRepository findByUrl(String url); +} diff --git a/src/main/java/ru/ulstu/extractor/service/GitRepositoryService.java b/src/main/java/ru/ulstu/extractor/gitrepository/GitRepositoryService.java similarity index 86% rename from src/main/java/ru/ulstu/extractor/service/GitRepositoryService.java rename to src/main/java/ru/ulstu/extractor/gitrepository/GitRepositoryService.java index 6f85552..311ddff 100644 --- a/src/main/java/ru/ulstu/extractor/service/GitRepositoryService.java +++ b/src/main/java/ru/ulstu/extractor/gitrepository/GitRepositoryService.java @@ -1,9 +1,4 @@ -/* - * Copyright (C) 2021 Anton Romanov - All Rights Reserved - * You may use, distribute and modify this code, please write to: romanov73@gmail.com. - */ - -package ru.ulstu.extractor.service; +package ru.ulstu.extractor.gitrepository; import org.apache.commons.io.FileUtils; import org.eclipse.jgit.api.CreateBranchCommand; @@ -15,19 +10,21 @@ import org.eclipse.jgit.internal.storage.file.FileRepository; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.ObjectReader; -import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.treewalk.TreeWalk; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import ru.ulstu.extractor.branch.model.Branch; +import ru.ulstu.extractor.gitrepository.model.GitRepository; import ru.ulstu.extractor.heuristic.model.BusinessLogicUnit; import ru.ulstu.extractor.heuristic.model.EntityUnit; import ru.ulstu.extractor.heuristic.model.ResourceUnit; import ru.ulstu.extractor.heuristic.service.StructuralUnitService; import ru.ulstu.extractor.model.Author; -import ru.ulstu.extractor.model.Branch; import ru.ulstu.extractor.model.Commit; import ru.ulstu.extractor.model.FileChange; import ru.ulstu.extractor.model.LineChange; @@ -61,18 +58,20 @@ public class GitRepositoryService { private String customProjectsDir; private final ExecutorService executorService = Executors.newFixedThreadPool(4); private final ExecutorService executorServiceCommits = Executors.newFixedThreadPool(4); - private final StructuralUnitService structuralUnitService; + private final GitRepositoryRepository gitRepositoryRepository; - public GitRepositoryService(StructuralUnitService structuralUnitService) { + public GitRepositoryService(StructuralUnitService structuralUnitService, + GitRepositoryRepository gitRepositoryRepository) { this.structuralUnitService = structuralUnitService; + this.gitRepositoryRepository = gitRepositoryRepository; } public List getRemoteBranches(String url) throws GitAPIException, IOException { LOG.debug("Get remote branches of {}. Clone", url); cloneOrUpdateRepo(url); LOG.debug("Get remote branches of {}. Get branches", url); - Repository localRepo = new FileRepository(getProjectGitDirectory(url)); + org.eclipse.jgit.lib.Repository localRepo = new FileRepository(getProjectGitDirectory(url)); Git git = new Git(localRepo); List branches = git.branchList().setListMode(ListBranchCommand.ListMode.REMOTE) .call() @@ -88,7 +87,7 @@ public class GitRepositoryService { LOG.debug("Get local branches of {}. Clone", url); cloneOrUpdateRepo(url); LOG.debug("Get local branches of {}. Get branches", url); - Repository localRepo = new FileRepository(getProjectGitDirectory(url)); + org.eclipse.jgit.lib.Repository localRepo = new FileRepository(getProjectGitDirectory(url)); Git git = new Git(localRepo); List branches = git.branchList() .call() @@ -105,7 +104,7 @@ public class GitRepositoryService { if (needUpdate) { cloneOrUpdateRepo(repositoryUrl, branchName); } - Repository localRepo = new FileRepository(getProjectGitDirectory(repositoryUrl)); + org.eclipse.jgit.lib.Repository localRepo = new FileRepository(getProjectGitDirectory(repositoryUrl)); Git git = new Git(localRepo); List commits = new ArrayList<>(); @@ -144,7 +143,7 @@ public class GitRepositoryService { return list; } - private void checkoutBranch(String repositoryUrl, Git git, Repository localRepo, String branchName) throws GitAPIException, IOException { + private void checkoutBranch(String repositoryUrl, Git git, org.eclipse.jgit.lib.Repository localRepo, String branchName) throws GitAPIException, IOException { LOG.debug("Checkout branch {} {}", repositoryUrl, branchName); git.pull().call(); if (!localRepo.getBranch().equals(branchName)) { @@ -192,7 +191,8 @@ public class GitRepositoryService { private void cloneOrUpdateRepo(String repositoryUrl, String branchName) throws GitAPIException, IOException { Git git; - Repository localRepo; + org.eclipse.jgit.lib.Repository localRepo; + validateOrClearRepositoryDirectory(getProjectDirectoryFile(repositoryUrl)); if (projectDirExists(getProjectDirectoryFile(repositoryUrl))) { localRepo = new FileRepository(getProjectGitDirectory(repositoryUrl)); git = new Git(localRepo); @@ -211,6 +211,26 @@ public class GitRepositoryService { git.close(); } + private void validateOrClearRepositoryDirectory(File projectDirectory) { + if (projectDirectory.exists()) { + try { + Git.open(projectDirectory).status().call(); + } catch (Exception e) { + deleteDirectory(projectDirectory); + } + } + } + + private boolean deleteDirectory(File directoryToBeDeleted) { + File[] allContents = directoryToBeDeleted.listFiles(); + if (allContents != null) { + for (File file : allContents) { + deleteDirectory(file); + } + } + return directoryToBeDeleted.delete(); + } + private void cloneOrUpdateRepo(String url) throws GitAPIException, IOException { cloneOrUpdateRepo(url, null); } @@ -240,7 +260,7 @@ public class GitRepositoryService { return file.exists(); } - private List findDiffBetweenTwoRevisions(RevCommit laterCommit, RevCommit earlierCommit, Repository localRepo) { + private List findDiffBetweenTwoRevisions(RevCommit laterCommit, RevCommit earlierCommit, org.eclipse.jgit.lib.Repository localRepo) { if (laterCommit == null || earlierCommit == null) { return null; } @@ -256,7 +276,7 @@ public class GitRepositoryService { return parseOutputDiff(output, localRepo, laterCommit); } - private List parseOutputDiff(String output, Repository repository, RevCommit commit) { + private List parseOutputDiff(String output, org.eclipse.jgit.lib.Repository repository, RevCommit commit) { List changes = new ArrayList<>(); String[] strings = output.split("\n"); FileChange fileChange = new FileChange(); @@ -322,7 +342,7 @@ public class GitRepositoryService { return changes; } - private String getContent(Repository repository, RevCommit commit, String path) { + private String getContent(org.eclipse.jgit.lib.Repository repository, RevCommit commit, String path) { try (TreeWalk treeWalk = TreeWalk.forPath(repository, path, commit.getTree())) { if (treeWalk != null) { ObjectId blobId = treeWalk.getObjectId(0); @@ -346,4 +366,8 @@ public class GitRepositoryService { } return Optional.empty(); } + + public Page findAll(Pageable pageable) { + return gitRepositoryRepository.findAll(pageable); + } } diff --git a/src/main/java/ru/ulstu/extractor/model/Repository.java b/src/main/java/ru/ulstu/extractor/gitrepository/model/GitRepository.java similarity index 51% rename from src/main/java/ru/ulstu/extractor/model/Repository.java rename to src/main/java/ru/ulstu/extractor/gitrepository/model/GitRepository.java index 651bfca..edabd3e 100644 --- a/src/main/java/ru/ulstu/extractor/model/Repository.java +++ b/src/main/java/ru/ulstu/extractor/gitrepository/model/GitRepository.java @@ -1,15 +1,17 @@ -package ru.ulstu.extractor.model; +package ru.ulstu.extractor.gitrepository.model; + +import ru.ulstu.extractor.model.BaseEntity; import javax.persistence.Entity; @Entity -public class Repository extends BaseEntity { +public class GitRepository extends BaseEntity { private String url; - public Repository() { + public GitRepository() { } - public Repository(String repositoryUrl) { + public GitRepository(String repositoryUrl) { url = repositoryUrl; } diff --git a/src/main/java/ru/ulstu/extractor/heuristic/controller/StructuralUnitController.java b/src/main/java/ru/ulstu/extractor/heuristic/controller/StructuralUnitController.java index 0939e08..ccedc05 100644 --- a/src/main/java/ru/ulstu/extractor/heuristic/controller/StructuralUnitController.java +++ b/src/main/java/ru/ulstu/extractor/heuristic/controller/StructuralUnitController.java @@ -11,10 +11,10 @@ import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import ru.ulstu.extractor.gitrepository.GitRepositoryService; import ru.ulstu.extractor.heuristic.model.BusinessLogicUnit; import ru.ulstu.extractor.heuristic.model.EntityUnit; import ru.ulstu.extractor.heuristic.model.ResourceUnit; -import ru.ulstu.extractor.service.GitRepositoryService; import ru.ulstu.extractor.util.HttpUtils; import javax.servlet.http.HttpServletRequest; diff --git a/src/main/java/ru/ulstu/extractor/http/HttpService.java b/src/main/java/ru/ulstu/extractor/http/HttpService.java new file mode 100644 index 0000000..9a5d660 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/http/HttpService.java @@ -0,0 +1,36 @@ +package ru.ulstu.extractor.http; + +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; + +import java.util.Optional; + +@Service +public class HttpService { + private final Logger log = LoggerFactory.getLogger(HttpService.class); + private final WebClient client; + + public HttpService(WebClient client) { + this.client = client; + } + + public JSONObject post(String url, JSONObject postData) { + log.debug("Service call: {}", url); + JSONObject response = new JSONObject(Optional.ofNullable(client + .post() + .uri(url) + .contentType(MediaType.APPLICATION_JSON) + .body(BodyInserters.fromValue(postData.toString())) + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(String.class) + .block()).orElse("{response:\"empty\"}")); + log.debug("Service response: {}", response); + return response; + } +} diff --git a/src/main/java/ru/ulstu/extractor/http/JsonTimeSeries.java b/src/main/java/ru/ulstu/extractor/http/JsonTimeSeries.java new file mode 100644 index 0000000..71506d1 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/http/JsonTimeSeries.java @@ -0,0 +1,35 @@ +package ru.ulstu.extractor.http; + +import ru.ulstu.extractor.model.TimeSeries; + +import java.util.List; +import java.util.stream.Collectors; + +public class JsonTimeSeries { + private String name; + private List values; + + public JsonTimeSeries(TimeSeries timeSeries) { + this.name = timeSeries.getName(); + this.values = timeSeries.getValues() + .stream() + .map(JsonTimeSeriesValue::new) + .collect(Collectors.toList()); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getValues() { + return values; + } + + public void setValues(List values) { + this.values = values; + } +} diff --git a/src/main/java/ru/ulstu/extractor/http/JsonTimeSeriesValue.java b/src/main/java/ru/ulstu/extractor/http/JsonTimeSeriesValue.java new file mode 100644 index 0000000..f615f7d --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/http/JsonTimeSeriesValue.java @@ -0,0 +1,35 @@ +package ru.ulstu.extractor.http; + +import ru.ulstu.extractor.model.TimeSeriesValue; + +import java.time.LocalDateTime; +import java.time.ZoneId; + +public class JsonTimeSeriesValue { + private LocalDateTime date; + private Double value; + + public JsonTimeSeriesValue(TimeSeriesValue timeSeriesValue) { + this.value = timeSeriesValue.getValue(); + this.date = timeSeriesValue.getDate() + .toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDateTime(); + } + + public LocalDateTime getDate() { + return date; + } + + public void setDate(LocalDateTime date) { + this.date = date; + } + + public Double getValue() { + return value; + } + + public void setValue(Double value) { + this.value = value; + } +} diff --git a/src/main/java/ru/ulstu/extractor/model/TimeSeries.java b/src/main/java/ru/ulstu/extractor/model/TimeSeries.java new file mode 100644 index 0000000..d04db07 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/model/TimeSeries.java @@ -0,0 +1,50 @@ +package ru.ulstu.extractor.model; + +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import java.util.ArrayList; +import java.util.List; + +@Entity +public class TimeSeries extends BaseEntity { + private String name; + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @JoinColumn(name = "time_series_id") + @Fetch(FetchMode.SUBSELECT) + private List values = new ArrayList<>(); + + public TimeSeries() { + } + + public TimeSeries(String name) { + this.name = name; + } + + public TimeSeries(String name, List values) { + this.name = name; + this.values = values; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getValues() { + return values; + } + + public void setValues(List values) { + this.values = values; + } + +} diff --git a/src/main/java/ru/ulstu/extractor/model/TimeSeriesValue.java b/src/main/java/ru/ulstu/extractor/model/TimeSeriesValue.java new file mode 100644 index 0000000..06fc168 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/model/TimeSeriesValue.java @@ -0,0 +1,39 @@ +package ru.ulstu.extractor.model; + +import javax.persistence.Entity; +import java.util.Date; + +@Entity +public class TimeSeriesValue extends BaseEntity { + private Date date; + private Double value; + + public TimeSeriesValue() { + } + + public TimeSeriesValue(Date date, Double value) { + this.date = date; + this.value = value; + } + + public TimeSeriesValue(TimeSeries timeSeries, Date date, Double value) { + this.date = date; + this.value = value; + } + + public Date getDate() { + return date; + } + + public Double getValue() { + return value; + } + + public void setDate(Date date) { + this.date = date; + } + + public void setValue(Double value) { + this.value = value; + } +} diff --git a/src/main/java/ru/ulstu/extractor/repository/AuthorRepository.java b/src/main/java/ru/ulstu/extractor/repository/AuthorRepository.java index 26b5f45..0ae8a20 100644 --- a/src/main/java/ru/ulstu/extractor/repository/AuthorRepository.java +++ b/src/main/java/ru/ulstu/extractor/repository/AuthorRepository.java @@ -8,14 +8,14 @@ package ru.ulstu.extractor.repository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import ru.ulstu.extractor.gitrepository.model.GitRepository; import ru.ulstu.extractor.model.Author; -import ru.ulstu.extractor.model.Repository; import java.util.List; public interface AuthorRepository extends JpaRepository { - @Query("SELECT DISTINCT a.name FROM Commit c, Repository r, Branch b, Author a WHERE c.author = a AND c.branch = b AND r = b.repository AND (:repository IS NULL OR r = :repository) AND (:branchName IS NULL OR :branchName = '' OR b.name = :branchName) AND a.name IS NOT NULL AND a.name <> '' ORDER BY a.name") - List findByRepositoryAndBranch(@Param("repository") Repository repository, @Param("branchName") String branchName); + @Query("SELECT DISTINCT a.name FROM Commit c, GitRepository r, Branch b, Author a WHERE c.author = a AND c.branch = b AND r = b.gitRepository AND (:repository IS NULL OR r = :repository) AND (:branchName IS NULL OR :branchName = '' OR b.name = :branchName) AND a.name IS NOT NULL AND a.name <> '' ORDER BY a.name") + List findByRepositoryAndBranch(@Param("repository") GitRepository gitRepository, @Param("branchName") String branchName); List findByName(String name); diff --git a/src/main/java/ru/ulstu/extractor/repository/BranchRepository.java b/src/main/java/ru/ulstu/extractor/repository/BranchRepository.java deleted file mode 100644 index d16b1a2..0000000 --- a/src/main/java/ru/ulstu/extractor/repository/BranchRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.ulstu.extractor.repository; - -import org.springframework.data.jpa.repository.JpaRepository; -import ru.ulstu.extractor.model.Branch; -import ru.ulstu.extractor.model.Repository; - -import java.util.List; - -public interface BranchRepository extends JpaRepository { - Branch findByRepositoryAndName(Repository repository, String name); - - List findByRepositoryId(Integer repositoryId); -} diff --git a/src/main/java/ru/ulstu/extractor/repository/CommitRepository.java b/src/main/java/ru/ulstu/extractor/repository/CommitRepository.java deleted file mode 100644 index a1845b4..0000000 --- a/src/main/java/ru/ulstu/extractor/repository/CommitRepository.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2021 Anton Romanov - All Rights Reserved - * You may use, distribute and modify this code, please write to: romanov73@gmail.com. - */ - -package ru.ulstu.extractor.repository; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import ru.ulstu.extractor.model.Commit; -import ru.ulstu.extractor.model.CommitAuthorStatistic; -import ru.ulstu.extractor.model.CommitEntityStatistic; -import ru.ulstu.extractor.model.CommitTimeStatistic; -import ru.ulstu.extractor.model.CommitUrlStatistic; -import ru.ulstu.extractor.model.Repository; - -import java.util.List; - -public interface CommitRepository extends JpaRepository { - @Query("SELECT DISTINCT c FROM Commit c LEFT JOIN c.branch b LEFT JOIN c.fileChanges f LEFT JOIN c.author a LEFT JOIN b.repository r WHERE r = :repository AND b.name = :branchName AND (:author IS NULL OR :author = '' OR a.name = :author) AND (:filter IS NULL OR :filter = '' OR lower(c.message) LIKE lower(concat('%', :filter,'%'))) AND (:entity IS NULL OR f.containsEntity = :entity)") - Page findByRepositoryAndBranch(Pageable pageable, @Param("repository") Repository repository, @Param("branchName") String branchName, @Param("author") String author, @Param("filter") String filter, @Param("entity") Boolean entity); - - @Query("SELECT new ru.ulstu.extractor.model.CommitAuthorStatistic(c.author.name, COUNT(DISTINCT c.hash)) FROM Commit c LEFT JOIN c.branch LEFT JOIN c.author a WHERE (:branchId IS NULL OR c.branch.id = :branchId) AND (:author IS NULL OR :author = '' OR a.name = :author) GROUP by c.author.name") - List getCommitAuthorStatistic(@Param("branchId") Integer branchId, @Param("author") String author); - - @Query("SELECT new ru.ulstu.extractor.model.CommitUrlStatistic(c.branch.repository.url, COUNT(DISTINCT c.hash)) FROM Commit c GROUP by c.branch.repository.url") - List getCommitUrlStatistic(); - - @Query("SELECT new ru.ulstu.extractor.model.CommitTimeStatistic(extract(month FROM c.date) as month, extract(year FROM c.date) as year, COUNT(DISTINCT c.hash)) FROM Commit c LEFT JOIN c.branch LEFT JOIN c.author a WHERE (:branchId IS NULL OR c.branch.id = :branchId) AND (:author IS NULL OR :author = '' OR a.name = :author) GROUP by extract(month from c.date), extract(year from c.date) ORDER by extract(year from c.date), extract(month from c.date)") - List getCommitTimeStatistic(@Param("branchId") Integer branchId, @Param("author") String author); - - @Query("SELECT new ru.ulstu.extractor.model.CommitEntityStatistic(f.containsEntity, COUNT(DISTINCT c.hash)) FROM Commit c LEFT JOIN c.branch LEFT JOIN c.author a LEFT JOIN c.fileChanges f WHERE (:branchId IS NULL OR c.branch.id = :branchId) AND (:author IS NULL OR :author = '' OR a.name = :author) GROUP by f.containsEntity") - List getCommitEntityStatistic(@Param("branchId") Integer branchId, @Param("author") String author); - - @Query("SELECT new ru.ulstu.extractor.model.CommitTimeStatistic(EXTRACT(MONTH FROM c.date), EXTRACT(YEAR FROM c.date), COUNT(DISTINCT c.hash)) FROM Commit c LEFT JOIN c.branch LEFT JOIN c.author a LEFT JOIN c.fileChanges f WHERE f.containsEntity = true AND (:branchId IS NULL OR c.branch.id = :branchId) AND (:author IS NULL OR :author = '' OR a.name = :author) GROUP by extract(month from c.date), extract(year from c.date) ORDER by extract(year from c.date), extract(month from c.date)") - List getCommitTimeEntityStatistic(@Param("branchId") Integer branchId, @Param("author") String author); - - void deleteByBranchIsNull(); -} diff --git a/src/main/java/ru/ulstu/extractor/repository/RepositoryRepository.java b/src/main/java/ru/ulstu/extractor/repository/RepositoryRepository.java deleted file mode 100644 index 21263f4..0000000 --- a/src/main/java/ru/ulstu/extractor/repository/RepositoryRepository.java +++ /dev/null @@ -1,8 +0,0 @@ -package ru.ulstu.extractor.repository; - -import org.springframework.data.jpa.repository.JpaRepository; -import ru.ulstu.extractor.model.Repository; - -public interface RepositoryRepository extends JpaRepository { - Repository findByUrl(String url); -} diff --git a/src/main/java/ru/ulstu/extractor/repository/TimeSeriesRepository.java b/src/main/java/ru/ulstu/extractor/repository/TimeSeriesRepository.java new file mode 100644 index 0000000..e324774 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/repository/TimeSeriesRepository.java @@ -0,0 +1,10 @@ +package ru.ulstu.extractor.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.ulstu.extractor.model.TimeSeries; + +import java.util.Optional; + +public interface TimeSeriesRepository extends JpaRepository { + Optional findByName(String name); +} diff --git a/src/main/java/ru/ulstu/extractor/repository/TimeSeriesValueRepository.java b/src/main/java/ru/ulstu/extractor/repository/TimeSeriesValueRepository.java new file mode 100644 index 0000000..b603ed5 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/repository/TimeSeriesValueRepository.java @@ -0,0 +1,14 @@ +package ru.ulstu.extractor.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.ulstu.extractor.model.TimeSeriesValue; + +import java.util.List; + +public interface TimeSeriesValueRepository extends JpaRepository { + //TimeSeriesValue findByTimeSeriesAndName(TimeSeries timeSeries, String name); + + //List findTimeSeriesValueById(Integer repositoryId); + + void deleteAllByIdIn(List ids); +} diff --git a/src/main/java/ru/ulstu/extractor/service/FilteringService.java b/src/main/java/ru/ulstu/extractor/service/FilteringService.java index 221f133..ddeda0c 100644 --- a/src/main/java/ru/ulstu/extractor/service/FilteringService.java +++ b/src/main/java/ru/ulstu/extractor/service/FilteringService.java @@ -9,10 +9,10 @@ import com.sun.istack.NotNull; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import ru.ulstu.extractor.commit.repository.CommitRepository; +import ru.ulstu.extractor.gitrepository.GitRepositoryRepository; import ru.ulstu.extractor.model.Commit; import ru.ulstu.extractor.repository.AuthorRepository; -import ru.ulstu.extractor.repository.CommitRepository; -import ru.ulstu.extractor.repository.RepositoryRepository; import java.util.List; import java.util.Map; @@ -21,20 +21,20 @@ import java.util.Map; public class FilteringService { private final AuthorRepository authorRepository; private final CommitRepository commitRepository; - private final RepositoryRepository repositoryRepository; + private final GitRepositoryRepository gitRepositoryRepository; public FilteringService(AuthorRepository authorRepository, CommitRepository commitRepository, - RepositoryRepository repositoryRepository) { + GitRepositoryRepository gitRepositoryRepository) { this.authorRepository = authorRepository; this.commitRepository = commitRepository; - this.repositoryRepository = repositoryRepository; + this.gitRepositoryRepository = gitRepositoryRepository; } public List getRepositoryAuthors(@NotNull String repositoryUrl, @NotNull String branchName) { return authorRepository.findByRepositoryAndBranch( - repositoryRepository.findByUrl(repositoryUrl), + gitRepositoryRepository.findByUrl(repositoryUrl), branchName ); } @@ -51,7 +51,7 @@ public class FilteringService { Pageable pageable) { return commitRepository.findByRepositoryAndBranch( pageable, - repositoryRepository.findByUrl(repositoryUrl), + gitRepositoryRepository.findByUrl(repositoryUrl), branchName, author, filter, diff --git a/src/main/java/ru/ulstu/extractor/service/IndexService.java b/src/main/java/ru/ulstu/extractor/service/IndexService.java index 3cd9644..d5415e2 100644 --- a/src/main/java/ru/ulstu/extractor/service/IndexService.java +++ b/src/main/java/ru/ulstu/extractor/service/IndexService.java @@ -10,10 +10,13 @@ import org.eclipse.jgit.api.errors.GitAPIException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import ru.ulstu.extractor.model.Branch; +import ru.ulstu.extractor.branch.model.Branch; +import ru.ulstu.extractor.branch.service.BranchService; +import ru.ulstu.extractor.gitrepository.GitRepositoryRepository; +import ru.ulstu.extractor.gitrepository.GitRepositoryService; +import ru.ulstu.extractor.gitrepository.model.GitRepository; import ru.ulstu.extractor.model.Commit; -import ru.ulstu.extractor.model.Repository; -import ru.ulstu.extractor.repository.RepositoryRepository; +import ru.ulstu.extractor.ts.AbstractTimeSeriesCreator; import java.io.IOException; import java.util.Collections; @@ -24,25 +27,28 @@ public class IndexService { private final static Logger LOG = LoggerFactory.getLogger(IndexService.class); private final static int COMMITS_PAGE_SIZE = 10; private final GitRepositoryService gitRepositoryService; - private final RepositoryRepository repositoryRepository; + private final GitRepositoryRepository gitRepositoryRepository; private final BranchService branchService; + private final List timeSeriesCreators; public IndexService(GitRepositoryService gitRepositoryService, - RepositoryRepository repositoryRepository, - BranchService branchService) { + GitRepositoryRepository gitRepositoryRepository, + BranchService branchService, + List timeSeriesCreators) { this.gitRepositoryService = gitRepositoryService; - this.repositoryRepository = repositoryRepository; + this.gitRepositoryRepository = gitRepositoryRepository; this.branchService = branchService; + this.timeSeriesCreators = timeSeriesCreators; } public void index(@NotNull String repositoryUrl, @NotNull String branchName) throws GitAPIException, IOException { - Repository repository = repositoryRepository.findByUrl(repositoryUrl); - if (repository == null) { - repository = repositoryRepository.save(new Repository(repositoryUrl)); + GitRepository gitRepository = gitRepositoryRepository.findByUrl(repositoryUrl); + if (gitRepository == null) { + gitRepository = gitRepositoryRepository.save(new GitRepository(repositoryUrl)); } - Branch branch = branchService.findByRepositoryAndName(repository, branchName); + Branch branch = branchService.findByRepositoryAndName(gitRepository, branchName); if (branch == null) { - branch = new Branch(repository, branchName); + branch = new Branch(gitRepository, branchName); } branchService.save(branch, Collections.emptyList()); int commitsFrom = 0; @@ -56,6 +62,8 @@ public class IndexService { commitsTo += COMMITS_PAGE_SIZE; commits = gitRepositoryService.getCommits(repositoryUrl, branchName, commitsFrom, commitsTo, false); } + Integer repositoryId = gitRepository.getId(); + timeSeriesCreators.forEach(tsCreator -> tsCreator.addTimeSeries(repositoryId, branchName)); LOG.debug("Complete indexing {} branch", branchName); } } diff --git a/src/main/java/ru/ulstu/extractor/service/TimeSeriesService.java b/src/main/java/ru/ulstu/extractor/service/TimeSeriesService.java new file mode 100644 index 0000000..706b52f --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/service/TimeSeriesService.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2021 Anton Romanov - All Rights Reserved + * You may use, distribute and modify this code, please write to: romanov73@gmail.com. + */ + +package ru.ulstu.extractor.service; + +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import ru.ulstu.extractor.http.HttpService; +import ru.ulstu.extractor.http.JsonTimeSeries; +import ru.ulstu.extractor.model.TimeSeries; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.repository.TimeSeriesRepository; +import ru.ulstu.extractor.repository.TimeSeriesValueRepository; +import ru.ulstu.extractor.ts.TimeSeriesDateMapper; + +import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +@Service +public class TimeSeriesService { + private final static Logger LOG = LoggerFactory.getLogger(TimeSeriesService.class); + private final TimeSeriesRepository timeSeriesRepository; + private final TimeSeriesValueRepository timeSeriesValueRepository; + private final TimeSeriesDateMapper.TimeSeriesInterval timeSeriesInterval = TimeSeriesDateMapper.TimeSeriesInterval.HOUR; + private final HttpService httpService; + private final static String TIME_SERIES_SERVICE_URL = "http://time-series.athene.tech/api/1.0/add-time-series?setKey=git-extractor"; + + public TimeSeriesService(TimeSeriesRepository timeSeriesRepository, + TimeSeriesValueRepository timeSeriesValueRepository, + HttpService httpService) { + this.timeSeriesRepository = timeSeriesRepository; + this.timeSeriesValueRepository = timeSeriesValueRepository; + this.httpService = httpService; + } + + /** + * Сохранить список временных рядов + * + * @param timeSeriesValues + * @return + */ + @Transactional + public List save(Map> timeSeriesValues) { + List results = new ArrayList<>(); + for (Map.Entry> entry : timeSeriesValues.entrySet()) { + results.add(save(entry.getKey(), entry.getValue())); + } + return results; + } + + @Transactional + public TimeSeries save(String timeSeriesName, List timeSeriesValues) { + LOG.debug("Start save {} time series with {} time series values ", timeSeriesName, timeSeriesValues.size()); + final TimeSeries timeSeries = findOrCreate(timeSeriesName); + List timeSeriesValuesToRemove = timeSeries.getValues(); + timeSeries.setValues(timeSeriesValues); + LOG.debug("Save time series {} ", timeSeries.getName()); + TimeSeries savedTimeSeries = timeSeriesRepository.save(timeSeries); + LOG.debug("Clear {} time series values ", timeSeriesValuesToRemove.size()); + timeSeriesValueRepository.deleteAll(timeSeriesValuesToRemove); + sendToTimeSeriesService(savedTimeSeries); + return savedTimeSeries; + } + + public TimeSeries findOrCreate(String timeSeriesName) { + Optional maybeTimeSeries = timeSeriesRepository.findByName(timeSeriesName); + if (maybeTimeSeries.isPresent()) { + LOG.debug("TimeSeries {} exists.", maybeTimeSeries.get().getName()); + return maybeTimeSeries.get(); + } + return timeSeriesRepository.save(new TimeSeries(timeSeriesName)); + } + + public List save(List timeSeriesValues) { + return timeSeriesValues.stream() + .map(timeSeriesValue -> { + timeSeriesValue.setValue((timeSeriesValue.getValue())); + timeSeriesValue.setDate((timeSeriesValue.getDate())); + return timeSeriesValueRepository.save(timeSeriesValue); + }).collect(Collectors.toList()); + } + + public void addTimeSeriesValue(String timeSeriesName, Date date, Double value) { + LOG.debug("Start add time series values to {} time series values ", timeSeriesName); + TimeSeries timeSeries = findOrCreate(timeSeriesName); + timeSeriesValueRepository.save(new TimeSeriesValue(timeSeries, date, value)); + } + + public List findAll() { + return timeSeriesValueRepository.findAll(); + } + + public TimeSeriesDateMapper.TimeSeriesInterval getTimeSeriesInterval() { + return timeSeriesInterval; + } + + private void sendToTimeSeriesService(TimeSeries timeSeries) { + new Thread(() -> { + try { + httpService.post(TIME_SERIES_SERVICE_URL, new JSONObject(new JsonTimeSeries(timeSeries))); + LOG.debug("Успешно отправлен на сервис"); + } catch (Exception ex) { + LOG.debug(ex.getMessage()); + } + }).start(); + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/AbstractTimeSeriesCreator.java b/src/main/java/ru/ulstu/extractor/ts/AbstractTimeSeriesCreator.java new file mode 100644 index 0000000..4fde2c8 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/AbstractTimeSeriesCreator.java @@ -0,0 +1,40 @@ +package ru.ulstu.extractor.ts; + +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.List; +import java.util.Map; + +import static ru.ulstu.extractor.ts.TimeSeriesDateMapper.mapTimeSeriesToInterval; + +public abstract class AbstractTimeSeriesCreator { + + public abstract String getTimeSeriesName(); + + /** + * Извлечь список точек временных рядов + * + * @param repositoryId + * @param branchName + * @return + */ + public abstract Map> getTimeSeriesValues(Integer repositoryId, String branchName); + + public abstract TimeSeriesService getTimeSeriesService(); + + /** + * Сохранить извлеченные временные ряды + * + * @param repositoryId + * @param branchName + */ + public void addTimeSeries(Integer repositoryId, String branchName) { + // извлеченные точки временных рядов + Map> timeSeriesValues = getTimeSeriesValues(repositoryId, branchName); + + // сгруппированные по временным интервалам точки временных рядов + timeSeriesValues.replaceAll((k, v) -> mapTimeSeriesToInterval(getTimeSeriesService().getTimeSeriesInterval(), v)); + getTimeSeriesService().save(timeSeriesValues); + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/AuthorTS.java b/src/main/java/ru/ulstu/extractor/ts/AuthorTS.java new file mode 100644 index 0000000..a6d01dc --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/AuthorTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class AuthorTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public AuthorTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество Авторов"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/AuthorsCommentTS.java b/src/main/java/ru/ulstu/extractor/ts/AuthorsCommentTS.java new file mode 100644 index 0000000..62ea9a7 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/AuthorsCommentTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class AuthorsCommentTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public AuthorsCommentTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество коммитов авторов"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/AuthorsCompletedIssueTS.java b/src/main/java/ru/ulstu/extractor/ts/AuthorsCompletedIssueTS.java new file mode 100644 index 0000000..7453fdb --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/AuthorsCompletedIssueTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class AuthorsCompletedIssueTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public AuthorsCompletedIssueTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество выполненных issues авторов"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/AuthorsIssueTS.java b/src/main/java/ru/ulstu/extractor/ts/AuthorsIssueTS.java new file mode 100644 index 0000000..d7318da --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/AuthorsIssueTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class AuthorsIssueTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public AuthorsIssueTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество issues авторов"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/BranchTS.java b/src/main/java/ru/ulstu/extractor/ts/BranchTS.java new file mode 100644 index 0000000..6233909 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/BranchTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class BranchTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public BranchTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество веток"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/ClassTS.java b/src/main/java/ru/ulstu/extractor/ts/ClassTS.java new file mode 100644 index 0000000..1fdf504 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/ClassTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ClassTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public ClassTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество классов"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/CommitsTS.java b/src/main/java/ru/ulstu/extractor/ts/CommitsTS.java new file mode 100644 index 0000000..3067117 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/CommitsTS.java @@ -0,0 +1,45 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.commit.service.CommitService; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Component +public class CommitsTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + private final CommitService commitService; + + public CommitsTS(TimeSeriesService timeSeriesService, + CommitService commitService) { + this.timeSeriesService = timeSeriesService; + this.commitService = commitService; + } + + @Override + public String getTimeSeriesName() { + return "Количество коммитов во времени"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + //TODO: добавить постраничное чтение + Map> result = new HashMap<>(); + result.put(String.format("%s %s %s", getTimeSeriesName(), repositoryId, branchName), + commitService.findByRepositoryIdAndName(repositoryId, branchName) + .stream() + .map(c -> new TimeSeriesValue(c.getDate(), 1.0)) + .collect(Collectors.toList())); + return result; + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/DependenceTS.java b/src/main/java/ru/ulstu/extractor/ts/DependenceTS.java new file mode 100644 index 0000000..26c0e39 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/DependenceTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class DependenceTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public DependenceTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество зависимостей"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/EntityTS.java b/src/main/java/ru/ulstu/extractor/ts/EntityTS.java new file mode 100644 index 0000000..ff6a2d9 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/EntityTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class EntityTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public EntityTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество сущностей"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/FileTS.java b/src/main/java/ru/ulstu/extractor/ts/FileTS.java new file mode 100644 index 0000000..e90ce57 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/FileTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class FileTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public FileTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество файлов"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/InterfaceTS.java b/src/main/java/ru/ulstu/extractor/ts/InterfaceTS.java new file mode 100644 index 0000000..7d26f00 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/InterfaceTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class InterfaceTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public InterfaceTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество интерфейсов"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/IssuesTS.java b/src/main/java/ru/ulstu/extractor/ts/IssuesTS.java new file mode 100644 index 0000000..51ecffd --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/IssuesTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class IssuesTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public IssuesTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество issues созданных во времени"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/ProcessTS.java b/src/main/java/ru/ulstu/extractor/ts/ProcessTS.java new file mode 100644 index 0000000..bc4b322 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/ProcessTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class ProcessTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public ProcessTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество процессов"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/StarTS.java b/src/main/java/ru/ulstu/extractor/ts/StarTS.java new file mode 100644 index 0000000..38455a3 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/StarTS.java @@ -0,0 +1,33 @@ +package ru.ulstu.extractor.ts; + +import org.springframework.stereotype.Component; +import ru.ulstu.extractor.model.TimeSeriesValue; +import ru.ulstu.extractor.service.TimeSeriesService; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class StarTS extends AbstractTimeSeriesCreator { + private final TimeSeriesService timeSeriesService; + + public StarTS(TimeSeriesService timeSeriesService) { + this.timeSeriesService = timeSeriesService; + } + + @Override + public String getTimeSeriesName() { + return "Количество звезд"; + } + + @Override + public Map> getTimeSeriesValues(Integer repositoryId, String branchName) { + return new HashMap<>(); + } + + @Override + public TimeSeriesService getTimeSeriesService() { + return timeSeriesService; + } +} diff --git a/src/main/java/ru/ulstu/extractor/ts/TimeSeriesDateMapper.java b/src/main/java/ru/ulstu/extractor/ts/TimeSeriesDateMapper.java new file mode 100644 index 0000000..dec6918 --- /dev/null +++ b/src/main/java/ru/ulstu/extractor/ts/TimeSeriesDateMapper.java @@ -0,0 +1,64 @@ +package ru.ulstu.extractor.ts; + +import org.apache.commons.lang3.time.DateUtils; +import ru.ulstu.extractor.model.TimeSeries; +import ru.ulstu.extractor.model.TimeSeriesValue; + +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Класс для регулировки дискретности временного ряда. + * Можно создать временной ряд с точками с секундными отметками, затем суммировать значения, + * применив одно из значений TimeSeriesInterval + */ +public class TimeSeriesDateMapper { + + public static List mapTimeSeriesToInterval(TimeSeriesInterval timeSeriesInterval, List timeSeriesValues) { + List trimmedTimeSeriesValues = timeSeriesValues + .stream() + .map(timeSeriesValue -> new TimeSeriesValue(trimTo(timeSeriesInterval, timeSeriesValue.getDate()), + timeSeriesValue.getValue())) + .collect(Collectors.toList()); + Map groupedTimeSeriesValues = trimmedTimeSeriesValues + .stream() + .collect(Collectors.groupingBy(TimeSeriesValue::getDate, + Collectors.summingDouble(TimeSeriesValue::getValue))); + + return groupedTimeSeriesValues.entrySet() + .stream() + .map(e -> new TimeSeriesValue(e.getKey(), e.getValue())) + .collect(Collectors.toList()); + } + + public static TimeSeries mapTimeSeriesToInterval(TimeSeriesInterval timeSeriesInterval, TimeSeries timeSeries) { + timeSeries.setValues(mapTimeSeriesToInterval(timeSeriesInterval, timeSeries.getValues())); + return timeSeries; + } + + private static Date trimTo(TimeSeriesInterval timeSeriesInterval, Date date) { + return DateUtils.truncate(date, timeSeriesInterval.calendarField); + } + + /** + * Интервальность временного ряда при преобразовании + */ + public enum TimeSeriesInterval { + SECOND(Calendar.SECOND), + MINUTE(Calendar.MINUTE), + HOUR(Calendar.HOUR_OF_DAY), + DAY(Calendar.DAY_OF_MONTH), + WEEK(Calendar.WEEK_OF_MONTH), + MONTH(Calendar.MONTH), + YEAR(Calendar.YEAR); + + private final int calendarField; + + TimeSeriesInterval(int calendarField) { + this.calendarField = calendarField; + } + } +} diff --git a/src/main/resources/db/changelog-20220422_120000-schema.xml b/src/main/resources/db/changelog-20220422_120000-schema.xml new file mode 100644 index 0000000..bec0b8d --- /dev/null +++ b/src/main/resources/db/changelog-20220422_120000-schema.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db/changelog-20220621_120000-schema.xml b/src/main/resources/db/changelog-20220621_120000-schema.xml new file mode 100644 index 0000000..e501fe2 --- /dev/null +++ b/src/main/resources/db/changelog-20220621_120000-schema.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db/changelog-master.xml b/src/main/resources/db/changelog-master.xml index 514d679..e2afa54 100644 --- a/src/main/resources/db/changelog-master.xml +++ b/src/main/resources/db/changelog-master.xml @@ -12,4 +12,6 @@ + + diff --git a/src/main/resources/templates/statistic.html b/src/main/resources/templates/statistic.html index e89c1a8..2ad0eb2 100644 --- a/src/main/resources/templates/statistic.html +++ b/src/main/resources/templates/statistic.html @@ -193,7 +193,7 @@