Very big generated file leads to very large one dimension layout unusable diagram

0 votes
asked Nov 23, 2020 in Question / help by nuclight

I'm trying to see relations in Telegram protocol scheme, for which I wrote a script which generates PlantUML file from classes generated from Telegram scheme, that's more than 160 Kb input and more than 1000 classes. However, generated PNG is very wide, is clipped even if I give -DPLANTUML_LIMIT_SIZE=81920, and - of course - unusable: all classes are in one horizontal row, all lines are mixed in one fat thread. How layout could be fixed? Or probably I need to generate some other type of diagram?

The part of generated file looks like:

Telegram::SendMessageGamePlayAction <|- Telegram::SendMessageActionABC
class Telegram::SendMessageGamePlayAction {
}
abstract class Telegram::MessageFwdHeaderABC
Telegram::MessageFwdHeader <|- Telegram::MessageFwdHeaderABC
class Telegram::MessageFwdHeader {
 + from_id : int
 date : int
 + channel_id : int
 + channel_post : int
 + post_author : string
 + saved_from_peer : Telegram::Peer
 + saved_from_msg_id : int
}
Telegram::MessageFwdHeader *- Telegram::Peer : saved_from_peer >
Telegram::RecentMeUrlUnknown <|- Telegram::RecentMeUrlABC
class Telegram::RecentMeUrlUnknown {
 url : string
}
Telegram::Auth::CodeTypeCall <|- Telegram::Auth::CodeTypeABC
class Telegram::Auth::CodeTypeCall {
}
Telegram::InputBotInlineMessageMediaContact <|- Telegram::InputBotInlineMessageABC
class Telegram::InputBotInlineMessageMediaContact {
 phone_number : string
 first_name : string
 last_name : string
 vcard : string
 + reply_markup : Telegram::ReplyMarkup
}
Telegram::InputBotInlineMessageMediaContact *- Telegram::ReplyMarkup : reply_markup >
abstract class Telegram::SecureFileABC
Telegram::SecureFileEmpty <|- Telegram::SecureFileABC
class Telegram::SecureFileEmpty {
}
Telegram::MessageActionPaymentSent <|- Telegram::MessageActionABC
class Telegram::MessageActionPaymentSent {
 currency : string
 total_amount : long
}
abstract class Telegram::InputEncryptedFileABC
Telegram::InputEncryptedFileEmpty <|- Telegram::InputEncryptedFileABC
class Telegram::InputEncryptedFileEmpty {
}
abstract class Telegram::ImportedContactABC
Telegram::ImportedContact <|- Telegram::ImportedContactABC
class Telegram::ImportedContact {
 user_id : int
 client_id : long
}
abstract class Telegram::InputPaymentCredentialsABC
Telegram::InputPaymentCredentialsApplePay <|- Telegram::InputPaymentCredentialsABC
class Telegram::InputPaymentCredentialsApplePay {
 payment_data : Telegram::DataJSON
}
Telegram::InputPaymentCredentialsApplePay *- Telegram::DataJSON : payment_data >
abstract class Telegram::ContactLinkABC
Telegram::ContactLinkNone <|- Telegram::ContactLinkABC
class Telegram::ContactLinkNone {
}
Telegram::PageBlockTable <|- Telegram::PageBlockABC
class Telegram::PageBlockTable {
 + bordered : true
 + striped : true
 title : Telegram::RichText
 rows : Telegram::PageTableRow[]
}

How to get full generated file:

  1. Checkout https://github.com/nuclight/teleperl
  2. Create parser by `yapp -m TL -s tl.yp`
  3. Generate classes by `perl tl-gen.pl Telegram res/layer91-madeline.tl`
  4. Generate PlantUML input from Telegram/ directory  by `tl-puml.pl > layer91.puml`

The tl-puml.pl script is as follows:

#!/usr/bin/perl -w

use strict;
use warnings;

use Telegram::ObjTable;

print <<'HEAD';
@startuml
set namespaceSeparator ::
HEAD

my %abcseen;
for my $type (grep { not exists $_->{func} } values %Telegram::ObjTable::tl_type) {
    require $type->{file};
    my $class = $type->{class};

    my (@fields, %TYPES, $parent);
    {
        no strict 'refs';
        # sort as in schema XXX kludge
        @fields = sort {
                ${"$class\::FIELDS"}{$a} <=> ${"$class\::FIELDS"}{$b}
            } keys %{"$class\::FIELDS"};
        %TYPES = %{"$class\::TYPES"};
        $parent = ${"$class\::parent"};
    }
    # filter out 'flags'
    # XXX we don't handle multiple such though they wasn't seen in real schemas
    my $optional = (map {
            exists $TYPES{$_}->{optional}
            ? (split(/\./, $TYPES{$_}->{optional}))[0]
            : ()
        } keys %TYPES)[0] // '';
    @fields = grep { $_ ne $optional } @fields;

    # $parent =~ s/ABC$//;
    unless (exists $abcseen{$parent}) {
        print "abstract class $parent\n";
        $abcseen{$parent} = 1;
    }
    print "$class <|- $parent\n";
    print "class $class {\n";
    my @contains;
    for my $name (@fields) {
        my $TYPE = $TYPES{$name};
        print " +" if $TYPE->{optional};    # abuse UML conventions :)
        print " $name : ";
        print $TYPE->{type};
        push @contains, $name unless $TYPE->{builtin};
        print '[]' if $TYPE->{vector};
        print "\n";
    }
    print "}\n";

    print "$class *- $TYPES{$_}->{type} : $_ > \n" for @contains;
}

print <<'FOOT';
@enduml
FOOT

3 Answers

0 votes
answered Nov 24, 2020 by Serge Wenger Work (15,620 points)
Hello,

When I have really big diagrams I use SVG instead of PNG . The result is not clipped. You can save after in PNG
0 votes
answered Nov 24, 2020 by plantuml (295,000 points)

You have to change all your :

@startuml
Telegram::ImportedContact <|- Telegram::ImportedContactABC
@enduml

to

@startuml
Telegram::ImportedContact <|-- Telegram::ImportedContactABC
@enduml

It will work better this way

commented Nov 24, 2020 by nuclight

OK, I tried this and output to SVG, got 2.7 Mb file, now there are two rows which are enough for some classes but most of them are still have all arrows in one fat line.

Here is current version of full generated file (5K lines, ~170 Kb):

https://gist.github.com/nuclight/9e2c47fc08b5431d10412be983991a9e

0 votes
answered Nov 24, 2020 by The-Lu (64,340 points)

Hello N.,

First test, you can add :

left to right direction

And now explore on SVG output (on a long column) all the classes, to see if some grouping are possible?

→ Link to the SVG output

That is just more readable than one long line...

That is only a first begin...wink
If that can help,
Regards,
Th.

commented Nov 24, 2020 by The-Lu (64,340 points)

According to @plantuml answer:

Here is a → Link to another SVG output

Regards,
Th.

commented Nov 24, 2020 by nuclight
Alas, I did not understood how to add "left to right direction" - and, in fact, in real full file (see another comment, I've added a link to github's gist with it) it's already horizontal.
commented Dec 22, 2020 by The-Lu (64,340 points)

Hello N.,

left to right direction

could be add on the first line of the plantuml file, as:

left to right direction

package foo1 {
class A
class B
class C
}

package foo2 {
  class a
}

Then the align will be vertical.


[See on PlantUML server]

Regards,
Th.

...