Skip to content

Commit 1e7a9c2

Browse files
Adds support for filtered deployment views (#409).
1 parent bb2428a commit 1e7a9c2

File tree

6 files changed

+55
-22
lines changed

6 files changed

+55
-22
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## v5.0.0 (unreleased)
44

55
- structurizr-core: Removes support for deprecated enterprise and location concepts.
6+
- structurizr-core: Adds support for filtered deployment views (https://github.com/structurizr/java/issues/409).
67
- structurizr-component: Fixes https://github.com/structurizr/java/issues/437 (Make ComponentFinder.run() not fail on empty Set<DiscoveredComponent>).
78
- structurizr-dsl: Adds support for `iconPosition` on element styles (options are `Top`, `Bottom`, `Left`).
89
- structurizr-dsl: Adds support for defining element and relationship styles for light and dark mode.

structurizr-core/src/main/java/com/structurizr/view/FilteredView.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*/
1212
public final class FilteredView extends View {
1313

14-
private StaticView view;
14+
private ModelView view;
1515
private String baseViewKey;
1616

1717
private FilterMode mode = FilterMode.Exclude;
@@ -20,7 +20,7 @@ public final class FilteredView extends View {
2020
FilteredView() {
2121
}
2222

23-
FilteredView(StaticView view, String key, String description, FilterMode mode, String... tags) {
23+
FilteredView(ModelView view, String key, String description, FilterMode mode, String... tags) {
2424
this.view = view;
2525
setKey(key);
2626
setDescription(description);
@@ -33,7 +33,7 @@ public View getView() {
3333
return view;
3434
}
3535

36-
void setView(StaticView view) {
36+
void setView(ModelView view) {
3737
this.view = view;
3838
}
3939

structurizr-core/src/main/java/com/structurizr/view/ViewSet.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,24 @@ public FilteredView createFilteredView(StaticView view, String key, FilterMode m
498498
* @return a FilteredView object
499499
*/
500500
public FilteredView createFilteredView(StaticView view, String key, String description, FilterMode mode, String... tags) {
501+
return newFilteredView(view, key, description, mode, tags);
502+
}
503+
504+
/**
505+
* Creates a FilteredView on top of an existing deployment view.
506+
*
507+
* @param view the deployment view to base the FilteredView upon
508+
* @param key the key for the filtered view (must be unique)
509+
* @param description a description
510+
* @param mode whether to Include or Exclude elements/relationships based upon their tag
511+
* @param tags the tags to include or exclude
512+
* @return a FilteredView object
513+
*/
514+
public FilteredView createFilteredView(DeploymentView view, String key, String description, FilterMode mode, String... tags) {
515+
return newFilteredView(view, key, description, mode, tags);
516+
}
517+
518+
private FilteredView newFilteredView(ModelView view, String key, String description, FilterMode mode, String... tags) {
501519
boolean keyIsAutomaticallyGenerated = false;
502520

503521
if (StringUtils.isNullOrEmpty(key)) {
@@ -900,11 +918,11 @@ void hydrate(Model model) {
900918
);
901919
}
902920

903-
if (view instanceof StaticView) {
904-
filteredView.setView((StaticView)view);
921+
if (view instanceof StaticView || view instanceof DeploymentView) {
922+
filteredView.setView((ModelView)view);
905923
} else {
906924
throw new WorkspaceValidationException(
907-
String.format("The filtered view with key \"%s\" is based upon a view (key=%s), but that view is not a static view.",
925+
String.format("The filtered view with key \"%s\" is based upon a view (key=%s), but that view is not a static or deployment view.",
908926
filteredView.getKey(), filteredView.getBaseViewKey())
909927
);
910928
}

structurizr-core/src/test/java/com/structurizr/view/ViewSetTests.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ void createDeploymentViewForSoftwareSystem() {
491491
void createFilteredView_ThrowsAnException_WhenANullViewIsSpecified() {
492492
try {
493493
Workspace workspace = new Workspace("Name", "Description");
494-
workspace.getViews().createFilteredView(null, "key", "Description", FilterMode.Include, "tag1", "tag2");
494+
workspace.getViews().createFilteredView((SystemLandscapeView)null, "key", "Description", FilterMode.Include, "tag1", "tag2");
495495
fail();
496496
} catch (IllegalArgumentException iae) {
497497
assertEquals("A view must be specified.", iae.getMessage());
@@ -530,7 +530,7 @@ void createFilteredView_ThrowsAnException_WhenADuplicateKeyIsUsed() {
530530
}
531531

532532
@Test
533-
void createFilteredView() {
533+
void createFilteredView_OnStaticView() {
534534
Workspace workspace = new Workspace("Name", "Description");
535535
SystemLandscapeView view = workspace.getViews().createSystemLandscapeView("systemLandscape", "Description");
536536
FilteredView filteredView = workspace.getViews().createFilteredView(view, "key", "Description", FilterMode.Include, "tag1", "tag2");
@@ -543,6 +543,20 @@ void createFilteredView() {
543543
assertTrue(filteredView.getTags().contains("tag2"));
544544
}
545545

546+
@Test
547+
void createFilteredView_OnDeploymentView() {
548+
Workspace workspace = new Workspace("Name", "Description");
549+
DeploymentView view = workspace.getViews().createDeploymentView("deployment");
550+
FilteredView filteredView = workspace.getViews().createFilteredView(view, "key", "Description", FilterMode.Include, "tag1", "tag2");
551+
552+
assertEquals("key", filteredView.getKey());
553+
assertEquals("Description", filteredView.getDescription());
554+
assertEquals(FilterMode.Include, filteredView.getMode());
555+
assertEquals(2, filteredView.getTags().size());
556+
assertTrue(filteredView.getTags().contains("tag1"));
557+
assertTrue(filteredView.getTags().contains("tag2"));
558+
}
559+
546560
@Test
547561
void copyLayoutInformationFrom_WhenAViewKeyIsNotSetButTheViewTitlesMatch() {
548562
Workspace workspace1 = createWorkspace();

structurizr-dsl/src/main/java/com/structurizr/dsl/FilteredViewParser.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22

33
import com.structurizr.Workspace;
44
import com.structurizr.util.StringUtils;
5-
import com.structurizr.view.FilterMode;
6-
import com.structurizr.view.FilteredView;
7-
import com.structurizr.view.StaticView;
5+
import com.structurizr.view.*;
86

97
import java.text.DecimalFormat;
108
import java.util.HashSet;
@@ -37,7 +35,7 @@ FilteredView parse(DslContext context, Tokens tokens) {
3735
Workspace workspace = context.getWorkspace();
3836
String key = "";
3937

40-
StaticView baseView;
38+
View baseView;
4139
String baseKey = tokens.get(BASE_KEY_INDEX);
4240
String mode = tokens.get(MODE_INDEX);
4341
String tagsAsString = tokens.get(TAGS_INDEX);
@@ -64,21 +62,23 @@ FilteredView parse(DslContext context, Tokens tokens) {
6462
throw new RuntimeException("Filter mode should be include or exclude");
6563
}
6664

67-
if (workspace.getViews().getViews().stream().noneMatch(v -> v.getKey().equals(baseKey))) {
68-
throw new RuntimeException("The view \"" + baseKey + "\" does not exist");
69-
}
70-
71-
baseView = (StaticView)workspace.getViews().getViews().stream().filter(v -> v instanceof StaticView && v.getKey().equals(baseKey)).findFirst().orElse(null);
65+
baseView = workspace.getViews().getViewWithKey(baseKey);
7266
if (baseView == null) {
73-
throw new RuntimeException("The view \"" + baseKey + "\" must be a System Landscape, System Context, Container, or Component view");
67+
throw new RuntimeException("The view \"" + baseKey + "\" does not exist");
7468
}
7569

7670
if (tokens.includes(KEY_INDEX)) {
7771
key = tokens.get(KEY_INDEX);
7872
validateViewKey(key);
7973
}
8074

81-
return workspace.getViews().createFilteredView(baseView, key, description, filterMode, tags.toArray(new String[0]));
75+
if (baseView instanceof StaticView) {
76+
return workspace.getViews().createFilteredView((StaticView)baseView, key, description, filterMode, tags.toArray(new String[0]));
77+
} else if (baseView instanceof DeploymentView) {
78+
return workspace.getViews().createFilteredView((DeploymentView)baseView, key, description, filterMode, tags.toArray(new String[0]));
79+
} else {
80+
throw new RuntimeException("The view \"" + baseKey + "\" must be a System Landscape, System Context, Container, Component, or Deployment view");
81+
}
8282
}
8383

8484
}

structurizr-dsl/src/test/java/com/structurizr/dsl/FilteredViewParserTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@ void test_parse_ThrowsAnException_WhenTheBaseViewDoesNotExist() {
8080
}
8181

8282
@Test
83-
void test_parse_ThrowsAnException_WhenTheBaseViewIsNotAStaticView() {
83+
void test_parse_ThrowsAnException_WhenTheBaseViewIsNotAStaticOrDeploymentView() {
8484
DslContext context = context();
85-
views.createDeploymentView("baseKey", "Description");
85+
views.createDynamicView("baseKey", "Description");
8686
try {
8787
parser.parse(context, tokens("filtered", "baseKey", "include", "Tag 1, Tag 2", "key"));
8888
fail();
8989
} catch (RuntimeException iae) {
90-
assertEquals("The view \"baseKey\" must be a System Landscape, System Context, Container, or Component view", iae.getMessage());
90+
assertEquals("The view \"baseKey\" must be a System Landscape, System Context, Container, Component, or Deployment view", iae.getMessage());
9191
}
9292
}
9393

0 commit comments

Comments
 (0)