Skip to content

Commit

Permalink
Separates severity levels from the violations, making it easier for t…
Browse files Browse the repository at this point in the history
…eams to customise how they use/extend the feature.
  • Loading branch information
simonbrowndotje committed Jan 19, 2024
1 parent e2a6600 commit cbd3e19
Show file tree
Hide file tree
Showing 74 changed files with 612 additions and 373 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,71 +14,78 @@
public class DefaultInspector extends Inspector {

public DefaultInspector(Workspace workspace) {
runWorkspaceInspections(workspace);
runModelInspections(workspace);
runViewInspections(workspace);
super(workspace);

runWorkspaceInspections();
runModelInspections();
runViewInspections();
}

private void runWorkspaceInspections(Workspace workspace) {
add(new WorkspaceToolingInspection(workspace).run());
add(new WorkspaceScopeInspection(workspace).run());
private void runWorkspaceInspections() {
add(new WorkspaceToolingInspection(this).run());
add(new WorkspaceScopeInspection(this).run());
}

private void runModelInspections(Workspace workspace) {
add(new EmptyModelInspection(workspace).run());
add(new MultipleSoftwareSystemsDetailedInspection(workspace).run());
ElementNotIncludedInAnyViewsInspection elementNotIncludedInAnyViewsCheck = new ElementNotIncludedInAnyViewsInspection(workspace);
OrphanedElementInspection orphanedElementCheck = new OrphanedElementInspection(workspace);
for (Element element : workspace.getModel().getElements()) {
private void runModelInspections() {
add(new EmptyModelInspection(this).run());
add(new MultipleSoftwareSystemsDetailedInspection(this).run());
ElementNotIncludedInAnyViewsInspection elementNotIncludedInAnyViewsCheck = new ElementNotIncludedInAnyViewsInspection(this);
OrphanedElementInspection orphanedElementCheck = new OrphanedElementInspection(this);
for (Element element : getWorkspace().getModel().getElements()) {
if (element instanceof Person) {
add(new PersonDescriptionInspection(workspace).run(element));
add(new PersonDescriptionInspection(this).run(element));
}

if (element instanceof SoftwareSystem) {
add(new SoftwareSystemDescriptionInspection(workspace).run(element));
add(new SoftwareSystemDocumentationInspection(workspace).run(element));
add(new SoftwareSystemDecisionsInspection(workspace).run(element));
add(new SoftwareSystemDescriptionInspection(this).run(element));
add(new SoftwareSystemDocumentationInspection(this).run(element));
add(new SoftwareSystemDecisionsInspection(this).run(element));
}

if (element instanceof Container) {
add(new ContainerDescriptionInspection(workspace).run(element));
add(new ContainerTechnologyInspection(workspace).run(element));
add(new ContainerDescriptionInspection(this).run(element));
add(new ContainerTechnologyInspection(this).run(element));
}

if (element instanceof Component) {
add(new ComponentDescriptionInspection(workspace).run(element));
add(new ComponentTechnologyInspection(workspace).run(element));
add(new ComponentDescriptionInspection(this).run(element));
add(new ComponentTechnologyInspection(this).run(element));
}

if (element instanceof DeploymentNode) {
add(new DeploymentNodeDescriptionInspection(workspace).run(element));
add(new DeploymentNodeTechnologyInspection(workspace).run(element));
add(new EmptyDeploymentNodeInspection(workspace).run(element));
add(new DeploymentNodeDescriptionInspection(this).run(element));
add(new DeploymentNodeTechnologyInspection(this).run(element));
add(new EmptyDeploymentNodeInspection(this).run(element));
}

if (element instanceof InfrastructureNode) {
add(new InfrastructureNodeDescriptionInspection(workspace).run(element));
add(new InfrastructureNodeTechnologyInspection(workspace).run(element));
add(new InfrastructureNodeDescriptionInspection(this).run(element));
add(new InfrastructureNodeTechnologyInspection(this).run(element));
}

add(orphanedElementCheck.run(element));
add(elementNotIncludedInAnyViewsCheck.run(element));
}

for (Relationship relationship : workspace.getModel().getRelationships()) {
add(new RelationshipDescriptionInspection(workspace).run(relationship));
add(new RelationshipTechnologyInspection(workspace).run(relationship));
for (Relationship relationship : getWorkspace().getModel().getRelationships()) {
add(new RelationshipDescriptionInspection(this).run(relationship));
add(new RelationshipTechnologyInspection(this).run(relationship));
}
}

private void runViewInspections(Workspace workspace) {
add(new EmptyViewsInspection(workspace).run());
add(new SystemContextViewsForMultipleSoftwareSystemsInspection(workspace).run());
add(new ContainerViewsForMultipleSoftwareSystemsInspection(workspace).run());
private void runViewInspections() {
add(new EmptyViewsInspection(this).run());
add(new SystemContextViewsForMultipleSoftwareSystemsInspection(this).run());
add(new ContainerViewsForMultipleSoftwareSystemsInspection(this).run());

for (ElementStyle elementStyle : workspace.getViews().getConfiguration().getStyles().getElements()) {
add(new ElementStyleMetadataInspection(workspace).run(elementStyle));
for (ElementStyle elementStyle : getWorkspace().getViews().getConfiguration().getStyles().getElements()) {
add(new ElementStyleMetadataInspection(this).run(elementStyle));
}
}

@Override
public SeverityStrategy getSeverityStrategy() {
return new PropertyBasedSeverityStrategy();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.structurizr.inspection;

import com.structurizr.Workspace;
import com.structurizr.model.Element;
import com.structurizr.model.Model;
import com.structurizr.model.Relationship;
import com.structurizr.view.ElementStyle;
import com.structurizr.view.View;
import com.structurizr.view.ViewSet;

public class FixedSeverityStrategy implements SeverityStrategy {

private final Severity severity;

public FixedSeverityStrategy(Severity severity) {
this.severity = severity;
}

@Override
public Severity getSeverity(Inspection inspection, Workspace workspace) {
return severity;
}

@Override
public Severity getSeverity(Inspection inspection, ViewSet viewSet) {
return severity;
}

@Override
public Severity getSeverity(Inspection inspection, View view) {
return severity;
}

@Override
public Severity getSeverity(Inspection inspection, ElementStyle elementStyle) {
return severity;
}

@Override
public Severity getSeverity(Inspection inspection, Model model) {
return severity;
}

@Override
public Severity getSeverity(Inspection inspection, Element element) {
return severity;
}

@Override
public Severity getSeverity(Inspection inspection, Relationship relationship) {
return severity;
}

}
Original file line number Diff line number Diff line change
@@ -1,73 +1,31 @@
package com.structurizr.inspection;

import com.structurizr.PropertyHolder;
import com.structurizr.Workspace;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public abstract class Inspection {

private static final String STRUCTURIZR_INSPECTION_PREFIX = "structurizr.inspection.";

private final Workspace workspace;
private final Inspector inspector;

protected Inspection(Workspace workspace) {
this.workspace = workspace;
protected Inspection(Inspector inspector) {
this.inspector = inspector;
}

protected abstract String getType();
protected abstract String getType();

protected Workspace getWorkspace() {
return workspace;
public Inspector getInspector() {
return inspector;
}

protected Severity getSeverity(PropertyHolder... propertyHolders) {
List<String> types = generateTypes();

for (String type : types) {
for (PropertyHolder propertyHolder : propertyHolders) {
if (propertyHolder != null) {
if (propertyHolder.getProperties().containsKey(type)) {
return Severity.valueOf(propertyHolder.getProperties().get(type).toUpperCase());
}
}
}
}

return Severity.ERROR;
protected Workspace getWorkspace() {
return inspector.getWorkspace();
}

protected Violation noViolation() {
return null;
}

protected Violation violation(String description) {
return new Violation(STRUCTURIZR_INSPECTION_PREFIX + getType(), description);
}

List<String> generateTypes() {
// example:
// structurizr.inspection.model.component.description
// structurizr.inspection.model.component.*
// structurizr.inspection.model.*
// structurizr.inspection.*

List<String> types = new ArrayList<>();

String[] parts = getType().split("\\.");
String buf = STRUCTURIZR_INSPECTION_PREFIX;
types.add(buf + "*");
for (int i = 0; i < parts.length-1; i++) {
buf = buf + parts[i] + ".";
types.add(buf + "*");
}

types.add(STRUCTURIZR_INSPECTION_PREFIX + getType());
Collections.reverse(types);

return types;
return new Violation(getType(), description);
}

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
package com.structurizr.inspection;

import com.structurizr.Workspace;

import java.util.ArrayList;
import java.util.List;

abstract class Inspector {
public abstract class Inspector {

private final Workspace workspace;

private final List<Violation> violations = new ArrayList<>();

protected Inspector(Workspace workspace) {
this.workspace = workspace;
}

public Workspace getWorkspace() {
return workspace;
}

public List<Violation> getViolations() {
return new ArrayList<>(violations);
}
Expand All @@ -17,4 +29,6 @@ protected void add(Violation violation) {
}
}

public abstract SeverityStrategy getSeverityStrategy();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.structurizr.inspection;

import com.structurizr.PropertyHolder;
import com.structurizr.Workspace;
import com.structurizr.model.Element;
import com.structurizr.model.Model;
import com.structurizr.model.Relationship;
import com.structurizr.util.StringUtils;
import com.structurizr.view.ElementStyle;
import com.structurizr.view.View;
import com.structurizr.view.ViewSet;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class PropertyBasedSeverityStrategy implements SeverityStrategy {

private static final String STRUCTURIZR_INSPECTION_PREFIX = "structurizr.inspection.";

public PropertyBasedSeverityStrategy() {
}

@Override
public Severity getSeverity(Inspection inspection, Workspace workspace) {
return getSeverityFromProperties(inspection, workspace);
}

@Override
public Severity getSeverity(Inspection inspection, ViewSet viewSet) {
return getSeverityFromProperties(inspection, inspection.getWorkspace(), viewSet.getConfiguration());
}

@Override
public Severity getSeverity(Inspection inspection, View view) {
return getSeverityFromProperties(inspection, inspection.getWorkspace(), inspection.getWorkspace().getViews().getConfiguration(), view);
}

@Override
public Severity getSeverity(Inspection inspection, ElementStyle elementStyle) {
return getSeverityFromProperties(inspection, inspection.getWorkspace(), inspection.getWorkspace().getViews().getConfiguration(), elementStyle);
}

@Override
public Severity getSeverity(Inspection inspection, Model model) {
return getSeverityFromProperties(inspection, inspection.getWorkspace(), model);
}

@Override
public Severity getSeverity(Inspection inspection, Element element) {
Element parentElement = element.getParent();

return getSeverityFromProperties(inspection, inspection.getWorkspace(), inspection.getWorkspace().getModel(), parentElement, element);
}

@Override
public Severity getSeverity(Inspection inspection, Relationship relationship) {
Element source = relationship.getSource();
Relationship linkedRelationship = null;
if (!StringUtils.isNullOrEmpty(relationship.getLinkedRelationshipId())) {
inspection.getWorkspace().getModel().getRelationship(relationship.getLinkedRelationshipId());
}

return getSeverityFromProperties(inspection, inspection.getWorkspace(), inspection.getWorkspace().getModel(), source.getParent(), source, linkedRelationship, relationship);
}

protected Severity getSeverityFromProperties(Inspection inspection, PropertyHolder... propertyHolders) {
List<String> types = generatePropertyNames(inspection.getType());

for (String type : types) {
for (PropertyHolder propertyHolder : propertyHolders) {
if (propertyHolder != null) {
if (propertyHolder.getProperties().containsKey(type)) {
return Severity.valueOf(propertyHolder.getProperties().get(type).toUpperCase());
}
}
}
}

return Severity.ERROR;
}

protected List<String> generatePropertyNames(String inspection) {
// example input:
// structurizr.inspection.model.component.description
//
// example output:
// structurizr.inspection.model.component.description
// structurizr.inspection.model.component.*
// structurizr.inspection.model.*
// structurizr.inspection.*

List<String> types = new ArrayList<>();

String[] parts = inspection.split("\\.");
String buf = STRUCTURIZR_INSPECTION_PREFIX;
types.add(buf + "*");
for (int i = 0; i < parts.length-1; i++) {
buf = buf + parts[i] + ".";
types.add(buf + "*");
}

types.add(STRUCTURIZR_INSPECTION_PREFIX + inspection);
Collections.reverse(types);

return types;
}

}
Loading

0 comments on commit cbd3e19

Please sign in to comment.