#12 -- Get file content for specific commit

This commit is contained in:
Anton Romanov 2021-04-12 10:41:26 +04:00
parent bf611faa38
commit 4265441490
6 changed files with 124 additions and 28 deletions

View File

@ -29,18 +29,24 @@ public abstract class StructuralUnitIdentifier {
return getEntityClasses(projectPath, subDirectory, projectFiles); return getEntityClasses(projectPath, subDirectory, projectFiles);
} }
public abstract boolean canAppliedToCode(String sourceCode);
public abstract boolean canAppliedToFile(File projectFile);
public abstract boolean canAppliedToProject(String projectPath, List<File> projectFiles, List<File> rootProjectFiles);
public abstract boolean isEntityClass(File file); public abstract boolean isEntityClass(File file);
public abstract boolean isEntityClass(String sourceCode);
protected abstract boolean isBusinessLogicClass(File file);
public abstract List<StructuralUnit> getBusinessLogicClasses(); public abstract List<StructuralUnit> getBusinessLogicClasses();
public abstract boolean isMultiModuleProject(); public abstract boolean isMultiModuleProject();
public abstract Optional<BuildTool> getBuildTool(List<File> rootDirectoryFiles); public abstract Optional<BuildTool> getBuildTool(List<File> rootDirectoryFiles);
public abstract boolean canAppliedToProject(String projectPath, List<File> projectFiles, List<File> rootProjectFiles);
public abstract boolean canAppliedToFile(File projectFile);
protected abstract List<StructuralUnit> getEntityClasses(String projectPath, String subDirectory, List<File> projectFiles); protected abstract List<StructuralUnit> getEntityClasses(String projectPath, String subDirectory, List<File> projectFiles);
protected abstract String getSourceDirectory(List<File> rootProjectFiles); protected abstract String getSourceDirectory(List<File> rootProjectFiles);
@ -51,8 +57,6 @@ public abstract class StructuralUnitIdentifier {
protected abstract ProgrammingLanguage getProgrammingLanguage(); protected abstract ProgrammingLanguage getProgrammingLanguage();
protected abstract boolean isBusinessLogicClass(File file);
protected Optional<ProgrammingLanguage> getMainProgrammingLanguage(String projectPath, List<File> projectFiles, List<File> rootProjectFiles) { protected Optional<ProgrammingLanguage> getMainProgrammingLanguage(String projectPath, List<File> projectFiles, List<File> rootProjectFiles) {
String subDirectory = getSourceDirectory(rootProjectFiles); String subDirectory = getSourceDirectory(rootProjectFiles);
Map<ProgrammingLanguage, Integer> projectFileLanguageFrequency = new HashMap<>(); Map<ProgrammingLanguage, Integer> projectFileLanguageFrequency = new HashMap<>();

View File

@ -10,7 +10,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import ru.ulstu.extractor.heuristic.model.StructuralUnit; import ru.ulstu.extractor.heuristic.model.StructuralUnit;
import ru.ulstu.extractor.heuristic.service.StructuralUnitService; import ru.ulstu.extractor.heuristic.service.StructuralUnitService;
import ru.ulstu.extractor.service.GitRepositoryService;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -18,13 +20,17 @@ import java.util.List;
@RequestMapping("StructuralUnitController") @RequestMapping("StructuralUnitController")
public class StructuralUnitController { public class StructuralUnitController {
private final StructuralUnitService structuralUnitService; private final StructuralUnitService structuralUnitService;
private final GitRepositoryService gitRepositoryService;
public StructuralUnitController(StructuralUnitService structuralUnitService) { public StructuralUnitController(StructuralUnitService structuralUnitService,
GitRepositoryService gitRepositoryService) {
this.structuralUnitService = structuralUnitService; this.structuralUnitService = structuralUnitService;
this.gitRepositoryService = gitRepositoryService;
} }
@GetMapping("get-entities") @GetMapping("get-entities")
public List<StructuralUnit> getEntities(String repositoryUrl) throws IOException { public List<StructuralUnit> getEntities(String repositoryUrl) throws IOException {
return structuralUnitService.getEntities(repositoryUrl); File rootPath = gitRepositoryService.getProjectDirectoryFile(repositoryUrl);
return structuralUnitService.getEntities(rootPath);
} }
} }

View File

@ -18,7 +18,8 @@ import ru.ulstu.extractor.heuristic.model.StructuralUnit;
import ru.ulstu.extractor.util.StringUtils; import ru.ulstu.extractor.util.StringUtils;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.IOException;
import java.nio.file.Files;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -27,6 +28,7 @@ import static ru.ulstu.extractor.heuristic.service.DetectorService.LangDetectScr
@Service @Service
public class JavaIdentifier extends StructuralUnitIdentifier { public class JavaIdentifier extends StructuralUnitIdentifier {
private static final String ENTITY_ANNOTATION = "@Entity";
private final DetectorService detectorService; private final DetectorService detectorService;
private final BuildToolService buildToolService; private final BuildToolService buildToolService;
private final ProgrammingLanguageService programmingLanguageService; private final ProgrammingLanguageService programmingLanguageService;
@ -49,6 +51,10 @@ public class JavaIdentifier extends StructuralUnitIdentifier {
return getMainProgrammingLanguage(projectFile, LOW).orElse(null) instanceof JavaProgrammingLanguage; return getMainProgrammingLanguage(projectFile, LOW).orElse(null) instanceof JavaProgrammingLanguage;
} }
public boolean canAppliedToCode(String sourceCode) {
return getMainProgrammingLanguage(sourceCode).orElse(null) instanceof JavaProgrammingLanguage;
}
@Override @Override
public List<StructuralUnit> getEntityClasses(String projectPath, String subDirectory, List<File> projectFiles) { public List<StructuralUnit> getEntityClasses(String projectPath, String subDirectory, List<File> projectFiles) {
return projectFiles.stream() return projectFiles.stream()
@ -58,6 +64,12 @@ public class JavaIdentifier extends StructuralUnitIdentifier {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
protected Optional<ProgrammingLanguage> getMainProgrammingLanguage(String sourceCode) {
return sourceCodeContainsClass(sourceCode)
? Optional.of(getProgrammingLanguage())
: Optional.empty();
}
@Override @Override
public List<StructuralUnit> getBusinessLogicClasses() { public List<StructuralUnit> getBusinessLogicClasses() {
return null; return null;
@ -91,16 +103,30 @@ public class JavaIdentifier extends StructuralUnitIdentifier {
@Override @Override
public boolean isEntityClass(File file) { public boolean isEntityClass(File file) {
try { try {
return file.getName().endsWith("java") && classContainsAnnotation(file, "@Entity"); return file.getName().endsWith("java") && classContainsAnnotation(file, ENTITY_ANNOTATION);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
} }
return false; return false;
} }
private boolean classContainsAnnotation(File file, String annotationDeclaration) throws FileNotFoundException { @Override
public boolean isEntityClass(String sourceCode) {
try {
return classContainsAnnotation(sourceCode, ENTITY_ANNOTATION);
} catch (Exception ex) {
ex.printStackTrace();
}
return false;
}
private boolean classContainsAnnotation(File file, String annotationDeclaration) throws IOException {
return classContainsAnnotation(new String(Files.readAllBytes(file.toPath())), annotationDeclaration);
}
private boolean classContainsAnnotation(String sourceCode, String annotationDeclaration) {
JavaParser parser = new JavaParser(); JavaParser parser = new JavaParser();
ParseResult<CompilationUnit> parseResult = parser.parse(file); ParseResult<CompilationUnit> parseResult = parser.parse(sourceCode);
if (parseResult.getResult().isPresent() && parseResult.getResult().get().findCompilationUnit().isPresent()) { if (parseResult.getResult().isPresent() && parseResult.getResult().get().findCompilationUnit().isPresent()) {
return parseResult.getResult().get().getTypes().stream() return parseResult.getResult().get().getTypes().stream()
.anyMatch(clazz -> clazz.getAnnotations().stream().anyMatch(annotation -> annotation.toString().startsWith(annotationDeclaration))); .anyMatch(clazz -> clazz.getAnnotations().stream().anyMatch(annotation -> annotation.toString().startsWith(annotationDeclaration)));
@ -108,6 +134,15 @@ public class JavaIdentifier extends StructuralUnitIdentifier {
return false; return false;
} }
private boolean sourceCodeContainsClass(String sourceCode) {
JavaParser parser = new JavaParser();
ParseResult<CompilationUnit> parseResult = parser.parse(sourceCode);
if (parseResult.getResult().isPresent() && parseResult.getResult().get().findCompilationUnit().isPresent()) {
return parseResult.getResult().get().getTypes().stream().findAny().isPresent();
}
return false;
}
@Override @Override
protected String getSourceDirectory(List<File> rootDirectoryFiles) { protected String getSourceDirectory(List<File> rootDirectoryFiles) {
return buildToolService.getProjectBuildTool(rootDirectoryFiles) return buildToolService.getProjectBuildTool(rootDirectoryFiles)

View File

@ -8,49 +8,53 @@ package ru.ulstu.extractor.heuristic.service;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.ulstu.extractor.heuristic.api.StructuralUnitIdentifier; import ru.ulstu.extractor.heuristic.api.StructuralUnitIdentifier;
import ru.ulstu.extractor.heuristic.model.StructuralUnit; import ru.ulstu.extractor.heuristic.model.StructuralUnit;
import ru.ulstu.extractor.service.GitRepositoryService;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.function.Predicate; import java.util.function.Predicate;
@Service @Service
public class StructuralUnitService { public class StructuralUnitService {
private final GitRepositoryService gitRepositoryService;
private final DirectoryService directoryService; private final DirectoryService directoryService;
private final List<StructuralUnitIdentifier> structuralUnitIdentifiers; private final List<StructuralUnitIdentifier> structuralUnitIdentifiers;
public StructuralUnitService(GitRepositoryService gitRepositoryService, public StructuralUnitService(DirectoryService directoryService,
DirectoryService directoryService,
List<StructuralUnitIdentifier> structuralUnitIdentifiers) { List<StructuralUnitIdentifier> structuralUnitIdentifiers) {
this.gitRepositoryService = gitRepositoryService;
this.directoryService = directoryService; this.directoryService = directoryService;
this.structuralUnitIdentifiers = structuralUnitIdentifiers; this.structuralUnitIdentifiers = structuralUnitIdentifiers;
} }
public List<StructuralUnit> getEntities(String repositoryUrl) throws IOException { public List<StructuralUnit> getEntities(File rootPath) throws IOException {
File rootPath = gitRepositoryService.getProjectDirectoryFile(repositoryUrl);
List<File> projectFiles = directoryService.getFilesRecursively(rootPath); List<File> projectFiles = directoryService.getFilesRecursively(rootPath);
List<File> rootProjectFiles = directoryService.getDirectoryFiles(rootPath.toPath()); List<File> rootProjectFiles = directoryService.getDirectoryFiles(rootPath.toPath());
return getStructuralUnitIdentifier( return getStructuralUnitIdentifier(
structuralUnitIdentifier -> structuralUnitIdentifier.canAppliedToProject( structuralUnitIdentifier -> structuralUnitIdentifier.canAppliedToProject(
rootPath.getPath(), rootPath.getPath(),
projectFiles, projectFiles,
rootProjectFiles) rootProjectFiles))
).getEntityClasses(rootPath.getPath(), projectFiles, rootProjectFiles); .orElseThrow(() -> new RuntimeException("Identifier not found"))
.getEntityClasses(rootPath.getPath(), projectFiles, rootProjectFiles);
} }
public boolean containsEntity(File projectFile) { public boolean containsEntity(File projectFile) {
return getStructuralUnitIdentifier( return getStructuralUnitIdentifier(
structuralUnitIdentifier -> structuralUnitIdentifier.canAppliedToFile(projectFile) structuralUnitIdentifier -> structuralUnitIdentifier.canAppliedToFile(projectFile))
).isEntityClass(projectFile); .map(identifier -> identifier.isEntityClass(projectFile))
.orElse(false);
} }
private StructuralUnitIdentifier getStructuralUnitIdentifier(Predicate<StructuralUnitIdentifier> predicate) { public boolean containsEntity(String sourceCode) {
return getStructuralUnitIdentifier(
structuralUnitIdentifier -> structuralUnitIdentifier.canAppliedToCode(sourceCode))
.map(identifier -> identifier.isEntityClass(sourceCode))
.orElse(false);
}
private Optional<StructuralUnitIdentifier> getStructuralUnitIdentifier(Predicate<StructuralUnitIdentifier> predicate) {
return structuralUnitIdentifiers.stream() return structuralUnitIdentifiers.stream()
.filter(predicate) .filter(predicate)
.findAny() .findAny();
.orElseThrow(() -> new RuntimeException("Identifier not found"));
} }
} }

View File

@ -1,3 +1,8 @@
/*
* 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.model; package ru.ulstu.extractor.model;
import org.hibernate.annotations.Fetch; import org.hibernate.annotations.Fetch;
@ -20,6 +25,9 @@ public class FileChange extends BaseEntity {
@Transient @Transient
private boolean added; private boolean added;
@Transient
private boolean containsEntity;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "file_change_id", unique = true) @JoinColumn(name = "file_change_id", unique = true)
@Fetch(FetchMode.SUBSELECT) @Fetch(FetchMode.SUBSELECT)
@ -71,4 +79,12 @@ public class FileChange extends BaseEntity {
public boolean isAdded() { public boolean isAdded() {
return added; return added;
} }
public boolean isContainsEntity() {
return containsEntity;
}
public void setContainsEntity(boolean containsEntity) {
this.containsEntity = containsEntity;
}
} }

View File

@ -12,10 +12,15 @@ import org.eclipse.jgit.api.ListBranchCommand;
import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffFormatter; import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.internal.storage.file.FileRepository; 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.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.ulstu.extractor.heuristic.service.StructuralUnitService;
import ru.ulstu.extractor.model.Author; import ru.ulstu.extractor.model.Author;
import ru.ulstu.extractor.model.Branch; import ru.ulstu.extractor.model.Branch;
import ru.ulstu.extractor.model.Commit; import ru.ulstu.extractor.model.Commit;
@ -28,6 +33,7 @@ import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path; import java.nio.file.Path;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
@ -44,6 +50,12 @@ public class GitRepositoryService {
@Value("${extractor.custom-projects-dir}") @Value("${extractor.custom-projects-dir}")
private String customProjectsDir; private String customProjectsDir;
private final StructuralUnitService structuralUnitService;
public GitRepositoryService(StructuralUnitService structuralUnitService) {
this.structuralUnitService = structuralUnitService;
}
public List<Branch> getRemoteBranches(String url) throws GitAPIException, IOException { public List<Branch> getRemoteBranches(String url) throws GitAPIException, IOException {
cloneOrUpdateRepo(url); cloneOrUpdateRepo(url);
Repository localRepo = new FileRepository(getProjectGitDirectory(url)); Repository localRepo = new FileRepository(getProjectGitDirectory(url));
@ -177,10 +189,10 @@ public class GitRepositoryService {
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("Error occurred during diff computation. Message: " + e.getMessage()); throw new RuntimeException("Error occurred during diff computation. Message: " + e.getMessage());
} }
return parseOutputDiff(output); return parseOutputDiff(output, localRepo, laterCommit);
} }
private List<FileChange> parseOutputDiff(String output) { private List<FileChange> parseOutputDiff(String output, Repository repository, RevCommit commit) {
List<FileChange> changes = new ArrayList<>(); List<FileChange> changes = new ArrayList<>();
String[] strings = output.split("\n"); String[] strings = output.split("\n");
FileChange fileChange = new FileChange(); FileChange fileChange = new FileChange();
@ -191,6 +203,9 @@ public class GitRepositoryService {
if (maybeFileName.isPresent()) { if (maybeFileName.isPresent()) {
fileChange = new FileChange(); fileChange = new FileChange();
fileChange.setFile(maybeFileName.get()); fileChange.setFile(maybeFileName.get());
fileChange.setContainsEntity(
structuralUnitService.containsEntity(getContent(repository, commit, maybeFileName.get()))
);
/// вытащить другие изменения из коммита /// вытащить другие изменения из коммита
changes.add(fileChange); changes.add(fileChange);
} }
@ -226,6 +241,22 @@ public class GitRepositoryService {
return changes; return changes;
} }
private String getContent(Repository repository, RevCommit commit, String path) {
try (TreeWalk treeWalk = TreeWalk.forPath(repository, path, commit.getTree())) {
if (treeWalk != null) {
ObjectId blobId = treeWalk.getObjectId(0);
try (ObjectReader objectReader = repository.newObjectReader()) {
ObjectLoader objectLoader = objectReader.open(blobId);
byte[] bytes = objectLoader.getBytes();
return new String(bytes, StandardCharsets.UTF_8);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
return "";
}
private Optional<String> getFileName(String commitString) { private Optional<String> getFileName(String commitString) {
String startString = "diff --git a/"; String startString = "diff --git a/";
if (commitString.startsWith(startString)) { if (commitString.startsWith(startString)) {