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:
- Checkout https://github.com/nuclight/teleperl
- Create parser by `yapp -m TL -s tl.yp`
- Generate classes by `perl tl-gen.pl Telegram res/layer91-madeline.tl`
- 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