/[Frey]/trunk/lib/Frey/Class/Graph.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/lib/Frey/Class/Graph.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1133 - (show annotations)
Tue Jun 30 15:10:55 2009 UTC (14 years, 10 months ago) by dpavlin
File size: 4471 byte(s)
make classes immutable and remove moose droppings to make Perl::Critic::Moose happy
1 package Frey::Class::Graph;
2 use Moose;
3
4 extends 'Frey';
5 with 'Frey::Web', 'Frey::File', 'Frey::Storage';
6
7 use GraphViz;
8
9 has filter => (
10 documentation => 'Regex to select classes',
11 is => 'rw',
12 isa => 'Str',
13 required => 1,
14 default => sub {
15 '(' . join('|', map { s{lib/}{}; $_ } sort grep { -d $_ } glob("lib/*") ) . ')'
16 },
17 );
18
19
20 has filter_class => (
21 is => 'rw',
22 isa => 'Bool',
23 default => 1,
24 );
25
26 has filter_extends => (
27 is => 'rw',
28 isa => 'Bool',
29 default => 1,
30 );
31
32 has filter_includes => (
33 is => 'rw',
34 isa => 'Bool',
35 default => 1,
36 );
37
38 has filter_roles => (
39 is => 'rw',
40 isa => 'Bool',
41 default => 1,
42 );
43
44
45 has show_extends => (
46 documentation => 'connect to superclasses',
47 is => 'rw',
48 isa => 'Bool',
49 );
50
51 has show_includes => (
52 documentation => 'use and require connections',
53 is => 'rw',
54 isa => 'Bool',
55 default => 1,
56 );
57
58 has show_roles => (
59 documentation => 'roles consumers connections',
60 is => 'rw',
61 isa => 'Bool',
62 );
63
64 has show_disconnected => (
65 is => 'ro',
66 isa => 'Bool',
67 );
68
69
70 has layout => (
71 documentation => 'layout algorithm',
72 is => 'rw',
73 isa => 'Str',
74 required => 1,
75 );
76
77 sub layout_available { q/
78 dot directed graph
79 neato spring model
80 twopi radial
81 circo circular
82 fdp force directed spring model
83 / }
84
85 has portrait => (
86 documentation => 'vertical layout',
87 is => 'rw',
88 isa => 'Bool',
89 );
90
91 has no_overlap => (
92 documentation => 'avoid overlaping nodes',
93 is => 'rw',
94 isa => 'Bool',
95 );
96
97 has produce_dot => (
98 documentation => 'dump .dot text format',
99 is => 'rw',
100 isa => 'Bool',
101 );
102
103 sub introspect_path { 'var/introspect/' };
104
105 sub as_markup {
106 my ($self) = @_;
107
108 my $rankdir = $self->portrait;
109
110 my $g = GraphViz->new(
111 rankdir => $rankdir,
112 layout => $self->layout,
113 # layout => 'neato', # grabs too much memory
114 # layout => 'twopi', # grabs too much memory
115 # overlap => 'compress',
116 no_overlap => $self->no_overlap,
117
118 node => {
119 shape => 'box',
120 style =>'filled',
121 color => 'grey',
122 fillcolor =>'lightgray',
123 fontname => 'verdana',
124 fontsize => '12',
125
126 },
127 edge => {
128 color => 'grey',
129 fontname => 'verdana',
130 fontsize => '8',
131 fontcolor => 'grey',
132 }
133 );
134
135 my $count;
136 my $filter = $self->filter;
137
138 foreach my $path ( $self->dir_extension( $self->introspect_path, qr{\.(ya?ml)$}) ) {
139
140 my $class = $self->strip_path_extension( $path ) || die "can't strip $path";
141
142 $count->{$class}++ if $self->show_disconnected;
143
144 my $data = $self->load( $path );
145 # warn "## $class $path ", $self->dump( $data ); # if $self->debug;
146
147 next if $filter && $self->filter_class && $class !~ m{$filter};
148
149 if ( $self->show_includes && defined $data->{includes} ) {
150 foreach my $type ( keys %{ $data->{includes} } ) {
151 foreach my $package ( @{ $data->{includes}->{$type} } ) {
152 next if $filter && $self->filter_includes && $package !~ m{$filter};
153 warn "# $class\t$type\t$package\n";
154 $g->add_edge( $class => $package, label => $type, color => 'blue' );
155 $count->{$class}++;
156 $count->{$package}++;
157 }
158 }
159 }
160
161 if ( $self->show_roles && defined $data->{roles} ) {
162 foreach my $role ( keys %{ $data->{roles} } ) {
163 next if $filter && $self->filter_roles && $role !~ m{$filter};
164 warn "# $class\trole\t$role\n";
165 $g->add_edge( $role => $class, label => 'with', color => 'yellow' );
166 $g->add_node( $role, shape => 'diamond' );
167 $count->{$class}++;
168 $count->{$role}++;
169 }
170 }
171
172 if ( $self->show_extends && defined $data->{superclass} ) {
173 foreach my $extends ( keys %{ $data->{superclass} } ) {
174 next if $filter && $self->filter_extends && $extends !~ m{$filter};
175 warn "# $class\textends\t$extends\n";
176 $g->add_edge( $extends => $class, label => 'extends', color => 'green' );
177 $count->{$class}++;
178 $count->{$extends}++;
179 }
180 }
181
182 }
183
184 warn "# count ",$self->dump( $count );
185
186 my $max_count = 1;
187 foreach ( keys %$count ) {
188 my $v = $count->{$_};
189 $max_count = $v if $v > $max_count;
190 }
191 warn "# max_count: $max_count";
192
193 foreach my $node ( keys %$count ) {
194 my $v = $count->{$node};
195 my $pcnt = $v / $max_count;
196 my $color = join(",", ( $pcnt, $pcnt, 0.75 ) );
197
198 $g->add_node( $node,
199 style =>'filled',
200 color => $color,
201 fillcolor => $color,
202 # label => "$node\n$v",
203 );
204
205 }
206
207 if ( $self->produce_dot ) {
208 $self->content_type( 'text/plain' );
209 $self->store( 'var/classes.dot', $g->as_canon );
210 return $g->as_canon;
211 }
212
213 $self->content_type( 'image/png' );
214 return $g->as_png;
215
216 }
217
218 __PACKAGE__->meta->make_immutable;
219 no Moose;
220
221 1;

  ViewVC Help
Powered by ViewVC 1.1.26