Skip to content
This repository was archived by the owner on Mar 28, 2026. It is now read-only.
This repository was archived by the owner on Mar 28, 2026. It is now read-only.

Support for user-defined syntax entities in structurizr dsl #385

Closed

Description

@Nifacy

Description

Summary

Feature will allow users to define custom syntax entities within Structurizr DSL,
enhancing it's extensibility and adaptability to diverse modeling requirements.

Background

Currently, structurizr dsl offers a fixed set of syntax entities for modeling software
architectures. While this sufficies for many scenarios, certain use cases necessitate
the definition of custom entities to represent domain-specific concepts more accurately.

Relevance

In large organizations like ours, recurring architectural patterns have emerged across
various projects. To effectively document and communicate these patterns within
our architecture descriptions, we require the ability to define them as distinct entities
in structurizr dsl.

While initial attempts using plugins and scripts provided some flexibility, a more
integrated and flexible approach is now necessary.

Priority

Low (I'm willing to make a pull request - please confirm approach first)

More information

Proposal

Implement functionality enabling users to create their own syntax entities
using a defined structure and parsing mechanism.

Details

Custom syntax entity format

Users can define custom entities using the following template:

$<entity-keyword> <param> ... {
    ...
}

Where:

  • <entity-keyword> - a unique keyword identifying the custom entity type.
    It must be alphanumeric and contain no spaces.

  • <param> ... - a set of parameters, each representing a distinct token.

  • { ... } - a context block containing additional information about the entity,
    similar to existing entities like container or group.

Parsing mechanism

Users will implement parsing logic for their custom entities,
adhering to a specified interface. This approach ensures that
the internal components of structurizr dsl remain encapsulated,
allowing users to extend functionality without having to
disclose the internal components form structurizr project.

The proposed interfaces are as follows:

Example

Here is an example of custom entity example:

import com.structurizr.dsl.CustomSyntaxEntity
import com.structurizr.dsl.CustomSyntaxEntityParser
import com.structurizr.dsl.CustomSyntaxEntityParserContext


class ExampleSyntaxEntityParser implements CustomSyntaxEntityParser {

    private String name;
    private String fieldA;
    private String fieldB;

    ExampleSyntaxEntityParser() {
        this.name = null;
        this.fieldA = null;
        this.fieldB = null;
    }

    public void parseHeader(String[] tokens) {
        if (tokens.length != 1) {
            throw new RuntimeException("Expected: $example <name>")
        }

        this.name = tokens[0];
    }

    public void parseContextBlockLine(String[] tokens) {
        if (tokens.length != 2) {
            throw new RuntimeException("Expected: <name> <value>");
        }

        String fieldName = tokens[0];
        String value = tokens[1];

        if (fieldName == "a") {
            if (this.fieldA != null) {
                throw new RuntimeException("Field 'a' already defined");
            }
            this.fieldA = value;
        }

        else if (fieldName == "b") {
            if (this.fieldB != null) {
                throw new RuntimeException("Field 'b' already defined");
            }
            this.fieldB = value;
        }

        else {
            throw new RuntimeException("Unknown field: " + key);
        }
    }

    public void onEnd() {
        System.out.println("Syntax entity info:");
        System.out.println("- name: " + this.name);
        System.out.println("- field a: " + this.fieldA);
        System.out.println("- field b: " + this.fieldB);
    }
}


class ExampleSyntaxEntity implements CustomSyntaxEntity {
    public String getKeyword() {
        return "example";
    }

    public CustomSyntaxEntityParser getParser(CustomSyntaxEntityParserContext context) {
        System.out.println("Parser context:");
        System.out.println("- workspace: " + context.getWorkspace());
        System.out.println("- file: " + context.getDslFile());
        System.out.println("- parser: " + context.getDslParser());

        return new ExampleSyntaxEntityParser();
    }
}

Conclusion

Benefits

  • Users can tailor the DSL to their specific needs without modifying the core library.
  • Facilitates the representation of domain-specific concepts, enhancing the
    expressiveness of models.
  • Maintains the integrity of core components by exposing only necessary interfaces
    for extension.

Activity

  1. Nifacy commented on Mar 8, 2025

    @Nifacy
    Author

    Some sketches regarding this feature are already ready. You can view them here: link.

  2. DVDemon commented on Mar 9, 2025

    @DVDemon

    Good Idea!
    Such mechanism could be used to separate logical description of architectural model from description of patterns realizing qualitative characteristics.

  3. szuev commented on Mar 9, 2025

    @szuev

    Sounds good!

  4. FightingFox commented on Mar 9, 2025

    @FightingFox

    I need this mechanism too! Very good.

  5. neopaf commented on Mar 9, 2025

    @neopaf

    Some sketches regarding this feature are already ready. You can view them here: link.

    Any pictures?

  6. archdevmikhail commented on Mar 10, 2025

    @archdevmikhail

    A much needed improvement! I support it! =)

  7. voriv commented on Mar 10, 2025

    @voriv

    This feature would be useful for me!

  8. locked and limited conversation to collaborators on Mar 10, 2025
  9. converted this issue into a discussion #386 on Mar 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions