File Coverage

blib/lib/Data/RuledCluster.pm
Criterion Covered Total %
statement 72 81 88.8
branch 27 38 71.0
condition 2 4 50.0
subroutine 17 17 100.0
pod 8 9 88.8
total 126 149 84.5


line stmt bran cond sub pod time code
1             package Data::RuledCluster;
2 7     7   153728 use 5.008_001;
  7         27  
3 7     7   43 use strict;
  7         16  
  7         222  
4 7     7   33 use warnings;
  7         22  
  7         255  
5 7     7   41 use Carp ();
  7         19  
  7         135  
6 7     7   4588 use Class::Load ();
  7         175037  
  7         308  
7 7     7   4673 use Data::Util qw(is_array_ref is_hash_ref);
  7         6068  
  7         14948  
8              
9             our $VERSION = '0.06';
10              
11             sub new {
12 6     6 1 110 my $class = shift;
13 6 50       75 my %args = @_ == 1 ? %{$_[0]} : @_;
  0         0  
14 6         36 bless \%args, $class;
15             }
16              
17             sub resolver {
18 55     55 0 126 my ($self, $strategy) = @_;
19              
20 55         109 my $pkg = $strategy;
21 55 50       312 $pkg = $pkg =~ s/^\+// ? $pkg : "Data::RuledCluster::Strategy::$pkg";
22 55         202 Class::Load::load_class($pkg);
23 55         4756 $pkg;
24             }
25              
26             sub config {
27 9     9 1 15462 my ($self, $config) = @_;
28 9 100       88 $self->{config} = $config if $config;
29 9         56 $self->{config};
30             }
31              
32             sub resolve {
33 59     59 1 49391 my ($self, $cluster_or_node, $args, $options) = @_;
34              
35 59 50       197 Carp::croak("missing mandatory config.") unless $self->{config};
36              
37 59 100       151 if ($self->is_cluster($cluster_or_node)) {
    50          
38 33         109 my ($resolved_node, @keys) = $self->_delegate(resolve => $cluster_or_node, $args, $options);
39 31         209 return $self->resolve($resolved_node, \@keys);
40             }
41             elsif ($self->is_node($cluster_or_node)) {
42 26         89 return $self->_make_node_hashref($cluster_or_node);
43             }
44              
45 0         0 Carp::croak("$cluster_or_node is not defined.");
46             }
47              
48             sub resolve_node_keys {
49 22     22 1 2747 my ($self, $cluster_or_node, $keys, $args, $options) = @_;
50 22         45 my $orig_args = $args;
51              
52 22 50       113 if ( is_hash_ref $args ) {
53 0         0 $args = {%$args}; # shallow copy
54 0   0     0 $args->{strategy} ||= 'Key';
55 0         0 $args->{key} = $keys;
56             }
57             else {
58 22         32 $args = $keys;
59             }
60              
61 22         60 my %node_keys = $self->_delegate(resolve_node_keys => $cluster_or_node, $args, $options);
62 22         132 for my $cluster_or_node (keys %node_keys) {
63 30 100       71 next if $self->is_node($cluster_or_node);
64 7 50       14 if ($self->is_cluster($cluster_or_node)) {
65 7         10 my $cluster = $cluster_or_node;
66 7         8 my @key_info = @{ delete $node_keys{$cluster_or_node} };
  7         23  
67 7         19 for my $key_info (@key_info) {
68 16         57 my %child_node_keys = $self->resolve_node_keys($cluster, $key_info->{next}, $orig_args, $options);
69 16         34 for my $node (keys %child_node_keys) {
70 16   100     15 push @{ $node_keys{$node} ||= [] } => $key_info->{root};
  16         103  
71             }
72             }
73 7         26 next;
74             }
75              
76 0         0 Carp::croak("$cluster_or_node is not defined.");
77             }
78 22 100       108 return wantarray ? %node_keys : \%node_keys;
79             }
80              
81             sub _delegate {
82 55     55   110 my ($self, $method, $cluster, $args, $options) = @_;
83              
84 55 50       167 Carp::croak("missing mandatory config.") unless $self->{config};
85              
86 55 50       196 if ( is_hash_ref($args) ) {
87 0 0       0 Carp::croak("args has not 'strategy' field") unless $args->{strategy};
88 0         0 return $self->resolver($args->{strategy})->$method(
89             $self,
90             $cluster,
91             $args,
92             $options,
93             );
94             }
95              
96 55         151 my $cluster_info = $self->cluster_info($cluster);
97 55 100       245 if (is_array_ref($cluster_info)) {
    50          
98 18         62 return $self->resolver('Key')->$method(
99             $self,
100             $cluster,
101             +{ key => $args, },
102             $options,
103             );
104             }
105             elsif (is_hash_ref($cluster_info)) {
106 37         119 return $self->resolver($cluster_info->{strategy})->$method(
107             $self,
108             $cluster,
109             +{ %$cluster_info, key => $args, },
110             $options,
111             );
112             }
113              
114 0         0 Carp::croak('$cluster_info is invalid.');
115             }
116              
117             sub _make_node_hashref {
118 26     26   47 my ($self, $node) = @_;
119             return {
120             node => $node,
121 26         310 node_info => $self->{config}->{node}->{$node},
122             };
123             }
124              
125             sub cluster_info {
126 84     84 1 135 my ($self, $cluster) = @_;
127 84         205 $self->{config}->{clusters}->{$cluster};
128             }
129              
130             sub clusters {
131 29     29 1 11325 my ($self, $cluster) = @_;
132 29         64 my $cluster_info = $self->cluster_info($cluster);
133 29 100       139 my @nodes = is_array_ref($cluster_info) ? @$cluster_info : @{ $cluster_info->{nodes} };
  7         17  
134 29 100       145 wantarray ? @nodes : \@nodes;
135             }
136              
137             sub is_cluster {
138 114     114 1 167 my ($self, $cluster) = @_;
139 114 100       578 exists $self->{config}->{clusters}->{$cluster} ? 1 : 0;
140             }
141              
142             sub is_node {
143 60     60 1 107 my ($self, $node) = @_;
144 60 100       293 exists $self->{config}->{node}->{$node} ? 1 : 0;
145             }
146              
147             1;
148             __END__