Commit | Line | Data |
499ebcdd |
1 | package System::Introspector::Report::Source; |
2 | use Moo; |
3 | use JSON::PP; |
4 | use IO::All; |
5 | use Module::Runtime qw( use_module ); |
55dfa20f |
6 | use Log::Contextual::WarnLogger; |
7 | use 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 | |
13 | my $_json = JSON::PP->new->utf8->relaxed->allow_nonref; |
14 | |
15 | has root => (is => 'ro', required => 1); |
16 | |
17 | sub 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 | |
29 | sub 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 | |
45 | sub _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 | |
64 | sub _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 | |
73 | sub _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 | |
80 | 1; |