File Coverage

blib/lib/Autodia/Diagram.pm
Criterion Covered Total %
statement 30 997 3.0
branch 0 356 0.0
condition 0 60 0.0
subroutine 10 53 18.8
pod 1 32 3.1
total 41 1498 2.7


line stmt bran cond sub pod time code
1             package Autodia::Diagram;
2 1     1   23625 use strict;
  1         2  
  1         43  
3              
4             =head1 NAME
5              
6             Autodia::Diagram - Class to hold a collection of objects representing parts of a Dia Diagram.
7              
8             =head1 SYNOPSIS
9              
10             use Autodia::Diagram;
11              
12             my $Diagram = Autodia::Diagram->new;
13              
14             =head2 Description
15              
16             Diagram is an object that contains a collection of diagram elements and the logic to generate the diagram layout as well as to output the diagram itself in Dia's XML format using template toolkit.
17              
18             =cut
19              
20 1     1   3834 use Template;
  1         99369  
  1         40  
21 1     1   3490 use Data::Dumper;
  1         11736  
  1         230  
22              
23             $Data::Dumper::Maxdepth = 2;
24              
25 1     1   732 use Autodia::Diagram::Class;
  1         4  
  1         53  
26 1     1   758 use Autodia::Diagram::Component;
  1         2  
  1         51  
27 1     1   705 use Autodia::Diagram::Superclass;
  1         3  
  1         45  
28 1     1   551 use Autodia::Diagram::Dependancy;
  1         2  
  1         43  
29 1     1   643 use Autodia::Diagram::Inheritance;
  1         2  
  1         48  
30 1     1   687 use Autodia::Diagram::Relation;
  1         2  
  1         42  
31 1     1   861 use Autodia::Diagram::Realization;
  1         3  
  1         14397  
32              
33             my %dot_filetypes = (
34             gif => 'as_gif',
35             png => 'as_png',
36             jpg => 'as_jpeg',
37             jpeg => 'as_jpeg',
38             dot => 'as_canon',
39             svg => 'as_svg',
40             fig => 'as_fig',
41             );
42              
43             my %vcg_filetypes = (
44             ps => 'as_ps',
45             pbm => 'as_pbm',
46             ppm => 'as_ppm',
47             vcg => 'as_vcg',
48             plainvcg => 'as_plainvcg',
49             );
50              
51             #----------------------------------------------------------------
52             # Constructor Methods
53              
54              
55             =head1 METHODS
56              
57             =head2 Class Methods
58              
59             =over 4
60              
61             =item new - constructor method
62              
63             creates and returns an unpopulated diagram object.
64              
65             =back
66              
67             =cut
68              
69             sub new
70             {
71 0     0 1   my $class = shift;
72              
73 0           my $config_ref = shift;
74 0           my $Diagram = {};
75 0   0       bless ($Diagram, ref($class) || $class);
76 0           $Diagram->directed(1);
77 0           $Diagram->_initialise($config_ref);
78 0           return $Diagram;
79             }
80              
81             =head2 Object methods
82              
83             To get a collection of a objects of a certain type you use the method of the same name. ie $Diagram->Classes() returns an array of 'class' objects.
84              
85             The methods available are Classes(), Components(), Superclasses(), Inheritances(), Relations(), and Dependancies(); These are all called in the template to get the collections of objects to loop through.
86              
87             To add an object to the diagram. You call the add_ method, for example $Diagram->add_class($class_name), passing the name of the object in the case of Class, Superclass and Component but not Inheritance or Dependancy which have their names generated automagically.
88              
89             Objects are not removed, they can only be superceded by another object; Component can be superceded by Superclass which can superceded by Class. This is handled by the object itself rather than the diagram.
90              
91             =head2 Accessing and manipulating the Diagram
92              
93             Elements are added to the Diagram through the add_ method (ie add_classes() ).
94              
95             Collections of elements are retrieved through the method (ie Classes() ).
96              
97             The diagram is laid out and output to a file using the export_xml() method.
98              
99             =cut
100              
101             ################
102             # Access Methods
103              
104             sub directed {
105 0     0 0   my $self = shift;
106 0           my $value = shift;
107 0 0         $self->{directed} = $value if (defined $value);
108 0   0       $self->{directed} ||= 0;
109 0           return $self->{directed};
110             }
111              
112             sub add_inputfile {
113 0     0 0   my $self = shift;
114 0           my $inputfile = shift;
115 0           $self->{input_files}{$inputfile} = 1;
116 0           return;
117             }
118              
119             sub is_inputfile {
120 0     0 0   my $self = shift;
121 0           my $name = shift;
122 0           return $self->{input_files}{$name};
123             }
124              
125              
126             sub add_dependancy
127             {
128 0     0 0   my $self = shift;
129 0           my $dependancy = shift;
130              
131 0           $self->_package_add($dependancy);
132 0           $dependancy->Set_Id($self->_object_count);
133              
134 0           return 1;
135             }
136              
137             sub add_realization {
138 0     0 0   my $self = shift;
139 0           my $realization = shift;
140              
141 0           $self->_package_add($realization);
142 0           $realization->Set_Id( $self->_object_count );
143              
144 0           return 1;
145             }
146              
147             sub add_inheritance {
148 0     0 0   my $self = shift;
149 0           my $inheritance = shift;
150              
151 0           $self->_package_add($inheritance);
152 0           $inheritance->Set_Id($self->_object_count);
153              
154 0           return 1;
155             }
156              
157             sub add_relation {
158 0     0 0   my $self = shift;
159 0           my $relation = shift;
160              
161 0           $self->_package_add($relation);
162 0           $relation->Set_Id($self->_object_count);
163              
164 0           return 1;
165             }
166              
167             sub add_component
168             {
169 0     0 0   my $self = shift;
170 0           my $component = shift;
171 0           my $return = 0;
172              
173             # check to see if package of this name already exists
174 0           my $exists = $self->_package_exists($component);
175              
176 0 0         if (ref($exists))
177             {
178 0 0         if ($exists->Type eq "Component")
179             {
180             # replace self with already present component
181 0           $component->Redundant($exists);
182 0           $return = $exists;
183             }
184             }
185             else
186             {
187             # component is new and unique
188 0           $self->_package_add($component);
189 0           $component->Set_Id($self->_object_count);
190             }
191              
192 0           return $return;
193             }
194              
195             sub add_superclass
196             {
197 0     0 0   my $self = shift;
198 0           my $superclass = shift;
199 0           my $return = 0;
200              
201             # check to see if package of this name already exists
202 0           my $exists = $self->_package_exists($superclass);
203              
204 0 0         if (ref($exists))
205             {
206 0 0         if ($exists->Type eq "superclass")
207 0           { $return = $exists;}
208 0           else { print STDERR "eek!! wrong type of object returned by _package_exists\n"; }
209             }
210             else
211             {
212 0           $self->_package_add($superclass);
213 0           $superclass->Set_Id($self->_object_count);
214             }
215 0           return $return;
216             }
217              
218             sub add_class
219             {
220 0     0 0   my $self = shift;
221 0           my $class = shift;
222              
223             # some perl modules such as CGI.pm do things by redeclaring packages - eek!
224             # this is a nasty hack to get around that nasty hack. ie class is not added
225             # to diagram and so everything is discarded until next new package declared
226 0 0         if (defined $self->{"packages"}{"class"}{$class->Name})
227             {
228 0           print STDERR "Diagram.pm : add_class : ignoring duplicate class",
229             $class->Name, "\n";
230             # warn Dumper (original_class=>$self->{"packages"}{"class"}{$class->Name});
231 0           return $self->{"packages"}{"class"}{$class->Name};
232             }
233             # note : when running benchmark.pl this seems to appear which I guess is a
234             # scoping issue when calling autodial multiple times - odd, beware if using
235             # mod_perl or something similar, not that it breaks anything but you never know
236              
237 0           $class->Set_Id($self->_object_count);
238 0           $self->_package_add($class);
239              
240 0           return $class;
241             }
242              
243             sub remove_duplicates
244             {
245 0     0 0   my $self = shift;
246              
247 0 0         if (defined $self->{"packages"}{"superclass"})
248             {
249 0           my @superclasses = @{$self->Superclasses};
  0            
250 0           foreach my $superclass (@superclasses)
251             {
252             # if a component exists with the same name as the superclass
253 0 0         if (defined $self->{"packages"}{"Component"}{$superclass->Name})
254             {
255 0           my $component = $self->{"packages"}{"Component"}{$superclass->Name};
256             # mark component redundant
257 0           $component->Redundant;
258             # remove component
259 0           $self->_package_remove($component);
260             # kill its dependancies
261 0           foreach my $dependancy ($component->Dependancies)
262             {
263             # remove dependancy
264 0           $self->_package_remove($dependancy);
265             }
266             }
267             }
268             }
269              
270 0 0         if (defined $self->{"packages"}{"class"})
271             {
272 0           my @classes = @{$self->Classes};
  0            
273 0           foreach my $class (@classes)
274             {
275             # if a superclass exists with the same name as the class
276 0 0         if (defined $self->{"packages"}{"superclass"}{$class->Name})
277             {
278             # mark as redundant, remove and steal its children
279 0           my $superclass = $self->{"packages"}{"superclass"}{$class->Name};
280 0           $superclass->Redundant;
281 0           $self->_package_remove($superclass);
282 0           foreach my $inheritance ($superclass->Inheritances) {
283 0 0         if (ref($inheritance)) {
284 0           $inheritance->Parent($class->Id);
285             } else {
286 0           warn "problem with inheritance : $inheritance - class : ",$class->Name,"\n";
287             }
288             }
289 0           $class->has_child(scalar $superclass->Inheritances);
290              
291 0           foreach my $relation ($superclass->Relations) {
292 0           $relation->Right($class);
293             }
294              
295             }
296              
297             # if a component exists with the same name as the class
298 0 0         if (defined $self->{"packages"}{"Component"}{$class->Name})
299             {
300             # mark as redundant, remove and steal its children
301 0           my $component = $self->{"packages"}{"Component"}{$class->Name};
302 0           $component->Redundant;
303 0           $self->_package_remove($component);
304 0           foreach my $dependancy ($component->Dependancies)
305 0           { $dependancy->Parent($class->Id); }
306             }
307              
308             }
309             }
310 0           return 1;
311             }
312              
313             ###
314              
315             sub Classes
316             {
317 0     0 0   my $self = shift;
318              
319 0           my ($cp, $cf, $cl) = caller;
320              
321 0           my %config = %{$self->{_config}};
  0            
322 0 0         unless (defined $self->{packages}{class})
323             {
324 0           print STDERR "Diagram.pm : Classes : no Classes to be printed\n";
325 0           return 0;
326             }
327 0           my @classes;
328 0           my %classes = %{$self->{"packages"}{"class"}};
  0            
329 0           my @keys = keys %classes;
330 0           my $i = 0;
331              
332 0           foreach my $key (@keys)
333 0           { $classes[$i++] = $classes{$key}; }
334              
335 0           my $return = \@classes;
336              
337 0 0 0       if (($config{sort}) && ($cp ne "Diagram"))
338 0           { $return = $self->_sort(\@classes); }
339              
340              
341 0           return $return;
342             }
343              
344              
345             sub InputFiles {
346 0     0 0   my $self = shift;
347 0           return $self->{input_files};
348             }
349              
350             sub Components
351             {
352 0     0 0   my $self = shift;
353 0 0         unless (defined $self->{"packages"}{"Component"})
354             {
355 0           print STDERR "Diagram.pm : Components : no Components to be printed\n";
356 0           return 0;
357             }
358 0           my @components;
359 0           my %components = %{$self->{"packages"}{"Component"}};
  0            
360 0           my @keys = keys %components;
361 0           my $i = 0;
362              
363 0           foreach my $key (@keys)
364 0           { $components[$i++] = $components{$key}; }
365              
366 0           return \@components;
367             }
368              
369             sub Superclasses
370             {
371 0     0 0   my $self = shift;
372 0 0         unless (defined $self->{"packages"}{"superclass"})
373             {
374 0           print STDERR "Diagram.pm : Superclasses : no superclasses to be printed\n";
375 0           return 0;
376             }
377 0           my @superclasses;
378 0           my %superclasses = %{$self->{"packages"}{"superclass"}};
  0            
379 0           my @keys = keys %superclasses;
380 0           my $i = 0;
381              
382 0           foreach my $key (@keys)
383             {
384 0           $superclasses[$i++] = $superclasses{$key};
385             }
386 0           return \@superclasses;
387             }
388              
389             sub Inheritances
390             {
391 0     0 0   my $self = shift;
392 0 0         unless (defined $self->{"packages"}{"inheritance"})
393             {
394 0           print STDERR "Diagram.pm : Inheritances : no Inheritances to be printed - ignoring..\n";
395 0           return 0;
396             }
397 0           my @inheritances;
398 0           my %inheritances = %{$self->{"packages"}{"inheritance"}};
  0            
399 0           my @keys = keys %inheritances;
400 0           my $i = 0;
401              
402 0           foreach my $key (@keys)
403             {
404 0           $inheritances[$i++] = $inheritances{$key};
405             }
406              
407 0           return \@inheritances;
408             }
409              
410             sub Relations {
411 0     0 0   my $self = shift;
412              
413 0 0         unless (defined $self->{"packages"}{"relation"}) {
414 0           print STDERR "Diagram.pm : Relations : no Relations to be printed - ignoring..\n";
415 0           return 0;
416             }
417              
418 0           my @relations;
419 0           my %relations = %{$self->{"packages"}{"relation"}};
  0            
420 0           my @keys = keys %relations;
421            
422              
423 0           my $i = 0;
424 0           foreach my $key (@keys) {
425 0           $relations[$i++] = $relations{$key};
426             }
427              
428 0           return \@relations;
429             }
430              
431             sub Realizations {
432 0     0 0   my $self = shift;
433              
434 0 0         unless( defined $self->{"packages"}{"realization"} ) {
435 0           print STDERR "Realizations Diagram.pm : none to be printed - ignoring..\n
436             ";
437 0           return 0;
438             }
439              
440 0           my @realizations;
441 0           my %realizations = %{ $self->{"packages"}{"realization"} };
  0            
442 0           my @keys = keys %realizations;
443 0           my $i = 0;
444              
445 0           foreach my $key (@keys) {
446 0           $realizations[ $i++ ] = $realizations{$key};
447             }
448              
449 0           return \@realizations;
450             }
451              
452             sub Dependancies
453             {
454 0     0 0   my $self = shift;
455 0 0         unless (defined $self->{"packages"}{"dependancy"})
456             {
457 0           print STDERR "Diagram.pm : Dependancies : no dependancies to be printed - ignoring..\n";
458 0           return 0;
459             }
460 0           my @dependancies;
461 0           my %dependancies = %{$self->{"packages"}{"dependancy"}};
  0            
462 0           my @keys = keys %dependancies;
463 0           my $i = 0;
464              
465 0           foreach my $key (@keys)
466             {
467 0           $dependancies[$i++] = $dependancies{$key};
468             }
469              
470 0           return \@dependancies;
471             }
472              
473             ##########################################################
474             # export_graphviz - output to file via GraphViz.pm and dot
475              
476             sub export_graphviz
477             {
478 0     0 0   my $self = shift;
479 0           require GraphViz;
480 0           require Data::Dumper;
481              
482 0           my %config = %{$self->{_config}};
  0            
483              
484 0           my $output_filename = $config{outputfile};
485              
486 0           my ($extension) = reverse (split(/\./,$output_filename));
487              
488 0 0         $extension = "gif" unless ($dot_filetypes{$extension});
489              
490 0           $output_filename =~ s/\.[^\.]+$/.$extension/;
491              
492 0           my %args = (directed => $self->directed, ratio => 'expand', concentrate => 1, splines=>'false', lines=>1);
493             # $args{layout} = 'fdp' unless ($self->directed);
494             # $args{overlap} = 'false' unless ($self->directed);
495 0           my $g = GraphViz->new( %args );
496              
497 0           my %nodes = ();
498              
499 0           my $classes = $self->Classes;
500 0 0         if (ref $classes) {
501 0           foreach my $Class (@$classes) {
502              
503 0           my $node = '{'.$Class->Name."|";
504              
505 0 0         if ($config{methods}) {
506 0           my @method_strings = ();
507 0           my ($methods) = ($Class->Operations);
508 0           foreach my $method (@$methods) {
509 0 0 0       next if ($method->{visibility} == 1 && $config{public});
510 0 0         my $method_string = ($method->{visibility} == 0) ? '+ ' : '- ';
511 0           $method_string .= $method->{name}."(";
512 0 0         if (ref $method->{"Params"} ) {
513 0           my @args = ();
514 0           foreach my $argument ( @{$method->{"Params"}} ) {
  0            
515 0 0         push (@args, ((defined ($argument->{Type}) )? $argument->{Type} . " " . $argument->{Name} : $argument->{Name}));
516             }
517 0 0         $method_string .= join (", ",@args) if (scalar @args);
518             }
519 0 0         $method_string .= " ) : ". (defined $method->{type} ? $method->{type} : '');
520 0           push (@method_strings,$method_string);
521             }
522 0           foreach my $method_string ( @method_strings ) {
523 0           $node .= "$method_string".'\l';
524             }
525             }
526 0           $node .= "|";
527 0 0         if ($config{attributes}) {
528 0           my ($attributes) = ($Class->Attributes);
529 0           foreach my $attribute (@$attributes) {
530 0 0 0       next if ($attribute->{visibility} == 1 && $config{public});
531 0 0         $node .= ($attribute->{visibility} == 0) ? '+ ' : '- ';
532 0           $node .= $attribute->{name};
533              
534             # Check if $attribute->{type} is defined.
535             # Otherwise we get warnings like:
536 0 0         if (defined $attribute->{type}) {
537 0           $node .= " : ".$attribute->{type}.'\l';
538             } else {
539 0           $node .= '\l';
540             }
541             }
542             }
543              
544 0           $node .= '}';
545              
546 0           $nodes{$Class->Id} = $node;
547              
548 0           $g->add_node($node,shape=>'record');
549              
550             }
551             } else {
552 0           return 0;
553             }
554              
555 0 0         unless ($config{skip_superclasses}) {
556 0           my $superclasses = $self->Superclasses;
557 0 0         if (ref $superclasses) {
558 0           foreach my $Superclass (@$superclasses) {
559             # warn "superclass name :", $Superclass->Name, " id :", $Superclass->Id, "\n";
560 0           my $node = $Superclass->Name;
561 0           $node=~ s/[\{\}]//g;
562 0           $node = '{'.$node."|\n}";
563             # warn "node : $node\n";
564 0           $nodes{$Superclass->Id} = $node;
565 0           $g->add_node($node,shape=>'record');
566             }
567             }
568             }
569              
570              
571 0           my $inheritances = $self->Inheritances;
572 0 0         if (ref $inheritances) {
573 0           foreach my $Inheritance (@$inheritances) {
574 0 0         next unless ($nodes{$Inheritance->Parent});
575             # warn "inheritance parent :", $Inheritance->Parent, " child :", $Inheritance->Child, "\n";
576 0           $g->add_edge($nodes{$Inheritance->Parent} => $nodes{$Inheritance->Child}, dir => 'back');
577             }
578             }
579              
580 0           my $relations = $self->Relations;
581 0 0         if (ref $relations) {
582 0           foreach my $Relation (@$relations) {
583 0 0         next unless ($nodes{$Relation->Left});
584 0           my %edge_args = (dir => 'none', weight => 1.2 );
585 0           $g->add_edge($nodes{$Relation->Left} => $nodes{$Relation->Right}, %edge_args);
586             }
587             }
588              
589 0 0         unless ($config{skip_packages}) {
590 0           my $components = $self->Components;
591 0 0         if (ref $components) {
592 0           foreach my $Component (@$components) {
593             # warn "component name :", $Component->Name, " id :", $Component->Id, "\n";
594 0           my $node = '{'.$Component->Name.'}';
595             # warn "node : $node\n";
596 0           $nodes{$Component->Id} = $node;
597 0           $g->add_node($node, shape=>'record');
598             }
599             }
600             }
601              
602 0           my $dependancies = $self->Dependancies;
603 0 0         if (ref $dependancies) {
604 0           foreach my $Dependancy (@$dependancies) {
605             # warn "dependancy parent ", $Dependancy->Parent, " child :", $Dependancy->Child, "\n";
606 0 0         next unless ($nodes{$Dependancy->Parent});
607 0           $g->add_edge($nodes{$Dependancy->Parent}=>$nodes{$Dependancy->Child}, dir => 'back', style=>'dashed');
608             }
609             }
610              
611 0 0         open (FILE,">$output_filename") or die "couldn't open $output_filename file for output : $!\n";
612 0           binmode FILE;
613 0           eval 'print FILE $g->'. $dot_filetypes{$extension};
614              
615 0           close FILE;
616              
617 0           return 1;
618             }
619              
620             sub Warn {
621 0     0 0   my ($self,$warning) = @_;
622 0           warn "warning : $warning\n";
623 0           return;
624             }
625              
626              
627             ########################################################
628             # export_springgraph - output to file via SpringGraph.pm
629              
630             sub export_springgraph
631             {
632 0     0 0   my $self = shift;
633 0           my %config = %{$self->{_config}};
  0            
634              
635 0           require SpringGraph;
636 0           require Data::Dumper;
637              
638 0           my $output_filename = $config{outputfile};
639 0           my ($extension) = reverse (split(/\./,$output_filename));
640 0 0         $extension = "gif" unless ($dot_filetypes{$extension});
641 0           $output_filename =~ s/\.[^\.]+$/.$extension/;
642              
643 0           my $g = new SpringGraph;
644              
645 0           my %nodes = ();
646 0           my $classes = $self->Classes;
647 0 0         if (ref $classes) {
648 0           foreach my $Class (@$classes) {
649              
650 0           my $node = $Class->Name."|";
651              
652 0 0         if ($config{methods}) {
653 0           my @method_strings = ();
654 0           my ($methods) = ($Class->Operations);
655 0           foreach my $method (@$methods) {
656 0 0 0       next if ($method->{visibility} == 1 && $config{public});
657 0 0         my $method_string = ($method->{visibility} == 0) ? '+ ' : '- ';
658 0           $method_string .= $method->{name}."(";
659 0 0         if (ref $method->{"Params"} ) {
660 0           my @args = ();
661 0           foreach my $argument ( @{$method->{"Params"}} ) {
  0            
662 0 0         push (@args, ((defined ($argument->{Type}) )? $argument->{Type} . " " . $argument->{Name} : $argument->{Name}));
663             }
664 0 0         $method_string .= join (", ",@args) if (scalar @args);
665             }
666 0 0         $method_string .= " ) : ". (defined $method->{type} ? $method->{type} : '');
667 0           push (@method_strings,$method_string);
668             }
669 0           foreach my $method_string ( @method_strings ) {
670 0           $node .= "$method_string\n";
671             }
672             }
673 0           $node .= "|";
674 0 0         if ($config{attributes}) {
675 0           my ($attributes) = ($Class->Attributes);
676 0           foreach my $attribute (@$attributes) {
677 0 0 0       next if ($attribute->{visibility} == 1 && $config{public});
678 0 0         $node .= "\n" . ($attribute->{visibility} == 0) ? '+ ' : '- ';
679 0           $node .= $attribute->{name};
680 0 0         $node .= " : ".$attribute->{type} if (defined $attribute->{type});
681 0           $node .= "\n";
682             }
683             }
684              
685 0           $nodes{$Class->Id} = $Class->Name;
686              
687 0           $g->add_node($Class->Name, label=>$node,shape=>'record');
688              
689             }
690             } else {
691 0           return 0;
692             }
693 0 0         unless ($config{skip_superclasses}) {
694 0           my $superclasses = $self->Superclasses;
695 0 0         if (ref $superclasses) {
696 0           foreach my $Superclass (@$superclasses) {
697             # warn "superclass name :", $Superclass->Name, " id :", $Superclass->Id, "\n";
698 0           my $node = $Superclass->Name;
699 0           $node=~ s/[\{\}]//g;
700 0           $node .= "|\n";
701             # warn "node : $node\n";
702 0           $nodes{$Superclass->Id} = $node;
703 0           $g->add_node($node,label=>$node,shape=>'record');
704             }
705             }
706             }
707 0           my $inheritances = $self->Inheritances;
708 0 0         if (ref $inheritances) {
709 0           foreach my $Inheritance (@$inheritances) {
710 0 0         next unless ($nodes{$Inheritance->Parent});
711             # warn "inheritance parent :", $Inheritance->Parent, " child :", $Inheritance->Child, "\n";
712 0           $g->add_edge(
713             $nodes{$Inheritance->Parent}=>$nodes{$Inheritance->Child},
714             dir=>'1',
715             );
716             }
717             }
718              
719 0           my $relations = $self->Relations;
720 0 0         if (ref $relations) {
721 0           foreach my $Relation (@$relations) {
722 0 0         next unless ($nodes{$Relation->Left});
723             # warn "relation left :", $Relation->Left, " right :", $Relation->Right, "\n";
724 0           my %edge_args = ($nodes{$Relation->Left} => $nodes{$Relation->Right}, style => 'dotted');
725 0           $g->add_edge(%edge_args);
726             }
727             }
728              
729 0 0         unless ($config{skip_packages}) {
730 0           my $components = $self->Components;
731 0 0         if (ref $components) {
732 0           foreach my $Component (@$components) {
733             # warn "component name :", $Component->Name, " id :", $Component->Id, "\n";
734 0           my $node = $Component->Name;
735             # warn "node : $node\n";
736 0           $nodes{$Component->Id} = $node;
737 0           $g->add_node($node,label=>$node, shape=>'record');
738             }
739             }
740             }
741              
742 0           my $dependancies = $self->Dependancies;
743 0 0         if (ref $dependancies) {
744 0           foreach my $Dependancy (@$dependancies) {
745 0 0         next unless ($nodes{$Dependancy->Parent});
746             # warn "dependancy parent ", $Dependancy->Parent, " child :", $Dependancy->Child, "\n";
747 0           $g->add_edge( $nodes{$Dependancy->Parent}=>$nodes{$Dependancy->Child}, style=>'dashed',dir=>1);
748             }
749             }
750              
751 0           $g->as_png($output_filename);
752              
753 0           return 1;
754             }
755              
756             ####################################################
757             # export_vcg - output to file via VCG.pm and xvcg
758              
759             sub export_vcg {
760 0     0 0   my $self = shift;
761 0           require VCG;
762 0           require Data::Dumper;
763              
764 0           my %config = %{$self->{_config}};
  0            
765 0           my $output_filename = $config{outputfile};
766 0           my ($extension) = reverse (split(/\./,$output_filename));
767 0 0         $extension = "pbm" unless ($vcg_filetypes{$extension});
768              
769 0           $output_filename =~ s/\.[^\.]+$/.$extension/;
770              
771 0           my $vcg = VCG->new(scale=>100,);
772 0           my %nodes = ();
773 0           my $classes = $self->Classes;
774              
775 0 0         if (ref $classes) {
776 0           foreach my $Class (@$classes) {
777             # warn "class name : ", $Class->Name , " id :", $Class->Id, "\n";
778 0           my $node = $Class->Name."\n----------------\n";
779              
780 0 0         if ($config{methods}) {
781 0           my @method_strings = ();
782 0           my ($methods) = ($Class->Operations);
783 0           foreach my $method (@$methods) {
784 0 0 0       next if ($method->{visibility} == 1 && $config{public});
785 0 0         my $method_string = ($method->{visibility} == 0) ? '+ ' : '- ';
786 0           $method_string .= $method->{name}."(";
787 0 0         if (ref $method->{"Params"} ) {
788 0           my @args = ();
789 0           foreach my $argument ( @{$method->{"Params"}} ) {
  0            
790 0           push (@args, $argument->{Type} . " " . $argument->{Name});
791             }
792 0           $method_string .= join (", ",@args);
793             }
794 0           $method_string .= " ) : ". $method->{type};
795 0           push (@method_strings,$method_string);
796             }
797 0           foreach my $method_string ( @method_strings ) {
798 0           $node .= "$method_string\n";
799             }
800             }
801 0           $node .= "----------------\n";
802 0 0         if ($config{attributes}) {
803 0           my ($attributes) = ($Class->Attributes);
804 0           foreach my $attribute (@$attributes) {
805 0 0 0       next if ($attribute->{visibility} == 1 && $config{public});
806 0 0         $node .= ($attribute->{visibility} == 0) ? '+ ' : '- ';
807 0           $node .= $attribute->{name};
808 0           $node .= " : $attribute->{type} \n";
809             }
810             }
811              
812 0           $nodes{$Class->Id} = $node;
813              
814 0           $vcg->add_node(label=>$node, title=>$node);
815              
816             }
817             } else {
818 0           return 0;
819             }
820              
821 0 0         unless ($config{skip_superclasses}) {
822 0           my $superclasses = $self->Superclasses;
823              
824 0 0         if (ref $superclasses) {
825 0           foreach my $Superclass (@$superclasses) {
826             # warn "superclass name :", $Superclass->Name, " id :", $Superclass->Id, "\n";
827 0           my $node = $Superclass->Name()."\n----------------\n";
828 0           $nodes{$Superclass->Id} = $node;
829 0           $vcg->add_node(title=>$node, label=> $node);
830             }
831             }
832             }
833              
834 0           my $inheritances = $self->Inheritances;
835 0 0         if (ref $inheritances) {
836 0           foreach my $Inheritance (@$inheritances) {
837 0 0         next unless ($nodes{$Inheritance->Parent});
838             # warn "inheritance parent :", $Inheritance->Parent, " child :", $Inheritance->Child, "\n";
839 0           $vcg->add_edge(
840             source=>$nodes{$Inheritance->Parent}, target=>$nodes{$Inheritance->Child},
841             );
842             }
843             }
844              
845 0           my $relations = $self->Relations;
846 0 0         if (ref $relations) {
847 0           foreach my $Relation (@$relations) {
848 0 0         next unless ($nodes{$Relation->Left});
849             # warn "relation left :", $Relation->Left, " right :", $Relation->Right, "\n";
850 0           my %edge_args = (source => $nodes{$Relation->Left}, target => $nodes{$Relation->Right});
851 0           $vcg->add_edge(%edge_args);
852             }
853             }
854              
855              
856 0 0         unless ($config{skip_packages}) {
857 0           my $components = $self->Components;
858 0 0         if (ref $components) {
859 0           foreach my $Component (@$components) {
860             # warn "component name :", $Component->Name, " id :", $Component->Id, "\n";
861 0           my $node = $Component->Name;
862 0           $nodes{$Component->Id} = $node;
863 0           $vcg->add_node(label=>$node, title=>$node);
864             }
865             }
866             }
867              
868 0           my $dependancies = $self->Dependancies;
869 0 0         if (ref $dependancies) {
870 0           foreach my $Dependancy (@$dependancies) {
871 0 0         next unless ($nodes{$Dependancy->Parent});
872             # warn "dependancy parent ", $Dependancy->Parent, " child :", $Dependancy->Child, "\n";
873 0           $vcg->add_edge(
874             source=>$nodes{$Dependancy->Parent}, target=>$nodes{$Dependancy->Child},
875             );
876             }
877             }
878              
879 0 0         open (FILE,">$output_filename") or die "couldn't open $output_filename file for output : $!\n";
880 0           binmode FILE;
881 0 0         eval 'print FILE $vcg->'. $vcg_filetypes{$extension} or die "can't eval : $! \n";;
882              
883 0           close FILE;
884              
885 0           return 1;
886             }
887              
888              
889             ####################################################
890             # export_xml - output to file via template toolkit
891              
892              
893             sub export_xml
894             {
895 0     0 0   my $self = shift;
896              
897 0           my %config = %{$self->{_config}};
  0            
898              
899 0           my $output_filename = $config{outputfile};
900 0   0       my $template_file = $config{templatefile} || get_template(%config);
901              
902 0 0         if ($config{no_deps})
903 0           { $self->_no_deps; }
904              
905 0           my $success = $self->_layout_dia_new;
906 0 0         return 0 unless $success;
907              
908 0 0         if (ref $self->Classes) {
909 0           foreach my $Class ( @{$self->Classes} ) {
  0            
910              
911             # warn "handling $Class->{name}\n";
912              
913 0           my ($methods) = ($Class->Operations);
914 0           foreach my $method (@$methods) {
915 0           $method->{name}=xml_escape($method->{name});
916 0 0         if (ref $method->{"Params"} ) {
917 0           foreach my $argument ( @{$method->{"Params"}} ) {
  0            
918 0 0         $argument->{Type} = xml_escape($argument->{Type}) if (defined $argument->{Type});
919 0           $argument->{Name} = xml_escape($argument->{Name});
920 0 0         $argument->{Kind} = xml_escape($argument->{Kind}) if (defined $argument->{Kind});
921             }
922             }
923             }
924              
925 0           my ($attributes) = ($Class->Attributes);
926 0           foreach my $attribute (@$attributes) {
927 0           $attribute->{name} = xml_escape($attribute->{name});
928             }
929             }
930             }
931              
932 0 0         print "\n\n" if ($config{use_stdout});
933              
934             # use a template for xml output.
935 0           my $template_conf = {
936             POST_CHOMP => 1,
937             # EVAL_PERL => 1, # debug
938             # INTERPOLATE =>1, # debug
939             # LOAD_PERL => 1, # debug
940             ABSOLUTE => 1,
941             OUTPUT_PATH => '.',
942             }; # cleanup whitespace and allow absolute paths
943 0           my $template = Template->new($template_conf);
944 0           my $template_variables = { "diagram" => $self, config => $self->{_config}};
945              
946 0           my @template_args = ($template_file,$template_variables);
947 0 0         push (@template_args, $output_filename)
948             unless ( $config{use_stdout} );
949              
950 0 0         $template->process(@template_args)
951             || die $template->error();
952              
953 0           return 1;
954             }
955              
956             #---------------------------------------------------------------------------------
957             # Internal Methods
958              
959             sub _no_deps
960             {
961 0     0     my $self = shift;
962 0           print STDERR "skipping dependancies..\n";
963 0           undef $self->{packages}{dependancy};
964 0           undef $self->{packages}{Component};
965 0           return;
966             }
967              
968             sub _initialise
969             {
970 0     0     my $self = shift;
971 0           $self->{_config} = shift; # ref to %conf
972 0           $self->{"_object_count"} = 0; # keeps count of objects
973 0           $self->{_nodes} = {};
974 0           return;
975             }
976              
977             sub _package_exists # check to see if a package already exists
978             {
979 0     0     my $self = shift;
980 0           my $object = shift;
981 0           my $return = 0;
982              
983             # check type of object, and only check for relevent packages.
984             SWITCH:
985             {
986 0 0         if ($object->Type eq "class")
  0            
987             {
988 0           last SWITCH;
989             }
990 0 0         if ($object->Type eq "superclass")
991             {
992              
993 0 0         if ($self->{"packages"}{"superclass"}{$object->Name})
994             {
995 0           $return = $self->{"packages"}{"superclass"}{$object->Name};
996 0           bless ($return, "Autodia::Diagram::Superclass");
997             }
998 0           last SWITCH;
999             }
1000 0 0         if ($object->Type eq "Component")
1001             {
1002 0 0         if ($self->{"packages"}{"Component"}{$object->Name})
1003             {
1004 0           $return = $self->{"packages"}{"Component"}{$object->Name};
1005 0           bless ($return, "Autodia::Diagram::Component");
1006             }
1007 0           last SWITCH;
1008             }
1009             }
1010 0           return $return;
1011             }
1012              
1013             sub _object_count
1014             {
1015 0     0     my $self = shift;
1016 0           my $id = $self->{"_object_count"};
1017 0           $self->{"_object_count"}++;
1018 0           return $id;
1019             }
1020              
1021             sub _package_add
1022             {
1023 0     0     my $self = shift;
1024 0           my $new_package = shift;
1025 0           my @packages;
1026              
1027 0 0         if (defined $self->{$new_package->Type})
1028 0           { @packages = @{$self->{$new_package->Type}}; }
  0            
1029              
1030 0           push(@packages, $self->{"_object_count"});
1031              
1032 0           $self->{$new_package->Type} = \@packages;
1033 0           $new_package->LocalId(scalar @packages);
1034 0           $self->{"packages"}{$new_package->Type}{$new_package->Name} = $new_package;
1035 0 0 0       if (defined $new_package->Type && defined $new_package->Id) {
1036 0           $self->{"package_types"}{$new_package->Type}{$new_package->Id} = 1;
1037             }
1038              
1039 0           return 1;
1040             }
1041              
1042             sub _package_remove
1043             {
1044 0     0     my $self = shift;
1045 0           my $package = shift;
1046              
1047 0           my @packages = @{$self->{$package->Type}};
  0            
1048 0           $packages[$package->LocalId] = "removed";
1049              
1050 0           $self->{$package->Type} = \@packages;
1051 0           delete $self->{"packages"}{$package->Type}{$package->Name};
1052              
1053 0           return 1;
1054             }
1055              
1056              
1057             sub _get_childless_classes
1058             {
1059 0     0     my $self = shift;
1060 0           my @classes;
1061              
1062 0           my $childless = $self->Classes;
1063 0 0         if (ref $childless)
1064             {
1065 0           foreach my $class (@$childless)
1066             {
1067 0 0         unless ($class->has_child)
1068 0           { push (@classes, $class); }
1069             }
1070             }
1071 0           else { warn "Diagram.pm : _get_childless_classes : no classes!\n"; }
1072 0           return @classes;
1073             }
1074              
1075             sub _get_parent_classes
1076             {
1077 0     0     my $self = shift;
1078 0           my @classes;
1079              
1080 0           my $parents = $self->Classes;
1081 0 0         if (ref $parents)
1082             {
1083 0           foreach my $class (@$parents)
1084             {
1085 0 0         if ($class->has_child)
1086 0           { push (@classes, $class); }
1087             }
1088             }
1089 0           else { warn "Diagram.pm : _get_parent_classes : no classes !\n"; }
1090 0           return @classes;
1091             }
1092              
1093             sub _sort
1094             {
1095 0     0     my $self = shift;
1096 0           my @classes = @{shift()};
  0            
1097              
1098 0 0         print "sorting classes alphabetically\n" unless ( $self->{config}->{silent} );
1099 0           my @sorted_classes = sort {$a->Name cmp $b->Name} @classes;
  0            
1100              
1101             return \@sorted_classes
1102 0           }
1103              
1104              
1105             # now returns 0 if no classes found
1106              
1107             sub _layout_dia_new {
1108 0     0     my $self = shift;
1109 0           my %config = %{$self->{_config}};
  0            
1110             # build table of nodes and relationships
1111 0           my %nodes = ();
1112 0           my @edges = ();
1113 0           my @rows = ();
1114 0           my @row_heights = ();
1115 0           my @row_widths = ();
1116             # - add classes nodes
1117 0           my $classes = $self->Classes;
1118 0 0         if (ref $classes) {
1119 0           foreach my $Class (@$classes) {
1120             # count methods and attributes to give height
1121 0           my $height = 23;
1122 0           my $width = 3 + ( (length ($Class->Name) - 3) * 0.75 );
1123 0           my ($methods) = ($Class->Operations);
1124 0 0         if (uc(ref $methods) eq 'SCALAR') {
1125 0           $height += scalar @$methods;
1126             }
1127 0 0         if ($config{attributes}) {
1128 0           my ($attributes) = ($Class->Attributes);
1129 0 0         if (uc(ref $attributes) eq 'SCALAR') {
1130 0           $height += (scalar @$attributes * 3.2);
1131             }
1132             }
1133             # warn "creating node for class : ", $Class->Id, "\n";
1134 0           $nodes{$Class->Id} = {parents=>[], weight=>0, center=>[], height=>$height,
1135             children=>[], entity=>$Class, width=>$width};
1136             }
1137             }
1138             # - add superclasses nodes
1139 0           my $superclasses = $self->Superclasses;
1140 0 0         if (ref $superclasses) {
1141 0           foreach my $Superclass (@$superclasses) {
1142 0           my $width = 3 + ( (length ($Superclass->Name) - 3) * 0.75 );
1143             # warn "creating node for class : ", $Superclass->Id, "\n";
1144 0           $nodes{$Superclass->Id} = {parents=>[], weight=>0, center=>[], height=>15,
1145             children=>[], entity=>$Superclass, width=>$width};
1146             }
1147             }
1148             # - add package nodes
1149 0           my $components = $self->Components;
1150 0 0         if (ref $components) {
1151 0           foreach my $Component (@$components) {
1152             # warn "creating node for class : ", $Component->Id, "\n";
1153 0           my $width = 3 + ( (length ($Component->Name) - 3) * 0.55 );
1154 0           $nodes{$Component->Id} = {parents=>[], weight=>0, center=>[], height=>15,
1155             children=>[], entity=>$Component, width=>$width};
1156             }
1157             }
1158             # - add inheritance edges
1159 0           my $inheritances = $self->Inheritances;
1160 0 0         if (ref $inheritances) {
1161 0           foreach my $Inheritance (@$inheritances) {
1162 0           push (@edges, { to => $Inheritance->Child, from => $Inheritance->Parent });
1163             }
1164             }
1165             # - add dependancy edges
1166 0           my $dependancies = $self->Dependancies;
1167 0 0         if (ref $dependancies) {
1168 0           foreach my $Dependancy (@$dependancies) {
1169 0           push (@edges, { to => $Dependancy->Child, from => $Dependancy->Parent });
1170             }
1171             }
1172              
1173             # add realization edges
1174 0           my $realizations = $self->Realizations;
1175 0 0         if( ref $realizations ) {
1176 0           foreach my $Realization (@$realizations) {
1177 0           push( @edges,
1178             { to => $Realization->Child, from => $Realization->Parent } );
1179             }
1180             }
1181              
1182              
1183             # add relation edges
1184 0           my $relations = $self->Relations;
1185 0 0         if (ref $relations) {
1186 0           foreach my $Relation (@$relations) {
1187 0           push (@edges, { to => $Relation->Left, from => $Relation->Right });
1188             }
1189             }
1190              
1191             # first pass (build network of edges to and from each node)
1192 0           foreach my $edge (@edges) {
1193             # warn Dumper (edge=>$edge) unless ($edge->{from} && $edge->{to});
1194 0           my ($from,$to) = ($edge->{from},$edge->{to});
1195 0           push(@{$nodes{$to}{parents}},$from);
  0            
1196 0           push(@{$nodes{$from}{children}},$to);
  0            
1197             }
1198              
1199             # second pass (establish depth ( ie verticle placement of each node )
1200 0           foreach my $node (keys %nodes) {
1201 0           my $depth = 0;
1202 0           foreach my $parent (@{$nodes{$node}{parents}}) {
  0            
1203 0           my $newdepth = get_depth($parent,$node,\%nodes);
1204 0 0         $depth = $newdepth if ($depth < $newdepth);
1205             }
1206 0           $nodes{$node}{depth} = $depth;
1207 0           push(@{$rows[$depth]},$node)
  0            
1208             }
1209              
1210             # calculate height and width of diagram in discrete steps
1211 0           my $i = 0;
1212 0           my $widest_row = 0;
1213 0           my $total_height = 0;
1214 0           my $total_width = 0;
1215 0           foreach my $row (@rows) {
1216 0 0         unless (ref $row) { $row = []; next }
  0            
  0            
1217 0           my $tallest_node_height = 0;
1218 0           my $widest_node_width = 0;
1219 0 0         $widest_row = scalar @$row if ( scalar @$row > $widest_row );
1220 0           my @newrow = ();
1221 0           foreach my $node (@$row) {
1222             # warn Dumper(node=>$node);
1223 0 0 0       unless (defined $node && defined $nodes{$node}) { warn "warning : empty class/package encountered, skipping"; Dumper(empty_node=>$nodes{$node}); next;}
  0            
  0            
  0            
1224 0 0         $tallest_node_height = $nodes{$node}{height}
1225             if ($nodes{$node}{height} > $tallest_node_height);
1226 0 0         $widest_node_width = $nodes{$node}{width}
1227             if ($nodes{$node}{width} > $widest_node_width);
1228 0           push (@newrow,$node);
1229             }
1230 0           $row = \@newrow;
1231 0           $row_heights[$i] = $tallest_node_height + 0.5;
1232 0           $row_widths[$i] = $widest_node_width;
1233 0           $total_height += $tallest_node_height + 0.5 ;
1234 0           $total_width += $widest_node_width;
1235 0           $i++;
1236             }
1237              
1238             # prepare table of available positions
1239 0           my @positions;
1240 0           foreach (@rows) {
1241 0           my %available;
1242 0           @available{(0 .. ($widest_row + 1))} = 1 x ($widest_row + 1);
1243 0           push (@positions,\%available);
1244             }
1245              
1246 0           my %done = ();
1247 0           $self->{_dia_done} = \%done;
1248 0           $self->{_dia_nodes} = \%nodes;
1249 0           $self->{_dia_positions} = \@positions;
1250 0           $self->{_dia_rows} = \@rows;
1251 0           $self->{_dia_row_heights} = \@row_heights;
1252 0           $self->{_dia_row_widths} = \@row_widths;
1253 0           $self->{_dia_total_height} = $total_height;
1254 0           $self->{_dia_total_width} = $total_width;
1255 0           $self->{_dia_widest_row} = $widest_row;
1256              
1257             #
1258             # plot (relative) position of nodes (left to right, follow branch)
1259 0           my $side;
1260 0 0         return 0 unless (ref $rows[0]);
1261 0           my @toprow = sort {$nodes{$b}{weight} <=> $nodes{$a}{weight} } @{$rows[0]};
  0            
  0            
1262 0 0         unshift (@toprow, pop(@toprow)) unless (scalar @toprow < 3);
1263 0           my $increment = $widest_row / ( scalar @toprow + 1 );
1264 0           my $pos = $increment;
1265 0           my $y = 0 - ( ( $self->{_dia_total_height} / 2) - 5 );
1266 0           my $done2ndrow = 0;
1267 0           foreach my $node ( @toprow ) {
1268 0           my $x = 0 - ( $self->{_dia_row_widths}[0] * $self->{_dia_widest_row} / 2)
1269             + ($pos * $self->{_dia_row_widths}[0]);
1270 0           $nodes{$node}{xx} = $x;
1271 0           $nodes{$node}{yy} = $y;
1272 0           $nodes{$node}{entity}->set_location($x,$y);
1273             # if (scalar @{$nodes{$node}{children}} && ( scalar @{$rows[1]} > 0)) {
1274 0 0 0       if (defined $nodes{$node}{children} && defined $rows[1]) {
1275 0 0 0       if (scalar @{$nodes{$node}{children}} && scalar(@rows) && ( scalar @{$rows[1]} > 0)) {
  0 0 0        
  0   0        
  0   0        
1276              
1277 0           my @sorted_children = sort {
1278 0           $nodes{$b}{weight} <=> $nodes{$a}{weight}
1279 0           } @{$nodes{$node}{children}};
1280 0           unshift (@sorted_children, pop(@sorted_children));
1281 0           my $child_increment = $widest_row / (scalar @{$rows[1]});
  0            
1282 0           my $childpos = $child_increment;
1283             # foreach my $child (@{$nodes{$node}{children}}) {
1284 0           foreach my $child (@sorted_children) {
1285 0           my $side;
1286 0 0         if ($childpos <= ( $widest_row * 0.385 ) ) {
    0          
1287 0           $side = 'left';
1288             } elsif ( $childpos <= ($widest_row * 0.615 ) ) {
1289 0           $side = 'center';
1290             } else {
1291 0           $side = 'right';
1292             }
1293 0           plot_branch($self,$nodes{$child},$childpos,$side);
1294 0           $childpos += $child_increment;
1295             }
1296             } elsif ( defined $rows[1] && scalar @{$rows[1]} && $done2ndrow == 0) {
1297 0           $done2ndrow = 1;
1298 0           foreach my $node ( @{$rows[1]} ) {
  0            
1299             # warn "handling node in next row\n";
1300             # warn Dumper(node=>$node{$node});
1301 0           my $x = 0 - ( $self->{_dia_row_widths}[1] * $self->{_dia_widest_row} / 2)
1302             + ($pos * $self->{_dia_row_widths}[1]);
1303 0           $nodes{$node}{x} = $x;
1304 0           $nodes{$node}{'y'} = $y;
1305 0 0 0       if (scalar @{$nodes{$node}{children}} && scalar @{$rows[2]}) {
  0            
  0            
1306 0           my @sorted_children = sort {
1307 0           $nodes{$b}{weight} <=> $nodes{$a}{weight}
1308 0           } @{$nodes{$node}{children}};
1309 0           unshift (@sorted_children, pop(@sorted_children));
1310 0           my $child_increment = $widest_row / (scalar @{$rows[2]});
  0            
1311 0           my $childpos = $child_increment;
1312             # foreach my $child (@{$nodes{$node}{children}}) {
1313 0           foreach my $child (@sorted_children) {
1314             # warn "child : $child\n";
1315 0 0         next unless ($child);
1316 0           my $side;
1317 0 0         if ($childpos <= ( $widest_row * 0.385 ) ) {
    0          
1318 0           $side = 'left';
1319             } elsif ( $childpos <= ($widest_row * 0.615 ) ) {
1320 0           $side = 'center';
1321             } else {
1322 0           $side = 'right';
1323             }
1324 0           plot_branch($self,$nodes{$child},$childpos,$side);
1325 0           $childpos += $child_increment;
1326             }
1327             }
1328             }
1329             }
1330             }
1331              
1332 0           $nodes{$node}{pos} = $pos;
1333              
1334 0           $pos += $increment;
1335 0           $done{$node} = 1;
1336             }
1337            
1338 0           my @relationships = ();
1339              
1340 0 0         if (ref $self->Dependancies)
1341 0           { push(@relationships, @{$self->Dependancies}); }
  0            
1342              
1343 0 0         if( ref $self->Realizations ) {
1344 0           push( @relationships, @{ $self->Realizations } );}
  0            
1345              
1346 0 0         if (ref $self->Inheritances)
1347 0           { push(@relationships, @{$self->Inheritances}); }
  0            
1348              
1349 0 0         if (ref $self->Relations)
1350 0           { push(@relationships, @{$self->Relations}); }
  0            
1351              
1352              
1353 0           foreach my $relationship (@relationships)
1354 0           { $relationship->Reposition; }
1355              
1356 0           $self->{_nodes} = \%nodes;
1357              
1358 0           return 1;
1359             }
1360              
1361             sub object_from_id {
1362 0     0 0   my ($self, $id) = @_;
1363 0           my $object;
1364 0 0         if (ref $self->{_nodes}) {
1365 0           $object = $self->{_nodes}{$id}{entity};
1366             };
1367 0           return $object;
1368             }
1369              
1370             #
1371             ## Functions used by _layout_dia_new method
1372             #
1373              
1374             # recursively calculate the depth of a node by following edges to its parents
1375             sub get_depth {
1376 0     0 0   my ($node,$child,$nodes) = @_;
1377 0           my $depth = 0;
1378 0           $nodes->{$node}{weight}++;
1379 0 0         if (exists $nodes->{$node}{depth}) {
1380 0           $depth = $nodes->{$node}{depth} + 1;
1381             } else {
1382 0           $nodes->{$node}{depth} = 1;
1383 0           my @parents = @{$nodes->{$node}{parents}};
  0            
1384 0 0         if (scalar @parents > 0) {
1385 0           foreach my $parent (@parents) {
1386 0           my $newdepth = get_depth($parent,$node,$nodes);
1387 0 0         $depth = $newdepth if ($depth < $newdepth);
1388             }
1389 0           $depth++;
1390             } else {
1391 0           $depth = 1;
1392 0           $nodes->{$node}{depth} = 0;
1393             }
1394             }
1395 0           return $depth;
1396             }
1397              
1398             # recursively plot the branches of a tree
1399             sub plot_branch {
1400 0     0 0   my ($self,$node,$pos,$side) = @_;
1401             # warn "plotting branch : ", $node->{entity}->Name," , $pos, $side\n";
1402              
1403 0           my $depth = $node->{depth};
1404 0           my $offset = 0.8;
1405 0           my $h = 0;
1406 0           while ( $h < $depth ) {
1407 0           $offset += $self->{_dia_row_heights}[$h++] + 0.1;
1408             }
1409              
1410             # warn Dumper(node=>$node);
1411 0           my (@parents,@children) = ($node->{parents},$node->{children});
1412 0 0 0       if ( $self->{_dia_done}{$node->{entity}->Id} && (scalar @children < 1) ) {
    0          
1413 0 0         if (scalar @parents > 1 ) {
1414 0           $self->{_dia_done}{$node}++;
1415 0           my $sum = 0;
1416 0           foreach my $parent (@parents) {
1417 0 0         return 0 unless (exists $self->{_dia_nodes}{$parent->{entity}->Id}{pos});
1418 0           $sum += $self->{_dia_nodes}{$parent->{entity}->Id}{pos};
1419             }
1420 0           $self->{_dia_positions}[$depth]{int($pos)} = 1;
1421 0           my $newpos = ( $sum / scalar @parents );
1422 0 0         unless (exists $self->{_dia_positions}[$depth]{int($newpos)}) {
1423             # use wherever is free if position already taken
1424 0           my $best_available = $pos;
1425 0 0         my $diff = ($best_available > $newpos )
1426             ? $best_available - $newpos : $newpos - $best_available ;
1427 0           foreach my $available (keys %{$self->{_dia_positions}[$depth]}) {
  0            
1428 0 0         my $newdiff = ($available > $newpos ) ? $available - $newpos : $newpos - $available ;
1429 0 0         if ($newdiff < $diff) {
1430 0           $best_available = $available;
1431 0           $diff = $newdiff;
1432             }
1433             }
1434 0           $pos = $best_available;
1435             } else {
1436 0           $pos = $newpos;
1437             }
1438             }
1439 0           my $y = 0 - ( ( $self->{_dia_total_height} / 2) - 4 ) + $offset;
1440 0           print "y : $y\n";
1441 0           my $x = 0 - ( $self->{_dia_row_widths}[$depth] * $self->{_dia_widest_row} / 2)
1442             + ($pos * $self->{_dia_row_widths}[$depth]);
1443             # my $x = 0 - ( $self->{_dia_widest_row} / 2) + ($pos * $self->{_dia_row_widths}[$depth]);
1444 0           $node->{xx} = int($x);
1445 0           $node->{yy} = int($y);
1446 0           $node->{entity}->set_location($x,$y);
1447 0           $node->{pos} = $pos;
1448 0           delete $self->{_dia_positions}[$depth]{int($pos)};
1449             # warn "node ", $node->{entity}->Name(), " : $pos xx : ", $node->{xx} ," yy : ",$node->{yy} ,"\n";
1450 0           return 0;
1451             } elsif ($self->{_dia_done}{$node}) {
1452             # warn "node ", $node->{entity}->Name(), " : $node->{pos}\n";
1453 0           return 0;
1454             }
1455              
1456 0 0         unless (exists $self->{_dia_positions}[$depth]{int($pos)}) {
1457 0           my $best_available;
1458 0           my $diff = $self->{_dia_widest_row} + 5;
1459 0           foreach my $available (keys %{$self->{_dia_positions}[$depth]}) {
  0            
1460 0   0       $best_available ||= $available;
1461 0 0         my $newdiff = ($available > $pos ) ? $available - $pos : $pos - $available ;
1462 0 0         if ($newdiff < $diff) {
1463 0           $best_available = $available;
1464 0           $diff = $newdiff;
1465             }
1466             }
1467 0           $pos = $best_available;
1468             }
1469              
1470 0           delete $self->{_dia_positions}[$depth]{int($pos)};
1471              
1472 0           my $y = 0 - ( ( $self->{_dia_total_height} / 2) - 1 ) + $offset;
1473 0           my $x = 0 - ( $self->{_dia_row_widths}[0] * $self->{_dia_widest_row} / 2)
1474             + ($pos * $self->{_dia_row_widths}[0]);
1475             # my $x = 0 - ( $self->{_dia_widest_row} / 2) + ($pos * $self->{_dia_row_widths}[$depth]);
1476             # my $x = 0 - ( ( $pos * $self->{_dia_row_widths}[0] ) / 2);
1477 0           $node->{xx} = int($x);
1478 0           $node->{yy} = int($y);
1479 0           $node->{entity}->set_location($x,$y);
1480              
1481 0           $self->{_dia_done}{$node} = 1;
1482 0           $node->{pos} = $pos;
1483              
1484 0 0         if (scalar @{$node->{children}}) {
  0 0          
1485 0           my @sorted_children = sort {
1486 0           $self->{_dia_nodes}{$b}{weight} <=> $self->{_dia_nodes}{$a}{weight}
1487 0           } @{$node->{children}};
1488 0           unshift (@sorted_children, pop(@sorted_children));
1489 0 0 0       my $child_increment = (ref $self->{_dia_rows}[$depth + 1]) ? $self->{_dia_widest_row} / (scalar @{$self->{_dia_rows}[$depth + 1]} || 1) : 0 ;
1490 0           my $childpos = 0;
1491 0 0         if ( $side eq 'left' ) {
    0          
1492 0           $childpos = 0
1493             } elsif ( $side eq 'center' ) {
1494 0           $childpos = $pos;
1495             } else {
1496 0           $childpos = $pos + $child_increment;
1497             }
1498 0           foreach my $child (@{$node->{children}}) {
  0            
1499 0 0         $childpos += $child_increment if (plot_branch($self,$self->{_dia_nodes}{$child},$childpos,$side));
1500             }
1501             } elsif ( scalar @parents == 1 ) {
1502 0           my $y = 0 - ( ( $self->{_dia_total_height} / 2) - 1 ) + $offset;
1503 0           my $x = 0 - ( $self->{_dia_row_widths}[0] * $self->{_dia_widest_row} / 2)
1504             + ($pos * $self->{_dia_row_widths}[0]);
1505             # my $x = 0 - ( $self->{_dia_widest_row} / 2) + ($pos * $self->{_dia_row_widths}[$depth]);
1506             # my $x = 0 - ( ( $pos * $self->{_dia_row_widths}[0] ) / 2);
1507 0           $node->{xx} = int($x);
1508 0           $node->{yy} = int($y);
1509 0           $node->{entity}->set_location($x,$y);
1510             }
1511             # warn "node ", $node->{entity}->Name(), " : $pos xx : ", $node->{xx} ," yy : ",$node->{yy} ,"\n";
1512 0           return 1;
1513             }
1514              
1515             #
1516             ########################################
1517             #
1518              
1519             sub _layout {
1520 0     0     my $self = shift;
1521 0           my @columns;
1522             my @orphan_classes;
1523 0           my $column_count=0;
1524              
1525             # populate a grid to be used for laying out the diagram.
1526              
1527             # put each parent class in a column
1528 0           my @parent_classes = $self->_get_parent_classes;
1529 0           my %parent_class;
1530 0           foreach my $class (@parent_classes) {
1531 0           $parent_class{$class->Id} = $column_count;
1532 0 0         if (defined $columns[$column_count][2][0]) {
1533 0           push (@{$columns[$column_count][2]},$class);
  0            
1534             } else {
1535 0           $columns[$column_count][2][0] = $class;
1536             }
1537 0           $column_count++;
1538             }
1539              
1540 0           $column_count = 0;
1541              
1542 0           my @childless_classes = $self->_get_childless_classes;
1543             # put each child class in its parent column
1544 0           foreach my $class (@childless_classes) {
1545 0 0         if (defined $class->Inheritances) {
1546 0           my ($inheritance) = $class->Inheritances;
1547 0   0       my $parents_column = $parent_class{$inheritance->Parent} || 0;
1548 0           push (@{$columns[$parents_column][3]},$class);
  0            
1549             } else {
1550 0           push (@orphan_classes,$class);
1551             }
1552             }
1553              
1554 0           $column_count++;
1555              
1556 0           foreach my $orphan (@orphan_classes) {
1557 0           push (@{$columns[$column_count][3]}, $orphan);
  0            
1558             }
1559              
1560             # put components in columns with the most of their kids
1561 0 0         if (ref $self->Components) {
1562 0           my @components = @{$self->Components};
  0            
1563 0           foreach my $component (@components) {
1564 0           my $i =0;
1565 0           my $current_column = 0;
1566 0           my $current_children = 0;
1567             # find column with most children
1568              
1569 0           my %child_ids = ();
1570 0           my @children = $component->Dependancies;
1571 0           foreach my $child (@children) {
1572 0           $child_ids{$child->Child} = 1;
1573             }
1574              
1575 0           foreach my $column (@columns) {
1576 0 0         if (ref $column) {
1577 0           my @column = @$column;
1578 0 0         next unless (defined $column);
1579 0           my $children = 0;
1580 0           foreach my $subcolumn (@column) {
1581 0           foreach my $child (@$subcolumn) {
1582 0 0         if (defined $child_ids{$child->Id}) {
1583 0           $children++;
1584             }
1585             }
1586             }
1587 0 0         if ($children > $current_children) {
1588 0           $current_column = $i; $current_children = $children;
  0            
1589             }
1590 0           $i++;
1591             } else {
1592 0           print STDERR "Diagram.pm : _layout() : empty column .. skipping\n";
1593             }
1594             }
1595 0           push(@{$columns[$current_column][0]},$component);
  0            
1596             }
1597             } else {
1598 0           print STDERR "Diagram.pm : _layout() : no components / dependancies\n";
1599             }
1600              
1601 0 0         if (ref $self->Superclasses) {
1602 0           my @superclasses = @{$self->Superclasses};
  0            
1603             # put superclasses in columns with most of their kids
1604 0           foreach my $superclass (@superclasses) {
1605 0           my $i=0;
1606 0           my $current_column = 0;
1607 0           my $current_children = 0;
1608             # find column with most children
1609              
1610 0           my %child_ids = ();
1611 0           my @children = $superclass->Inheritances;
1612 0           foreach my $child (@children) {
1613 0           $child_ids{$child->Child} = 1;
1614             }
1615              
1616 0           foreach my $column (@columns) {
1617 0 0         if (ref $column) {
1618 0           my @column = @$column;
1619 0           my $children = 0;
1620 0           foreach my $subcolumn (@column) {
1621 0           foreach my $child (@$subcolumn) {
1622 0 0         if (defined $child_ids{$child->Id}) {
1623 0           $children++;
1624             }
1625             }
1626             }
1627 0 0         if ($children > $current_children) {
1628 0           $current_column = $i; $current_children = $children;
  0            
1629             }
1630 0           $i++;
1631             } else {
1632 0           print STDERR "Diagram.pm : _layout() : empty column .. skipping\n";
1633             }
1634             }
1635 0           push(@{$columns[$current_column][1]},$superclass);
  0            
1636             }
1637             } else {
1638 0           print STDERR "Diagram.pm : _layout() : no superclasses / inheritances\n";
1639             }
1640              
1641             # grid now created - Components in top row, superclasses in second,
1642             # classes with subclasses in 3rd row, childless & orphan classes in 4th row.
1643              
1644             # now we position the contents of the grid.
1645 0           my $next_row_y = 0;
1646 0           my $next_col_x = 0;
1647 0           my ($colspace, $rowspace) = (1.5 , 0.5);
1648              
1649 0           foreach my $column (@columns) {
1650 0           my $x = $next_col_x;
1651 0           foreach my $subcolumn (@$column) {
1652 0           my $count = 0;
1653 0           my $y = $next_row_y;
1654 0           $next_row_y += 3;
1655 0           foreach my $entity (@$subcolumn)
1656             {
1657 0           my $next_xy = $entity->set_location($x,$y);
1658 0           ($x,$y) = @$next_xy;
1659 0           $x-=3;
1660 0           $y-=(2+($entity->Height/5));
1661 0 0         if ($count >= 4) {
1662 0           $next_row_y = 0;
1663 0           $y = 0;
1664 0           $x += $colspace;
1665 0           $count = 0;
1666             }
1667 0           $count++;
1668             }
1669 0           $y += $rowspace;
1670             }
1671 0           $x += $colspace;
1672 0           $next_col_x = $x;
1673             }
1674              
1675 0           my @relationships = ();
1676              
1677 0 0         if (ref $self->Dependancies)
1678 0           { push(@relationships, @{$self->Dependancies}); }
  0            
1679              
1680 0 0         if( ref $self->Realizations ) {
1681 0           push( @relationships, @{ $self->Realizations } );}
  0            
1682              
1683 0 0         if (ref $self->Inheritances)
1684 0           { push(@relationships, @{$self->Inheritances}); }
  0            
1685              
1686 0           foreach my $relationship (@relationships)
1687 0           { $relationship->Reposition; }
1688              
1689 0           return 1;
1690             }
1691              
1692             sub xml_escape {
1693 0     0 0   my $retval = shift;
1694 0 0         return '' unless $retval;
1695              
1696 0           $retval =~ s/\&/\&/;
1697 0           $retval =~ s/\'/\"/;
1698 0           $retval =~ s/\"/\"/;
1699 0           $retval =~ s/\
1700 0           $retval =~ s/\>/\>/;
1701              
1702 0           return $retval;
1703             }
1704              
1705              
1706             sub get_template {
1707 0     0 0   my %config = @_;
1708             # warn "get_template called : outfile -- $config{outputfile}\n";
1709 0           my $template;
1710             TEMPLATE_SWITCH: {
1711 0 0         if ($config{outputfile} =~ /\.xmi$/) {
  0            
1712 0           $template = get_umbrello_template($config{outputfile});
1713 0           last TEMPLATE_SWITCH;
1714             }
1715 0           $template = get_default_template($config{outputfile});
1716             } # end of TEMPLATE_SWITCH
1717             # warn "template : ", $template, "\n";
1718             # NOTE: $template should always be a ref to a string
1719 0           return $template;
1720             }
1721              
1722             sub get_umbrello_template {
1723 0     0 0   my $outfile = shift;
1724 0           warn "using umbrello template for $outfile\n";
1725 0           my $pwd = $ENV{PWD};
1726 0           my $template =<
1727            
1728            
1729            
1730            
1731             umbrello uml modeller http://uml.sf.net
1732             1.1
1733            
1734            
1735            
1736            
1737            
1738            
1739            
1740            
1746             [%# -------------------------------------------- %]
1747             [% classes = diagram.Classes %]
1748             [% xmictr = 1 %]
1749             [% FOREACH class = classes %]
1750             [% xmictr = xmictr + 1 %]
1751            
1752            
1753             [% FOREACH at = class.Attributes %]
1754            
1755             [% END %]
1756             [% FOREACH op = class.Operations %]
1757            
1758            
1759             [% FOREACH par = op.Params %]
1760            
1761             [% END %]
1762            
1763            
1764             [% END %]
1765            
1766            
1767             [% END %]
1768             [% SET superclasses = diagram.Superclasses %]
1769             [% FOREACH superclass = superclasses %]
1770            
1771            
1772             [% END %]
1773             [% SET components = diagram.Components %]
1774             [% FOREACH component = components %]
1775            
1776             [% FOREACH at = class.Attributes %]
1777             [% xmictr = xmictr + 1 %]
1778            
1779             documentation="" name="[% at.name FILTER html %]" static="0" scope="200" />
1780             [% END %]
1781             [% FOREACH op = class.Operations %]
1782             [% xmictr = xmictr + 1 %]
1783            
1784             [% FOREACH par = op.Params %]
1785             [% xmictr = xmictr + 1 %]
1786            
1787             [% END %]
1788            
1789             [% END %]
1790            
1791             [% END %]
1792             [% SET inheritances = diagram.Inheritances %]
1793             [% FOREACH inheritance = inheritances %]
1794             [%- IF inheritance.Parent >0 AND inheritance.Child >0 -%]
1795            
1803            
1804             [%- END %]
1805             [% END %]
1806             [% SET dependencies = diagram.Dependancies %]
1807             [% FOREACH dependency = dependencies %]
1808            
1809             [% END %]
1810            
1811            
1812            
1813            
1814            
1815            
1816            
1817             xmi.id="2" documentation="" type="402" showops="1" showpackage="0" name="class diagram" localid="30000"
1818             showstereotype="0" showscope="1" snapcsgrid="0" font="Sans,10,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="632" >
1819              
1820              
1821            
1822             [%# -------------------------------------------- %]
1823             [% classes = diagram.Classes %]
1824             [% FOREACH class = classes %]
1825            
1826             x="[% class.left_x %]" linecolour="#ff0000" y="[% class.top_y %]" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="0"
1827             fillcolour="#ffffc0" height="[% class.Height %]" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="[% class.Id %]"
1828             showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Sans,10,-1,5,50,0,0,0,0,0" />
1829             [% END %]
1830             [% SET superclasses = diagram.Superclasses %]
1831             [% FOREACH class = superclasses %]
1832             [% xmictr = xmictr + 1 %]
1833            
1834             x="[% class.left_x %]" linecolour="#ff0000" y="[% class.top_y %]" showopsigs="601" usesdiagramlinecolour="0"
1835             fillcolour="#ffffc0" height="[% class.Height %]" usefillcolor="1" showattributes="1" xmi.id="[% xmictr %]"
1836             showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Sans,10,-1,5,50,0,0,0,0,0" />
1837              
1838             [% END %]
1839            
1840            
1841            
1842             [% SET inheritances = diagram.Inheritances %]
1843             [% FOREACH inheritance = inheritances %]
1844             [%- IF inheritance.Parent >0 AND inheritance.Child >0 -%]
1845            
1846            
1847            
1848            
1849            
1850            
1851             [%- END %]
1852             [% END %]
1853             [% SET dependencies = diagram.Dependancies %]
1854             [% FOREACH dependency = dependencies %]
1855             [%- IF dependency.Parent >0 AND dependency.Child >0 -%]
1856            
1857            
1858            
1859            
1860            
1861            
1862             [%- END %]
1863             [% END %]
1864            
1865            
1866            
1867            
1868            
1869            
1870            
1871            
1872            
1873            
1874            
1875            
1876            
1877            
1878            
1879             END_UMBRELLO_TEMPLATE
1880 0           return \$template;
1881             }
1882              
1883             sub get_default_template {
1884 0     0 0   warn "using default (dia) template\n";
1885 0           my $template = <<'END_TEMPLATE';
1886            
1887             [%# #################################################### %]
1888             [%# Autodia Template for Dia XML. (c)Copyright 2001-2004 %]
1889             [%# #################################################### %]
1890            
1891            
1892            
1893            
1894            
1895            
1896            
1897            
1898             #A4#
1899            
1900            
1901            
1902            
1903            
1904            
1905            
1906            
1907            
1908            
1909            
1910            
1911            
1912            
1913            
1914            
1915            
1916            
1917            
1918            
1919            
1920            
1921            
1922            
1923            
1924            
1925            
1926            
1927            
1928            
1929            
1930            
1931            
1932            
1933            
1934            
1935            
1936            
1937            
1938            
1939            
1940            
1941            
1942            
1943            
1944            
1945            
1946            
1947             [%# -------------------------------------------- %]
1948             [% classes = diagram.Classes %]
1949             [% FOREACH class = classes %]
1950            
1951            
1952            
1953            
1954            
1955            
1956            
1957            
1958            
1959            
1960            
1961            
1962            
1963            
1964            
1965            
1966            
1967             #[% class.Name | html %]#
1968            
1969            
1970             [% IF class.Parent %]
1971             #[% class.Parent | html %]#
1972             [% ELSE %]
1973            
1974             [% END %]
1975            
1976            
1977            
1978            
1979            
1980            
1981            
1982            
1983            
1984            
1985            
1986            
1987            
1988            
1989            
1990            
1991            
1992            
1993            
1994            
1995            
1996            
1997              
1998             [% IF class.Attributes %]
1999            
2000             [% FOREACH at = class.Attributes %]
2001            
2002            
2003             #[% at.name FILTER html %]#
2004            
2005            
2006             #[% at.type FILTER html %]#
2007            
2008            
2009             [% at.value | html %]
2010            
2011            
2012            
2013            
2014            
2015            
2016            
2017            
2018            
2019            
2020            
2021             [% END %]
2022            
2023             [% ELSE %]
2024            
2025             [% END %]
2026             [% IF class.Operations %]
2027            
2028             [% FOREACH op = class.Operations %]
2029            
2030            
2031             #[% op.name FILTER html %]#
2032            
2033            
2034             [% IF op.type %]
2035             #[% op.type FILTER html %]#
2036             [% ELSE %]
2037            
2038             [% END %]
2039            
2040            
2041            
2042            
2043            
2044            
2045            
2046            
2047            
2048            
2049             [% IF op.Params.0 %]
2050            
2051             [% FOREACH par = op.Params %]
2052            
2053            
2054             #[% par.Name FILTER html %]#
2055            
2056            
2057             #[% par.Type FILTER html %]#
2058            
2059            
2060             [% IF par.Value %]
2061            
2062             [% ELSE %]
2063            
2064             [% END %]
2065            
2066            
2067             [% IF par.Kind %]
2068            
2069             [% ELSE %]
2070            
2071             [% END %]
2072            
2073            
2074             [% END %]
2075            
2076             [% ELSE %]
2077            
2078             [% END %]
2079            
2080             [% END %]
2081            
2082             [% ELSE %]
2083            
2084             [% END %]
2085            
2086            
2087            
2088            
2089            
2090             [% END %]
2091             [%#%]
2092             [% UNLESS config.skip_packages %]
2093             [% SET components = diagram.Components %]
2094             [%#%]
2095             [% FOREACH component = components %]
2096            
2097            
2098            
2099            
2100            
2101            
2102            
2103            
2104            
2105            
2106            
2107            
2108            
2109            
2110            
2111            
2112            
2113            
2114            
2115             #[% component.Name | html %]#
2116            
2117            
2118            
2119            
2120            
2121            
2122            
2123            
2124            
2125            
2126            
2127            
2128            
2129            
2130            
2131            
2132            
2133            
2134            
2135             [% END %]
2136             [% # %]
2137             [% SET realizations = diagram.Realizations %]
2138             [% # %]
2139             [% FOREACH realization = realizations %]
2140            
2141            
2142            
2143            
2144            
2145            
2146            
2147            
2148            
2149            
2150            
2151            
2152            
2153            
2154            
2155            
2156            
2157            
2158            
2159            
2160            
2161            
2162            
2163            
2164            
2165            
2166            
2167            
2168            
2169            
2170            
2171            
2172             [% END %]
2173             [% # %]
2174             [% SET dependancies = diagram.Dependancies %]
2175             [% # %]
2176             [% FOREACH dependancy = dependancies %]
2177            
2178            
2179            
2180            
2181            
2182            
2183            
2184            
2185            
2186            
2187            
2188            
2189            
2190            
2191            
2192            
2193            
2194            
2195            
2196            
2197            
2198            
2199            
2200            
2201            
2202            
2203            
2204            
2205            
2206            
2207            
2208            
2209             [% END %]
2210             [% END %]
2211             [% # %]
2212             [% UNLESS config.skip_superclasses %]
2213             [% SET superclasses = diagram.Superclasses %]
2214             [% # %]
2215             [% FOREACH superclass = superclasses %]
2216            
2217            
2218            
2219            
2220            
2221            
2222            
2223            
2224            
2225            
2226            
2227            
2228            
2229            
2230            
2231            
2232            
2233             #[% superclass.Name %]#
2234            
2235            
2236            
2237            
2238            
2239            
2240            
2241            
2242            
2243            
2244            
2245            
2246            
2247            
2248            
2249            
2250            
2251            
2252            
2253            
2254            
2255            
2256            
2257            
2258            
2259            
2260             [% END %]
2261             [% END %]
2262             [% #### %]
2263             [% SET inheritances = diagram.Inheritances %]
2264             [% FOREACH inheritance = inheritances %]
2265             [% IF config.skip_superclasses %]
2266             [% SET parent = inheritance.Parent %]
2267             [% UNLESS diagram.package_types.class.$parent %] [% NEXT %] [% END %]
2268             [% END %]
2269            
2270            
2271            
2272            
2273            
2274            
2275            
2276            
2277            
2278            
2279            
2280            
2281            
2282            
2283            
2284            
2285            
2286            
2287            
2288            
2289            
2290            
2291            
2292            
2293            
2294            
2295            
2296            
2297            
2298            
2299            
2300            
2301             [% END %]
2302              
2303             [% SET relations = diagram.Relations %]
2304             [% FOREACH relation = relations %]
2305            
2306            
2307            
2308            
2309            
2310            
2311            
2312            
2313            
2314            
2315            
2316            
2317            
2318            
2319            
2320            
2321            
2322            
2323            
2324            
2325            
2326            
2327             ##
2328            
2329            
2330            
2331            
2332            
2333            
2334            
2335             ##
2336            
2337            
2338             ##
2339            
2340            
2341            
2342            
2343            
2344            
2345            
2346            
2347            
2348            
2349            
2350            
2351            
2352             ##
2353            
2354            
2355             ##
2356            
2357            
2358            
2359            
2360            
2361            
2362            
2363            
2364            
2365            
2366            
2367            
2368            
2369            
2370            
2371            
2372            
2373             [% END %]
2374              
2375            
2376            
2377             END_TEMPLATE
2378              
2379 0           return \$template;
2380             }
2381              
2382             1;
2383              
2384             ##################################################################
2385              
2386             =head2 See Also
2387              
2388             Autodia
2389              
2390             Autodia::Diagram::Object
2391              
2392             Autodia::Diagram::Class
2393              
2394             Autodia::Diagram::Superclass
2395              
2396             Autodia::Diagram::Component
2397              
2398             Autodia::Diagram::Inheritance
2399              
2400             Autodia::Diagram::Relation
2401              
2402             Autodia::Diagram::Dependancy
2403              
2404             =head1 AUTHOR
2405              
2406             Aaron Trevena, Eaaron.trevena@gmail.comE
2407              
2408             =head1 COPYRIGHT AND LICENSE
2409              
2410             Copyright (C) 2004 by Aaron Trevena
2411              
2412             This library is free software; you can redistribute it and/or modify
2413             it under the same terms as Perl itself, either Perl version 5.8.1 or,
2414             at your option, any later version of Perl 5 you may have available.
2415              
2416              
2417             =cut
2418              
2419             ########################################################################
2420              
2421              
2422              
2423              
2424              
2425