MDA with plantuml

0 votes
asked Mar 11, 2014 in Wanted features by taharqa (240 points)
edited Mar 11, 2014 by taharqa
This is not really a user question more a developer one.

This may seems weird but I planned to build a plain text MDA platform and wanted to use plantuml as modeling component.

I want to know if there is an internal PSM / AST / Representation / Whatever in internal so I can reach the data from to plantuml sources to generate sources. Or is there any MDA project with plantuml ?

Thank you !

7 Answers

0 votes
answered Mar 12, 2014 by plantuml (294,960 points)

Hello,

There are some internal representation of data, but those data structures are not stable : they can change from version to version, without any notice.
So relying on this is probably not a good idea.

The best option we can see for your project is to use XMI: http://www.plantuml.com/xmi.html
Some feature are likely missing, so do not hesitate to post here for enhancement request.
 

commented Mar 12, 2014 by taharqa (240 points)
Hello, I saw the xmi export and I was not interested too much.
In fact as plantuml is a command line tool with one input and one ouput, there is no plugin system for now. The thing I'll need is your developper API you are using to generate your xmi.
Can you consider stabilizate it and propose it to developers ? I think with this we can do things awesome.
+1 vote
answered Mar 12, 2014 by plantuml (294,960 points)

Stabilizate the code will be very difficult, because refactoring is strong way of enhancement for us.

But here what we could do:

  •  Option 1: Publish a stabilized class MDAUtils. This class would have a method getXmi() which will return a org.w3c.dom.Document that is XMI formatted.


So you could have in your own code:
  String plantumlDiagramSource = "@startuml\n....";
  Document xmi = MDAUtils.getXmi(plantumlDiagramSource);
  // Now let's use standard org.w3c.dom methods to get information

 
 

  • Option 2 : We define together some interfaces that would modelize the MDA.

For example:
interface MDACore {
  Collection<MDAPackage> getPackages();
  ...
}
interface MDAPackage {
  Collection<MDAClass> getClasses();
  ...
}


Then we publish a stabilized class MDAUtils:
  String plantumlDiagramSource = "@startuml\n....";
  MDACore model = MDAUtils.getMDACore(plantumlDiagramSource);
  // Now let's use MDACore to get informations

 

  • Option 3 : any other ideas welcome :-)
commented Mar 12, 2014 by taharqa (240 points)
I understand very well that the internals can not be exposed this way, as this is not its main purpose when designed at first place.

I must admit the Option2 is a very good candidate in order to achieve what we want. This will have the advantage to formalize and start a new collaboration with developpers :)

The Option 3  can look  like this : You do not defined by yourself the Model,Package,etc Api. You just expose a Visitor like API. Developers just subclasses Visitors to get information they want in the model they want.

And of course Option 2 and 3 apply for all diagram not only Class Diagram :) Class Diagram have priority of course.

What do you think ?
0 votes
answered Mar 13, 2014 by plantuml (294,960 points)

Ok, let's give a try.
We have created a list of class to have a minimum working product.
Those class are in net.sourceforge.plantuml.api.mda.option2 package, to denotate that this is an alpha release.

public interface MDAEntity {
    public String getName();
}
public interface MDAPackage {
    public String getName();
    public Collection<MDAEntity> getEntities();
}
public interface MDADiagram {
    public Collection<MDAPackage> getPackages();
}


Finally, you have a factory class.

public class MDAUtils {
    public static MDADiagram getMDADiagram(String plantumlDiagramSource)
    ...
}

Theses classes are available in this zip archive: https://dl.dropboxusercontent.com/u/13064071/mda.zip

Knowing that, with the last beta ( https://dl.dropboxusercontent.com/u/13064071/plantuml.jar ), you can have:

    public void testGetMDADiagram01() {
        String s = "@startuml\n";
        s += "class Foo1\n";
        s += "@enduml";
        final MDADiagram diagram = MDAUtils.getMDADiagram(s);
        assertNotNull(diagram);
        final List<MDAPackage> packages = new ArrayList<MDAPackage>(diagram.getPackages());
        assertEquals(1, packages.size());
        assertEquals("", packages.get(0).getName());

        final List<MDAEntity> entities = new ArrayList<MDAEntity>(packages.get(0).getEntities());
        assertEquals(1, entities.size());
        assertEquals("Foo1", entities.get(0).getName());
    }

    public void testGetMDADiagram02() {
        String s = "@startuml\n";
        s += "class Foo1\n";
        s += "package package1 {\n";
        s += "class Foo2\n";
        s += "}\n";
        s += "\n";
        s += "\n";
        s += "@enduml";
        final MDADiagram diagram = MDAUtils.getMDADiagram(s);
        assertNotNull(diagram);
        final List<MDAPackage> packages = new ArrayList<MDAPackage>(diagram.getPackages());
        assertEquals(2, packages.size());
        assertEquals("", packages.get(0).getName());
        assertEquals("package1", packages.get(1).getName());

        final List<MDAEntity> rootEntities = new ArrayList<MDAEntity>(packages.get(0).getEntities());
        assertEquals(1, rootEntities.size());
        assertEquals("Foo1", rootEntities.get(0).getName());

        final List<MDAEntity> package1Entities = new ArrayList<MDAEntity>(packages.get(1).getEntities());
        assertEquals(1, package1Entities.size());
        assertEquals("Foo2", package1Entities.get(0).getName());

    }


Now we let you tell us which methods you need if the MDAxxx interfaces : you can modify them, or even create new interfaces.

About option3, we have also created a interface net.sourceforge.plantuml.api.mda.option3.MDAVisitor :


public interface MDAVisitor {
}

Feel free to add methods here also.
 

0 votes
answered Mar 13, 2014 by taharqa (240 points)
edited Mar 13, 2014 by taharqa
I'll look your code carefully this week and come back to you.
 
In the mean time, always regarding make plantuml plugin compatible. 
 
Can you imagine create a SPI net.sf.plantuml.spi.PlantUmlPlugin. 
 
  public interface PlantUmlPlugin {
      void provideDiagram( MDADiagram diagram ) ;
   }
 
You reach developers plugin via the standard java ServiceLoader mechanism
and run them if found them in the classpath. This way developers can extends 
plantuml using the options 2 and 3 we were talking about. without any impact 
on your workflow.
 
What do you think ?
 
 
 
0 votes
answered May 31, 2017 by giflw (200 points)
Hi

Is there some news on this subject? I notice that all diagrams are classes derived from class Diagram. Is this internal API or could be used/expanded to be a public API?

Best regards

Guilherme Weizenmann
0 votes
answered May 31, 2017 by taharqa (240 points)
Hi Guilherme, I must admit real life detach me from my goals.

But now I wll be ready to continue to test this enhancement.

@plantuml what do you think ?
0 votes
answered Jun 1, 2017 by giflw (200 points)
Hi I was thinking: what about we create a tree of nodes, with properties backed by a Map, to hold the intermediate state of diagrams. Parser could generate this state, and the final serialization could be done from those intermediate states. This could work as an AST. This could be used to generate those AST programatically and plantuml could generate the diagrams. So, these would allow the use of plantuml as parser to generate code, or from code to generate diagrams, without writing the plantuml source file. What do you think? Best regards Guilherme Weizenmann
...