package sample; import com.github.javaparser.JavaParser; import com.github.javaparser.Range; import com.github.javaparser.ast.CompilationUnit; import org.junit.Test; import strip.Detector; import strip.javadoctrim.JavadocToTrimDetector; import strip.finder.SourceFileFinder; import strip.copyright.CopyrightBlockDetector; import strip.javadoctag.UnwantedJavaDocTagDetector; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.function.IntPredicate; import java.util.stream.Collectors; import java.util.stream.IntStream; import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; import static java.nio.file.StandardOpenOption.WRITE; public class RemoveCopyrightHeaders { private final SourceFileFinder sourceFileFinder = new SourceFileFinder(this::log); private final Path pathToSampleJavaFile = Paths.get("src/main/java/sample/JavaDocOnClass.java"); @Test public void removeCopyrightHeaderInSampleFile() throws Exception { remove(copyrightBlock(), pathToSampleJavaFile); } @Test public void removeCopyRightHeadersInProject() throws Exception { removeInProject(copyrightBlock(), Paths.get("")); } @Test public void removeAuthorTagInSampleFile() throws Exception { remove(javadocTag("author"), pathToSampleJavaFile); remove(javadocTag("since"), pathToSampleJavaFile); } @Test public void runAllDetectors() throws Exception { remove(copyrightBlock(), pathToSampleJavaFile); remove(javadocTag("author"), pathToSampleJavaFile); remove(javadocTag("since"), pathToSampleJavaFile); remove(new JavadocToTrimDetector(this::log), pathToSampleJavaFile); } @Test public void removeAuthorTagInProject() throws Exception { Path projectDirectory = Paths.get(""); removeInProject(javadocTag("author"), projectDirectory); removeInProject(javadocTag("since"), projectDirectory); } private CopyrightBlockDetector copyrightBlock() { return new CopyrightBlockDetector(this::log); } private UnwantedJavaDocTagDetector javadocTag(String author) { return new UnwantedJavaDocTagDetector(author, this::log); } private void removeInProject(Detector detector, Path projectDirectory) throws IOException { sourceFileFinder.javaFilesInProjectAt(projectDirectory) .parallelStream() .forEach(javaSourceFile -> remove(detector, javaSourceFile)); } private void remove(Detector detector, Path javaSourceFile) { CompilationUnit cu = parseAsCompilationUnit(javaSourceFile); List<Range> maybeToRemove = detector.findCodeToRemoveIn(cu, javaSourceFile); List<Range> sortedByLine = maybeToRemove.stream().sorted((o1, o2) -> o1.end.compareTo(o2.begin)).collect(Collectors.toList()); Collections.reverse(sortedByLine); sortedByLine.forEach(rangeToRemove -> removeRangeIn(rangeToRemove, javaSourceFile)); } private void removeRangeIn(Range locationToRemove, Path javaSourceFile) { List<String> allLines = readAllLinesIn(javaSourceFile); List<String> copyrightNotice = extractLines(allLines, copyrightNotice(locationToRemove)); String lastCopyrightLine = copyrightNotice.get(copyrightNotice.size() - 1); if (lastCopyrightLine.length() != locationToRemove.end.column - 1) { log("Skipping file where last line of copyright notice seems not to span the entire line: " + javaSourceFile); return; } List<String> sourceLinesWithoutCopyrightNotice = extractLines(allLines, copyrightNotice(locationToRemove).negate()); while (sourceLinesWithoutCopyrightNotice.get(0).trim().isEmpty()) { sourceLinesWithoutCopyrightNotice.remove(0); } byte[] bytes = sourceLinesWithoutCopyrightNotice.stream().collect(Collectors.joining("\n")).getBytes(utf_8); write(javaSourceFile, bytes); } private List<String> extractLines(List<String> allLines, IntPredicate lineSelector) { return IntStream.range(0, allLines.size()) .filter(lineSelector) .mapToObj(allLines::get) .collect(Collectors.toList()); } private IntPredicate copyrightNotice(Range location) { return line -> { int beginLineZeroBased = location.begin.line - 1; int endLineZeroBased = location.end.line - 1; return !(line < beginLineZeroBased | line > endLineZeroBased); }; } private final Charset utf_8 = Charset.forName("UTF-8"); private List<String> readAllLinesIn(Path javaSourceFile) { try { byte[] bytes = Files.readAllBytes(javaSourceFile); String javaSource = new String(bytes, utf_8); return Arrays.asList(javaSource.split("\n", -1)); } catch (IOException e) { throw new RuntimeException("should never happen", e); } } private CompilationUnit parseAsCompilationUnit(Path javaSourceFile) { try { return JavaParser.parse(javaSourceFile.toAbsolutePath().toFile()); } catch (FileNotFoundException e) { throw new RuntimeException("should never happen", e); } } private Path write(Path javaSourceFile, byte[] bytes) { try { return Files.write(javaSourceFile, bytes, WRITE, TRUNCATE_EXISTING); } catch (IOException e) { throw new RuntimeException("should never happen", e); } } private void log(String message) { System.out.println(message); } }