File Coverage

blib/lib/Persevere/Client/Class.pm
Criterion Covered Total %
statement 12 174 6.9
branch 0 60 0.0
condition 0 9 0.0
subroutine 4 21 19.0
pod 9 17 52.9
total 25 281 8.9


line stmt bran cond sub pod time code
1             package Persevere::Client::Class;
2              
3 1     1   6 use strict;
  1         2  
  1         49  
4 1     1   7 use warnings;
  1         2  
  1         95  
5              
6             =head1 NAME
7              
8             Persevere::Client::Class - The Class interface to Persevere the JSON Database
9              
10             =cut
11              
12             our $VERSION = '0.31';
13              
14 1     1   3282 use HTTP::Request::Common qw(GET HEAD POST PUT DELETE);
  1         3069  
  1         127  
15 1     1   12 use Carp qw(confess);
  1         3  
  1         3007  
16              
17             sub new{
18 0     0 1   my $class = shift;
19 0 0         my %opt = @_ == 1 ? %{$_[0]} : @_;
  0            
20 0           my %self;
21              
22 0   0       $self{name} = $opt{name} || confess "Persevere Class requires a name.";
23 0 0         $self{name} .= '/' unless $self{name} =~ m{/$};
24 0   0       $self{client} = $opt{client} || confess "Persevere requires a client.";
25 0           return bless \%self, $class;
26             }
27              
28             sub fullname {
29 0     0 1   my $self = shift;
30 0           my $name = $self->{name};
31 0           $name =~ s/\/$//g;
32 0           return $name;
33             }
34              
35             sub exists {
36 0     0 1   my $self = shift;
37 0           my $name = $self->fullname;
38 0 0         if ($self->{client}->classExists($self->fullname)){
39 0           return 1;
40             }else{
41 0           return 0;
42             }
43             }
44              
45             sub properties{
46 0     0 0   my $self = shift;
47 0           my %args = @_;
48             # TODO This should do some error checking
49 0           $self->{properties} = \%args;
50 0           return $self;
51             }
52              
53             sub sourceClass{
54 0     0 0   my $self = shift;
55 0           my $sourceClass = shift;
56 0           $self->{sourceClass} = $sourceClass;
57 0           return $self;
58             }
59              
60             sub uuid{
61 0     0 0   my $self = shift;
62 0           $self->{uuid} = 1;
63 0           return $self;
64             }
65              
66             sub nouuid{
67 0     0 0   my $self = shift;
68 0           $self->{uuid} = 0;
69 0           return $self;
70             }
71              
72             sub create {
73 0     0 1   my $self = shift;
74 0           my $classpath = $self->{client}->{uri} . "Class/";
75 0 0         if ($self->fullname !~ /\w|\d/){
76 0           $self->{client}->alert("No Name defined for class, Can't create it");
77 0           my $failed = {
78             success => 0
79             };
80 0           return $failed;
81             }
82 0 0         if (!($self->{client}->classExists($self->fullname))){
83 0           my (%newclass, %extends);
84 0           $extends{'$ref'} = "Object";
85 0           $newclass{id} = $self->fullname;
86 0           $newclass{extends} = \%extends;
87 0 0         if ($self->{uuid}){
88 0           $newclass{useUUIDs} = $self->{client}->{json}->true;
89             }
90 0 0         if (defined $self->{properties}){
91 0           $newclass{properties} = \%{$self->{properties}};
  0            
92             }
93 0 0 0       if ((defined $self->{client}->{defaultSourceClass}) && (!(defined $self->{sourceClass}))){
94             # if a default sourceClass is defined, and we didn't explicitly define a source class
95 0           $self->{sourceClass} = $self->{client}->{defaultSourceClass};
96             }
97 0 0         if (defined $self->{sourceClass}){
98 0           $newclass{sourceClass} = $self->{sourceClass};
99             }
100 0 0         if ($self->{client}->{debug}){
101 0           print "DEBUG (FUNCTION create): POST $classpath " . $self->{client}->{json}->encode(\%newclass) . "\n";
102             }
103 0           my $req = $self->{client}->req('POST', $classpath, undef, \%newclass);
104 0           $req->{path} = $classpath;
105 0           return $req;
106             }else{
107 0 0         if ($self->{exist_is_error}){
108 0           $self->{client}->alert("Class " . $self->fullname . " Already Exists");
109             }
110 0           return $self;
111             }
112             }
113              
114             sub createObjects{
115 0     0 1   my $self = shift;
116 0           my $data = shift;
117 0           my $classpath = $self->{client}->{uri} . $self->{name};
118 0 0         if ($self->{client}->{debug}){
119 0           print "DEBUG (FUNCTION createObjects): POST $classpath " . $self->{client}->{json}->encode(\@{$data}) . "\n";
  0            
120 0           }my $req = $self->{client}->req('POST', $classpath, undef, $data);
121 0 0         if (!($req->{success})){
122 0           $self->{client}->alert($req->{content});
123             }
124            
125 0           $req->{path} = $classpath;
126 0           return $req;
127             }
128              
129             sub updateObjects{
130 0     0 1   my $self = shift;
131 0           my $data = shift;
132 0           my $classpath = $self->{client}->{uri} . $self->{name};
133 0 0         if ($self->{client}->{debug}){
134 0           print "DEBUG (FUNCTION updateObjects): PUT $classpath " . $self->{client}->{json}->encode(\@{$data}) . "\n";
  0            
135             }
136 0           my $req = $self->{client}->req('PUT', $classpath, undef, $data);
137 0 0         if (!($req->{success})){
138 0           $self->{client}->alert($req->{content});
139             }
140            
141 0           $req->{path} = $classpath;
142 0           return $req;
143             }
144              
145             sub idGet(){
146 0     0 0   my $self = shift;
147 0           my $id = shift;
148 0           my $path = $self->{client}->{uri} . $self->{name} . $id;
149 0 0         if ($self->{client}->{debug}){
150 0           print "DEBUG (FUNCTION idGet): GET $path \n";
151             }
152 0           my $idresponse = $self->{client}->req('GET', $path, undef, undef, 1);
153 0           $idresponse->{path} = $path;
154 0           return $idresponse;
155             }
156              
157             sub propSet(){
158 0     0 0   my $self = shift;
159 0           my $id = shift;
160 0           my $data = shift;
161 0           my $path = $self->{client}->{uri} . $self->{name} . $id;
162 0 0         if ($self->{client}->{debug}){
163 0           print "DEBUG (FUNCTION propSet): PUT $path $data \n";
164             }
165 0           my $idresponse = $self->{client}->req('PUT', $path ,undef, $data, 0, 1);
166 0           $idresponse->{path} = $path;
167 0           return $idresponse;
168             }
169              
170             sub idExists(){
171 0     0 0   my $self = shift;
172 0           my $id = shift;
173 0           my $path = $self->{client}->{uri} . $self->{name} . $id;
174 0 0         if ($self->{client}->{debug}){
175 0           print "DEBUG (FUNCTION idExists): GET $path\n";
176             }
177 0           my $idresponse = $self->{client}->req('GET', $path, undef, undef, 1);
178 0 0         if ($idresponse->{code} == "404"){
179 0           return 0;
180             }else{
181 0           return 1;
182             }
183             }
184              
185             sub queryRange(){
186 0     0 1   my $self = shift;
187 0           my $query = shift;
188 0           my $sub_range_start = shift;
189 0           my $sub_range_end = shift;
190 0           my $classpath = $self->{client}->{uri} . $self->{name};
191 0           my @original_data;
192              
193 0           my $header = HTTP::Headers->new;
194 0           $header->header('Range' => "items=$sub_range_start-$sub_range_end");
195 0           my $path = "$classpath$query";
196 0 0         if ($self->{client}->{debug}){
197 0           print "DEBUG (FUNCTION queryRange): GET $path $header\n";
198             }
199 0           my $testresponse = $self->{client}->req('GET', $path, $header);
200              
201 0 0         if ($testresponse->{code} != 200){
202 0           $self->{client}->alert($testresponse->{status_line});
203             }
204 0           return $testresponse;
205             }
206              
207             sub query(){
208 0     0 1   my $self = shift;
209 0           my $query = shift;
210 0 0         if (!(defined $query)){
211 0           $query = '';
212             }
213 0           my $classpath = $self->{client}->{uri} . $self->{name};
214 0           my @original_data;
215 0           my $path = "$classpath$query";
216 0 0         if ($self->{client}->{debug}){
217 0           print "DEBUG (FUNCTION query): GET $path\n";
218             }
219 0           my $testresponse = $self->{client}->req('GET', $path);
220 0 0         if ($testresponse->{code} != 200){
221 0           $self->{client}->alert($testresponse->{status_line});
222             }
223 0           return $testresponse;
224             }
225              
226             sub delete{
227 0     0 1   my $self = shift;
228 0           my $dpath = $self->{client}->{uri} . "Class/" . $self->fullname;
229             # this should be converted to use the req wrapper
230 0 0         if ($self->{client}->{debug}){
231 0           print "DEBUG (FUNCTION delete): DELETE $dpath\n";
232             }
233 0           my $res = $self->{client}->{ua}->request(DELETE $dpath);
234 0           $res->{path} = $dpath;
235 0           my $auth_status = 1;
236 0 0         if ($res->code == 401){
237 0           $auth_status = 0;
238             }
239 0           my $ret = {
240             code => $res->code,
241             status_line => $res->status_line,
242             success => 0,
243             content => $res->content,
244             auth => $auth_status
245             };
246 0 0         if ($res->is_success){
247 0           $ret->{success} = 1;
248             }
249 0           return $ret;
250             }
251              
252             sub deleteById{
253 0     0 0   my $self = shift;
254 0           my $id = shift;
255 0           my $dpath = $self->{client}->{uri} . $self->fullname . "/$id";
256             # this should be converted to use the req wrapper
257 0 0         if ($self->{client}->{debug}){
258 0           print "DEBUG (FUNCTION delete): DELETE $dpath\n";
259             }
260 0           my $res = $self->{client}->{ua}->request(DELETE $dpath);
261 0           $res->{path} = $dpath;
262 0           my $auth_status = 1;
263 0 0         if ($res->code == 401){
264 0           $auth_status = 0;
265             }
266 0           my $ret = {
267             code => $res->code,
268             status_line => $res->status_line,
269             success => 0,
270             content => $res->content,
271             auth => $auth_status
272             };
273 0 0         if ($res->is_success){
274 0           $ret->{success} = 1;
275             }
276 0           return $ret;
277             }
278             =pod
279              
280             =head1 SYNOPSIS
281              
282             This module provides an interface to the classes in persevere
283              
284             $persvr = Persevere::Client->new(
285             host => "localhost",
286             port => "8080",
287             auth_type => "basic",
288             username => "test",
289             password => "pass"
290             );
291             %hash1 = ("name1" => "test1", "type" => "odd");
292             %hash2 = ("name2" => "test2", "type" => "even");
293             push @post_data, \%hash1;
294             push @post_data, \%hash2;
295             # createObjects and updateObjects require and array of hashes
296             $postreq = $initialclass->createObjects(\@post_data);
297             $datareq = $initialclass->query("[?type='even']");
298             # query returns an array of hashes
299             if ($datareq->{success}){
300             # array of hashes
301             @data = @{$datareq->{data}};
302             }
303              
304             =head1 METHODS
305              
306             =over 8
307              
308             =item new
309              
310             This is called from Persevere::Client->class.
311              
312             =item fullname
313              
314             Returns a scalar of the name of the class the object refers to, removes trailing slash.
315              
316             =item exists
317              
318             Returns true if the class the object refers to exists.
319              
320             =item create
321              
322             Creates the class the object refers to. calling $persvr->class("classname"); does not create a class, it only creates an object that refers to the class, calling create on that object creates the actual class.
323              
324             =item delete
325              
326             Deletes the class the object refers to.
327              
328             =item createObjects
329              
330             Creates new objects, takes an array of hashes as input.
331              
332             =item updateObjects
333              
334             Updates existing objects, takes an array of hashes as input. Hashes must have id's correcly set to update objects.
335              
336             =item queryRange
337              
338             Queries a range of results from the objects class.
339              
340             =item query
341              
342             Queries all results from the objects class.
343              
344             =back
345              
346             =head1 AUTHOR
347              
348             Nathanael Anderson, C<< >>
349              
350             =head1 BUGS
351              
352             Please report any bugs or feature requests to C, or through
353             the web interface at L. I will be notified, and then you'll
354             automatically be notified of progress on your bug as I make changes.
355              
356             =head1 COPYRIGHT & LICENSE
357              
358             Copyright 2009-2011 Nathanael Anderson.
359              
360             s program is free software; you can redistribute it and/or modify it
361             under the same terms as Perl itself.
362              
363             =cut
364              
365             1; # End of Persevere::Client::Class