plantuml / plantuml

Generate diagrams from textual description
https://plantuml.com
Other
9.73k stars 881 forks source link

Dynamically create a json structure inside the preprecessor function #328

Open break2make opened 4 years ago

break2make commented 4 years ago

I have an usecase where I want to find the max of an array. If I have a predefined json struct having a {"key": [12, 13, 14]}, then max() function return the max value 14. However, there are few cases, where I have to generate {"key": [12, 13, 14]} dynamically with variable number of elements in list. Please help to generate a dynamic json structure or update an existing jason structure in plantuml preprocessor.

abhijeet-pathak commented 3 years ago

Can you please provide an example of your preprocessor function?

Potherca commented 9 months ago

For the sake of completion:

philCryoport commented 3 months ago

My use case:

I'm tracking in a sequence diagrams multiple queues which would greatly benefit from the ability to (a) start with an empty JSON array, and then (b) have the ability to add and remove entries.

My queues are:

I'll also comment in the above links

The-Lum commented 3 weeks ago

Hello @break2make, @philCryoport, @Potherca, and all,

Available from last snapshot (~v1.2024.5beta1), you can now use:

Then:

From:

See also:

Regards, Th.

philCryoport commented 3 weeks ago

Hi @The-Lum -- Trying this out first with a "Hello World":

➜ java --version
openjdk 21.0.2 2024-01-16 LTS
OpenJDK Runtime Environment Temurin-21.0.2+13 (build 21.0.2+13-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.2+13 (build 21.0.2+13-LTS, mixed mode)
@startuml
!$a  = 42
!$ab = "foo1"
!$cd = "foo2"
!$ef = $ab + $cd
!$foo = { "name": "John", "age" : 30 }
%json_remove($foo,name)
%json_add($foo,name,"Sally")

Alice -> Bob : $a
Alice -> Bob : $ab
Alice -> Bob : $cd
Alice -> Bob : $ef
Alice -> Bob : Do you know **$foo.name** ?
@enduml

It threw the following error:

java.lang.NullPointerException: value is null
    at net.sourceforge.plantuml.json.JsonObject.add(JsonObject.java:331)
    at net.sourceforge.plantuml.tim.stdlib.JsonAdd.executeReturnFunction(JsonAdd.java:84)
    at net.sourceforge.plantuml.tim.TContext.applyFunctionsAndVariables(TContext.java:486)
    at net.sourceforge.plantuml.tim.TContext.applyFunctionsAndVariablesInternal(TContext.java:431)
    at net.sourceforge.plantuml.tim.TContext.addPlain(TContext.java:391)
    at net.sourceforge.plantuml.tim.TContext.executeOneLineNotSafe(TContext.java:360)
    at net.sourceforge.plantuml.tim.TContext.executeOneLineSafe(TContext.java:321)
    at net.sourceforge.plantuml.tim.TContext.executeLines(TContext.java:295)
    at net.sourceforge.plantuml.tim.TimLoader.load(TimLoader.java:68)
    at net.sourceforge.plantuml.BlockUml.<init>(BlockUml.java:147)
    at net.sourceforge.plantuml.BlockUmlBuilder.init(BlockUmlBuilder.java:144)
    at net.sourceforge.plantuml.BlockUmlBuilder.<init>(BlockUmlBuilder.java:102)
    at net.sourceforge.plantuml.SourceFileReaderAbstract.<init>(SourceFileReaderAbstract.java:98)
    at net.sourceforge.plantuml.SourceFileReader.<init>(SourceFileReader.java:77)
    at net.sourceforge.plantuml.Run.manageFileInternal(Run.java:479)
    at net.sourceforge.plantuml.Run.processArgs(Run.java:404)
    at net.sourceforge.plantuml.Run.manageAllFiles(Run.java:371)
    at net.sourceforge.plantuml.Run.main(Run.java:206)
Error line 8 in file: /foo/test.puml
Some diagram description contains errors

Line 8 is %json_add($foo,name,"Sally")

Note that I tried both "Sally" and Sally (i.e. without the double quotes). In both cases, it threw the same error.

I also tried assigning the return of the remove and the add calls to newly declared variables -- identical NPE to the above...except it doesn't call out line 8, nor does it say "Some diagram description contains errors":

@startuml
!$a  = 42
!$ab = "foo1"
!$cd = "foo2"
!$ef = $ab + $cd
!$foo = { "name": "John", "age" : 30 }
!$foo2 = %json_remove($foo,name)
!$foo3 = %json_add($foo2,name,"Sally")

Alice -> Bob : $a
Alice -> Bob : $ab
Alice -> Bob : $cd
Alice -> Bob : $ef
Alice -> Bob : Do you know **$foo3.name** ?
@enduml

I also tried assigning to the same variable -- identical to the second situation, "value is null" NPE, doesn't call out line 8, nor does it say "Some diagram description contains errors":

@startuml
!$a  = 42
!$ab = "foo1"
!$cd = "foo2"
!$ef = $ab + $cd
!$foo = { "name": "John", "age" : 30 }
!$foo = %json_remove($foo,name)
!$foo = %json_add($foo,name,"Sally")

Alice -> Bob : $a
Alice -> Bob : $ab
Alice -> Bob : $cd
Alice -> Bob : $ef
Alice -> Bob : Do you know **$foo3.name** ?
@enduml
The-Lum commented 3 weeks ago

Hi @philCryoport,

Thanks a lot for your detailed tests.

Currently the %json_add runs only with JSON Array or Object, as:

@startuml
!$foo = [12, 13]
!$a  = [14, "ab"]
!$foo = %json_add($foo, $a)

Alice -> Bob : $a
Alice -> Bob : $foo
@enduml
@startuml
!$a  = 42
!$foo = { "name": "John", "age" : 30 }
!$foo = %json_remove($foo, name)
!$v = %str2json("[1, 2]")
!$foo = %json_add($foo, "name", $v)

Alice -> Bob : $a
Alice -> Bob : $foo
Alice -> Bob : Do you know **$foo.name** ?
@enduml

And there are some side effects on scalar type (string, integer, boolean, null) [ -> As you point out with your tests].

Then I must to do more boundary check on that. I must to go to new tests... on scalar...

Thanks for your tests. See you on next correction, Regards, Th.

philCryoport commented 3 weeks ago

Thank you @The-Lum -- lemme know when you have a snapshot build ready and I'll test it on my box:

The-Lum commented 3 weeks ago

Hello @philCryoport,

With the last snapshot of yesterday evening you can now test.

Good test... Don't hesitate to make feedback...

Regards, Th.

philCryoport commented 2 weeks ago

Hi @The-Lum

Yep, tried out the basic stuff with 1.2024.5beta:

@startuml
!$a  = 42
Alice -> Bob : Original $a
!$foo = { "name": "John", "age" : 30 }
Alice -> Bob : Original foo: $foo
!$foo = %json_remove($foo, name)
Alice -> Bob : Revised foo: $foo -- name attribute should be gone
!$v = %str2json("[1, 2]")
!$foo = %json_add($foo, "name", Sally)
Alice -> Bob : Revised foo again: $foo -- name attribute should be "Sally"
!$v = %str2json("[1, 2]")
!$foo = %json_add($foo, "new array", $v)
Alice -> Bob : Revised foo again: $foo -- should have the "new array" of [1,2]
Alice -> Bob : Do you know **$foo.name** ?
@enduml

The basic stuff worked fine: image

However there's no checking with a json_add to see if the attribute already exists :(

@startuml
!$a  = 42
Alice -> Bob : Original $a
!$foo = { "name": "John", "age" : 30 }
Alice -> Bob : Original foo: $foo
!$foo = %json_add($foo, "name", Sally)
Alice -> Bob : Revised foo again: $foo - should have one name attribute "Sally" - but end up with two "name" attributes
@enduml

Result - two "name" attributes: image

I also tried removing an attribute that I had already removed:

@startuml
!$a  = 42
Alice -> Bob : Original $a
!$foo = { "name": "John", "age" : 30 }
Alice -> Bob : Original foo: $foo
!$foo = %json_remove($foo, "name")
Alice -> Bob : Revised foo again: $foo - "name" attribute should be gone
!$foo = %json_remove($foo, "name")
Alice -> Bob : Revised foo again: $foo - what happens if I try to remove the "name" attribute when it's already gone?
@enduml

Result - No warning thrown...which might be ok...that depends on the standard being followed: image

The classic sempf joke is running through my head...

The-Lum commented 2 weeks ago

Hi @philCryoport,

Good catch!

Internally plantuml use the minimal-json; then for:

However there's no checking with a json_add to see if the attribute already exists :(

We will now create the new function %json_set a wrapper of set, in order to set the last existing attribute....

And you're right, unit tests look strangely like:

The classic sempf joke is running through my head...

Regards, Th.