File Coverage

blib/lib/RDF/AllegroGraph/Server.pm
Criterion Covered Total %
statement 27 63 42.8
branch 0 14 0.0
condition n/a
subroutine 9 15 60.0
pod 2 3 66.6
total 38 95 40.0


line stmt bran cond sub pod time code
1             package LWP::UserAgent::AG;
2              
3 15     15   290896 use LWP::UserAgent;
  15         875571  
  15         647  
4 15     15   193 use base 'LWP::UserAgent';
  15         31  
  15         4669  
5              
6             #use LWP::Debug qw(+ -conns);
7             #use LWP::Debug qw(+);
8              
9             sub new {
10 0     0     my $class = shift;
11 0           my %options = @_;
12 0           my $self = $class->SUPER::new;
13 0           $self->timeout(10);
14 0           $self->env_proxy;
15 0           $self->default_header('Accept' => "application/json");
16 0 0         if ($options{AUTHENTICATION}) {
17 0           ( $self->{USERNAME}, $self->{PASSWORD} ) = ($options{AUTHENTICATION} =~ /^(.+):(.*)$/);
18             }
19 0           return $self;
20             }
21              
22             sub get_basic_credentials {
23 0     0     my $self = shift;
24 0           return ($self->{USERNAME}, $self->{PASSWORD});
25             }
26              
27             sub xrequest {
28 0     0     my $self = shift;
29 0           my $req = shift;
30 0           warn $req->as_string;
31             # warn "requesting ". $req->method . ' ' . $req->uri ;
32             # $req->header( 'Connection' => 'close' );
33 0           $self->SUPER::request ($req, @_);
34             }
35              
36             package RDF::AllegroGraph::Server;
37              
38 15     15   99 use strict;
  15         46  
  15         572  
39 15     15   85 use warnings;
  15         39  
  15         698  
40              
41             require Exporter;
42 15     15   79 use base qw(Exporter);
  15         35  
  15         1123  
43              
44 15     15   87 use feature 'switch';
  15         37  
  15         4573  
45              
46             =pod
47              
48             =head1 NAME
49              
50             RDF::AllegroGraph::Server - AllegroGraph server handle
51              
52             =head1 SYNOPSIS
53              
54             #-- orthodox approach
55             my $server = new RDF::AllegroGraph::Server (ADDRESS => 'http://localhost:8080',
56             AUTHENTICATION => 'joe:secret');
57             my @catalogs = $server->catalogs;
58              
59             #-- commodity
60             # get handles to all models (repositories) at the server
61             my @models = $server->models;
62              
63             # get one in particular
64             my $model = $server->model ('/testcat/testrepo');
65              
66             =head1 DESCRIPTION
67              
68             Objects of this class represent handles to a remote AllegroGraph HTTP server. Such a server can hold
69             several I and each of them can hold I. Here we also use the orthodox concept
70             of a I which is simply one particular repository in one particular catalog.
71              
72             For addressing one model we use a simple path structure, such as C.
73              
74             All methods die with C if they do not receive an expected success.
75              
76             =head1 INTERFACE
77              
78             =head2 Constructor
79              
80             To get a handle to the AG server, you can instantiate this class. The following options are
81             recognized:
82              
83             =over
84              
85             =item C
(no default)
86              
87             Specifies the REST HTTP address. Must be an absolute URL, without a trailing slash. The
88             constructor dies otherwise.
89              
90             =item C (no default)
91              
92             String which must be of the form C (separated by C<:>). That will be interpreted
93             as username and password to do basic HTTP authentication against the server.
94              
95             =back
96              
97             =cut
98              
99             sub new {
100 0     0 0   my $class = shift;
101 0           my %options = @_;
102 0 0         die "no HTTP URL as ADDRESS specified" unless $options{ADDRESS} =~ q|^http://|;
103 0           my $self = bless \%options, $class;
104 0           $self->{ua} = new LWP::UserAgent::AG (AUTHENTICATION => $options{AUTHENTICATION});
105 0           my $version = $self->protocol; # try to figure out the version
106 0 0         if ($version =~ /^3/) { # version 3.x
    0          
107 0           $self->{ua}->timeout(10);
108 15     15   17539 use RDF::AllegroGraph::Server3;
  15         196  
  15         1573  
109 0           return bless $self, "${class}3";
110             } elsif ($version =~ /^4/) {
111 0           $self->{ua}->timeout(120); # NOTA BENE: v4 can be really slow when creating/deleting repos
112 15     15   10908 use RDF::AllegroGraph::Server4;
  15         51  
  15         2575  
113 0           return bless $self, "${class}4";
114             } else {
115 0           die "cannot handle protocol version ($version)";
116             }
117 0           return $self;
118             }
119              
120             =pod
121              
122             =head2 Methods
123              
124             =over
125              
126             =item B
127              
128             This method tries to figure out which protocol version the server talks. As the
129             AG 3.x servers do not seem to support a dedicated endpoint, some guesswork is involved.
130              
131             =cut
132              
133             sub protocol {
134 0     0 1   my $self = shift;
135 0           my $resp = $self->{ua}->get ($self->{ADDRESS} . '/protocol');
136 15     15   92 use HTTP::Status;
  15         30  
  15         9787  
137 0 0         if ($resp->is_success) {
    0          
138 0           return $resp->content;
139             } elsif ($resp->code == RC_NOT_FOUND) { # heuristics: we are just guessing now, that this is a 3.x version
140 0           return 3;
141             } else { # this is really an error
142 0           die "protocol error: ".$resp->status_line;
143             }
144             }
145              
146             =pod
147              
148             =item B
149              
150             I<$server>->ping
151              
152             This method tries to connect to the server and will return C<1> on success. Otherwise an exception
153             will be raised.
154              
155             =cut
156              
157             sub ping {
158 0     0 1   my $self = shift;
159 0 0         $self->catalogs and return 1; # even if there are no catalogs, we survived the call
160             }
161              
162             =pod
163              
164             =item B
165              
166             I<@cats> = I<$server>->catalogs
167              
168             This method lists the catalogs available on the remote server. The result is a list of relative
169             paths.
170              
171             =item B
172              
173             I<%models> = I<$server>->models
174              
175             This method lists all models available on the server. Returned is a hash reference. The keys are the
176             model identifiers, all of the form C. The values are repository objects.
177              
178             =item B
179              
180             I<$server>->model (I<$mod_id>, I => I, ...)
181              
182             This method tries to find an repository in a certain catalog. This I is always of the form
183             C. The following options are understood:
184              
185             =over
186              
187             =item C (default: C)
188              
189             This POSIX file mode determines how the model will be opened.
190              
191             =back
192              
193             If the model already does exist, then an L object will be
194             returned. If the specified catalog does not exist, then a C exception will be raised.
195             Otherwise, if the repository there does not exist and the C option is C, then it will
196             be generated. Otherwise an exception C will be raised.
197              
198              
199             =back
200              
201             =head1 AUTHOR
202              
203             Robert Barta, C<< >>
204              
205             =head1 COPYRIGHT & LICENSE
206              
207             Copyright 20(09|11) Robert Barta, all rights reserved.
208              
209             This program is free software; you can redistribute it and/or modify it under the same terms as Perl
210             itself.
211              
212             L, L
213              
214             =cut
215              
216             our $VERSION = '0.04';
217              
218             1;
219              
220             __END__