File Coverage

blib/lib/JIP/DataPath.pm
Criterion Covered Total %
statement 88 92 95.6
branch 34 40 85.0
condition 21 41 51.2
subroutine 17 17 100.0
pod 10 10 100.0
total 170 200 85.0


line stmt bran cond sub pod time code
1             package JIP::DataPath;
2              
3 1     1   78214 use strict;
  1         2  
  1         29  
4 1     1   5 use warnings;
  1         2  
  1         27  
5              
6 1     1   5 use Carp qw(croak);
  1         4  
  1         60  
7 1     1   7 use Exporter qw(import);
  1         2  
  1         34  
8 1     1   6 use English qw(-no_match_vars);
  1         1  
  1         5  
9              
10             our $VERSION = '0.043';
11              
12             our @EXPORT_OK = qw(path);
13              
14             sub path {
15 4     4 1 3013 my ($document) = @ARG;
16              
17 4         11 return __PACKAGE__->new( document => $document );
18             }
19              
20             sub default_value {
21 13     13 1 61 return __PACKAGE__ . '::default_value';
22             }
23              
24             sub is_default_value {
25 9     9 1 4611 my ( $self, $value ) = @ARG;
26              
27 9 100       27 return 0 if !defined $value;
28 8 100       29 return 0 if ref $value;
29 4 100       9 return 0 if $value ne $self->default_value();
30              
31 1         4 return 1;
32             }
33              
34             sub document {
35 67     67 1 7565 my ($self) = @ARG;
36              
37 67         223 return $self->{document};
38             }
39              
40             sub new {
41 21     21 1 63267 my ( $class, %param ) = @ARG;
42              
43             # Mandatory params
44 21 100       61 if ( !exists $param{document} ) {
45 1         192 croak 'Mandatory argument "document" is missing';
46             }
47              
48             return bless(
49             {
50             document => $param{document},
51             },
52 20         92 $class,
53             );
54             }
55              
56             sub get {
57 27     27 1 932 my ( $self, $path_parts, $default_value ) = @ARG;
58              
59 27 100       38 if ( @{$path_parts} == 0 ) {
  27         75  
60 7         14 return $self->document();
61             }
62              
63 20         58 my ( $contains, $context ) = $self->_accessor($path_parts);
64              
65 20 100       72 return $default_value if !$contains;
66              
67 10   50     25 my $last_part = $path_parts->[-1] // q{};
68 10   50     28 my $type = ref $context // q{};
69              
70 10 100 66     54 if ( $type eq 'HASH' && length $last_part ) {
    50 33        
71 8         42 return $context->{$last_part};
72             }
73             elsif ( $type eq 'ARRAY' && $last_part =~ m{^\d+$}x ) {
74 2         11 return $context->[$last_part];
75             }
76              
77 0         0 return $default_value;
78             } ## end sub get
79              
80             sub get_new {
81 5     5 1 20 my ( $self, $path_parts, $default_value ) = @ARG;
82              
83 5 100       7 if ( @{$path_parts} == 0 ) {
  5         15  
84 2         6 return path( $self->document() );
85             }
86              
87 3         8 my ( $contains, $context ) = $self->_accessor($path_parts);
88              
89 3 100       17 return $default_value if !$contains;
90              
91 1   50     5 my $last_part = $path_parts->[-1] // q{};
92 1   50     4 my $type = ref $context // q{};
93              
94 1 50 33     7 if ( $type eq 'HASH' && length $last_part ) {
    0 0        
95 1         4 return path( $context->{$last_part} );
96             }
97             elsif ( $type eq 'ARRAY' && $last_part =~ m{^\d+$}x ) {
98 0         0 return path( $context->[$last_part] );
99             }
100              
101 0         0 return $default_value;
102             } ## end sub get_new
103              
104             sub contains {
105 9     9 1 37 my ( $self, @xargs ) = @ARG;
106              
107 9         20 my ($contains) = $self->_accessor(@xargs);
108              
109 9         48 return $contains;
110             }
111              
112             sub set {
113 9     9 1 3282 my ( $self, $path_parts, $value ) = @ARG;
114              
115 9 100       10 if ( @{$path_parts} == 0 ) {
  9         29  
116 4         12 $self->_set_document($value);
117 4         15 return 1;
118             }
119              
120 5         12 my ( $contains, $context ) = $self->_accessor($path_parts);
121              
122 5 50       13 return 0 if !$contains;
123              
124 5   50     15 my $last_part = $path_parts->[-1] // q{};
125 5   50     14 my $type = ref $context // q{};
126              
127 5 100 66     30 if ( $type eq 'HASH' && length $last_part ) {
    50 33        
128 4         7 $context->{$last_part} = $value;
129 4         18 return 1;
130             }
131             elsif ( $type eq 'ARRAY' && $last_part =~ m{^\d+$}x ) {
132 1         5 $context->[$last_part] = $value;
133 1         4 return 1;
134             }
135              
136 0         0 return 0;
137             } ## end sub set
138              
139             sub perform {
140 5     5 1 8335 my ( $self, $method, $path_parts, @xargs ) = @ARG;
141              
142 5         30 return $self->$method( $path_parts, @xargs );
143             }
144              
145             sub _set_document {
146 4     4   9 my ( $self, $document ) = @ARG;
147              
148 4         5 $self->{document} = $document;
149              
150 4         8 return;
151             }
152              
153             sub _accessor {
154 46     46   8883 my ( $self, $path_parts ) = @ARG;
155              
156 46         117 my $context = $self->document();
157 46         68 my $last_index = $#{$path_parts};
  46         113  
158              
159 46         114 foreach my $part_index ( 0 .. $last_index ) {
160 80         116 my $part = $path_parts->[$part_index];
161 80   50     177 my $type = ref $context // q{};
162 80         121 my $last = $part_index == $last_index;
163              
164 80 100 100     358 if ( $type eq 'HASH' && exists $context->{$part} ) {
    100 66        
      66        
165 49 100       129 return ( 1, $context ) if $last;
166              
167 29         53 $context = $context->{$part};
168             }
169 15         49 elsif ( $type eq 'ARRAY' && $part =~ m{^\d+$}x && @{$context} > $part ) {
170 15 100       44 return ( 1, $context ) if $last;
171              
172 8         17 $context = $context->[$part];
173             }
174             else {
175 16         48 return ( 0, undef );
176             }
177             }
178              
179 3         8 return ( 1, $context );
180             } ## end sub _accessor
181              
182             1;
183              
184             __END__