File Coverage

blib/lib/DMOSS.pm
Criterion Covered Total %
statement 55 170 32.3
branch 3 36 8.3
condition 1 8 12.5
subroutine 13 26 50.0
pod 10 11 90.9
total 82 251 32.6


line stmt bran cond sub pod time code
1             package DMOSS;
2             # ABSTRACT: Data Mining Open Source Software
3             $DMOSS::VERSION = '0.01_2';
4 2     2   66456 use strict;
  2         5  
  2         85  
5 2     2   14 use warnings;
  2         4  
  2         59  
6              
7 2     2   1099 use DMOSS::Oracle;
  2         8  
  2         70  
8 2     2   1404 use DMOSS::File;
  2         7  
  2         64  
9 2     2   1347 use DMOSS::Attr;
  2         5  
  2         62  
10 2     2   13 use File::Basename;
  2         3  
  2         198  
11 2     2   2339 use Storable qw/store retrieve dclone store_fd fd_retrieve/;
  2         7566  
  2         205  
12 2     2   1983 use Module::Find;
  2         2776  
  2         146  
13 2     2   7219 use Data::Dumper;
  2         16376  
  2         1386  
14              
15             sub new {
16 1     1 1 640 my ($class,$basedir,@files) = @_;
17 1         3 my $self = bless({}, $class);
18 1         7 $self->{basedir} = $basedir;
19 1         3 $self->{typeof} = {};
20 1         2 $self->{res} = {};
21 1         3 $self->{meta} = {};
22              
23 1 50       4 my $dist = basename $basedir if $basedir;
24              
25 1         4 $self->{meta}->{dist} = $dist;
26 1 50 33     9 if ($dist and $dist =~ m/([\d\-\.]+)$/) {
27 0         0 my $version = $1;
28 0         0 $version =~ s/^[\-\.]+//;
29 0 0       0 if ($version) {
30 0         0 $self->{meta}->{version} = $version;
31             }
32             }
33              
34             # start with an empty tree
35 1         3 $self->{tree} = {};
36              
37             # init files, and populate tree
38 1         7 $self->__init_files($basedir, @files);
39              
40             # find available plugins
41 1         6 my @available = findallmod DMOSS::Plugin;
42 1         2788 my @plugins;
43 1         4 foreach (@available) {
44 7         432 eval "require $_;";
45 7         1012 my $skip = eval '$'.$_ .'::SKIP or 0';
46 7 50       45 push @plugins, $_ unless $skip;
47             }
48 1         7 $self->{plugins} = [@plugins];
49              
50 1         8 return $self;
51             }
52              
53             sub __init_files {
54 1     1   3 my ($self, $basedir, @files) = @_;
55 1         11 my $ora = DMOSS::Oracle->new();
56              
57 1         12 foreach (@files) {
58 0           my $file = DMOSS::File->new($basedir, $_);
59 0           $self->{files}->{$file->path} = $file;
60              
61 0           my $type = $ora->type($file);
62 0 0         if ($type) {
63 0           $file->type($type);
64 0           $self->{files}->{$file->path}->{type} = $type;
65 0           $self->{typeof}->{$file->path} = $type;
66             }
67              
68 0           $self->__add_tree($file->path, $_);
69             }
70             }
71              
72             sub __add_tree {
73 0     0     my ($self, $path, $id) = @_;
74              
75 0           my @l = split /[\\\/]+/, $path; # FIXME generalize file separator
76              
77 0           my $root = $self->{tree};
78 0           my $next = shift @l;
79 0           while (@l) {
80 0 0         $root->{$next} = {} unless exists($root->{$next});
81 0           $root = $root->{$next};
82 0           $next = shift @l;
83             }
84 0           $root->{$path} = $id;
85             }
86              
87             my $curr_file; # FIXME remove global variables
88              
89             sub process {
90 0     0 1   my ($self) = @_;
91 0           my @plugins = @{$self->{plugins}};
  0            
92 0           my $ora = DMOSS::Oracle->new;
93              
94             # load plugins and populate dispatch table per type
95 0           my $dispatch;
96             my @package_plugins;
97 0           foreach (@plugins) {
98 2     2   22 no strict 'refs';
  2         5  
  2         1966  
99 0           eval "require $_";
100 0           my @types = @{ $_ . '::types' };
  0            
101 0           foreach my $t (@types) {
102 0 0         if ($t =~ m/_PACKAGE/) {
103 0           push @package_plugins, $_;
104             }
105 0 0         if ($t =~ m/^_/) {
106 0           foreach my $tt ($ora->group($t)) {
107 0           push @{$dispatch->{$tt}}, $_;
  0            
108             }
109             }
110 0           else { push @{$dispatch->{$t}}, $_; }
  0            
111             }
112             }
113              
114             # run plugins procesors for each file
115 0           foreach (keys %{$self->{files}}) {
  0            
116 0           my $file = $self->{files}->{$_};
117 0 0 0       next unless ($file->type and exists($dispatch->{$file->type}));
118 0           $curr_file = $file;
119              
120 0           my @watchers = @{$dispatch->{$file->type}};
  0            
121 0           foreach (@watchers) {
122 0           my $obj = $_->new;
123 0           $obj->process($self, $file);
124             }
125             }
126             # run package processors
127 0           foreach (@package_plugins) {
128 0           $curr_file = DMOSS::File->new($self->{basedir}, '');
129 0           my $obj = $_->new;
130 0           $obj->process($self, $curr_file);
131             }
132              
133             # run post processing (reduce) functions
134 0           $self->tree_process($self->{tree}, '');
135 0           $self->__handle_level($self->{tree}, '');
136             }
137              
138             sub tree_process {
139 0     0 1   my ($self, $root, $path) = @_;
140              
141 0           foreach my $k (keys %$root) {
142 0 0         if (ref($root->{$k}) eq 'HASH') {
143 0 0         my $curr = $path ? "$path/$k" : $k;
144 0           $self->tree_process($root->{$k}, $curr);
145 0           $self->__handle_level($root->{$k}, $curr);
146             }
147             }
148             }
149              
150             sub __handle_level {
151 0     0     my ($self, $root, $path) = @_;
152 0           $curr_file = DMOSS::File->new($self->{basedir}, $path);
153              
154 0           foreach my $p ( @{ $self->{plugins} } ) {
  0            
155 0           my @attrs;
156 0           foreach my $k (keys %$root) {
157 0 0         next unless $self->{attrs}->{$k}->{$p};
158 0           push @attrs, @{ $self->{attrs}->{$k}->{$p} };
  0            
159             }
160 0 0         $p->reduce($self, @attrs) if (@attrs);
161             }
162             }
163              
164             sub add_attr {
165 0     0 1   my ($self, $name, $value) = @_;
166 0           my ($plugin) = caller;
167              
168 0           my $attr = DMOSS::Attr->new($curr_file, $plugin, $name, $value);
169 0   0       push @{ $self->{attrs}->{$attr->file->path or ''}->{$plugin} }, $attr;
  0            
170             }
171              
172             sub report_attrs_plugin {
173 0     0 1   my ($self, $report, $plugin) = @_;
174 0           my @reports;
175 0           eval "require $plugin;";
176              
177 0           foreach my $k (keys %{ $self->{attrs} }) {
  0            
178 0           foreach (@{ $self->{attrs}->{$k}->{$plugin} }) {
  0            
179 0           my $r = $plugin->report($self, $_);
180 0 0         if (ref($r->[0]) eq 'ARRAY') { push @reports, @$r; }
  0            
181 0           else { push @reports, $r; }
182             }
183             }
184              
185 0           return @reports;
186             }
187              
188             sub plugin_grade {
189 0     0 0   my ($self, $plugin) = @_;
190              
191 0           eval "require $plugin;";
192 0           return $plugin->grade($self, $self->{attrs}->{''}->{$plugin}->[0]);
193             }
194              
195             sub dt {
196 0     0 1   my ($self, $f) = @_;
197              
198 0           $self->__dt($self->{tree}, '', $f);
199             }
200              
201             sub __dt {
202 0     0     my ($self, $root, $path, $f) = @_;
203 2     2   14 no strict 'refs';
  2         13  
  2         632  
204              
205 0           foreach my $k (keys %$root) {
206 0 0         if (ref($root->{$k}) eq 'HASH') {
207 0 0         my $curr = $path ? "$path/$k" : $k;
208 0           $self->__dt($root->{$k}, $curr, $f);
209             }
210             }
211              
212 0           my $tmp = dclone($self->{res});
213 0           foreach my $k (keys %$root) {
214 0           &$f(dclone($self), $k);
215             }
216              
217             }
218              
219             sub save {
220 0     0 1   my ($self, $file) = @_;
221 0 0         $file = 'dmoss.data' unless $file;
222              
223 0           store $self, $file;
224              
225 0           return $file;
226             }
227              
228             sub to_stdout {
229 0     0 1   my ($self) = @_;
230              
231 0           store_fd($self, *STDOUT);
232             }
233              
234             sub load {
235 0     0 1   my ($file) = @_;
236 0 0         $file = 'dmoss.data' unless $file;
237              
238 0           my $ref = retrieve($file);
239 0           my $self = bless($ref, 'DMOSS');
240              
241 0           return $self;
242             }
243              
244             sub from_stdout {
245 0     0 1   my $ref = fd_retrieve(*STDIN);
246 0           my $self = bless($ref, 'DMOSS');
247              
248 0           return $self;
249             }
250              
251             1;
252              
253             __END__