File Coverage

blib/lib/KiokuDB/Backend/Serialize/JSPON/Expander.pm
Criterion Covered Total %
statement 83 86 96.5
branch 48 70 68.5
condition 10 12 83.3
subroutine 10 10 100.0
pod 1 1 100.0
total 152 179 84.9


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             package KiokuDB::Backend::Serialize::JSPON::Expander;
4 6     6   34 use Moose;
  6         9  
  6         37  
5              
6 6     6   29980 use Carp qw(croak);
  6         18  
  6         374  
7 6     6   29 use Scalar::Util qw(weaken);
  6         10  
  6         282  
8              
9 6     6   795 use KiokuDB::Entry;
  6         12  
  6         205  
10 6     6   975 use KiokuDB::Reference;
  6         14  
  6         211  
11              
12 6     6   37 use namespace::clean -except => 'meta';
  6         10  
  6         47  
13              
14             with qw(KiokuDB::Backend::Serialize::JSPON::Converter);
15              
16             sub expand_jspon {
17 1754     1754 1 16853 my ( $self, $data, @attrs ) = @_;
18              
19 1754         61295 return $self->_expander->($data, @attrs);
20             }
21              
22             has _expander => (
23             isa => "CodeRef",
24             is => "ro",
25             lazy_build => 1,
26             );
27              
28             sub _build__expander {
29 19     19   37 my $self = shift;
30              
31 19         26 my $expander;
32              
33             my (
34 190         236 $ref_field, $id_field, $data_field,
35             $class_field, $tied_field, $root_field,
36             $deleted_field, $class_meta_field, $class_version_field,
37             $backend_data_field
38             )
39 19         55 = map { my $m = $_ . "_field"; $self->$m() }
  190         6092  
40             qw(ref id data class tied root deleted class_meta class_version backend_data);
41              
42 19 100       628 unless ( $self->inline_data ) {
43 18         169 my $data_field_re = qr/\. \Q$data_field\E $/x;
44              
45             $expander = sub {
46 9686     9686   10358 my ( $data, @attrs ) = @_;
47              
48 9686 100       16349 if ( my $ref = ref($data) ) {
49 9638 100       16421 if ( $ref eq 'HASH' ) {
    50          
50 5028 100 100     21232 if ( my $id = $data->{$ref_field} ) {
    100 100        
51 1476         8089 $id =~ s/$data_field_re//;
52 1476 100       44637 return KiokuDB::Reference->new( id => $id, ( $data->{weak} ? ( is_weak => 1 ) : () ) );
53             } elsif ( exists $data->{$class_field}
54             or exists $data->{$id_field}
55             or exists $data->{$tied_field}
56             ) {
57 1808 100       3776 if ( exists $data->{$class_field} ) {
58             # check the class more thoroughly here ...
59 1748         4846 my ($class, $version, $authority) = (split '-' => $data->{$class_field});
60 1748         2898 push @attrs, class => $class;
61              
62 1748 100       3201 push @attrs, class_meta => $data->{$class_meta_field} if exists $data->{$class_meta_field};
63 1748 100       4382 push @attrs, class_version => $data->{$class_version_field} if exists $data->{$class_version_field};
64             }
65              
66 1808 100       4501 push @attrs, id => $data->{$id_field} if exists $data->{$id_field};
67 1808 100       3219 push @attrs, tied => substr($data->{$tied_field}, 0, 1) if exists $data->{$tied_field};
68 1808 50       32221 push @attrs, root => $data->{$root_field} ? 1 : 0 if exists $data->{$root_field};
    100          
69 1808 0       9220 push @attrs, deleted => $data->{$deleted_field} ? 1 : 0 if exists $data->{$deleted_field};
    50          
70 1808 50       3700 push @attrs, backend_data => $data->{$backend_data_field} if exists $data->{$backend_data_field};
71              
72 1808         3776 push @attrs, data => $expander->( $data->{$data_field} );
73              
74 1808         51586 return KiokuDB::Entry->new( @attrs );
75             } else {
76 1744         1788 my %hash;
77              
78 1744         5585 foreach my $key ( keys %$data ) {
79 7619         6548 my $unescaped = $key;
80 7619         6446 $unescaped =~ s/^public:://;
81              
82 7619         7194 my $value = $data->{$key};
83 7619 100       15054 $hash{$unescaped} = ref($value) ? $expander->($value) : $value;
84             }
85              
86 1744         4581 return \%hash;
87             }
88             } elsif ( ref $data eq 'ARRAY' ) {
89 4610 100       11358 return [ map { ref($_) ? $expander->($_) : $_ } @$data ];
  1294         4079  
90             }
91             }
92              
93 48         99 return $data;
94             }
95 18         173 } else {
96             $expander = sub {
97 4     4   6 my ( $data, @attrs ) = @_;
98              
99 4 50       9 if ( my $ref = ref($data) ) {
100 4 50       6 if ( $ref eq 'HASH' ) {
    0          
101              
102 4 100 66     24 if ( my $id = $data->{$ref_field} ) {
    100 66        
103 1 50       33 return KiokuDB::Reference->new( id => $id, ( $data->{weak} ? ( is_weak => 1 ) : () ) );
104             } elsif ( exists $data->{$class_field}
105             or exists $data->{$id_field}
106             or exists $data->{$tied_field}
107             ) {
108 1         6 my %copy = %$data;
109              
110 1 50       5 if ( exists $copy{$class_field} ) {
111             # check the class more thoroughly here ...
112 1         4 my ($class, $version, $authority) = (split '-' => delete $copy{$class_field});
113 1         3 push @attrs, class => $class;
114              
115 1 50       5 push @attrs, class_meta => delete $copy{$class_meta_field} if exists $copy{$class_meta_field};
116             }
117              
118 1 50       5 push @attrs, id => delete $copy{$id_field} if exists $copy{$id_field};
119 1 50       7 push @attrs, tied => delete $copy{$tied_field} if exists $copy{$tied_field};
120 1 50       7 push @attrs, root => delete $copy{$root_field} ? 1 : 0 if exists $copy{$root_field};
    50          
121 1 0       8 push @attrs, deleted => delete $copy{$deleted_field} ? 1 : 0 if exists $copy{$deleted_field};
    50          
122              
123 1         6 push @attrs, data => $expander->( \%copy );
124              
125 1         29 return KiokuDB::Entry->new( @attrs );
126             } else {
127 2         1 my %hash;
128              
129 2         5 foreach my $key ( keys %$data ) {
130 5         5 my $unescaped = $key;
131 5         9 $unescaped =~ s/^public:://;
132              
133 5         4 my $value = $data->{$key};
134 5 100       16 $hash{$unescaped} = ref($value) ? $expander->($value) : $value;
135             }
136              
137 2         6 return \%hash;
138             }
139             } elsif ( ref $data eq 'ARRAY' ) {
140 0 0       0 return [ map { ref($_) ? $expander->($_) : $_ } @$data ];
  0         0  
141             }
142             }
143              
144 0         0 return $data;
145             }
146 1         10 }
147              
148 19         32 my $copy = $expander;
149 19         54 weaken($expander);
150              
151 19         619 return $copy;
152             }
153              
154             __PACKAGE__->meta->make_immutable;
155              
156             __PACKAGE__
157              
158             __END__
159              
160             =pod
161              
162             =head1 NAME
163              
164             KiokuDB::Backend::Serialize::JSPON::Expander - Inflate JSPON to entry
165             data.
166              
167             =head1 SYNOPSIS
168              
169             my $c = KiokuDB::Backend::Serialize::JSPON::Expander->new(
170             id_field => "_id",
171             );
172              
173             my $entry = $c->collapse_jspon($hashref);
174              
175             =head1 DESCRIPTION
176              
177             This object is used by L<KiokuDB::Backend::Serialize::JSPON> to expand JSPON
178             compliant hash references to L<KiokuDB::Entry> objects.
179              
180             =head1 ATTRIBUTES
181              
182             See L<KiokuDB::Backend::Serialize::JSPON::Converter> for attributes shared by
183             L<KiokuDB::Backend::Serialize::JSPON::Collapser> and
184             L<KiokuDB::Backend::Serialize::JSPON::Expander>.
185              
186             =head1 METHODS
187              
188             =over 4
189              
190             =item expand_jspon $hashref
191              
192             Recursively inlates the hash reference, returning a L<KiokuDB::Entry> object.
193              
194             =back