From 1af4ce1020729cada3517f4d4bbda6088276ae63 Mon Sep 17 00:00:00 2001 From: Simon Brown Date: Sat, 26 Aug 2023 10:00:07 +0100 Subject: [PATCH] DSL identifiers (if present) will now be loaded when extending a JSON workspace (see https://github.com/structurizr/dsl/discussions/328). --- build.gradle | 2 +- docs/changelog.md | 3 +- .../com/structurizr/dsl/WorkspaceParser.java | 32 +++++ .../extend/extend-workspace-from-dsl-file.dsl | 25 +--- .../extend/extend-workspace-from-dsl-url.dsl | 25 +--- .../extend-workspace-from-json-file.dsl | 29 ++--- .../extend/extend-workspace-from-json-url.dsl | 29 ++--- src/test/dsl/extend/workspace.dsl | 9 +- src/test/dsl/extend/workspace.json | 36 ++++-- .../java/com/structurizr/dsl/DslTests.java | 118 ++---------------- 10 files changed, 96 insertions(+), 212 deletions(-) diff --git a/build.gradle b/build.gradle index 1b27139..3edcf01 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ targetCompatibility = 11 description = 'Structurizr DSL' group = 'com.structurizr' -version = '1.32.1' +version = '1.33.0' test { useJUnitPlatform() diff --git a/docs/changelog.md b/docs/changelog.md index c50f3c0..23ba3ce 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,7 +1,8 @@ # Changelog -## 1.32.1 (unreleased) +## 1.33.0 (unreleased) +- DSL identifiers (if present) will now be loaded when extending a JSON workspace (see https://github.com/structurizr/dsl/discussions/328). - Fixes https://github.com/structurizr/dsl/issues/324 (Groups with no curly braces breaks diagrams). ## 1.32.0 (28th July 2023) diff --git a/src/main/java/com/structurizr/dsl/WorkspaceParser.java b/src/main/java/com/structurizr/dsl/WorkspaceParser.java index 4a2ce87..9052d6d 100644 --- a/src/main/java/com/structurizr/dsl/WorkspaceParser.java +++ b/src/main/java/com/structurizr/dsl/WorkspaceParser.java @@ -2,6 +2,8 @@ import com.structurizr.Workspace; import com.structurizr.model.CreateImpliedRelationshipsUnlessAnyRelationshipExistsStrategy; +import com.structurizr.model.Element; +import com.structurizr.model.Relationship; import com.structurizr.util.WorkspaceUtils; import java.io.File; @@ -11,6 +13,8 @@ final class WorkspaceParser extends AbstractParser { private static final String GRAMMAR_STANDALONE = "workspace [name] [description]"; private static final String GRAMMAR_EXTENDS = "workspace extends "; + private static final String STRUCTURIZR_DSL_IDENTIFIER_PROPERTY_NAME = "structurizr.dsl.identifier"; + private static final int FIRST_INDEX = 1; private static final int SECOND_INDEX = 2; @@ -37,6 +41,7 @@ Workspace parse(DslParserContext context, Tokens tokens) { if (source.endsWith(".json")) { String json = readFromUrl(source); workspace = WorkspaceUtils.fromJson(json); + registerIdentifiers(workspace, context); } else { String dsl = readFromUrl(source); StructurizrDslParser structurizrDslParser = new StructurizrDslParser(); @@ -60,6 +65,7 @@ Workspace parse(DslParserContext context, Tokens tokens) { if (source.endsWith(".json")) { workspace = WorkspaceUtils.loadWorkspaceFromJson(file); + registerIdentifiers(workspace, context); } else { StructurizrDslParser structurizrDslParser = new StructurizrDslParser(); structurizrDslParser.parse(context, file); @@ -85,6 +91,32 @@ Workspace parse(DslParserContext context, Tokens tokens) { return workspace; } + private void registerIdentifiers(Workspace workspace, DslParserContext context) { + for (Element element : workspace.getModel().getElements()) { + if (element.getProperties().containsKey(STRUCTURIZR_DSL_IDENTIFIER_PROPERTY_NAME)) { + String identifier = element.getProperties().get(STRUCTURIZR_DSL_IDENTIFIER_PROPERTY_NAME); + try { + context.identifiersRegister.validateIdentifierName(identifier); + context.identifiersRegister.register(identifier, element); + } catch (Exception e) { + // ignore, don't register the identifier + } + } + } + + for (Relationship relationship : workspace.getModel().getRelationships()) { + if (relationship.getProperties().containsKey(STRUCTURIZR_DSL_IDENTIFIER_PROPERTY_NAME)) { + String identifier = relationship.getProperties().get(STRUCTURIZR_DSL_IDENTIFIER_PROPERTY_NAME); + try { + context.identifiersRegister.validateIdentifierName(identifier); + context.identifiersRegister.register(identifier, relationship); + } catch (Exception e) { + // ignore, don't register the identifier + } + } + } + } + void parseName(DslContext context, Tokens tokens) { // name if (tokens.hasMoreThan(FIRST_INDEX)) { diff --git a/src/test/dsl/extend/extend-workspace-from-dsl-file.dsl b/src/test/dsl/extend/extend-workspace-from-dsl-file.dsl index d7bcc70..8bbd4d3 100644 --- a/src/test/dsl/extend/extend-workspace-from-dsl-file.dsl +++ b/src/test/dsl/extend/extend-workspace-from-dsl-file.dsl @@ -1,30 +1,11 @@ workspace extends workspace.dsl { - name "A new name" - description "A new description" model { - softwareSystem = softwareSystem "Software System" { + !ref softwareSystem1 { webapp = container "Web Application" } - } - - views { - systemContext softwareSystem "SystemContext" "An example of a System Context diagram." { - include * - autoLayout - } - styles { - element "Software System" { - background #1168bd - color #ffffff - } - element "Person" { - shape person - background #08427b - color #ffffff - } - } + user -> softwareSystem1 "Uses" } - + } \ No newline at end of file diff --git a/src/test/dsl/extend/extend-workspace-from-dsl-url.dsl b/src/test/dsl/extend/extend-workspace-from-dsl-url.dsl index 8977a0c..e586f67 100644 --- a/src/test/dsl/extend/extend-workspace-from-dsl-url.dsl +++ b/src/test/dsl/extend/extend-workspace-from-dsl-url.dsl @@ -1,30 +1,11 @@ workspace extends https://raw.githubusercontent.com/structurizr/dsl/master/src/test/dsl/extend/workspace.dsl { - name "A new name" - description "A new description" model { - softwareSystem = softwareSystem "Software System" { + !ref softwareSystem1 { webapp = container "Web Application" } - } - - views { - systemContext softwareSystem "SystemContext" "An example of a System Context diagram." { - include * - autoLayout - } - styles { - element "Software System" { - background #1168bd - color #ffffff - } - element "Person" { - shape person - background #08427b - color #ffffff - } - } + user -> softwareSystem1 "Uses" } - + } \ No newline at end of file diff --git a/src/test/dsl/extend/extend-workspace-from-json-file.dsl b/src/test/dsl/extend/extend-workspace-from-json-file.dsl index b7d4305..8c6ecda 100644 --- a/src/test/dsl/extend/extend-workspace-from-json-file.dsl +++ b/src/test/dsl/extend/extend-workspace-from-json-file.dsl @@ -1,30 +1,17 @@ workspace extends workspace.json { - name "A new name" - description "A new description" model { - softwareSystem = softwareSystem "Software System" { - webapp = container "Web Application" + // !ref with DSL identifier + !ref softwareSystem1 { + webapp1 = container "Web Application 1" } - } - views { - systemContext softwareSystem "SystemContext" "An example of a System Context diagram." { - include * - autoLayout + // !ref with canonical name + !ref "SoftwareSystem://Software System 1" { + webapp2 = container "Web Application 2" } - styles { - element "Software System" { - background #1168bd - color #ffffff - } - element "Person" { - shape person - background #08427b - color #ffffff - } - } + user -> softwareSystem1 "Uses" } - + } \ No newline at end of file diff --git a/src/test/dsl/extend/extend-workspace-from-json-url.dsl b/src/test/dsl/extend/extend-workspace-from-json-url.dsl index 8ebcb1b..1279eeb 100644 --- a/src/test/dsl/extend/extend-workspace-from-json-url.dsl +++ b/src/test/dsl/extend/extend-workspace-from-json-url.dsl @@ -1,30 +1,17 @@ workspace extends https://raw.githubusercontent.com/structurizr/dsl/master/src/test/dsl/extend/workspace.json { - name "A new name" - description "A new description" model { - softwareSystem = softwareSystem "Software System" { - webapp = container "Web Application" + // !ref with DSL identifier + !ref softwareSystem1 { + webapp1 = container "Web Application 1" } - } - views { - systemContext softwareSystem "SystemContext" "An example of a System Context diagram." { - include * - autoLayout + // !ref with canonical name + !ref "SoftwareSystem://Software System 1" { + webapp2 = container "Web Application 2" } - styles { - element "Software System" { - background #1168bd - color #ffffff - } - element "Person" { - shape person - background #08427b - color #ffffff - } - } + user -> softwareSystem1 "Uses" } - + } \ No newline at end of file diff --git a/src/test/dsl/extend/workspace.dsl b/src/test/dsl/extend/workspace.dsl index 08f39ad..4fd1cf3 100644 --- a/src/test/dsl/extend/workspace.dsl +++ b/src/test/dsl/extend/workspace.dsl @@ -1,10 +1,9 @@ -workspace "Getting Started" "This is a model of my software system." { +workspace { model { - user = person "User" "A user of my software system." - softwareSystem = softwareSystem "Software System" "My software system." - - user -> softwareSystem "Uses" + user = person "User" + softwareSystem1 = softwareSystem "Software System 1" + softwareSystem "Software System 2" } } \ No newline at end of file diff --git a/src/test/dsl/extend/workspace.json b/src/test/dsl/extend/workspace.json index 30a7e43..2b05d53 100644 --- a/src/test/dsl/extend/workspace.json +++ b/src/test/dsl/extend/workspace.json @@ -1,29 +1,39 @@ { "id" : 0, - "name" : "Getting Started", - "description" : "This is a model of my software system.", + "name" : "Name", + "description" : "Description", + "properties" : { + "structurizr.dsl" : "d29ya3NwYWNlIHsKCiAgICBtb2RlbCB7CiAgICAgICAgdXNlciA9IHBlcnNvbiAiVXNlciIKICAgICAgICBzb2Z0d2FyZVN5c3RlbTEgPSBzb2Z0d2FyZVN5c3RlbSAiU29mdHdhcmUgU3lzdGVtIDEiCiAgICAgICAgc29mdHdhcmVTeXN0ZW0gIlNvZnR3YXJlIFN5c3RlbSAyIgogICAgfQoKfQo=" + }, "configuration" : { }, "model" : { "people" : [ { "id" : "1", "tags" : "Element,Person", + "properties" : { + "structurizr.dsl.identifier" : "user" + }, "name" : "User", - "description" : "A user of my software system.", - "relationships" : [ { - "id" : "3", - "tags" : "Relationship", - "sourceId" : "1", - "destinationId" : "2", - "description" : "Uses" - } ], "location" : "Unspecified" } ], "softwareSystems" : [ { "id" : "2", "tags" : "Element,Software System", - "name" : "Software System", - "description" : "My software system.", - "location" : "Unspecified" + "properties" : { + "structurizr.dsl.identifier" : "softwaresystem1" + }, + "name" : "Software System 1", + "location" : "Unspecified", + "documentation" : { } + }, { + "id" : "3", + "tags" : "Element,Software System", + "properties" : { + "structurizr.dsl.identifier" : "9c50bae2-474c-4fb6-9cc0-ef1da359673b" + }, + "name" : "Software System 2", + "location" : "Unspecified", + "documentation" : { } } ] }, "documentation" : { }, diff --git a/src/test/java/com/structurizr/dsl/DslTests.java b/src/test/java/com/structurizr/dsl/DslTests.java index dec8a70..1a8338a 100644 --- a/src/test/java/com/structurizr/dsl/DslTests.java +++ b/src/test/java/com/structurizr/dsl/DslTests.java @@ -445,44 +445,21 @@ void test_extendWorkspaceFromJsonFile() throws Exception { Workspace workspace = parser.getWorkspace(); Model model = workspace.getModel(); - ViewSet views = workspace.getViews(); - - assertEquals("A new name", workspace.getName()); - assertEquals("A new description", workspace.getDescription()); assertEquals(1, model.getPeople().size()); Person user = model.getPersonWithName("User"); - assertEquals("A user of my software system.", user.getDescription()); - assertEquals(1, workspace.getModel().getSoftwareSystems().size()); - SoftwareSystem softwareSystem = model.getSoftwareSystemWithName("Software System"); - assertEquals("My software system.", softwareSystem.getDescription()); + assertEquals(2, workspace.getModel().getSoftwareSystems().size()); + SoftwareSystem softwareSystem = model.getSoftwareSystemWithName("Software System 1"); - assertEquals(1, softwareSystem.getContainers().size()); - assertEquals("Web Application", softwareSystem.getContainers().iterator().next().getName()); + assertEquals(2, softwareSystem.getContainers().size()); + assertNotNull(softwareSystem.getContainers().stream().filter(c -> c.getName().equals("Web Application 1")).findFirst()); + assertNotNull(softwareSystem.getContainers().stream().filter(c -> c.getName().equals("Web Application 2")).findFirst()); assertEquals(1, workspace.getModel().getRelationships().size()); Relationship relationship = user.getRelationships().iterator().next(); assertEquals("Uses", relationship.getDescription()); assertSame(softwareSystem, relationship.getDestination()); - - assertEquals(1, views.getViews().size()); - assertEquals(1, views.getSystemContextViews().size()); - SystemContextView view = views.getSystemContextViews().iterator().next(); - assertEquals("SystemContext", view.getKey()); - assertEquals("An example of a System Context diagram.", view.getDescription()); - assertEquals(2, view.getElements().size()); - assertEquals(1, view.getRelationships().size()); - - assertEquals(2, views.getConfiguration().getStyles().getElements().size()); - ElementStyle personStyle = views.getConfiguration().getStyles().getElements().stream().filter(es -> es.getTag().equals("Person")).findFirst().get(); - assertEquals(Shape.Person, personStyle.getShape()); - assertEquals("#08427b", personStyle.getBackground()); - assertEquals("#ffffff", personStyle.getColor()); - - ElementStyle softwareSystemStyle = views.getConfiguration().getStyles().getElements().stream().filter(es -> es.getTag().equals("Software System")).findFirst().get(); - assertEquals("#1168bd", softwareSystemStyle.getBackground()); - assertEquals("#ffffff", softwareSystemStyle.getColor()); } @Test @@ -492,44 +469,21 @@ void test_extendWorkspaceFromJsonUrl() throws Exception { Workspace workspace = parser.getWorkspace(); Model model = workspace.getModel(); - ViewSet views = workspace.getViews(); - - assertEquals("A new name", workspace.getName()); - assertEquals("A new description", workspace.getDescription()); assertEquals(1, model.getPeople().size()); Person user = model.getPersonWithName("User"); - assertEquals("A user of my software system.", user.getDescription()); assertEquals(1, workspace.getModel().getSoftwareSystems().size()); - SoftwareSystem softwareSystem = model.getSoftwareSystemWithName("Software System"); - assertEquals("My software system.", softwareSystem.getDescription()); + SoftwareSystem softwareSystem = model.getSoftwareSystemWithName("Software System 1"); - assertEquals(1, softwareSystem.getContainers().size()); - assertEquals("Web Application", softwareSystem.getContainers().iterator().next().getName()); + assertEquals(2, softwareSystem.getContainers().size()); + assertNotNull(softwareSystem.getContainers().stream().filter(c -> c.getName().equals("Web Application 1")).findFirst()); + assertNotNull(softwareSystem.getContainers().stream().filter(c -> c.getName().equals("Web Application 2")).findFirst()); assertEquals(1, workspace.getModel().getRelationships().size()); Relationship relationship = user.getRelationships().iterator().next(); assertEquals("Uses", relationship.getDescription()); assertSame(softwareSystem, relationship.getDestination()); - - assertEquals(1, views.getViews().size()); - assertEquals(1, views.getSystemContextViews().size()); - SystemContextView view = views.getSystemContextViews().iterator().next(); - assertEquals("SystemContext", view.getKey()); - assertEquals("An example of a System Context diagram.", view.getDescription()); - assertEquals(2, view.getElements().size()); - assertEquals(1, view.getRelationships().size()); - - assertEquals(2, views.getConfiguration().getStyles().getElements().size()); - ElementStyle personStyle = views.getConfiguration().getStyles().getElements().stream().filter(es -> es.getTag().equals("Person")).findFirst().get(); - assertEquals(Shape.Person, personStyle.getShape()); - assertEquals("#08427b", personStyle.getBackground()); - assertEquals("#ffffff", personStyle.getColor()); - - ElementStyle softwareSystemStyle = views.getConfiguration().getStyles().getElements().stream().filter(es -> es.getTag().equals("Software System")).findFirst().get(); - assertEquals("#1168bd", softwareSystemStyle.getBackground()); - assertEquals("#ffffff", softwareSystemStyle.getColor()); } @Test @@ -555,18 +509,12 @@ void test_extendWorkspaceFromDslFile() throws Exception { Workspace workspace = parser.getWorkspace(); Model model = workspace.getModel(); - ViewSet views = workspace.getViews(); - - assertEquals("A new name", workspace.getName()); - assertEquals("A new description", workspace.getDescription()); assertEquals(1, model.getPeople().size()); Person user = model.getPersonWithName("User"); - assertEquals("A user of my software system.", user.getDescription()); - assertEquals(1, workspace.getModel().getSoftwareSystems().size()); - SoftwareSystem softwareSystem = model.getSoftwareSystemWithName("Software System"); - assertEquals("My software system.", softwareSystem.getDescription()); + assertEquals(2, workspace.getModel().getSoftwareSystems().size()); + SoftwareSystem softwareSystem = model.getSoftwareSystemWithName("Software System 1"); assertEquals(1, softwareSystem.getContainers().size()); assertEquals("Web Application", softwareSystem.getContainers().iterator().next().getName()); @@ -575,24 +523,6 @@ void test_extendWorkspaceFromDslFile() throws Exception { Relationship relationship = user.getRelationships().iterator().next(); assertEquals("Uses", relationship.getDescription()); assertSame(softwareSystem, relationship.getDestination()); - - assertEquals(1, views.getViews().size()); - assertEquals(1, views.getSystemContextViews().size()); - SystemContextView view = views.getSystemContextViews().iterator().next(); - assertEquals("SystemContext", view.getKey()); - assertEquals("An example of a System Context diagram.", view.getDescription()); - assertEquals(2, view.getElements().size()); - assertEquals(1, view.getRelationships().size()); - - assertEquals(2, views.getConfiguration().getStyles().getElements().size()); - ElementStyle personStyle = views.getConfiguration().getStyles().getElements().stream().filter(es -> es.getTag().equals("Person")).findFirst().get(); - assertEquals(Shape.Person, personStyle.getShape()); - assertEquals("#08427b", personStyle.getBackground()); - assertEquals("#ffffff", personStyle.getColor()); - - ElementStyle softwareSystemStyle = views.getConfiguration().getStyles().getElements().stream().filter(es -> es.getTag().equals("Software System")).findFirst().get(); - assertEquals("#1168bd", softwareSystemStyle.getBackground()); - assertEquals("#ffffff", softwareSystemStyle.getColor()); } @Test @@ -602,18 +532,12 @@ void test_extendWorkspaceFromDslUrl() throws Exception { Workspace workspace = parser.getWorkspace(); Model model = workspace.getModel(); - ViewSet views = workspace.getViews(); - - assertEquals("A new name", workspace.getName()); - assertEquals("A new description", workspace.getDescription()); assertEquals(1, model.getPeople().size()); Person user = model.getPersonWithName("User"); - assertEquals("A user of my software system.", user.getDescription()); assertEquals(1, workspace.getModel().getSoftwareSystems().size()); - SoftwareSystem softwareSystem = model.getSoftwareSystemWithName("Software System"); - assertEquals("My software system.", softwareSystem.getDescription()); + SoftwareSystem softwareSystem = model.getSoftwareSystemWithName("Software System 1"); assertEquals(1, softwareSystem.getContainers().size()); assertEquals("Web Application", softwareSystem.getContainers().iterator().next().getName()); @@ -622,24 +546,6 @@ void test_extendWorkspaceFromDslUrl() throws Exception { Relationship relationship = user.getRelationships().iterator().next(); assertEquals("Uses", relationship.getDescription()); assertSame(softwareSystem, relationship.getDestination()); - - assertEquals(1, views.getViews().size()); - assertEquals(1, views.getSystemContextViews().size()); - SystemContextView view = views.getSystemContextViews().iterator().next(); - assertEquals("SystemContext", view.getKey()); - assertEquals("An example of a System Context diagram.", view.getDescription()); - assertEquals(2, view.getElements().size()); - assertEquals(1, view.getRelationships().size()); - - assertEquals(2, views.getConfiguration().getStyles().getElements().size()); - ElementStyle personStyle = views.getConfiguration().getStyles().getElements().stream().filter(es -> es.getTag().equals("Person")).findFirst().get(); - assertEquals(Shape.Person, personStyle.getShape()); - assertEquals("#08427b", personStyle.getBackground()); - assertEquals("#ffffff", personStyle.getColor()); - - ElementStyle softwareSystemStyle = views.getConfiguration().getStyles().getElements().stream().filter(es -> es.getTag().equals("Software System")).findFirst().get(); - assertEquals("#1168bd", softwareSystemStyle.getBackground()); - assertEquals("#ffffff", softwareSystemStyle.getColor()); } @Test