File Coverage

blib/lib/PlantUML/ClassDiagram/Parse.pm
Criterion Covered Total %
statement 47 47 100.0
branch 4 4 100.0
condition n/a
subroutine 11 11 100.0
pod 1 2 50.0
total 63 64 98.4


line stmt bran cond sub pod time code
1             package PlantUML::ClassDiagram::Parse;
2              
3 1     1   15835 use strict;
  1         2  
  1         24  
4 1     1   3 use warnings;
  1         1  
  1         27  
5 1     1   3 use utf8;
  1         1  
  1         4  
6 1     1   334 use PlantUML::ClassDiagram::Class;
  1         2  
  1         5  
7 1     1   367 use PlantUML::ClassDiagram::Relation;
  1         2  
  1         6  
8              
9             our $VERSION = "0.1";
10              
11 1     1   37 use parent qw/Class::Accessor::Fast/;
  1         1  
  1         2  
12             __PACKAGE__->follow_best_practice;
13              
14             my @self_valiables = qw/
15             classes
16             relations
17             class_strings
18             relation_strings
19             /;
20             __PACKAGE__->mk_ro_accessors(@self_valiables);
21              
22             sub new {
23 1     1 1 3 my ($class, $class_strings, $relation_strings) = @_;
24              
25 1         2 my $relations = +[ map { PlantUML::ClassDiagram::Relation->build($_) } @{$relation_strings} ];
  8         80  
  1         2  
26 1         8 my $classes = +[ map { PlantUML::ClassDiagram::Class->build($_, $relations) } @{$class_strings} ];
  9         81  
  1         3  
27              
28 1         12 my $attr = +{
29             class_strings => $class_strings,
30             relation_strings => $relation_strings,
31             classes => $classes,
32             relations => $relations,
33             };
34 1         14 return $class->SUPER::new($attr);
35             }
36              
37             sub parse {
38 1     1 0 9785 my ($class, $text) = @_;
39              
40 1         5 my $filtered_text = $class->_remove_commentout($text);
41 1         5 my $class_strings = $class->_extract_class_strings($filtered_text);
42 1         4 my $relation_strings = $class->_extract_relation_strings($filtered_text);
43              
44 1         5 return $class->new($class_strings, $relation_strings);
45             }
46              
47             sub _remove_commentout {
48 1     1   2 my ($class, $string) = @_;
49              
50 1         21 $string =~ s/\/'.*?'\///sg;
51 1         3 return $string;
52             }
53              
54             sub _extract_class_strings {
55 1     1   2 my ($class, $string) = @_;
56              
57 1         25 my @class_strings = $string =~ /(?:abstract\s+)*class.*?{.*?\n}/sg; # '\n}' for capture nest bracket
58 1         3 return \@class_strings;
59             }
60              
61             sub _extract_relation_strings {
62 1     1   2 my ($class, $string) = @_;
63              
64 1         3 my $relation_strings = +[];
65 1         23 my @lines = split('\n', $string);
66 1         3 for my $line (@lines){
67             # *- , <- , <|- , <|.
68 70 100       145 if ($line =~ /(\*|<)\|?(-|\.)/) {
    100          
69 4         7 push(@$relation_strings, $line);
70             # -* , -> , -|> , .|>
71             } elsif ($line =~ /(-|\.)\|?(\*|>)/) {
72 4         5 push(@$relation_strings, $line);
73             }
74             }
75              
76 1         5 chomp $_ for @$relation_strings;
77 1         5 return $relation_strings;
78             }
79              
80              
81             1;
82              
83             =encoding utf-8
84              
85             =head1 NAME
86              
87             PlantUML::ClassDiagram::Parse - PlantUML class diagram syntax parser
88              
89             =head1 SYNOPSIS
90              
91             use List::Util qw/first/;
92             use Data::Section::Simple qw/get_data_section/;
93              
94             my $pu_string = get_data_section('synopsis.pu');
95             my $parse = PlantUML::ClassDiagram::Parse->parse($pu_string);
96              
97             my $classes = $parse->get_classes;
98              
99             # bless( {
100             # 'relations' => [
101             # bless( {
102             # 'from' => 'Foo',
103             # 'to' => 'Base',
104             # 'name' => 'generalization'
105             # }, 'PlantUML::ClassDiagram::Relation' )
106             # ],
107             # 'variables' => [
108             # bless( {
109             # 'attribute' => '',
110             # 'name' => 'foo'
111             # }, 'PlantUML::ClassDiagram::Class::Variable' )
112             # ],
113             # 'attribute' => '',
114             # 'name' => 'Base',
115             # 'methods' => [
116             # bless( {
117             # 'name' => 'new',
118             # 'attribute' => 'static'
119             # }, 'PlantUML::ClassDiagram::Class::Method' ),
120             # bless( {
121             # 'name' => 'bar',
122             # 'attribute' => 'abstract'
123             # }, 'PlantUML::ClassDiagram::Class::Method' )
124             # ]
125             # }, 'PlantUML::ClassDiagram::Class' ),
126             # bless( {
127             # 'methods' => [
128             # bless( {
129             # 'name' => 'new',
130             # 'attribute' => 'static'
131             # }, 'PlantUML::ClassDiagram::Class::Method' ),
132             # bless( {
133             # 'name' => 'bar',
134             # 'attribute' => ''
135             # }, 'PlantUML::ClassDiagram::Class::Method' )
136             # ],
137             # 'name' => 'Foo',
138             # 'relations' => [
139             # $VAR1->[0]{'relations'}[0]
140             # ],
141             # 'variables' => [
142             # bless( {
143             # 'name' => 'foo',
144             # 'attribute' => ''
145             # }, 'PlantUML::ClassDiagram::Class::Variable' )
146             # ],
147             # 'attribute' => ''
148             # }, 'PlantUML::ClassDiagram::Class' )
149              
150             my $foo = first { $_->get_name eq 'Foo' } @$classes;
151             $foo->get_parents;
152              
153             # [ 'Base' ];
154              
155             __DATA__
156             @@ synopsis.pu
157             @startuml
158              
159             class Base {
160             foo
161              
162             {static} new()
163             {abstract} bar()
164             }
165             class Foo {
166             foo
167              
168             {static} new()
169             bar()
170             }
171             Foo --|> Base
172              
173             @enduml
174              
175             =head1 DESCRIPTION
176              
177             PlantUML::ClassDiagram::Parse is parser for PlantUML class diagram syntax
178             It generate objects that represent class structure written in class diagram.
179              
180             =head2 WAY TO USE
181              
182             Generate perl module using PlantUML::ClassDiagram::Class objects.
183             In fact you will also use template engine (ex: Text::Xslate) together.
184              
185             Sample script:
186             See examples/generate_pm_sample.pl
187              
188             =head2 class
189              
190             PlantUML::ClassDiagram::Class - represent each class
191              
192             =over
193              
194             =item get_name()
195              
196             own class name
197              
198             =item get_attribute()
199              
200             '' or 'abstract'
201              
202             =item get_variables()
203              
204             PlantUML::ClassDiagram::Class::Variable objects
205              
206             =item get_methods()
207              
208             PlantUML::ClassDiagram::Class::Method objects
209              
210             =item get_relations()
211              
212             PlantUML::ClassDiagram::Relation objects related in own class
213              
214             =item get_parents()
215              
216             parent class names it guessed from 'generalization' relation
217              
218             =back
219              
220             =head2 method
221              
222             PlantUML::ClassDiagram::Class::Method - represent each method
223              
224             =over
225              
226             =item get_name()
227              
228             own method name
229              
230             =item get_attribute()
231              
232             '' or 'abstract' or 'static'
233              
234             =back
235              
236             =head2 variable
237              
238             PlantUML::ClassDiagram::Class::Variable - represent each member variable
239              
240             =over
241              
242             =item get_name()
243              
244             own method name
245              
246             =item get_attribute()
247              
248             '' or 'abstract' or 'static'
249              
250             =back
251              
252             =head2 relations
253              
254             PlantUML::ClassDiagram::Relation - represent class to class relation
255              
256             =over
257              
258             =item get_name()
259              
260             own relation name
261              
262             =item get_from()
263              
264             from class name
265              
266             =item get_to()
267              
268             to class name
269              
270             =back
271              
272             Only support follow relation syntax
273              
274             =over
275              
276             =item association
277              
278             =item generalization
279              
280             =item realization
281              
282             =item aggregation
283              
284             =item composite
285              
286             =back
287              
288              
289             =head1 LICENSE
290              
291             Copyright (C) Kenta Kase.
292              
293             This library is free software; you can redistribute it and/or modify
294             it under the same terms as Perl itself.
295              
296             =head1 AUTHOR
297              
298             Kenta Kase Ekesin1202000@gmail.comE
299              
300             =cut