File Coverage

blib/lib/Clustericious/Client/Object.pm
Criterion Covered Total %
statement 46 46 100.0
branch 16 20 80.0
condition 8 12 66.6
subroutine 9 9 100.0
pod 1 1 100.0
total 80 88 90.9


line stmt bran cond sub pod time code
1             package Clustericious::Client::Object;
2              
3 31     31   134677 use strict;
  31         88  
  31         845  
4 31     31   160 use warnings;
  31         63  
  31         3629  
5              
6             # ABSTRACT: default object returned from client methods
7             our $VERSION = '1.27'; # VERSION
8              
9              
10             sub new
11             {
12 19     19 1 2039 my $class = shift;
13 19         45 my ($self, $client) = @_;
14              
15 19 50       57 return $self unless ref $self;
16              
17 19 100       56 if (ref $self eq 'ARRAY')
18             {
19 5         13 foreach (@$self)
20             {
21 11 100       36 $_ = $class->new($_, $client) if ref eq 'HASH';
22             }
23 5         35 return $self;
24             }
25              
26 31     31   206 while (my ($attr, $type) = do { no strict 'refs'; each %{"${class}::classes"} })
  31         76  
  31         10413  
  14         23  
  16         23  
  16         110  
27             {
28 2         107 eval "require $type";
29              
30 2 50       15 if (exists $self->{$attr})
31             {
32 2         16 $self->{$attr} = $type->new($self->{$attr}, $client)
33             }
34             }
35              
36 14         28 bless $self, $class;
37              
38 14         49 $self->_client($client);
39              
40 14         52 return $self;
41             }
42              
43             {
44             my %clientcache;
45              
46              
47             sub _client
48             {
49 15     15   25 my $self = shift;
50 15         26 my ($client) = @_;
51            
52 15 100       66 $client ? ($clientcache{$self} = $client) : $clientcache{$self};
53             }
54              
55             sub DESTROY
56             {
57 14     14   3093 delete $clientcache{shift};
58             }
59             }
60              
61             sub AUTOLOAD
62             {
63 8     8   2234 my $self = shift;
64              
65 8         76 my ($class, $called) = our $AUTOLOAD =~ /^(.+)::([^:]+)$/;
66              
67             my $sub = sub
68             {
69 14     14   303 my $self = shift;
70 14         46 my ($value) = @_;
71              
72 14 100       38 $self->{$called} = $value if defined $value; # Can't set undef
73            
74 14         40 $value = $self->{$called};
75              
76 14 100 100     71 if (ref $value eq 'HASH' or ref $value eq 'ARRAY')
77             {
78 4         12 $value = __PACKAGE__->new($value);
79             }
80              
81 14 50 66     114 return wantarray && !defined($value) ? ()
    100 66        
    50 33        
82             : wantarray && (ref $value eq 'ARRAY') ? @$value
83             : wantarray && (ref $value) ? %$value
84             : $value;
85 8         38 };
86              
87 31     31   221 do { no strict 'refs'; *{ "${class}::$called" } = $sub };
  31         68  
  31         2164  
  8         15  
  8         11  
  8         33  
88              
89 8         30 $self->$called(@_);
90             }
91              
92             1;
93              
94             __END__
95              
96             =pod
97              
98             =encoding UTF-8
99              
100             =head1 NAME
101              
102             Clustericious::Client::Object - default object returned from client methods
103              
104             =head1 VERSION
105              
106             version 1.27
107              
108             =head1 SYNOPSIS
109              
110             my $obj = Clustericious::Client::Object->new({some => 'stuff'});
111              
112             $obj->some; # 'stuff'
113             $obj->some('foo'); # Set to 'foo'
114              
115             #----------------------------------------------------------------------
116              
117             package Foo::Object;
118              
119             use base 'Clustericious::Client::Object';
120              
121             sub meth { ... };
122              
123             #----------------------------------------------------------------------
124              
125             package Foo::OtherObject;
126              
127             use base 'Clustericious::Client::Object';
128              
129             our %classes =
130             (
131             myobj => 'Foo::Object'
132             );
133              
134             #----------------------------------------------------------------------
135              
136             my $obj = Foo::Client::OtherObj({ myobj => { my => 'foo' },
137             some => 'stuff' });
138              
139             $obj->myobj->meth();
140             $obj->myobj->my; # 'foo'
141             $obj->some; # 'stuff'
142              
143             =head1 DESCRIPTION
144              
145             The Clustericious::Client derived methods receive a possibly
146             nested/complex data structure with their results. This Object helps
147             turn those data structures into simple (or possibly more complex)
148             objects.
149              
150             By default, it just makes a method for each attribute in the returned
151             data structure. It does this lazily through AUTOLOAD, so it won't
152             make them unless you are using them. If used as a base class, you can
153             override new() to do more initialization (possibly using the client to
154             download more information), or add other methods to the object as
155             needed.
156              
157             A %classes hash can also be included in a derived class specifying
158             classes to use for certain attributes.
159              
160             Each Clustericious::Client::Object derived object can also call
161             $obj->_client to get the original client if it was stored with new()
162             (L<Clustericious::Client> does this). This can be used by derived
163             object methods to further interact with the REST server.
164              
165             =head1 METHODS
166              
167             =head2 new
168              
169             my $obj = Clustericious::Client::Object->new({ some => 'stuff'});
170              
171             my $obj = Clustericious::Client::Object->new([ { some => 'stuff' } ]);
172              
173             Makes a hash into an object (or an array of hashes into an array of
174             objects).
175              
176             You can access or update elements of the hash using method calls:
177             my $x = $obj->some;
178             $obj->some('foo');
179              
180             In the array case, you can do my $x = $obj->[0]->some;
181              
182             If a derived class has a %classes package variable, new() will
183             automatically call the right new() for each specified attribute. (See
184             synopsis and examples).
185              
186             You can also include an optional 'client' parameter:
187              
188             my $obj = Clustericious::Client::Object->new({ ...}, $client);
189              
190             that can be retrieved with $obj->_client(). This is useful for
191             derived objects methods which need to access the Clustericious server.
192              
193             =head2 _client
194              
195             my $obj->_client->do_something();
196              
197             Access the stashed client. This is useful within derived class
198             methods that need to interact with the server.
199              
200             =head1 SEE ALSO
201              
202             These are also interesting:
203              
204             =over 4
205              
206             =item L<Data::AsObject>
207              
208             =item L<Data::Autowrap>
209              
210             =item L<Hash::AsObject>
211              
212             =item L<Class::Builtin::Hash>
213              
214             =item L<Hash::AutoHash>
215              
216             =item L<Hash::Inflator>
217              
218             =item L<Data::OpenStruct::Deep>
219              
220             =item L<Object::AutoAccessor>
221              
222             =item L<Mojo::Base>
223              
224             =item L<Clustericious::Config>
225              
226             =back
227              
228             =head1 AUTHOR
229              
230             Original author: Brian Duggan
231              
232             Current maintainer: Graham Ollis E<lt>plicease@cpan.orgE<gt>
233              
234             Contributors:
235              
236             Curt Tilmes
237              
238             Yanick Champoux
239              
240             =head1 COPYRIGHT AND LICENSE
241              
242             This software is copyright (c) 2013 by NASA GSFC.
243              
244             This is free software; you can redistribute it and/or modify it under
245             the same terms as the Perl 5 programming language system itself.
246              
247             =cut