give modules default loggers so they are usable on their own (in tests)
[scpubgit/System-Introspector-Report.git] / lib / System / Introspector / Report / Source.pm
CommitLineData
499ebcdd 1package System::Introspector::Report::Source;
2use Moo;
3use JSON::PP;
4use IO::All;
5use Module::Runtime qw( use_module );
55dfa20f 6use Log::Contextual::WarnLogger;
7use Log::Contextual qw( :log ),
8 -default_logger => Log::Contextual::WarnLogger->new({
9 env_prefix => 'SI_REPORT_SOURCE',
10 levels => [qw( error fatal warn )],
11 });
499ebcdd 12
13my $_json = JSON::PP->new->utf8->relaxed->allow_nonref;
14
15has root => (is => 'ro', required => 1);
16
17sub new_from_root {
18 my ($class, $root, @args) = @_;
19 if ($root =~ m{^(.+):(.+)$}) {
20 my ($remote, $remote_root) = ($1, $2);
21 require Object::Remote;
22 return $class->new::on($remote, @args, root => $remote_root);
23 }
24 else {
25 return $class->new(@args, root => $root);
26 }
27}
28
29sub generate {
30 my ($self, @types) = @_;
31 my @generators = map { $self->_make_generator($_) } @types;
32 my $required = +{ map { ($_ => 1) } map $_->required_data, @generators };
33 my @dirs = $self->_find_source_dirs;
34 for my $dir_spec (@dirs) {
35 my ($id, $path) = @$dir_spec;
36 my $data = $self->_load_dataset($path, $required)
37 or next;
f0a14f8a 38 log_trace { "loading node '$id' from '$path'" };
499ebcdd 39 $_->collect_from($id, $data)
40 for @generators;
41 }
42 return map { ($_->render_reports) } @generators;
43}
44
45sub _load_dataset {
46 my ($self, $path, $required) = @_;
47 my $root = $self->root;
48 return +{
49 map {
50 ($_->[0], $_json->decode(scalar $_->[1]->slurp) || {});
51 } grep {
52 $required->{$_->[0]};
53 } map {
54 my $key = $_;
55 $key =~ s!^\Q$root\E/*(?:[^/]+/+){2}!!;
56 $key =~ s{\.json$}{};
57 [$key, $_];
58 } grep {
59 not(m{^\.}) and m{\.json$};
60 } $path->deep->all_files
61 };
62}
63
64sub _find_source_dirs {
65 my ($self) = @_;
66 my $root = $self->root;
67 return map {
68 (my $id = $_) =~ s{^\Q$root\E/*}{};
69 [$id, $_];
70 } io($root)->all_dirs;
71}
72
73sub _make_generator {
74 my ($self, $spec) = @_;
75 my ($type, $args) = @$spec;
76 return use_module("System::Introspector::Report::Builder::$type")
77 ->new($args || {});
78}
79
801;