package org.jabref;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class MainArchitectureTests {
public static final String CLASS_ORG_JABREF_GLOBALS = "org.jabref.Globals";
private static final String PACKAGE_JAVAX_SWING = "javax.swing";
private static final String PACKAGE_JAVA_AWT = "java.awt";
private static final String PACKAGE_JAVA_FX = "javafx";
private static final String PACKAGE_ORG_JABREF_GUI = "org.jabref.gui";
private static final String PACKAGE_ORG_JABREF_LOGIC = "org.jabref.logic";
private static final String PACKAGE_ORG_JABREF_MODEL = "org.jabref.model";
private static final String EXCEPTION_PACKAGE_JAVA_AWT_GEOM = "java.awt.geom";
private static final String EXCEPTION_PACKAGE_JAVA_FX_COLLECTIONS = "javafx.collections";
private static final String EXCEPTION_PACKAGE_JAVA_FX_BEANS = "javafx.beans";
private static final String EXCEPTION_CLASS_JAVA_FX_COLOR = "javafx.scene.paint.Color";
private final String firstPackage;
private final String secondPackage;
private Map<String, List<String>> exceptions;
public MainArchitectureTests(String firstPackage, String secondPackage) {
this.firstPackage = firstPackage;
this.secondPackage = secondPackage;
// Add exceptions for the architectural test here
// Note that bending the architectural constraints should not be done inconsiderately
exceptions = new HashMap<>();
List<String> logicExceptions = new ArrayList<>(4);
logicExceptions.add(EXCEPTION_PACKAGE_JAVA_AWT_GEOM);
logicExceptions.add(EXCEPTION_PACKAGE_JAVA_FX_COLLECTIONS);
logicExceptions.add(EXCEPTION_PACKAGE_JAVA_FX_BEANS);
logicExceptions.add(EXCEPTION_CLASS_JAVA_FX_COLOR);
List<String> modelExceptions = new ArrayList<>(4);
modelExceptions.add(EXCEPTION_PACKAGE_JAVA_FX_COLLECTIONS);
modelExceptions.add(EXCEPTION_CLASS_JAVA_FX_COLOR);
modelExceptions.add(EXCEPTION_PACKAGE_JAVA_FX_COLLECTIONS);
modelExceptions.add(EXCEPTION_PACKAGE_JAVA_FX_BEANS);
exceptions.put(PACKAGE_ORG_JABREF_LOGIC, logicExceptions);
exceptions.put(PACKAGE_ORG_JABREF_MODEL, modelExceptions);
}
@Parameterized.Parameters(name = "{index} -- is {0} independent of {1}?")
public static Iterable<Object[]> data() {
return Arrays.asList(
new Object[][]{
{PACKAGE_ORG_JABREF_LOGIC, PACKAGE_JAVA_AWT},
{PACKAGE_ORG_JABREF_LOGIC, PACKAGE_JAVAX_SWING},
{PACKAGE_ORG_JABREF_LOGIC, PACKAGE_JAVA_FX},
{PACKAGE_ORG_JABREF_LOGIC, PACKAGE_ORG_JABREF_GUI},
{PACKAGE_ORG_JABREF_LOGIC, CLASS_ORG_JABREF_GLOBALS},
{PACKAGE_ORG_JABREF_MODEL, PACKAGE_JAVA_AWT},
{PACKAGE_ORG_JABREF_MODEL, PACKAGE_JAVAX_SWING},
{PACKAGE_ORG_JABREF_MODEL, PACKAGE_JAVA_FX},
{PACKAGE_ORG_JABREF_MODEL, PACKAGE_ORG_JABREF_GUI},
{PACKAGE_ORG_JABREF_MODEL, PACKAGE_ORG_JABREF_LOGIC},
{PACKAGE_ORG_JABREF_MODEL, CLASS_ORG_JABREF_GLOBALS}
}
);
}
@Test
public void firstPackageIsIndependentOfSecondPackage() throws IOException {
Predicate<String> isExceptionPackage = (s) ->
s.startsWith("import " + secondPackage)
&& exceptions.getOrDefault(firstPackage, Collections.emptyList()).stream()
.noneMatch(exception -> s.startsWith("import " + exception));
Predicate<String> isPackage = (s) -> s.startsWith("package " + firstPackage);
List<Path> files = Files.walk(Paths.get("src/main/"))
.filter(p -> p.toString().endsWith(".java"))
.filter(p -> {
try {
return Files.readAllLines(p, StandardCharsets.UTF_8).stream().anyMatch(isPackage);
} catch (IOException e) {
return false;
}
})
.filter(p -> {
try {
return Files.readAllLines(p, StandardCharsets.UTF_8).stream().anyMatch(isExceptionPackage);
} catch (IOException e) {
return false;
}
}).collect(Collectors.toList());
Assert.assertEquals("The following classes are not allowed to depend on " + secondPackage,
Collections.emptyList(), files);
}
}