Commit 7d562437 authored by untereiner's avatar untereiner

adding doxygraph support to build UML diagrams from doxygen...

adding Implicit MR support
parent c272c6b5
......@@ -1390,7 +1390,7 @@ MAN_LINKS = NO
# generate an XML file that captures the structure of
# the code including all documentation.
GENERATE_XML = NO
GENERATE_XML = YES
# The XML_OUTPUT tag is used to specify where the XML pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
......
This diff is collapsed.
About
=====
http://code.google.com/p/doxygraph
This is doxygraph, a free system for reverse engineering UML class diagrams
from source code, and presenting those diagrams as interactive web apps. It
relies on Doxygen for parsing source code, so it supports all the languages
that Doxygen supports: C, C++, C#, Objective C, Java, Python, PHP, Tcl, D, IDL,
VHDL, and Fortran.
Doxygraph is composed of two parts:
doxygraph
A Perl script that will generate a diagram in Graphviz dot format, using
as input the XML based format generated by Doxygen.
doxyviz
A JavaScript app that will interactively present a diagram generated
by the doxygraph Perl script. The manipulation and rendering of graphs
relies on bindviz, which is an automated JavaScript port of Graphviz
ported using emscripten.
Quick Start
===========
If you have a project for which you want to generate a class diagram, and you
are already using Doxygen to generate API documentation for this project, then
as a preliminary step, you simply need to edit your Doxyfile and ensure that it
sets the option GENERATE_XML = YES.
If you are not already using Doxygen to generate API documentation for your
project, then the preliminary step is to install Doxygen and configure it to
process your project's header files. This is a simple process, documented at
http://www.doxygen.org/. During this process, make sure to set the option
GENERATE_XML = YES. In addition, if you set the option EXTRACT_ALL = YES then
you won't need to worry about adding special Doxygen comments to all of your
classes; this option will cause Doxygen to parse the classes even if the
comments are not present.
When you have a project with a Doxyfile properly set up for generating Doxygen
XML files from your project's header files, then the first step in the doxygraph
pipeline is to run Doxygen, which will generate a set of XML files.
If you don't have a specific project for which you want to generate a diagram,
but just want to try out doxygraph and see how it works, there are some example
Doxygen XML files provided in the examples directory.
When you have your Doxygen XML files, the next step is to run the following
command from within the doxygraph root directory, which will convert the XML
files into a Graphviz dot file:
perl doxygraph/doxygraph /path/to/your/index.xml doxyviz/htdocs/graph.dot
If Perl emits any errors of the form "Can't locate ____ in @INC", that is
usually an indication that you are missing one or more of the dependencies of
the script, which can easily be installed using Perl's cpan utility.
When you have generated your graph.dot file, then you are ready to go. You
can open doxyviz/htdocs/index.html in your web browser to view your interactive
UML class diagram locally, or copy the contents of the htdocs directory into a
subdirectory of your web server's htdocs directory in order to deploy your
interactive diagram to the web.
More Details
============
More detailed documentation for the component parts of doxygraph is provided in
the relevant subdirectories.
License
=======
Copyright 2013 Doxygraph project
These Source Code Forms are subject to the terms of the Mozilla Public License
version 2.0. If a copy of the MPL was not distributed with this file, You can
obtain one at http://mozilla.org/MPL/2.0/.
\ No newline at end of file
doxygraph
Makefile.PL
MANIFEST
lib/Doxygen/XML.pm
lib/GraphViz/UML.pm
README
\ No newline at end of file
use ExtUtils::MakeMaker;
WriteMakefile(
NAME => 'doxygraph',
AUTHOR => 'Doxygraph project http://code.google.com/p/doxygraph',
ABSTRACT_FROM => 'doxygraph',
VERSION_FROM => 'doxygraph',
LICENSE => 'mozilla',
EXE_FILES => ['doxygraph'],
PREREQ_PM => {qw(
File::Spec 0
GraphViz2 0
Hash::FieldHash 0
lib::abs 0
Moose 0
namespace::autoclean 0
XML::Rabbit 0
)}
);
\ No newline at end of file
About
=====
http://code.google.com/p/doxygraph
This is doxygraph, a Perl script that will generate a diagram in Graphviz dot
format, using as input the XML based format generated by Doxygen. Doxygraph is
part of doxygraph, a free system for reverse engineering UML class diagrams from
source code, and presenting those diagrams as interactive web apps.
Dependencies
============
The following CPAN modules are required:
File::Spec
GraphViz2
Hash::FieldHash
lib::abs
Moose
namespace::autoclean
XML::Rabbit
Usage
=====
The doxygraph Perl script can be used without needing to install it, although a
Makefile is provided for optional installation.
The script expects two commandline arguments: the first is the name of the input
file (usually index.xml generated by Doxygen) and the second is the name of the
output file.
To instruct Doxygen to generate XML output, set the option GENERATE_XML = YES
in your Doxyfile.
Installation
============
If you want to install doxygraph, follow the usual procedure for installing Perl
modules:
perl Makefile.PL
make
make install
License
=======
Copyright 2013 Doxygraph project
These Source Code Forms are subject to the terms of the Mozilla Public License,
version 2.0. If a copy of the MPL was not distributed with this file, You can
obtain one at http://mozilla.org/MPL/2.0/.
\ No newline at end of file
#!/usr/bin/perl
package doxygraph 0.1;
use strict;
use warnings;
use lib::abs 'lib';
use Doxygen::XML;
use GraphViz::UML;
@ARGV == 2 or usage();
grep { /^-/ } @ARGV and usage();
my ($index, $output) = @ARGV;
my $uml = GraphViz::UML->new;
my $xml = Doxygen::XML->new({ handler => $uml });
my @compounds = $xml->parse_index($index);
$xml->parse_compound($_) for @compounds;
my $dot = $uml->export->command;
open my $fh, '>', $output or die "$output: $!";
$dot->foreach(sub { print $fh $_ });
print $fh "}\n";
close $fh;
sub usage
{
print STDERR << "EOF";
Expected commandline usage:
doxygraph path/to/index.xml path/to/output.dot
EOF
exit 0;
}
=head1 NAME
doxygraph - Create Graphviz UML class diagram from Doxygen XML output
=head1 SYNOPSIS
doxygraph index.xml graph.dot
=head1 DESCRIPTION
Doxygen can output an XML representation of all the documented entities it
encounters in the source code it examines, by setting C<GENERATE_XML = YES> in
your C<Doxyfile>. Doxygraph will convert this XML representation into a UML
class diagram in the format recognized by Graphviz and its C<dot> command.
All the heavy lifting is done in the L<Doxygen::XML> and L<GraphViz::UML>
modules.
=head1 OPTIONS
None.
=head1 EXAMPLES
doxygen
doxygraph xml/index.xml graph.dot
dot -T svg -o graph.svg graph.dot
=head1 AUTHORS
Available through the git repository at L<http://code.google.com/p/doxygraph>.
=head1 COPYRIGHT AND LICENSE
Copyright 2013 Doxygraph project
This Source Code Form is subject to the terms of the Mozilla Public License,
version 2.0. If a copy of the MPL was not distributed with this file, You can
obtain one at L<http://mozilla.org/MPL/2.0/>.
=head1 SEE ALSO
L<http://www.doxygen.org/>, L<http://www.graphviz.org/>.
This diff is collapsed.
package GraphViz::UML;
use strict;
use warnings;
use namespace::autoclean;
use Hash::FieldHash qw(:all);
use GraphViz2;
{ fieldhash my %hash, 'classes_by_name' }
{ fieldhash my %hash, 'classes_by_refid' }
=head1 NAME
GraphViz::UML - build GraphViz graphs representing UML class diagrams
=head1 SYNOPSIS
use GraphViz::UML;
my $uml = GraphViz::UML->new;
$uml->add_class('Base', 'class_base_0');
$uml->add_class('Derived', 'class_derived_0');
$uml->add_generalization('Derived', 'class_base_0');
my $gv = $uml->export;
=head1 DESCRIPTION
This module provides methods to build up a UML class diagram and export it as
a L<GraphViz2> object. It is designed to be used as a handler for
L<Doxygen::XML> but it can also be used on its own.
=head1 EXAMPLES
See L<Doxygen::XML> to see an example of how to use these two modules together.
=head1 METHODS
=over
=item new
The constructor takes no arguments.
=item export
Returns a L<GraphViz2> object that reflects the UML class diagram.
=item add_class($classname, $classid)
Adds a class to the diagram, with a unique identifier.
=item set_stereotype($classname, $stereotype)
Sets the stereotype of the named class (e.g. "abstract" or "interface").
=item add_operation($classname, $hashref)
Adds an operation to the named class. The hashref has the following keys:
=over
=item name
The operation's name.
=item type
The operation's return type.
=item properties
An arrayref of property strings (e.g. "public", "private", "const", "volatile").
=item parameters
An arrayref of arrayrefs, each one being a C<[name, type]> pair.
=item paramstring
A flat string representation of the parameters list, used for sorting.
=back
=item add_attribute($classname, $hashref)
Adds an attribute to the named class. The hashref has the following keys:
=over
=item name
The attribute's name.
=item type
The attribute's type.
=item properties
An arrayref of property strings (e.g. "public", "private", "const", "volatile").
=back
=item add_generalization($derived_name, $base_id)
Creates a generalization relationship between two classes.
=item add_aggregation($aggregator_name, $aggregee_id)
Creates an aggregation relationship between two classes.
=item add_composition($composer_name, $composee_id)
Creates a composition relationship between two classes.
=back
=head1 AUTHORS
Available through the git repository at L<http://code.google.com/p/doxygraph>.
=head1 COPYRIGHT AND LICENSE
Copyright 2013 Doxygraph project
This Source Code Form is subject to the terms of the Mozilla Public License,
version 2.0. If a copy of the MPL was not distributed with this file, You can
obtain one at L<http://mozilla.org/MPL/2.0/>.
=head1 SEE ALSO
L<http://www.graphviz.org/>.
=cut
sub add_class
{
my ($self, $classname, $refid) = @_;
my $class = {
name => $classname,
refid => $refid,
stereotype => '',
operations => [],
attributes => [],
generalizations => {},
aggregations => {},
compositions => {}
};
$self->classes_by_name->{$classname} = $class;
$self->classes_by_refid->{$refid} = $class;
}
sub set_stereotype
{
my ($self, $classname, $stereotype) = @_;
exists $self->classes_by_name->{$classname} or die;
$self->classes_by_name->{$classname}{stereotype} = $stereotype;
}
sub add_operation
{
my ($self, $classname, $operation) = @_;
exists $self->classes_by_name->{$classname} or die;
push @{ $self->classes_by_name->{$classname}{operations} }, $operation;
}
sub add_attribute
{
my ($self, $classname, $attribute) = @_;
exists $self->classes_by_name->{$classname} or die;
push @{ $self->classes_by_name->{$classname}{attributes} }, $attribute;
}
sub add_generalization
{
my ($self, $classname, $baseclassid) = @_;
exists $self->classes_by_name->{$classname} or die;
exists $self->classes_by_refid->{$baseclassid} or return;
$self->classes_by_name->{$classname}{generalizations}{$baseclassid} = 1;
}
sub add_aggregation
{
my ($self, $classname, $aggregeeid) = @_;
exists $self->classes_by_name->{$classname} or die;
exists $self->classes_by_refid->{$aggregeeid} or return;
$self->classes_by_name->{$classname}{aggregations}{$aggregeeid} = 1;
}
sub add_composition
{
my ($self, $classname, $composeeid) = @_;
exists $self->classes_by_name->{$classname} or die;
exists $self->classes_by_refid->{$composeeid} or return;
$self->classes_by_name->{$classname}{compositions}{$composeeid} = 1;
}
sub new
{
my ($package) = @_;
my $self = bless {} => $package;
return from_hash($self, classes_by_name => {}, classes_by_refid => {});
}
sub export
{
my ($self) = @_;
my $gv = GraphViz2->new(
global => {
name => 'doxygraph',
directed => 1,
record_shape => 'record'
}, graph => {
rankdir => 'RL'
}
);
my @classes = sort { $a->{name} cmp $b->{name} }
values %{$self->classes_by_name};
for my $class (@classes) {
$gv->add_node(
name => $class->{refid},
label => $self->_make_label($class),
shape => 'record'
);
for (keys %{$class->{generalizations}}) {
$gv->add_edge(from => $class->{refid}, to => $_,
arrowhead => 'empty', style =>
$self->classes_by_refid->{$_}{stereotype} =~ m(abstract|interface)
? 'bold,dashed' : 'bold');
}
for (keys %{$class->{aggregations}}) {
$gv->add_edge(from => $class->{refid}, to => $_,
arrowtail => 'odiamond', dir => 'back');
}
for (keys %{$class->{compositions}}) {
$gv->add_edge(from => $class->{refid}, to => $_,
arrowtail => 'diamond', dir => 'back');
}
}
return $gv;
}
# Compose a label for a GraphViz record node representing a UML class.
#
sub _make_label
{
my ($self, $class) = @_;
my $label = _q($class->{name});
$label .= "\\n" . _angleq(_q($class->{stereotype})) if $class->{stereotype};
$label .= "\\n|";
$label .= _q($self->_make_operation($_)) . "\\l"
for sort { _cmp_members($a, $b) } @{$class->{operations}};
$label .= "|";
$label .= _q($self->_make_attribute($_)) . "\\l"
for sort { _cmp_members($a, $b) } @{$class->{attributes}};
return $label;
}
# Compose a UML operation string from a member hash.
#
sub _make_operation
{
my ($self, $operation) = @_;
my $line = '';
$line .= _make_prefix($operation);
$line .= $operation->{name};
$line .= " ( ";
$line .= join ", ",
map { $_->[0] . " : " . $_->[1] } @{$operation->{parameters}};
$line = _clamp($line);
$line .= " )";
$line .= " : " . $operation->{type} if $operation->{type};
$line .= " $_" for _make_suffix($operation);
return $line;
}
# Compose a UML attribute string from a member hash.
#
sub _make_attribute
{
my ($self, $attribute) = @_;
my $line = '';
$line .= _make_prefix($attribute);
$line .= $attribute->{name};
$line = _clamp($line);
$line .= " : " . $attribute->{type} if $attribute->{type};
$line .= " $_" for _make_suffix($attribute);
return $line;
}
# Construct a UML visibility prefix from a member hash's properties array.
#
sub _make_prefix
{
my ($member) = @_;
my %props = map { $_ => 1 } @{$member->{properties}};
my $prefix = '';
$prefix .= '/' if $props{derived};
$prefix .= '-' if $props{private};
$prefix .= '+' if $props{public};
$prefix .= '#' if $props{protected};
return $prefix;
}
# Construct a UML properties suffix from a member hash's properties array.
#
sub _make_suffix
{
my ($member) = @_;
my %props = map { $_ => 1 } @{$member->{properties}};
return map { "{$_}" } grep { exists $props{$_} } qw(
readable writable initonly settable gettable final sealed add remove
static virtual pure-virtual volatile mutable optional required package
retain copy assign weak strong unretained);
}
# Comparison function for sorting member hashes by visibility and by name.
#
sub _cmp_members
{
my ($a, $b) = @_;
my %props = (none => 0, public => 1, protected => 2, private => 3);
my $a_prop = _get_visibility($a);
my $b_prop = _get_visibility($b);
my $cmp = $props{$a_prop} <=> $props{$b_prop};
return $cmp if $cmp;
$cmp = $a->{name} cmp $b->{name};
return $cmp if $cmp;
$cmp = exists($a->{paramstring}) <=> exists($b->{paramstring});
return $cmp if $cmp;
return $a->{paramstring} cmp $b->{paramstring} if exists $a->{paramstring};
return 0;
}
# Returns any visibility property present in a member hash's properties array.
#
sub _get_visibility
{
my ($member) = @_;
for my $prop (@{$member->{properties}}) {
return $prop if grep { $_ eq $prop } qw(public private protected);
}
return 'none';
}
# Return the given string truncated to a maximum length and an ellipsis added.
#
sub _clamp
{
my ($text) = @_;
return (length($text) < 120) ? $text : substr($text, 0, 120) . '...';
}
# Return the given string with special GraphViz characters escaped.
#
sub _q
{
my ($text) = @_;
$text =~ s(([{}<>\|]))(\\$1)g;
return $text;
}
# Return the given string surrounded by a pair of guillemets.
#
sub _angleq
{
my ($text) = @_;
return "\N{U+00AB}$text\N{U+00BB}";
}
1;
\ No newline at end of file
About
=====
http://code.google.com/p/doxygraph
This is doxyviz, a free web app for presenting interactive UML class diagrams
generated from Doxygen XML files by its companion Perl script doxygraph.
Doxyviz and the doxygraph Perl script are collectively referred to as doxygraph.
For the manipulation and rendering of graphs, doxyviz relies on bindviz, which
is an automated JavaScript port of Graphviz ported using emscripten.
Usage
=====
Doxyviz expects to be able to find a file named graph.dot in the same folder as
its HTML and JavaScript files; this file will be the UML diagram generated by
the doxygraph Perl script. After this file has been generated, you only need to
open the Doxyviz app's index.html in your web browser to begin interacting with
your diagram.
You are encouraged to edit index.html and doxyviz.js to adapt and improve them
as you see fit, and to submit patches to the Doxygraph project if your changes
may be useful to other users. It is an ongoing community development effort.
Documentation covering the graph manipulation and rendering API provided by
bindviz.js can be found in the bindviz folder.
Installation
============
All the necessary HTML and JavaScript files are located in the htdocs folder.
After generating your graph.dot file, simply copy these files into your web
server's htdocs folder in order to deploy your interactive diagram to the web.
A precompiled bindviz.js is provided, which doxyviz will use to help it
manipulate and render the diagrams. Therefore you do not need to compile it
yourself, although you may do so if you wish, using emscripten. Instructions
for doing this may be found in the bindviz folder.
License
=======
Copyright 2013 Doxygraph project
These Source Code Forms are subject to the terms of the Mozilla Public License,
version 2.0. If a copy of the MPL was not distributed with this file, You can
obtain one at http://mozilla.org/MPL/2.0/.
\ No newline at end of file
<
About
=====
http://code.google.com/p/doxygraph
This is bindviz, an automated port of Graphviz to JavaScript using emscripten.
This folder contains C++ source code, build instructions, and API documentation.
A precompiled version of bindviz itself can be found in the sibling folder htdocs.
API documentation
=================
For the most part, the bindviz JavaScript API mirrors the Graphviz C API, albeit
a modest subset of it. Documentation for the Graphviz C API is provided in two
PDF files. The following describes the ways in which the JavaScript API differs
from this.
The following functions are provided as methods on the Module object:
Function Remarks
------------------------------------------------
gvcVersion
gvcBuildDate
gvContext
gvLayout
gvRenderString (1)
gvFreeLayout
gvFreeContext
agopen (2)
agclose
agread (2)
agconcat (2)
agnnodes
agnedges
agnode
agidnode
agfirstnode (3)
agnextnode (3)
agprevnode (3)