File Coverage

lib/File/DataClass/Schema.pm
Criterion Covered Total %
statement 101 101 100.0
branch 17 18 94.4
condition 16 22 77.2
subroutine 28 28 100.0
pod 6 6 100.0
total 168 175 96.5


line stmt bran cond sub pod time code
1             package File::DataClass::Schema;
2              
3 3     3   10591 use namespace::autoclean;
  3         4  
  3         24  
4              
5 3     3   1391 use Class::Null;
  3         871  
  3         61  
6 3     3   1017 use File::DataClass::Cache;
  3         8  
  3         89  
7 3     3   16 use File::DataClass::Constants qw( EXCEPTION_CLASS FALSE NUL PERMS TRUE );
  3         5  
  3         190  
8 3         170 use File::DataClass::Functions qw( ensure_class_loaded first_char
9             qualify_storage_class map_extension2class
10             merge_attributes supported_extensions
11 3     3   12 throw );
  3         3  
12 3     3   12 use File::DataClass::IO;
  3         3  
  3         23  
13 3     3   1518 use File::DataClass::ResultSource;
  3         6  
  3         113  
14 3     3   1660 use File::DataClass::Storage;
  3         6  
  3         141  
15 3         19 use File::DataClass::Types qw( Bool Cache ClassName Directory DummyClass
16 3     3   19 HashRef Lock Num Object Path Str );
  3         4  
17 3     3   3228 use File::Spec;
  3         4  
  3         70  
18 3     3   10 use Scalar::Util qw( blessed );
  3         5  
  3         162  
19 3     3   50 use Unexpected::Functions qw( Unspecified );
  3         5  
  3         13  
20 3     3   622 use Moo;
  3         3  
  3         13  
21              
22             my $_cache_objects = {};
23              
24             # Private methods
25             my $_build_cache = sub {
26 16     16   2710 my $self = shift;
27             my $attr = { builder => $self,
28 16         35 cache_attributes => { %{ $self->cache_attributes } }, };
  16         112  
29 16         36 my $cattr = $attr->{cache_attributes};
30 16         74 (my $ns = lc __PACKAGE__) =~ s{ :: }{-}gmx;
31              
32 16   66     77 $ns = $cattr->{namespace} //= $ns;
33 16 100       231 exists $_cache_objects->{ $ns } and return $_cache_objects->{ $ns };
34 4 100       27 $self->cache_class eq 'none' and return Class::Null->new;
35 3   66     22 $cattr->{share_file} //= $self->tempdir->catfile( "${ns}.dat" )->pathname;
36              
37 3         57 return $_cache_objects->{ $ns } = $self->cache_class->new( $attr );
38             };
39              
40             my $_build_source_registrations = sub {
41 7     7   1662 my $self = shift; my $sources = {};
  7         13  
42              
43 7         11 for my $moniker (keys %{ $self->result_source_attributes }) {
  7         41  
44 6         9 my $attr = { %{ $self->result_source_attributes->{ $moniker } } };
  6         27  
45             my $class = delete $attr->{result_source_class}
46 6   66     43 // $self->result_source_class;
47              
48 6         12 $attr->{name} = $moniker; $attr->{schema} = $self;
  6         12  
49              
50 6         70 $sources->{ $moniker } = $class->new( $attr );
51             }
52              
53 7         267 return $sources;
54             };
55              
56             my $_build_storage = sub {
57 17     17   5258 my $self = shift; my $class = $self->storage_class;
  17         210  
58              
59 17 100       2153 if (first_char $class eq '+') { $class = substr $class, 1 }
  2         6  
60 15         47 else { $class = qualify_storage_class $class }
61              
62 17         61 ensure_class_loaded $class;
63              
64 17         477 return $class->new( { %{ $self->storage_attributes }, schema => $self } );
  17         292  
65             };
66              
67             my $_constructor = sub {
68             my $class = shift;
69             my $attr = { cache_class => 'none', storage_class => 'Any' };
70              
71             return $class->new( $attr );
72             };
73              
74             # Private attributes
75             has 'cache' => is => 'lazy', isa => Cache,
76             builder => $_build_cache;
77              
78             has 'cache_attributes' => is => 'ro', isa => HashRef,
79             builder => sub { {
80 17     17   396 page_size => 131_072,
81             num_pages => 89,
82             unlink_on_exit => TRUE, } };
83              
84             has 'cache_class' => is => 'ro', isa => ClassName | DummyClass,
85             default => 'File::DataClass::Cache';
86              
87             has 'lock' => is => 'lazy', isa => Lock,
88 16     16   3629 builder => sub { Class::Null->new };
89              
90             has 'log' => is => 'lazy', isa => Object,
91 14     14   2287 builder => sub { Class::Null->new };
92              
93             has 'path' => is => 'rw', isa => Path, coerce => TRUE;
94              
95             has 'perms' => is => 'rw', isa => Num, default => PERMS;
96              
97             has 'result_source_attributes' => is => 'ro', isa => HashRef,
98 8     8   437 builder => sub { {} };
99              
100             has 'result_source_class' => is => 'ro', isa => ClassName,
101             default => 'File::DataClass::ResultSource';
102              
103             has 'source_registrations' => is => 'lazy', isa => HashRef[Object],
104             builder => $_build_source_registrations;
105              
106             has 'storage' => is => 'rw', isa => Object,
107             builder => $_build_storage, lazy => TRUE;
108              
109             has 'storage_attributes' => is => 'ro', isa => HashRef,
110 15     15   1151 builder => sub { {} };
111              
112             has 'storage_class' => is => 'rw', isa => Str,
113             default => 'JSON', lazy => TRUE;
114              
115             has 'tempdir' => is => 'ro', isa => Directory,
116 5     5   396 coerce => TRUE, builder => sub { File::Spec->tmpdir };
117              
118             # Construction
119             around 'BUILDARGS' => sub {
120             my ($orig, $self, @args) = @_; my $attr = $orig->( $self, @args );
121              
122             my $builder = $attr->{builder} or return $attr;
123             my $config = $builder->can( 'config' ) ? $builder->config : {};
124             my $keys = [ qw( cache_attributes cache_class lock log tempdir ) ];
125              
126             merge_attributes $attr, $builder, $keys;
127             merge_attributes $attr, $config, $keys;
128              
129             return $attr;
130             };
131              
132             # Public methods
133             sub dump {
134 8 50   8 1 178 my ($self, $args) = @_; blessed $self or $self = $self->$_constructor;
  8         34  
135              
136 8 100 66     71 my $path = $args->{path} // $self->path; blessed $path or $path = io $path;
  8         63  
137              
138 8         123 return $self->storage->dump( $path, $args->{data} );
139             }
140              
141             sub load {
142 13 100   13 1 4705 my ($self, @paths) = @_; blessed $self or $self = $self->$_constructor;
  13         83  
143              
144 13   66     150 $paths[ 0 ] //= $self->path;
145              
146 13 100       251 return $self->storage->load( map { (blessed $_) ? $_ : io $_ } @paths );
  15         640  
147             }
148              
149             sub resultset {
150 22     22 1 12176 my ($self, $moniker) = @_; return $self->source( $moniker )->resultset;
  22         64  
151             }
152              
153             sub source {
154 22     22 1 31 my ($self, $moniker) = @_;
155              
156 22 100       65 $moniker or throw Unspecified, [ 'result source' ];
157              
158 21 100       366 my $source = $self->source_registrations->{ $moniker }
159             or throw 'Result source [_1] unknown', [ $moniker ];
160              
161 20         278 return $source;
162             }
163              
164             sub sources {
165 1     1 1 21 return keys %{ shift->source_registrations };
  1         16  
166             }
167              
168             sub translate {
169 2     2 1 1404 my ($self, $args) = @_;
170              
171 2   66     12 my $class = blessed $self || $self; # uncoverable condition false
172 2   100     8 my $from_class = $args->{from_class} // 'Any';
173 2   100     7 my $to_class = $args->{to_class } // 'Any';
174 2         6 my $attr = { path => $args->{from}, storage_class => $from_class };
175 2         40 my $data = $class->new( $attr )->load;
176              
177 2         37 $attr = { path => $args->{to}, storage_class => $to_class };
178 2         63 $class->new( $attr )->dump( { data => $data } );
179 2         36 return;
180             }
181              
182             1;
183              
184             __END__