File Coverage

blib/lib/Map/Tube/GraphViz.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Map::Tube::GraphViz;
2              
3             # Pragmas.
4 3     3   42535 use strict;
  3         5  
  3         129  
5 3     3   19 use warnings;
  3         5  
  3         130  
6              
7             # Modules.
8 3     3   1876 use Class::Utils qw(set_params);
  0            
  0            
9             use English;
10             use Error::Pure qw(err);
11             use GraphViz2;
12             use List::MoreUtils qw(none);
13             use Map::Tube::GraphViz::Utils qw(node_color);
14             use Scalar::Util qw(blessed);
15              
16             # Version.
17             our $VERSION = 0.04;
18              
19             # Constructor.
20             sub new {
21             my ($class, @params) = @_;
22              
23             # Create object.
24             my $self = bless {}, $class;
25              
26             # Edge callback.
27             $self->{'callback_edge'} = sub {
28             my ($self, $from, $to) = @_;
29             $self->{'g'}->add_edge(
30             'from' => $from,
31             'to' => $to,
32             );
33             return;
34             };
35              
36             # Node callback.
37             $self->{'callback_node'} = \&node_color;
38              
39             # Driver.
40             $self->{'driver'} = 'neato';
41              
42             # Name of map.
43             $self->{'name'} = undef;
44              
45             # GraphViz2 object.
46             $self->{'g'} = undef;
47              
48             # Output.
49             $self->{'output'} = 'png';
50              
51             # Map::Tube object.
52             $self->{'tube'} = undef;
53              
54             # Process params.
55             set_params($self, @params);
56              
57             # Check Map::Tube object.
58             if (! defined $self->{'tube'}) {
59             err "Parameter 'tube' is required.";
60             }
61             if (! blessed($self->{'tube'})
62             || ! $self->{'tube'}->does('Map::Tube')) {
63              
64             err "Parameter 'tube' must be 'Map::Tube' object.";
65             }
66              
67             # GraphViz2 object.
68             if (defined $self->{'g'}) {
69             if (defined $self->{'name'}) {
70             err "Parameter 'name' cannot be used with ".
71             "'g' parameter.";
72             }
73              
74             # Check GraphViz2 object.
75             if (! blessed($self->{'g'})
76             || ! $self->{'g'}->isa('GraphViz2')) {
77              
78             err "Parameter 'g' must be 'GraphViz2' object.";
79             }
80             } else {
81             my $name = $self->{'name'};
82             if (! defined $name) {
83             $name = $self->{'tube'}->name;
84             }
85             $self->{'g'} = GraphViz2->new(
86             'global' => {
87             'directed' => 0,
88             },
89             $name ? (
90             'graph' => {
91             'label' => $name,
92             'labelloc' => 'top',
93             },
94             ) : (),
95             );
96             }
97              
98             # Check output format.
99             if (! defined $self->{'output'}) {
100             err "Parameter 'output' is required.";
101             }
102             if (none { $self->{'output'} eq $_ }
103             keys %{$self->{'g'}->valid_attributes->{'output_format'}}) {
104              
105             err "Unsupported 'output' parameter '$self->{'output'}'.";
106             }
107              
108             # Object.
109             return $self;
110             }
111              
112             # Get graph.
113             sub graph {
114             my ($self, $output_file) = @_;
115             foreach my $node (values %{$self->{'tube'}->nodes}) {
116             $self->{'callback_node'}->($self, $node);
117             }
118             my @processed;
119             foreach my $node (values %{$self->{'tube'}->nodes}) {
120             foreach my $link (split m/,/ms, $node->link) {
121             if (none {
122             ($_->[0] eq $node->id && $_->[1] eq $link)
123             ||
124             ($_->[0] eq $link && $_->[1] eq $node->id)
125             } @processed) {
126              
127             $self->{'callback_edge'}->($self, $node->id,
128             $link);
129             push @processed, [$node->id, $link];
130             }
131             }
132             }
133             eval {
134             $self->{'g'}->run(
135             'driver' => $self->{'driver'},
136             'format' => $self->{'output'},
137             'output_file' => $output_file,
138             );
139             };
140             if ($EVAL_ERROR) {
141             err 'Cannot create GraphViz output.',
142             'Error', $EVAL_ERROR,
143             'Dot input', $self->{'g'}->dot_input;
144             }
145             return;
146             }
147              
148             1;
149              
150             __END__