Open jtrunick opened 1 year ago
It looks like when using the keyword as a reference the schema resolves the type differently compared to a string reference or a qualified keyword reference:
(require '[malli.core :as m])
(def s [:schema
{:registry {:a :any
:a/b :any
"c" :any
"d" [:map
[:x :a]
[:y :a/b]
[:z "c"]]}}
"d"])
(m/schema s {})
;; returns the following
[:schema
{:registry
{:a :any,
:a/b :any,
"c" :any,
"d" [:map
[:x :any] ;; keyword is resolved
[:y :a/b] ;; qualified keyword is referenced
[:z "c"]] ;; string is referenced
}}
"d"]
In the case a keyword ref is used we generate an abstract class representing the referenced value.
(require '[malli.plantuml :as p])
(p/transform
(m/schema
[:schema
{:registry {"b" :any
"d" [:map [:x "b"]]
:a :any
:b [:map [:x :a]] ;; this breaks the rendering
:c [:map [:y :b]]}}
"d"]
{}))
@startuml
entity :a {
:any
}
entity :b {
:x :any
}
entity :c {
:y ":c$Y"
}
abstract :c$Y {
:x :any
}
entity b {
:any
}
entity d {
:x "b"
}
:c *-- :c$Y /' this will cause the render to fail since colon is reserved character '/
d o-- b : colon used for labels
@enduml
By removing the invalid format line the graph can be rendered without the edge.
But now the graph has an object :c$Y
that should just be :b
. and because of this just stripping the :
from the name during plantuml generation wouldn't work as a solution and it would consider :b
and "b"
as equal.
To my understanding what is happening right now malli.plantuml/transform
generates a new abstract class instead of referencing the type :b
, since it is not recognized as a reference by malli.core/-reference?
.
To summarize, AFAIK :
can not be used in node names when defining edges in PlantUML and this causes the rendering to fail. I need to do some more investigating if it'd be possible to encode the colon into the edge definitions.
It is possible to alias the entity names to avoid the rendering error.
@startuml
entity :a {
:any
}
entity :b {
:x :any
}
entity ":c" as COLON_c {
:y ":c$Y"
}
abstract ":c$Y" as COLON_c$Y {
:x :any
}
entity b {
:any
}
entity d {
:x "b"
}
COLON_c *-- COLON_c$Y
d o-- b : colon used for labels
@enduml
Which results in:
I'll create a PR for this.
I changed the Address example so that Burger is a keyword, the generated plant uml gives an error when rendering.
(def Address [:schema {:registry {"Country" [:map [:name [:enum :FI :PO]] [:neighbors [:vector [:ref "Country"]]]] :Burger [:map [:name string?] [:description {:optional true} string?] [:origin [:maybe "Country"]] [:price pos-int?]] "OrderLine" [:map [:burger :Burger] [:amount int?]] "Order" [:map [:lines [:vector "OrderLine"]] [:delivery [:map [:delivered boolean?] [:address [:map [:street string?] [:zip int?] [:country "Country"]]]]]]}}