Raku UML::Translators
In brief
This repository is for a Raku package for the translations of code into
Unified Modeling Language (UML)
specifications and vice versa.
Currently, the package only translates Object-Oriented Programming (OOP) Raku code into:
See [AA2] for usage examples of both PlantUML and UMLClassGraph in Mathematica.
Remark: The package provides Command Line Interface (CLI) script.
Remark: (Currently) the development of PlantUML is more robust and complete than that of Mermaid-JS.
Hence, workflow-wise, using this package to generate PlantUML specs would produce (on average) best results.
Future plans
A fully fledged version of this package would translate:
- C++, Java, Kotlin, or Raku code into UML specs
- UML specs into C++, Java, Kotlin, or Raku code
Currently, only UML specs are generated to PlantUML's DSL and a much poorer WL DSL.
Ideally, subsequent versions of this package would be able to use UML specifications
encoded in XML and JSON.
Installation
From zef's ecosystem
zef install UML::Translators
From GitHub
zef install https://github.com/antononcube/Raku-UML-Translators.git 
Command Line Interface
The package provides the CLI script to-uml-spec. Here is its usage message:
to-uml-spec --help
# Usage:
#   to-uml-spec <packageName> [--type=<Str>] [-I=<Str>] [--attributes] [--methods] [--concise-grammar-classes] [--format=<Str>] [--plot] [--jar=<Str>] [--viewer=<Str>] -- Make a UML diagram for a specified package.
#   
#     <packageName>                Package name.
#     --type=<Str>                 Type of the UML diagram. [default: 'class']
#     -I=<Str>                     Using include path to find libraries. [default: '']
#     --attributes                 Should the class attributes be included in the UML diagrams or not? [default: True]
#     --methods                    Should the class methods be included in the UML diagrams or not? [default: True]
#     --concise-grammar-classes    Should grammar classes be shortened or not? [default: True]
#     --format=<Str>               Format of the output, one of 'Mermaid', 'MermaidJS', 'Plant', 'PlantUML', 'WL', 'WLUML', or 'Whatever'. [default: 'PlantUML']
#     --plot                       Should the result be plotted or not? [default: False]
#     --jar=<Str>                  JAR file to use if --plot. If --jar is an empty string then PLANTUMLJAR and PLANTUML_JAR are attempted. [default: '']
#     --viewer=<Str>               Image viewer program to use if --plot. If --viewer is an empty string then open is used on macOS and xdg-open on Linux. [default: '']
Usage examples
Generate PlantUML spec for the Raku package
"ML::Clustering":
to-uml-spec --/methods --/attributes "ML::Clustering"
# @startuml
# class "find-clusters" <<routine>> {
# }
# "find-clusters" --|> Routine
# "find-clusters" --|> Block
# "find-clusters" --|> Code
# "find-clusters" --|> Callable
# 
# 
# class "k-means" <<routine>> {
# }
# "k-means" --|> Routine
# "k-means" --|> Block
# "k-means" --|> Code
# "k-means" --|> Callable
# 
# 
# class ML::Clustering::KMeans  {
# }
# ML::Clustering::KMeans --|> ML::Clustering::DistanceFunctions
# 
# 
# class ML::Clustering::DistanceFunctions <<role>> {
# }
# 
# 
# @enduml
With this shell command we generate a Plant UML spec for the package
"Chemistry::Stoichiometry"
and create the UML diagram image with a local PlantUML JAR file (downloaded from [PUML1]):
to-uml-spec --/methods --/attributes 'Chemistry::Stoichiometry' | java -jar ~/Downloads/plantuml-1.2022.5.jar -pipe -tjpg > /tmp/myuml.jpg
Raku session
UML for ad hoc classes
Here we generate a PlantUML spec:
use UML::Translators;
module MyPackageClass {
  role A { method a1 {} }
  role B { method b1 {} }
  class C does A { has $!c-var; method c1 {} }
  class D does B is C { has $!d-var; method d1 {} }
}
to-uml-spec('MyPackageClass')
# @startuml
# class MyPackageClass::C  {
#   {field} $!c-var
#   {method} BUILDALL
#   {method} a1
#   {method} c1
# }
# MyPackageClass::C --|> MyPackageClass::A
# 
# 
# class MyPackageClass::D  {
#   {field} $!c-var
#   {field} $!d-var
#   {method} BUILDALL
#   {method} b1
#   {method} d1
# }
# MyPackageClass::D --|> MyPackageClass::C
# MyPackageClass::D --|> MyPackageClass::A
# MyPackageClass::D --|> MyPackageClass::B
# 
# 
# class MyPackageClass::B <<role>> {
#   {method} b1
# }
# 
# 
# class MyPackageClass::A <<role>> {
#   {method} a1
# }
# 
# 
# @enduml
Here we generate a MermaidJS spec:
to-uml-spec('MyPackageClass', format => 'mermaid')
classDiagram
class MyPackageClass_C {
  +$!c-var
  +BUILDALL()
  +a1()
  +c1()
}
MyPackageClass_C --|> MyPackageClass_A
class MyPackageClass_D {
  +$!c-var
  +$!d-var
  +BUILDALL()
  +b1()
  +d1()
}
MyPackageClass_D --|> MyPackageClass_C
MyPackageClass_D --|> MyPackageClass_A
MyPackageClass_D --|> MyPackageClass_B
class MyPackageClass_B {
  <<role>>
  +b1()
}
class MyPackageClass_A {
  <<role>>
  +a1()
}
UML for packages
Get PlantUML code for the package
'Chemistry::Stoichiometry':
say to-uml-spec('Chemistry::Stoichiometry'):!methods:!attributes
# @startuml
# class Chemistry::Stoichiometry::ResourceAccess  {
# }
# 
# 
# class Chemistry::Stoichiometry::Grammar <<grammar>> {
# }
# Chemistry::Stoichiometry::Grammar --|> Grammar
# Chemistry::Stoichiometry::Grammar --|> Match
# Chemistry::Stoichiometry::Grammar --|> Capture
# Chemistry::Stoichiometry::Grammar --|> Chemistry::Stoichiometry::Grammar::ChemicalElement
# Chemistry::Stoichiometry::Grammar --|> Chemistry::Stoichiometry::Grammar::ChemicalEquation
# Chemistry::Stoichiometry::Grammar --|> NQPMatchRole
# 
# 
# class Chemistry::Stoichiometry::Grammar::ChemicalEquation <<role>> {
# }
# 
# 
# class Chemistry::Stoichiometry::Grammar::ChemicalElement <<role>> {
# }
# 
# 
# class Chemistry::Stoichiometry::Actions::EquationBalance  {
# }
# Chemistry::Stoichiometry::Actions::EquationBalance --|> Chemistry::Stoichiometry::Actions::EquationMatrix
# 
# 
# class Chemistry::Stoichiometry::Actions::MolecularMass  {
# }
# 
# 
# class Chemistry::Stoichiometry::Actions::EquationMatrix  {
# }
# 
# 
# class Chemistry::Stoichiometry::Actions::WL::System  {
# }
# 
# 
# @enduml
Get WL UML graph spec for the package [AAp1]:
say to-uml-spec('Chemistry::Stoichiometry', format => 'wluml'):!methods:!attributes
# UMLClassGraph[
# "Parents" -> Flatten[{"Chemistry::Stoichiometry::Grammar" \[DirectedEdge] "Grammar", "Chemistry::Stoichiometry::Grammar" \[DirectedEdge] "Match", "Chemistry::Stoichiometry::Grammar" \[DirectedEdge] "Capture", "Chemistry::Stoichiometry::Grammar" \[DirectedEdge] "Chemistry::Stoichiometry::Grammar::ChemicalElement", "Chemistry::Stoichiometry::Grammar" \[DirectedEdge] "Chemistry::Stoichiometry::Grammar::ChemicalEquation", "Chemistry::Stoichiometry::Grammar" \[DirectedEdge] "NQPMatchRole", "Chemistry::Stoichiometry::Actions::EquationBalance" \[DirectedEdge] "Chemistry::Stoichiometry::Actions::EquationMatrix"}],
# "RegularMethods" -> Flatten[{}],
# "Abstract" -> Flatten[{"Chemistry::Stoichiometry::Grammar::ChemicalElement", "Chemistry::Stoichiometry::Grammar::ChemicalEquation", "NQPMatchRole"}],
# "EntityColumn" -> False, VertexLabelStyle -> "Text", ImageSize -> Large, GraphLayout -> Automatic]
Classes in a name space
Get the classes, roles, subs, and constants of a namespace:
.say for namespace-types('ML::TriesWithFrequencies', :how-pairs).sort(*.key)
# ML::TriesWithFrequencies::LeafProbabilitiesGatherer => Perl6::Metamodel::ClassHOW
# ML::TriesWithFrequencies::ParetoBasedRemover => Perl6::Metamodel::ClassHOW
# ML::TriesWithFrequencies::PathsGatherer => Perl6::Metamodel::ClassHOW
# ML::TriesWithFrequencies::RegexBasedRemover => Perl6::Metamodel::ClassHOW
# ML::TriesWithFrequencies::ThresholdBasedRemover => Perl6::Metamodel::ClassHOW
# ML::TriesWithFrequencies::Trie => Perl6::Metamodel::ClassHOW
# ML::TriesWithFrequencies::TrieTraverse => Perl6::Metamodel::ParametricRoleGroupHOW
# ML::TriesWithFrequencies::Trieish => Perl6::Metamodel::ParametricRoleGroupHOW
# TRIEROOT => Str
# TRIEVALUE => Str
Potential problems
Mermaid JS
The package can export class diagrams in the
Mermaid-JS format.
Unfortunately, currently (November 2022) Mermaid-JS does not support colon characters in class names.
Hence, colons are replaced with underscores.
Also, currently (November 2022) class specs in Mermaid-JS cannot be empty. I.e. the Mermaid JS code
generated here will not produce a diagram:
to-uml-spec --/methods --/attributes "ML::Clustering" --format=mermaid  
# classDiagram
# class ML_Clustering_KMeans {
# }
# ML_Clustering_KMeans --|> ML_Clustering_DistanceFunctions
# 
# 
# class k_means {
#   <<routine>>
# }
# k_means --|> Routine
# k_means --|> Block
# k_means --|> Code
# k_means --|> Callable
# 
# 
# class ML_Clustering_DistanceFunctions {
#   <<role>>
# }
# 
# 
# class find_clusters {
#   <<routine>>
# }
# find_clusters --|> Routine
# find_clusters --|> Block
# find_clusters --|> Code
# find_clusters --|> Callable
(Because of the empty definition ML_Clustering_KMeans { }.)
This command should produce Mermaid JS code that will produce diagram:
to-uml-spec --/methods --/attributes "ML::Clustering" --format=mermaid  
References
[AA1] Anton Antonov, et al.,
"Find programmatically all classes, grammars, and roles in a Raku package",
(2021),
StackOverflow.
[AA2] Anton Antonov,
"Generating UML diagrams for Raku namespaces",
(2022),
community.wolfram.com.
[AAp1] Anton Antonov,
"UML Diagram Generation Mathematica package",
(2016),
MathematicaForPrediction at GitHub/antononcube.
[ES1] Eugene Steinberg and Vojtech Krasa,
PlantUML integration IntelliJ IDEA plugin,
JetBrains Plugins Marketplace.
[GV1] graphviz.org.
[PUML1] plantuml.com.
[PUML2] PlantUML online demo server.
[UMLD1] uml-diagrams.org.
[WK1] Wikipedia entry, "Graphviz".
[WK2] Wikipedia entry, "PlantUML".
[WK3] Wikipedia entry, "Unified Modeling Language".