Skip to content

Commit

Permalink
moditect#28 Basing internal model on components instead of packages;
Browse files Browse the repository at this point in the history
A component can comprise one or more package, the architecture is now
defined in terms of component relationships. The external format (deptective.json)
is still based on packages, using a 1:1 relationship between packages and
components.
  • Loading branch information
gunnarmorling committed Jan 20, 2019
1 parent 11a4fb9 commit fff700e
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ public DeptectiveTreeVisitor(JavacTask task, Log log, PackageReferenceHandler pa
@Override
public Void visitCompilationUnit(CompilationUnitTree tree, Void p) {
log.useSource(tree.getSourceFile());
packageReferenceHandler.onEnteringCompilationUnit(tree);
boolean proceed = packageReferenceHandler.onEnteringCompilationUnit(tree);

return super.visitCompilationUnit(tree, p);
return proceed ? super.visitCompilationUnit(tree, p) : null;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
import java.util.TreeMap;
import java.util.TreeSet;

import org.moditect.deptective.internal.model.Package;
import org.moditect.deptective.internal.model.Package.ReadKind;
import org.moditect.deptective.internal.model.Component;
import org.moditect.deptective.internal.model.PackagePattern;
import org.moditect.deptective.internal.model.ReadKind;

/**
* Serializes models to GraphViz format ("DOT files").
Expand All @@ -50,19 +50,19 @@ public DotSerializer() {
}

@Override
public void addPackage(Package pakkage) {
allPackages.add(pakkage.getName());
public void addComponent(Component component) {
allPackages.add(component.getName());

SortedSet<String> allowed = new TreeSet<>();
allowedReads.put(pakkage.getName(), allowed);
allowedReads.put(component.getName(), allowed);

SortedSet<String> disallowed = new TreeSet<>();
disallowedReads.put(pakkage.getName(), disallowed);
disallowedReads.put(component.getName(), disallowed);

SortedSet<String> unknown = new TreeSet<>();
unknownReads.put(pakkage.getName(), unknown);
unknownReads.put(component.getName(), unknown);

for (Entry<String, ReadKind> referencedPackage : pakkage.getReads().entrySet()) {
for (Entry<String, ReadKind> referencedPackage : component.getReads().entrySet()) {
String referencedPackageName = referencedPackage.getKey();
allPackages.add(referencedPackageName);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
package org.moditect.deptective.internal.export;

import org.moditect.deptective.internal.model.Package;
import org.moditect.deptective.internal.model.Component;
import org.moditect.deptective.internal.model.PackagePattern;

import com.fasterxml.jackson.core.JsonProcessingException;
Expand Down Expand Up @@ -48,8 +48,8 @@ public JsonSerializer() {
}

@Override
public void addPackage(Package pakkage) {
packages.add(toJsonNode(pakkage, mapper));
public void addComponent(Component component) {
packages.add(toJsonNode(component, mapper));
}

@Override
Expand All @@ -67,14 +67,14 @@ public String serialize() {
}
}

private JsonNode toJsonNode(Package pakkage, ObjectMapper mapper) {
private JsonNode toJsonNode(Component component, ObjectMapper mapper) {
ObjectNode node = mapper.createObjectNode();

node.put("name", pakkage.getName());
node.put("name", component.getName());

if (!pakkage.getReads().isEmpty()) {
if (!component.getReads().isEmpty()) {
ArrayNode reads = node.putArray("reads");
pakkage.getReads()
component.getReads()
.keySet()
.stream()
.sorted()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
package org.moditect.deptective.internal.export;

import org.moditect.deptective.internal.model.Package;
import org.moditect.deptective.internal.model.Component;
import org.moditect.deptective.internal.model.PackagePattern;

/**
Expand All @@ -25,7 +25,7 @@
*/
public interface ModelSerializer {

void addPackage(Package pakkage);
void addComponent(Component component);

void addWhitelistedPackagePattern(PackagePattern pattern);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@
import org.moditect.deptective.internal.export.ModelSerializer;
import org.moditect.deptective.internal.log.DeptectiveMessages;
import org.moditect.deptective.internal.log.Log;
import org.moditect.deptective.internal.model.Package.ReadKind;
import org.moditect.deptective.internal.model.PackageDependencies;
import org.moditect.deptective.internal.model.PackagePattern;
import org.moditect.deptective.internal.model.ReadKind;

import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.ExpressionTree;
Expand Down Expand Up @@ -73,16 +73,18 @@ public PackageReferenceCollector(JavaFileManager jfm, Log log, List<PackagePatte
}

@Override
public void onEnteringCompilationUnit(CompilationUnitTree tree) {
public boolean onEnteringCompilationUnit(CompilationUnitTree tree) {
ExpressionTree packageNameTree = tree.getPackageName();

// TODO deal with default package
if (packageNameTree == null) {
return;
return false;
}

currentPackageName = packageNameTree.toString();
packagesOfCurrentCompilation.add(currentPackageName);

return true;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,12 @@ default public boolean configIsValid() {

/**
* Invoked when entering a new compilation unit.
*
* @return Whether the invoking visitor should continue to step down into the AST or not. Implementation should
* return false when detecting an invalid configuration.
*/
default void onEnteringCompilationUnit(CompilationUnitTree tree) {
default boolean onEnteringCompilationUnit(CompilationUnitTree tree) {
return true;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@
import org.moditect.deptective.internal.export.DotSerializer;
import org.moditect.deptective.internal.log.DeptectiveMessages;
import org.moditect.deptective.internal.log.Log;
import org.moditect.deptective.internal.model.Package;
import org.moditect.deptective.internal.model.Package.ReadKind;
import org.moditect.deptective.internal.model.Component;
import org.moditect.deptective.internal.model.PackageAssignedToMultipleComponentsException;
import org.moditect.deptective.internal.model.PackageDependencies;
import org.moditect.deptective.internal.model.ReadKind;
import org.moditect.deptective.internal.options.ReportingPolicy;

import com.sun.source.tree.CompilationUnitTree;
Expand All @@ -54,7 +55,8 @@ public class PackageReferenceValidator implements PackageReferenceHandler {

private final PackageDependencies.Builder actualPackageDependencies;

private Package currentPackage;
private String currentPackageName;
private Component currentComponent;

public PackageReferenceValidator(JavaFileManager jfm, PackageDependencies packageDependencies,
ReportingPolicy reportingPolicy, ReportingPolicy unconfiguredPackageReportingPolicy, boolean createDotFile,
Expand All @@ -80,20 +82,36 @@ public boolean configIsValid() {
}

@Override
public void onEnteringCompilationUnit(CompilationUnitTree tree) {
public boolean onEnteringCompilationUnit(CompilationUnitTree tree) {
ExpressionTree packageNameTree = tree.getPackageName();

// TODO deal with default package
if (packageNameTree == null) {
return;
return false;
}

String packageName = packageNameTree.toString();
currentPackage = allowedPackageDependencies.getPackage(packageName);
currentPackageName = packageName;

try {
currentComponent = allowedPackageDependencies.getComponentByPackage(packageName);

if (currentComponent == null) {
reportUnconfiguredPackageIfNeeded(tree, packageName);
}
}
catch (PackageAssignedToMultipleComponentsException e) {
log.report(
ReportingPolicy.ERROR,
DeptectiveMessages.PACKAGE_CONTAINED_IN_MULTIPLE_COMPONENTS,
e.getMatchingComponents(),
packageName
);

if (!currentPackage.isConfigured()) {
reportUnconfiguredPackageIfNeeded(tree, packageName);
return false;
}

return true;
}

@Override
Expand All @@ -102,30 +120,34 @@ public void onPackageReference(Tree referencingNode, String referencedPackageNam
return;
}

ReadKind readKind;
Component referencedComponent = Component.builder(referencedPackageName).build();

if (!currentPackage.isConfigured()) {
readKind = ReadKind.UKNOWN;
if (currentComponent == null) {
actualPackageDependencies.addRead(
Component.builder(currentPackageName).build().getName(),
referencedComponent.getName(),
ReadKind.UKNOWN
);
}
else if (currentPackage.allowedToRead(referencedPackageName)) {
readKind = ReadKind.ALLOWED;
else if (currentComponent.allowedToRead(referencedComponent)) {
actualPackageDependencies.addRead(
currentComponent.getName(),
referencedComponent.getName(),
ReadKind.ALLOWED
);
}
else {
readKind = ReadKind.DISALLOWED;
}

actualPackageDependencies.addRead(currentPackage.getName(), referencedPackageName, readKind);

if (readKind == ReadKind.UKNOWN) {
return;
}
actualPackageDependencies.addRead(
currentComponent.getName(),
referencedComponent.getName(),
ReadKind.DISALLOWED
);

if (readKind == ReadKind.DISALLOWED) {
log.report(
reportingPolicy,
(com.sun.tools.javac.tree.JCTree) referencingNode,
DeptectiveMessages.ILLEGAL_PACKAGE_DEPENDENCY,
currentPackage,
currentComponent.getName(),
referencedPackageName
);
}
Expand All @@ -140,7 +162,8 @@ public void onCompletingCompilation() {
}

DotSerializer serializer = new DotSerializer();
actualPackageDependencies.build().serialize(serializer);
PackageDependencies build = actualPackageDependencies.build();
build.serialize(serializer);

try {
FileObject output = jfm.getFileForOutput(StandardLocation.CLASS_OUTPUT, "", "deptective.dot", null);
Expand All @@ -157,7 +180,7 @@ public void onCompletingCompilation() {
private boolean isIgnoredDependency(String referencedPackageName) {
return "java.lang".equals(referencedPackageName) ||
allowedPackageDependencies.isWhitelisted(referencedPackageName) ||
currentPackage.getName().equals(referencedPackageName) ||
currentPackageName.equals(referencedPackageName) ||
referencedPackageName.isEmpty();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class DeptectiveMessages extends ListResourceBundle {
public static final String PACKAGE_NOT_CONFIGURED = "deptective.packagenotconfigured";
public static final String GENERATED_CONFIG = "deptective.generatedconfig";
public static final String GENERATED_DOT_REPRESENTATION = "deptective.dotrepresentation";
public static final String PACKAGE_CONTAINED_IN_MULTIPLE_COMPONENTS = "deptective.packageinmultiplecomponents";

@Override
protected final Object[][] getContents() {
Expand All @@ -39,7 +40,9 @@ protected final Object[][] getContents() {
{ ERROR_PREFIX + NO_DEPTECTIVE_CONFIG_FOUND, "Config file deptective.json was not found" },
{ NOTE_PREFIX + GENERATED_CONFIG, "Generated Deptective configuration template at {0}" },
{ NOTE_PREFIX + GENERATED_DOT_REPRESENTATION,
"Created DOT file representing the Deptective configuration at {0}" }
"Created DOT file representing the Deptective configuration at {0}" },
{ ERROR_PREFIX + PACKAGE_CONTAINED_IN_MULTIPLE_COMPONENTS,
"Multiple components match package {1}: {0}" },
};
}

Expand Down
Loading

0 comments on commit fff700e

Please sign in to comment.