-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Import package detector from analysis-model.
- Loading branch information
Showing
11 changed files
with
519 additions
and
0 deletions.
There are no files selected for viewing
99 changes: 99 additions & 0 deletions
99
src/main/java/edu/hm/hafner/util/AbstractPackageDetector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package edu.hm.hafner.util; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.nio.charset.Charset; | ||
import java.nio.file.InvalidPathException; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
import java.util.stream.Stream; | ||
|
||
import org.apache.commons.io.input.BOMInputStream; | ||
|
||
import edu.hm.hafner.util.PackageDetectors.*; | ||
|
||
import static edu.hm.hafner.util.PackageDetectors.*; | ||
|
||
/** | ||
* Base class for package detectors. | ||
* | ||
* @author Ullrich Hafner | ||
*/ | ||
abstract class AbstractPackageDetector { | ||
private final FileSystem fileSystem; | ||
|
||
/** | ||
* Creates a new instance of {@link AbstractPackageDetector}. | ||
* | ||
* @param fileSystem | ||
* file system facade | ||
*/ | ||
AbstractPackageDetector(final FileSystem fileSystem) { | ||
this.fileSystem = fileSystem; | ||
} | ||
|
||
/** | ||
* Detects the package or namespace name of the specified file. | ||
* | ||
* @param fileName | ||
* the file name of the file to scan | ||
* @param charset | ||
* the charset to use when reading the source files | ||
* | ||
* @return the detected package or namespace name | ||
*/ | ||
public String detectPackageName(final String fileName, final Charset charset) { | ||
if (accepts(fileName)) { | ||
try (InputStream stream = fileSystem.openFile(fileName)) { | ||
return detectPackageName(stream, charset); | ||
} | ||
catch (IOException | InvalidPathException ignore) { | ||
// ignore IO errors | ||
} | ||
} | ||
return UNDEFINED_PACKAGE; | ||
} | ||
|
||
@VisibleForTesting | ||
String detectPackageName(final InputStream stream, final Charset charset) throws IOException { | ||
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(BOMInputStream.builder().setInputStream(stream).get(), charset))) { | ||
return detectPackageName(buffer.lines()); | ||
} | ||
} | ||
|
||
/** | ||
* Detects the package or namespace name of the specified input stream. The stream will be closed automatically by | ||
* the caller of this method. | ||
* | ||
* @param lines | ||
* the content of the file to scan | ||
* | ||
* @return the detected package or namespace name | ||
*/ | ||
String detectPackageName(final Stream<String> lines) { | ||
Pattern pattern = getPattern(); | ||
return lines.map(pattern::matcher) | ||
.filter(Matcher::matches) | ||
.findFirst() | ||
.map(matcher -> matcher.group(1)) | ||
.orElse(UNDEFINED_PACKAGE).trim(); | ||
} | ||
|
||
/** | ||
* Returns the Pattern for the Package Name in this kind of file. | ||
* @return the Pattern. | ||
*/ | ||
abstract Pattern getPattern(); | ||
|
||
/** | ||
* Returns whether this classifier accepts the specified file for processing. | ||
* | ||
* @param fileName | ||
* the file name | ||
* | ||
* @return {@code true} if the classifier accepts the specified file for processing. | ||
*/ | ||
abstract boolean accepts(String fileName); | ||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/edu/hm/hafner/util/CSharpNamespaceDetector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package edu.hm.hafner.util; | ||
|
||
import java.util.regex.Pattern; | ||
|
||
import edu.hm.hafner.util.PackageDetectors.FileSystem; | ||
|
||
/** | ||
* Detects the namespace of a C# workspace file. | ||
* | ||
* @author Ullrich Hafner | ||
*/ | ||
class CSharpNamespaceDetector extends AbstractPackageDetector { | ||
private static final Pattern NAMESPACE_PATTERN = Pattern.compile("^\\s*namespace\\s+([^{]*)\\s*\\{?\\s*$"); | ||
|
||
CSharpNamespaceDetector() { | ||
this(new FileSystem()); | ||
} | ||
|
||
@VisibleForTesting | ||
CSharpNamespaceDetector(final FileSystem fileSystem) { | ||
super(fileSystem); | ||
} | ||
|
||
@Override | ||
public boolean accepts(final String fileName) { | ||
return fileName.endsWith(".cs"); | ||
} | ||
|
||
@Override | ||
Pattern getPattern() { | ||
return NAMESPACE_PATTERN; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package edu.hm.hafner.util; | ||
|
||
import java.util.regex.Pattern; | ||
|
||
import edu.hm.hafner.util.PackageDetectors.FileSystem; | ||
|
||
/** | ||
* Detects the package name of a Java file. | ||
* | ||
* @author Ullrich Hafner | ||
*/ | ||
class JavaPackageDetector extends AbstractPackageDetector { | ||
private static final Pattern PACKAGE_PATTERN = Pattern.compile( | ||
"^\\s*package\\s*([a-z]+[.\\w]*)\\s*;.*"); | ||
|
||
JavaPackageDetector() { | ||
this(new FileSystem()); | ||
} | ||
|
||
@VisibleForTesting | ||
JavaPackageDetector(final FileSystem fileSystem) { | ||
super(fileSystem); | ||
} | ||
|
||
@Override | ||
Pattern getPattern() { | ||
return PACKAGE_PATTERN; | ||
} | ||
|
||
@Override | ||
public boolean accepts(final String fileName) { | ||
return fileName.endsWith(".java"); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/edu/hm/hafner/util/KotlinPackageDetector.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package edu.hm.hafner.util; | ||
|
||
import java.util.regex.Pattern; | ||
|
||
import edu.hm.hafner.util.PackageDetectors.FileSystem; | ||
|
||
/** | ||
* Detects the package name of a Kotlin file. | ||
* | ||
* @author Bastian Kersting | ||
*/ | ||
class KotlinPackageDetector extends AbstractPackageDetector { | ||
private static final Pattern PACKAGE_PATTERN = Pattern.compile( | ||
"^\\s*package\\s*([a-z]+[.\\w]*)\\s*.*"); | ||
|
||
KotlinPackageDetector() { | ||
this(new FileSystem()); | ||
} | ||
|
||
@VisibleForTesting | ||
KotlinPackageDetector(final FileSystem fileSystem) { | ||
super(fileSystem); | ||
} | ||
|
||
@Override | ||
Pattern getPattern() { | ||
return PACKAGE_PATTERN; | ||
} | ||
|
||
@Override | ||
boolean accepts(final String fileName) { | ||
return fileName.endsWith(".kt"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package edu.hm.hafner.util; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.nio.charset.Charset; | ||
import java.nio.file.Files; | ||
import java.nio.file.InvalidPathException; | ||
import java.nio.file.Paths; | ||
import java.util.List; | ||
|
||
import com.google.errorprone.annotations.MustBeClosed; | ||
|
||
/** | ||
* Provides convenient methods to determine the package or namespace names of a file. | ||
* | ||
* @author Ullrich Hafner | ||
*/ | ||
class PackageDetectors { | ||
/** If no package could be assigned this value is used as package name. */ | ||
static final String UNDEFINED_PACKAGE = "-"; | ||
|
||
private final List<AbstractPackageDetector> detectors; | ||
|
||
@VisibleForTesting | ||
PackageDetectors(final List<AbstractPackageDetector> detectors) { | ||
this.detectors = detectors; | ||
} | ||
|
||
/** | ||
* Detects the package name of the specified file based on several detector strategies. | ||
* | ||
* @param fileName | ||
* the filename of the file to scan | ||
* @param charset | ||
* the charset to use when reading the source files | ||
* | ||
* @return the package name or the String {@link #UNDEFINED_PACKAGE} if no package could be detected | ||
*/ | ||
public String detectPackageName(final String fileName, final Charset charset) { | ||
for (AbstractPackageDetector detector : detectors) { | ||
if (detector.accepts(fileName)) { | ||
return detector.detectPackageName(fileName, charset); | ||
} | ||
} | ||
return UNDEFINED_PACKAGE; | ||
} | ||
|
||
/** | ||
* Facade for file system operations. May be replaced by stubs in test cases. | ||
*/ | ||
@VisibleForTesting | ||
static class FileSystem { | ||
@MustBeClosed | ||
InputStream openFile(final String fileName) throws IOException, InvalidPathException { | ||
return Files.newInputStream(Paths.get(fileName)); | ||
} | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
src/test/java/edu/hm/hafner/util/PackageDetectorsTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package edu.hm.hafner.util; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
|
||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.CsvSource; | ||
|
||
import edu.hm.hafner.util.PackageDetectors.FileSystem; | ||
|
||
import static edu.hm.hafner.util.assertions.Assertions.*; | ||
import static org.mockito.Mockito.*; | ||
|
||
/** | ||
* Tests the class {@link PackageDetectors}. | ||
* | ||
* @author Ullrich Hafner | ||
*/ | ||
class PackageDetectorsTest extends ResourceTest { | ||
@ParameterizedTest(name = "{index} => file={0}, expected package={1}") | ||
@CsvSource({ | ||
"MavenJavaTest.txt.java, hudson.plugins.tasks.util", | ||
"ActionBinding.cs, Avaloq.SmartClient.Utilities", | ||
"MavenJavaTest.txt, -", | ||
"relative.txt, -", | ||
"KotlinTest.txt, -", | ||
"KotlinTest.txt.kt, edu.hm.kersting", | ||
}) | ||
void shouldExtractPackageNames(final String fileName, final String expectedPackage) throws IOException { | ||
try (InputStream stream = asInputStream(fileName)) { | ||
FileSystem fileSystem = mock(FileSystem.class); | ||
when(fileSystem.openFile(fileName)).thenReturn(stream); | ||
|
||
ArrayList<AbstractPackageDetector> detectors = new ArrayList<>(Arrays.asList( | ||
new JavaPackageDetector(fileSystem), | ||
new CSharpNamespaceDetector(fileSystem), | ||
new KotlinPackageDetector(fileSystem) | ||
)); | ||
|
||
assertThat(new PackageDetectors(detectors).detectPackageName(fileName, StandardCharsets.UTF_8)) | ||
.isEqualTo(expectedPackage); | ||
} | ||
} | ||
} |
Oops, something went wrong.