File Coverage

blib/lib/Catmandu/FedoraCommons.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             Catmandu::FedoraCommons - Low level Catmandu interface to the Fedora Commons REST API
4              
5             =head1 SYNOPSIS
6              
7             # Use the command line tools
8             $ fedora_admin.pl
9              
10             # Or the low-level API-s
11             use Catmandu::FedoraCommons;
12            
13             my $fedora = Catmandu::FedoraCommons->new('http://localhost:8080/fedora','fedoraAdmin','fedoraAdmin');
14            
15             my $result = $fedora->findObjects(terms=>'*');
16            
17             die $result->error unless $result->is_ok;
18            
19             my $hits = $result->parse_content();
20            
21             for my $hit (@{ $hits->{results} }) {
22             printf "%s\n" , $hit->{pid};
23             }
24            
25             # Or using the higher level Catmandu::Store codes you can do things like
26            
27             use Catmandu::Store::FedoraCommons;
28              
29             my $store = Catmandu::Store::FedoraCommons->new(
30             baseurl => 'http://localhost:8080/fedora',
31             username => 'fedoraAdmin',
32             password => 'fedoraAdmin',
33             model => 'Catmandu::Store::FedoraCommons::DC' # default
34             );
35            
36             $store->bag->each(sub {
37             my $model = shift;
38             printf "title: %s\n" , join("" , @{ $model->{title} });
39             printf "creator: %s\n" , join("" , @{ $model->{creator} });
40            
41             my $pid = $model->{_id};
42             my $ds = $store->fedora->listDatastreams(pid => $pid)->parse_content;
43             });
44            
45             my $obj = $store->bag->add({
46             title => ['The Master and Margarita'] ,
47             creator => ['Bulgakov, Mikhail'] }
48             );
49            
50             $store->fedora->addDatastream(pid => $obj->{_id} , url => "http://myurl/rabbit.jpg");
51            
52             # Add your own perl version of a descriptive metadata model by implementing your own
53             # model that can do a serialize and deserialize.
54            
55             =head1 DESCRIPTION
56              
57             Catmandu::FedoraCommons is an Perl API to the Fedora Commons REST API (http://www.fedora.info/).
58             Supported versions are Fedora Commons 3.6 or better.
59              
60             =head1 ACCESS METHODS
61              
62             =cut
63             package Catmandu::FedoraCommons;
64              
65 4     4   108746 use Catmandu::FedoraCommons::Response;
  0            
  0            
66              
67             our $VERSION = '0.273';
68             use URI::Escape;
69             use HTTP::Request::Common qw(GET POST DELETE PUT HEAD);
70             use LWP::UserAgent;
71             use MIME::Base64;
72             use strict;
73             use Carp;
74             use Data::Validate::URI qw(is_uri);
75             use Data::Dumper;
76              
77             =head2 new($base_url,$username,$password)
78              
79             Create a new Catmandu::FedoraCommons connecting to the baseurl of the Fedora Commons installation.
80              
81             =cut
82             sub new {
83             my ($class,$baseurl,$username,$password) = @_;
84            
85             Carp::croak "baseurl missing" unless defined $baseurl;
86            
87             my $ua = LWP::UserAgent->new(
88             agent => 'Catmandu-FedoraCommons/' . $VERSION,
89             timeout => 180,
90             );
91            
92             $baseurl =~ m/(\w+):\/\/([^\/:]+)(:(\d+))?(\S+)/;
93            
94             bless { baseurl => $baseurl,
95             scheme => $1,
96             host => $2,
97             port => $4 || 8080,
98             path => $5,
99             username => $username,
100             password => $password,
101             ua => $ua} , $class;
102             }
103              
104             sub _GET {
105             my ($self,$path,$data,$callback,$headers) = @_;
106             $headers = {} unless $headers;
107            
108             my @parts;
109             for my $part (@$data) {
110             my ($key) = keys %$part;
111             my $name = uri_escape($key) || "";
112             my $value = uri_escape($part->{$key}) || "";
113             push @parts , "$name=$value";
114             }
115            
116             my $query = join("&",@parts);
117            
118             my $req = GET $self->{baseurl} . $path . '?' . $query , %$headers;
119            
120             $req->authorization_basic($self->{username}, $self->{password});
121            
122             defined $callback ?
123             return $self->{ua}->request($req, $callback, 4096) :
124             return $self->{ua}->request($req);
125             }
126              
127             sub _POST {
128             my ($self,$path,$data,$callback) = @_;
129            
130             my $content = undef;
131             my @parts;
132            
133             for my $part (@$data) {
134             my ($key) = keys %$part;
135            
136             if (ref $part->{$key} eq 'ARRAY') {
137             $content = [ $key => $part->{$key} ];
138             }
139             else {
140             my $name = uri_escape($key) || "";
141             my $value = uri_escape($part->{$key}) || "";
142             push @parts , "$name=$value";
143             }
144             }
145            
146             my $query = join("&",@parts);
147            
148             my $req;
149            
150             if (defined $content) {
151             $req = POST $self->{baseurl} . $path . '?' . $query, Content_Type => 'form-data' , Content => $content;
152             }
153             else {
154             # Need a Content_Type text/xml because of a Fedora 'ingest' feature that requires it...
155             $req = POST $self->{baseurl} . $path . '?' . $query, Content_Type => 'text/xml';
156             }
157            
158             $req->authorization_basic($self->{username}, $self->{password});
159              
160             defined $callback ?
161             return $self->{ua}->request($req, $callback, 4096) :
162             return $self->{ua}->request($req);
163             }
164              
165             sub _PUT {
166             my ($self,$path,$data,$callback) = @_;
167              
168             my $content = undef;
169             my @parts;
170            
171             for my $part (@$data) {
172             my ($key) = keys %$part;
173            
174             if (ref $part->{$key} eq 'ARRAY') {
175             $content = $part->{$key};
176             }
177             else {
178             push @parts , uri_escape($key) . "=" . uri_escape($part->{$key});
179             }
180             }
181            
182             my $query = join("&",@parts);
183            
184             my $req;
185            
186             if (defined $content) {
187             if (@$content == 1) {
188             my $file = $content->[0];
189             $req = PUT $self->{baseurl} . $path . '?' . $query;
190             open(my $fh,'<',$file) or Carp::croak "can't open $file : $!";
191             local($/) = undef;
192             $req->content(scalar(<$fh>));
193             close($fh);
194             }
195             else {
196             my $xml = $content->[-1];
197             $req = PUT $self->{baseurl} . $path . '?' . $query;
198             $req->content($xml);
199             $req->header( 'Content-Length' => length($xml) );
200             }
201             }
202             else {
203             # Need a Content_Type text/xml because of a Fedora 'ingest' feature that requires it...
204             $req = PUT $self->{baseurl} . $path . '?' . $query, Content_Type => 'text/xml';
205             }
206              
207             $req->authorization_basic($self->{username}, $self->{password});
208            
209             defined $callback ?
210             return $self->{ua}->request($req, $callback, 4096) :
211             return $self->{ua}->request($req);
212             }
213              
214             sub _DELETE {
215             my ($self,$path,$data,$callback) = @_;
216            
217             my @parts;
218             for my $part (@$data) {
219             my ($key) = keys %$part;
220             my $name = uri_escape($key) || "";
221             my $value = uri_escape($part->{$key}) || "";
222             push @parts , "$name=$value";
223             }
224            
225             my $query = join("&",@parts);
226            
227             my $req = DELETE sprintf("%s%s%s", $self->{baseurl} , $path , $query ? '?' . $query : "");
228            
229             $req->authorization_basic($self->{username}, $self->{password});
230              
231             defined $callback ?
232             return $self->{ua}->request($req, $callback, 4096) :
233             return $self->{ua}->request($req);
234             }
235              
236             =head2 findObjects(query => $query, maxResults => $maxResults)
237              
238             =head2 findObjects(terms => $terms , maxResults => $maxResults)
239              
240             Execute a search query on the Fedora Commons server. One of 'query' or 'terms' is required. Query
241             contains a phrase optionally including '*' and '?' wildcards. Terms contain one or more conditions separated by space.
242             A condition is a field followed by an operator, followed by a value. The = operator will match if the field's
243             entire value matches the value given. The ~ operator will match on phrases within fields, and accepts
244             the ? and * wildcards. The <, >, <=, and >= operators can be used with numeric values, such as dates.
245              
246             Examples:
247              
248             query => "*o*"
249            
250             query => "?edora"
251            
252             terms => "pid~demo:* description~fedora"
253              
254             terms => "cDate>=1976-03-04 creator~*n*"
255              
256             terms => "mDate>2002-10-2 mDate<2002-10-2T12:00:00"
257            
258             Optionally a maxResults parameter may be specified limiting the number of search results (default is 20). This method
259             returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::findObjects> model.
260              
261             =cut
262             sub findObjects {
263             my $self = shift;
264             my %args = (query => "", terms => "", maxResults => 20, @_);
265            
266             Carp::croak "terms or query required" unless defined $args{terms} || defined $args{query};
267            
268             my %defaults = (pid => 'true' , label => 'true' , state => 'true' , ownerId => 'true' ,
269             cDate => 'true' , mDate => 'true' , dcmDate => 'true' , title => 'true' ,
270             creator => 'true' , subject => 'true' , description => 'true' , publisher => 'true' ,
271             contributor => 'true' , date => 'true' , type => 'true' , format => 'true' ,
272             identifier => 'true' , source => 'true' , language => 'true' , relation => 'true' ,
273             coverage => 'true' , rights => 'true' , resultFormat => 'xml');
274            
275             my %values = (%defaults,%args);
276             my $form_data = [];
277            
278             for my $name (keys %values) {
279             push @$form_data , { $name => $values{$name} };
280             }
281            
282             return Catmandu::FedoraCommons::Response->factory(
283             'findObjects' , $self->_GET('/objects',$form_data)
284             );
285             }
286              
287             =head2 resumeFindObjects(sessionToken => $token)
288              
289             This method returns the next batch of search results. This method returns a L<Catmandu::FedoraCommons::Response> object
290             with a L<Catmandu::FedoraCommons::Model::findObjects> model.
291              
292             Example:
293              
294             my $result = $fedora->findObjects(terms=>'*');
295              
296             die $result->error unless $result->is_ok;
297              
298             my $hits = $result->parse_content();
299            
300             for my $hit (@{ $hits->{results} }) {
301             printf "%s\n" , $hit->{pid};
302             }
303            
304             my $result = $fedora->resumeFindObjects(sessionToken => $hits->{token});
305            
306             my $hits = $result->parse_content();
307            
308             ...
309            
310             =cut
311             sub resumeFindObjects {
312             my $self = shift;
313             my %args = (sessionToken => undef , query => "", terms => "", maxResults => 20, @_);
314            
315             Carp::croak "sessionToken required" unless defined $args{sessionToken};
316             Carp::croak "terms or query required" unless defined $args{terms} || defined $args{query};
317            
318             my %defaults = (pid => 'true' , label => 'true' , state => 'true' , ownerId => 'true' ,
319             cDate => 'true' , mDate => 'true' , dcmDate => 'true' , title => 'true' ,
320             creator => 'true' , subject => 'true' , description => 'true' , publisher => 'true' ,
321             contributor => 'true' , date => 'true' , type => 'true' , format => 'true' ,
322             identifier => 'true' , source => 'true' , language => 'true' , relation => 'true' ,
323             coverage => 'true' , rights => 'true' , resultFormat => 'xml');
324            
325             my %values = (%defaults,%args);
326             my $form_data = [];
327            
328             for my $name (keys %values) {
329             push @$form_data , { $name => $values{$name} };
330             }
331            
332             return Catmandu::FedoraCommons::Response->factory(
333             'resumeFindObjects' , $self->_GET('/objects',$form_data)
334             );
335             }
336              
337             =head2 getDatastreamDissemination(pid => $pid, dsID=> $dsID, asOfDateTime => $date, callback => \&callback)
338              
339             This method returns a datastream from the Fedora Commons repository. Required parameters are
340             the identifier of the object $pid and the identifier of the datastream $dsID. Optionally a datestamp $asOfDateTime
341             can be provided. This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::getDatastreamDissemination>
342             model.
343              
344             To stream the contents of the datastream a callback function can be provided.
345              
346             Example:
347            
348             $fedora->getDatastreamDissemination(pid => 'demo:5', dsID => 'VERYHIGHRES', callback => \&process);
349            
350             sub process {
351             my ($data, $response, $protocol) = @_;
352             print $data;
353             }
354            
355             =cut
356             sub getDatastreamDissemination {
357             my $self = shift;
358             my %args = (pid => undef , dsID => undef , asOfDateTime => undef, download => undef, @_);
359            
360             Carp::croak "need pid" unless $args{pid};
361             Carp::croak "need dsID" unless $args{dsID};
362            
363             my $pid = $args{pid};
364             my $dsId = $args{dsID};
365             my $callback = $args{callback};
366            
367             delete $args{pid};
368             delete $args{dsID};
369             delete $args{callback};
370            
371             my $form_data = [];
372            
373             for my $name (keys %args) {
374             push @$form_data , { $name => $args{$name} };
375             }
376            
377             return Catmandu::FedoraCommons::Response->factory(
378             'getDatastreamDissemination' , $self->_GET('/objects/' . $pid . '/datastreams/' . $dsId . '/content' , $form_data, $callback)
379             );
380             }
381              
382             =head2 getDissemination(pid => $pid , sdefPid => $sdefPid , method => $method , %method_parameters , callback => \&callback)
383              
384             This method execute a dissemination method on the Fedora Commons server. Required parametes are the object $pid, the service definition $sdefPid and the name of the method $method. Optionally
385             further method parameters can be provided and a callback function to stream the results (see getDatastreamDissemination).
386             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::getDatastreamDissemination> model.
387              
388             Example:
389            
390             $fedora->getDissemination(pid => 'demo:29', sdefPid => 'demo:27' , method => 'resizeImage' , width => 100, callback => \&process);
391            
392             =cut
393             sub getDissemination {
394             my $self = shift;
395             my %args = (pid => undef , sdefPid => undef , method => undef, @_);
396            
397             Carp::croak "need pid" unless $args{pid};
398             Carp::croak "need dsID" unless $args{sdefPid};
399             Carp::croak "need method" unless $args{method};
400            
401             my $pid = $args{pid};
402             my $sdefPid = $args{sdefPid};
403             my $method = $args{method};
404             my $callback = $args{callback};
405            
406             delete $args{pid};
407             delete $args{sdefPid};
408             delete $args{method};
409             delete $args{callback};
410            
411             my $form_data = [];
412            
413             for my $name (keys %args) {
414             push @$form_data , { $name => $args{$name} };
415             }
416            
417             return Catmandu::FedoraCommons::Response->factory(
418             'getDissemination' , $self->_GET('/objects/' . $pid . '/methods/' . $sdefPid . '/' . $method , $form_data, $callback)
419             );
420             }
421              
422             =head2 getObjectHistory(pid => $pid)
423              
424             This method returns the version history of an object. Required is the object $pid.
425             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::getObjectHistory> model.
426              
427             Example:
428            
429             my $obj = $fedora->getObjectHistory(pid => 'demo:29')->parse_content;
430            
431             for @{$obj->{objectChangeDate}} {}
432             print "$_\n;
433             }
434            
435             =cut
436             sub getObjectHistory {
437             my $self = shift;
438             my %args = (pid => undef , @_);
439              
440             Carp::croak "need pid" unless $args{pid};
441            
442             my $pid = $args{pid};
443            
444             delete $args{pid};
445            
446             my %defaults = ( format => 'xml' );
447            
448             my %values = (%defaults,%args);
449             my $form_data = [];
450            
451             for my $name (keys %values) {
452             push @$form_data , { $name => $values{$name} };
453             }
454            
455             return Catmandu::FedoraCommons::Response->factory(
456             'getObjectHistory' , $self->_GET('/objects/' . $pid . '/versions', $form_data)
457             );
458             }
459              
460             =head2 getObjectProfile(pid => $pid, asOfDateTime => $date)
461              
462             This method returns a detailed description of an object. Required is the object $pid. Optionally a
463             version date asOfDateTime can be provided. This method returns a L<Catmandu::FedoraCommons::Response> object
464             with a L<Catmandu::FedoraCommons::Model::getObjectProfile> model.
465              
466             Example:
467              
468             my $obj = $fedora->getObjectProfile(pid => 'demo:29')->parse_content;
469              
470             printf "Label: %s\n" , $obj->{objLabel};
471            
472             =cut
473             sub getObjectProfile {
474             my $self = shift;
475             my %args = (pid => undef , asOfDateTime => undef , @_);
476              
477             Carp::croak "need pid" unless $args{pid};
478            
479             my $pid = $args{pid};
480            
481             delete $args{pid};
482            
483             my %defaults = ( format => 'xml' );
484            
485             my %values = (%defaults,%args);
486             my $form_data = [];
487            
488             for my $name (keys %values) {
489             push @$form_data , { $name => $values{$name} };
490             }
491            
492             return Catmandu::FedoraCommons::Response->factory(
493             'getObjectProfile' , $self->_GET('/objects/' . $pid , $form_data)
494             );
495             }
496              
497             =head2 listDatastreams(pid => $pid, asOfDateTime => $date)
498              
499             This method returns a list of datastreams provided in the object. Required is the object $pid.
500             Optionally a version date asOfDateTime can be provided. This method returns a L<Catmandu::FedoraCommons::Response> object
501             with a L<Catmandu::FedoraCommons::Model::listDatastreams> model.
502              
503             Example:
504            
505             my $obj = $fedora->listDatastreams(pid => 'demo:29')->parse_content;
506            
507             for (@{ $obj->{datastream}} ) {
508             printf "Label: %s\n" , $_->{label};
509             }
510            
511             =cut
512             sub listDatastreams {
513             my $self = shift;
514             my %args = (pid => undef , asOfDateTime => undef , @_);
515              
516             Carp::croak "need pid" unless $args{pid};
517            
518             my $pid = $args{pid};
519            
520             delete $args{pid};
521            
522             my %defaults = ( format => 'xml' );
523            
524             my %values = (%defaults,%args);
525             my $form_data = [];
526            
527             for my $name (keys %values) {
528             push @$form_data , { $name => $values{$name} };
529             }
530            
531             return Catmandu::FedoraCommons::Response->factory(
532             'listDatastreams' , $self->_GET('/objects/' . $pid . '/datastreams', $form_data)
533             );
534             }
535              
536             =head2 listMethods(pid => $pid , sdefPid => $sdefPid , asOfDateTime => $date)
537              
538             This method return a list of methods that can be executed on an object. Required is the object $pid
539             and the object $sdefPid. Optionally a version date asOfDateTime can be provided.
540             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::listMethods>
541             model.
542              
543             Example:
544            
545             my $obj = $fedora->listMethods(pid => 'demo:29')->parse_content;
546            
547             for ( @{ $obj->{sDef} }) {
548             printf "[%s]\n" , $_->{$pid};
549            
550             for my $m ( @{ $_->{method} } ) {
551             printf "\t%s\n" , $m->{name};
552             }
553             }
554              
555             =cut
556             sub listMethods {
557             my $self = shift;
558             my %args = (pid => undef , sdefPid => undef, asOfDateTime => undef , @_);
559              
560             Carp::croak "need pid" unless $args{pid};
561            
562             my $pid = $args{pid};
563             my $sdefPid = $args{sdefPid};
564            
565             delete $args{pid};
566             delete $args{sdefPid};
567            
568             my %defaults = ( format => 'xml' );
569            
570             my %values = (%defaults,%args);
571             my $form_data = [];
572            
573             for my $name (keys %values) {
574             push @$form_data , { $name => $values{$name} };
575             }
576            
577             return Catmandu::FedoraCommons::Response->factory(
578             'listMethods' , $self->_GET('/objects/' . $pid . '/methods' . ( defined $sdefPid ? "/$sdefPid" : "" ), $form_data)
579             );
580             }
581             =head2 describeRepository
582              
583             This method returns information about the fedora repository. No arguments required.
584             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::describeRepository> model.
585              
586             Example:
587              
588             my $desc = $fedora->describeRepository()->parse_content();
589              
590             =cut
591              
592             sub describeRepository {
593             my $self = $_[0];
594             my $form_data = [ { xml => "true" } ];
595              
596             return Catmandu::FedoraCommons::Response->factory(
597             'describeRepository' , $self->_GET('/describe', $form_data)
598             );
599             }
600             *describe = \&describeRepository;
601              
602             =head1 MODIFY METHODS
603              
604             =head2 addDatastream(pid => $pid , dsID => $dsID, url => $remote_location, %args)
605              
606             =head2 addDatastream(pid => $pid , dsID => $dsID, file => $filename , %args)
607              
608             =head2 addDatastream(pid => $pid , dsID => $dsID, xml => $xml , %args)
609              
610             This method adds a data stream to the object. Required parameters are the object $pid, a new datastream $dsID and
611             a remote $url, a local $file or an $xml string which contains the content. Optionally any of these datastream modifiers
612             may be provided: controlGroup, altIDs, dsLabel, versionable, dsState, formatURI, checksumType, checksum,
613             mimeType, logMessage. See: https://wiki.duraspace.org/display/FEDORA36/REST+API for more information.
614             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::datastreamProfile>
615             model.
616              
617             Example:
618            
619             my $obj = $fedora->addDatastream(pid => 'demo:29', dsID => 'TEST' , file => 'README', mimeType => 'text/plain')->parse_content;
620            
621             print "Uploaded at: %s\n" , $obj->{dateTime};
622            
623             =cut
624             sub addDatastream {
625             my $self = shift;
626             my %args = (pid => undef , dsID => undef, url => undef , file => undef , xml => undef , @_);
627            
628             Carp::croak "need pid" unless $args{pid};
629             Carp::croak "need dsID" unless $args{dsID};
630             Carp::croak "need url or file (filename)" unless defined $args{url} || defined $args{file} || defined $args{xml};
631            
632             my $pid = $args{pid};
633             my $dsID = $args{dsID};
634             my $url = $args{url};
635             my $file = $args{file};
636             my $xml = $args{xml};
637            
638             delete $args{pid};
639             delete $args{dsID};
640             delete $args{url};
641             delete $args{file};
642             delete $args{xml};
643            
644             my %defaults = ( versionable => 'false');
645            
646             if (defined $file) {
647             $defaults{file} = ["$file"];
648             $defaults{controlGroup} = 'M';
649             }
650             elsif (defined $xml) {
651             $defaults{file} = [ undef , 'upload.xml' , Content => $xml ];
652             $defaults{controlGroup} = 'X';
653             $defaults{mimeType} = 'text/xml';
654             }
655             elsif (defined $url) {
656             $defaults{dsLocation} = $url;
657             $defaults{controlGroup} = 'M';
658             }
659            
660             my %values = (%defaults,%args);
661             my $form_data = [];
662            
663             for my $name (keys %values) {
664             push @$form_data , { $name => $values{$name} };
665             }
666            
667             return Catmandu::FedoraCommons::Response->factory(
668             'addDatastream' , $self->_POST('/objects/' . $pid . '/datastreams/' . $dsID, $form_data)
669             );
670             }
671              
672             =head2 addRelationship(pid => $pid, relation => [ $subject, $predicate, $object] [, dataType => $dataType])
673              
674             This methods adds a triple to the 'RELS-EXT' data stream of the object. Requires parameters are the object
675             $pid and a relation as a triple ARRAY reference. Optionally the $datatype of the literal may be provided.
676             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::addRelationship>
677             model.
678              
679             Example:
680            
681             $fedora->addRelationship(pid => 'demo:29' , relation => [ 'info:fedora/demo:29' , 'http://my.org/name' , 'Peter']);
682              
683             =cut
684             sub addRelationship {
685             my $self = shift;
686             my %args = (pid => undef , relation => undef, @_);
687            
688             Carp::croak "need pid" unless $args{pid};
689             Carp::croak "need relation" unless defined $args{relation} && ref $args{relation} eq 'ARRAY';
690            
691             my $pid = $args{pid};
692             my $subject = $args{relation}->[0];
693             my $predicate = $args{relation}->[1];
694             my $object = $args{relation}->[2];
695             my $dataType = $args{dataType};
696             my $isLiteral = is_uri($object) ? "false" : "true";
697            
698             my $form_data = [
699             { subject => $subject },
700             { predicate => $predicate },
701             { object => $object },
702             { dataType => $dataType },
703             { isLiteral => $isLiteral },
704             ];
705              
706             return Catmandu::FedoraCommons::Response->factory(
707             'addRelationship' , $self->_POST('/objects/' . $pid . '/relationships/new', $form_data)
708             );
709             }
710              
711             =head2 export(pid => $pid [, format => $format , context => $context , encoding => $encoding])
712              
713             This method exports the data model of the object in FOXML,METS or ATOM. Required is $pid of the object.
714             Optionally a $context may be provided and the $format of the export.
715             See: https://wiki.duraspace.org/display/FEDORA36/REST+API for more information.
716             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::export>
717             model.
718              
719             Example:
720            
721             my $res = $fedora->export(pid => 'demo:29');
722            
723             print $res->raw;
724            
725             print "%s\n" , $res->parse_content->{objectProperties}->{label};
726              
727             =cut
728             sub export {
729             my $self = shift;
730             my %args = (pid => undef , format => undef , context => undef , encoding => undef, @_);
731            
732             Carp::croak "need pid" unless $args{pid};
733            
734             my $pid = $args{pid};
735            
736             delete $args{pid};
737            
738             my %defaults = ();
739            
740             my %values = (%defaults,%args);
741             my $form_data = [];
742            
743             for my $name (keys %values) {
744             push @$form_data , { $name => $values{$name} };
745             }
746            
747             return Catmandu::FedoraCommons::Response->factory(
748             'export' , $self->_GET('/objects/' . $pid . '/export', $form_data)
749             );
750             }
751              
752             =head2 getDatastream(pid => $pid, dsID => $dsID , %args)
753              
754             This method return metadata about a data stream. Required is the object $pid and the $dsID of the data stream.
755             Optionally a version 'asOfDateTime' can be provided and a 'validateChecksum' check.
756             See: https://wiki.duraspace.org/display/FEDORA36/REST+API for more information.
757             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::datastreamProfile>
758             model.
759              
760             Example:
761            
762             my $obj = $fedora->getDatastream(pid => 'demo:29', dsID => 'DC')->parse_content;
763            
764             printf "Label: %s\n" , $obj->{profile}->{dsLabel};
765            
766             =cut
767             sub getDatastream {
768             my $self = shift;
769             my %args = (pid => undef , dsID => undef, @_);
770            
771             Carp::croak "need pid" unless $args{pid};
772             Carp::croak "need dsID" unless $args{dsID};
773            
774             my $pid = $args{pid};
775             my $dsID = $args{dsID};
776            
777             delete $args{pid};
778             delete $args{dsID};
779            
780             my %defaults = ( format => 'xml');
781            
782             my %values = (%defaults,%args);
783             my $form_data = [];
784            
785             for my $name (keys %values) {
786             push @$form_data , { $name => $values{$name} };
787             }
788            
789             return Catmandu::FedoraCommons::Response->factory(
790             'getDatastream' , $self->_GET('/objects/' . $pid . '/datastreams/' . $dsID, $form_data)
791             );
792             }
793              
794             =head2 getDatastreamHistory(pid => $pid , dsID => $dsID , %args)
795              
796             This method returns the version history of a data stream. Required paramter is the $pid of the object and the $dsID of the
797             data stream. This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::datastreamHistory>
798             model.
799              
800             Example:
801            
802             my $obj = $fedora->getDatastreamHistory(pid => 'demo:29', dsID => 'DC')->parse_content;
803            
804             for (@{ $obj->{profile} }) {
805             printf "Version: %s\n" , $_->{dsCreateDate};
806             }
807              
808             =cut
809             sub getDatastreamHistory {
810             my $self = shift;
811             my %args = (pid => undef , dsID => undef, @_);
812            
813             Carp::croak "need pid" unless $args{pid};
814             Carp::croak "need dsID" unless $args{dsID};
815            
816             my $pid = $args{pid};
817             my $dsID = $args{dsID};
818            
819             delete $args{pid};
820             delete $args{dsID};
821            
822             my %defaults = ( format => 'xml');
823            
824             my %values = (%defaults,%args);
825             my $form_data = [];
826            
827             for my $name (keys %values) {
828             push @$form_data , { $name => $values{$name} };
829             }
830            
831             return Catmandu::FedoraCommons::Response->factory(
832             'getDatastreamHistory' , $self->_GET('/objects/' . $pid . '/datastreams/' . $dsID . '/history', $form_data)
833             );
834             }
835              
836             =head2 getNextPID(namespace => $namespace, numPIDs => $numPIDs)
837              
838             This method generates a new pid. Optionally a 'namespace' can be provided and the required 'numPIDs' you need. This method returns a L<Catmandu::FedoraCommons::Response> object with a
839             L<Catmandu::FedoraCommons::Model::pidList> model.
840              
841             Example:
842            
843             my $pid = $fedora->getNextPID()->parse_content->[0];
844            
845             =cut
846             sub getNextPID {
847             my $self = shift;
848             my %args = (namespace => undef, @_);
849            
850             my %defaults = ( format => 'xml');
851            
852             my %values = (%defaults,%args);
853             my $form_data = [];
854            
855             for my $name (keys %values) {
856             push @$form_data , { $name => $values{$name} };
857             }
858            
859             return Catmandu::FedoraCommons::Response->factory(
860             'getNextPID' , $self->_POST('/objects/nextPID', $form_data)
861             );
862             }
863              
864             =head2 getObjectXML(pid => $pid)
865              
866             This method exports the data model of the object in FOXML format. Required is $pid of the object.
867             This method returns a L<Catmandu::FedoraCommons::Response> object .
868              
869             Example:
870            
871             my $res = $fedora->getObjectXML(pid => 'demo:29');
872            
873             print $res->raw;
874            
875             =cut
876             sub getObjectXML {
877             my $self = shift;
878             my %args = (pid => undef, @_);
879            
880             Carp::croak "need pid" unless $args{pid};
881            
882             my $pid = $args{pid};
883            
884             delete $args{pid};
885            
886             my %defaults = ();
887            
888             my %values = (%defaults,%args);
889             my $form_data = [];
890            
891             for my $name (keys %values) {
892             push @$form_data , { $name => $values{$name} };
893             }
894            
895             return Catmandu::FedoraCommons::Response->factory(
896             'getObjectXML' , $self->_GET('/objects/' . $pid . '/objectXML', $form_data)
897             );
898             }
899              
900             =head2 getRelationships(pid => $pid [, relation => [$subject, $predicate, undef] , format => $format ])
901              
902             This method returns all RELS-EXT triples for an object. Required parameter is the $pid of the object.
903             Optionally the triples may be filetered using the 'relation' parameter. Format defines the returned format.
904             See: https://wiki.duraspace.org/display/FEDORA36/REST+API for more information.
905             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::getRelationships> model.
906              
907             Example:
908            
909             my $obj = $fedora->getRelationships(pid => 'demo:29')->parse_content;
910              
911             my $iter = $obj->get_statements();
912            
913             print "Names of things:\n";
914             while (my $st = $iter->next) {
915             my $s = $st->subject;
916             my $name = $st->object;
917             print "The name of $s is $name\n";
918             }
919            
920             =cut
921             sub getRelationships {
922             my $self = shift;
923             my %args = (pid => undef , relation => undef, @_);
924            
925             Carp::croak "need pid" unless $args{pid};
926            
927             my $pid = $args{pid};
928             my $format = $args{format};
929            
930             my ($subject,$predicate);
931            
932             if (defined $args{relation} && ref $args{relation} eq 'ARRAY') {
933             $subject = $args{relation}->[0];
934             $predicate = $args{relation}->[1];
935             }
936            
937             my %defaults = (subject => $subject, predicate => $predicate, format => 'xml');
938            
939             my %values = (%defaults,%args);
940             my $form_data = [];
941            
942             for my $name (keys %values) {
943             push @$form_data , { $name => $values{$name} } if defined $values{$name};
944             }
945             return Catmandu::FedoraCommons::Response->factory(
946             'getRelationships' , $self->_GET('/objects/' . $pid . '/relationships', $form_data)
947             );
948             }
949              
950             =head2 ingest(pid => $pid , file => $filename , xml => $xml , format => $format , %args)
951              
952             =head2 ingest(pid => 'new' , file => $filename , xml => $xml , format => $format , %args)
953              
954             This method ingest an object into Fedora Commons. Required is the $pid of the new object (which can be
955             the string 'new' when Fedora has to generate a new pid), and the $filename or $xml to upload writen as $format.
956             Optionally the following parameters can be provided: label, encoding, namespace, ownerId, logMessage.
957             See: https://wiki.duraspace.org/display/FEDORA36/REST+API for more information.
958             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::ingest> model.
959              
960             Example:
961              
962             my $obj = $fedora->ingest(pid => 'new', file => 't/obj_demo_40.zip', format => 'info:fedora/fedora-system:ATOMZip-1.1')->parse_content;
963            
964             printf "created: %s\n" , $obj->{pid};
965            
966             =cut
967             sub ingest {
968             my $self = shift;
969             my %args = (pid => undef , file => undef , xml => undef , @_);
970            
971             Carp::croak "need pid" unless $args{pid};
972             Carp::croak "need file or xml" unless defined $args{file} || defined $args{xml};
973            
974             my $pid = $args{pid};
975             my $file = $args{file};
976             my $xml = $args{xml};
977            
978             delete $args{pid};
979             delete $args{file};
980             delete $args{xml};
981              
982             my %defaults = (ignoreMime => 'true');
983            
984             if (defined $file) {
985             $defaults{format} = 'info:fedora/fedora-system:FOXML-1.1';
986             $defaults{encoding} = 'UTF-8';
987             $defaults{file} = ["$file"];
988             }
989             elsif (defined $xml) {
990             $defaults{format} = 'info:fedora/fedora-system:FOXML-1.1';
991             $defaults{encoding} = 'UTF-8';
992             $defaults{file} = [undef, 'upload.xml' , Content => $xml];
993             }
994            
995             my %values = (%defaults,%args);
996             my $form_data = [];
997            
998             for my $name (keys %values) {
999             push @$form_data , { $name => $values{$name} };
1000             }
1001            
1002             return Catmandu::FedoraCommons::Response->factory(
1003             'ingest' , $self->_POST('/objects/' . $pid, $form_data)
1004             );
1005             }
1006              
1007             =head2 modifyDatastream(pid => $pid , dsID => $dsID, url => $remote_location, %args)
1008              
1009             =head2 modifyDatastream(pid => $pid , dsID => $dsID, file => $filename , %args)
1010              
1011             =head2 modifyDatastream(pid => $pid , dsID => $dsID, xml => $xml , %args)
1012              
1013             This method updated a data stream in the object. Required parameters are the object $pid, a new datastream $dsID and
1014             a remote $url, a local $file or an $xml string which contains the content. Optionally any of these datastream modifiers
1015             may be provided: controlGroup, altIDs, dsLabel, versionable, dsState, formatURI, checksumType, checksum,
1016             mimeType, logMessage. See: https://wiki.duraspace.org/display/FEDORA36/REST+API for more information.
1017             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::datastreamProfile>
1018             model.
1019              
1020             Example:
1021            
1022             my $obj = $fedora->modifyDatastream(pid => 'demo:29', dsID => 'TEST' , file => 'README', mimeType => 'text/plain')->parse_content;
1023            
1024             print "Uploaded at: %s\n" , $obj->{dateTime};
1025            
1026             =cut
1027             sub modifyDatastream {
1028             my $self = shift;
1029             my %args = (pid => undef , dsID => undef, url => undef , file => undef , xml => undef , @_);
1030            
1031             Carp::croak "need pid" unless $args{pid};
1032             Carp::croak "need dsID" unless $args{dsID};
1033             Carp::croak "need url or file (filename)" unless defined $args{url} || defined $args{file} || defined $args{xml};
1034            
1035             my $pid = $args{pid};
1036             my $dsID = $args{dsID};
1037             my $url = $args{url};
1038             my $file = $args{file};
1039             my $xml = $args{xml};
1040            
1041             delete $args{pid};
1042             delete $args{dsID};
1043             delete $args{url};
1044             delete $args{file};
1045             delete $args{xml};
1046            
1047             my %defaults = (versionable => 'false');
1048            
1049             if (defined $file) {
1050             $defaults{file} = ["$file"];
1051             $defaults{controlGroup} = 'M';
1052             }
1053             elsif (defined $xml) {
1054             $defaults{file} = [undef, 'upload.xml' , Content => $xml];
1055             $defaults{controlGroup} = 'X';
1056             $defaults{mimeType} = 'text/xml';
1057             }
1058             elsif (defined $url) {
1059             $defaults{dsLocation} = $url;
1060             $defaults{controlGroup} = 'E';
1061             }
1062            
1063             my %values = (%defaults,%args);
1064             my $form_data = [];
1065            
1066             for my $name (keys %values) {
1067             push @$form_data , { $name => $values{$name} };
1068             }
1069            
1070             return Catmandu::FedoraCommons::Response->factory(
1071             'modifyDatastream' , $self->_PUT('/objects/' . $pid . '/datastreams/' . $dsID, $form_data)
1072             );
1073             }
1074              
1075             =head2 modifyObject(pid => $pid, label => $label , ownerId => ownerId , state => $state , logMessage => $logMessage , lastModifiedDate => $lastModifiedDate)
1076              
1077             This method updated the metadata of an object. Required parameter is the $pid of the object. Optionally one or more of label, ownerId, state, logMessage
1078             and lastModifiedDate can be provided.
1079             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::modifyObject> model.
1080              
1081             Example:
1082            
1083             $fedora->modifyObject(pid => 'demo:29' , state => 'I');
1084            
1085             =cut
1086             sub modifyObject {
1087             my $self = shift;
1088             my %args = (pid => undef , @_);
1089            
1090             Carp::croak "need pid" unless $args{pid};
1091            
1092             my $pid = $args{pid};
1093            
1094             delete $args{pid};
1095            
1096             my %defaults = ();
1097              
1098             my %values = (%defaults,%args);
1099             my $form_data = [];
1100            
1101             for my $name (keys %values) {
1102             push @$form_data , { $name => $values{$name} };
1103             }
1104            
1105             return Catmandu::FedoraCommons::Response->factory(
1106             'modifyObject' , $self->_PUT('/objects/' . $pid , $form_data)
1107             );
1108             }
1109              
1110             =head2 purgeDatastream(pid => $pid , dsID => $dsID , startDT => $startDT , endDT => $endDT , logMessage => $logMessage)
1111              
1112             This method purges a data stream from an object. Required parameters is the $pid of the object and the $dsID of the data
1113             stream. Optionally a range $startDT to $endDT versions can be provided to be deleted.
1114             See: https://wiki.duraspace.org/display/FEDORA36/REST+API for more information.
1115             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::purgeDatastream> model.
1116              
1117             Example:
1118            
1119             $fedora->purgeDatastream(pid => 'demo:29', dsID => 'TEST')->parse_content;
1120            
1121             =cut
1122             sub purgeDatastream {
1123             my $self = shift;
1124             my %args = (pid => undef , dsID => undef, @_);
1125            
1126             Carp::croak "need pid" unless $args{pid};
1127             Carp::croak "need dsID" unless $args{dsID};
1128            
1129             my $pid = $args{pid};
1130             my $dsID = $args{dsID};
1131            
1132             delete $args{pid};
1133             delete $args{dsID};
1134            
1135             my %defaults = ();
1136            
1137             my %values = (%defaults,%args);
1138             my $form_data = [];
1139            
1140             for my $name (keys %values) {
1141             push @$form_data , { $name => $values{$name} };
1142             }
1143            
1144             return Catmandu::FedoraCommons::Response->factory(
1145             'purgeDatastream' , $self->_DELETE('/objects/' . $pid . '/datastreams/' . $dsID, $form_data)
1146             );
1147             }
1148              
1149             =head2 purgeObject(pid => $pid, logMessage => $logMessage)
1150              
1151             This method purges an object from Fedora Commons. Required parameter is the $pid of the object. Optionally a $logMessage can
1152             be provided.
1153             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::purgeObject> model.
1154              
1155             Example:
1156            
1157             $fedora->purgeObject(pid => 'demo:29');
1158              
1159             =cut
1160             sub purgeObject {
1161             my $self = shift;
1162             my %args = (pid => undef, @_);
1163            
1164             Carp::croak "need pid" unless $args{pid};
1165            
1166             my $pid = $args{pid};
1167            
1168             delete $args{pid};
1169            
1170             my %defaults = ();
1171            
1172             my %values = (%defaults,%args);
1173             my $form_data = [];
1174            
1175             for my $name (keys %values) {
1176             push @$form_data , { $name => $values{$name} };
1177             }
1178            
1179             return Catmandu::FedoraCommons::Response->factory(
1180             'purgeObject' , $self->_DELETE('/objects/' . $pid, $form_data)
1181             );
1182             }
1183              
1184             =head2 purgeRelationship(pid => $pid, relation => [ $subject, $predicate, $object] [, dataType => $dataType])
1185              
1186             This method removes a triple from the RELS-EXT data stream of an object. Required parameters are the $pid of
1187             the object and the relation to be deleted. Optionally the $dataType of the literal can be provided.
1188             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::purgeRelationship> model.
1189              
1190             Example:
1191            
1192             $fedora->purgeRelationship(pid => 'demo:29' , relation => [ 'info:fedora/demo:29' , 'http://my.org/name' , 'Peter'])
1193              
1194             =cut
1195             sub purgeRelationship {
1196             my $self = shift;
1197             my %args = (pid => undef , relation => undef, @_);
1198            
1199             Carp::croak "need pid" unless $args{pid};
1200             Carp::croak "need relation" unless defined $args{relation} && ref $args{relation} eq 'ARRAY';
1201            
1202             my $pid = $args{pid};
1203             my $subject = $args{relation}->[0];
1204             my $predicate = $args{relation}->[1];
1205             my $object = $args{relation}->[2];
1206             my $dataType = $args{dataType};
1207             my $isLiteral = is_uri($object) ? "false" : "true";
1208            
1209             my $form_data = [
1210             { subject => $subject },
1211             { predicate => $predicate },
1212             { object => $object },
1213             { dataType => $dataType },
1214             { isLiteral => $isLiteral },
1215             ];
1216              
1217             return Catmandu::FedoraCommons::Response->factory(
1218             'purgeRelationship' , $self->_DELETE('/objects/' . $pid . '/relationships', $form_data)
1219             );
1220             }
1221              
1222             =head2 setDatastreamState(pid => $pid, dsID => $dsID, dsState => $dsState)
1223              
1224             This method can be used to put a data stream on/offline. Required parameters are the $pid of the object , the
1225             $dsID of the data stream and the required new $dsState ((A)ctive, (I)nactive, (D)eleted).
1226             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::datastreamProfile> model.
1227            
1228             Example:
1229            
1230             $fedora->setDatastreamState(pid => 'demo:29' , dsID => 'url' , dsState => 'I');
1231            
1232             =cut
1233             sub setDatastreamState {
1234             my $self = shift;
1235             my %args = (pid => undef , dsID => undef, dsState => undef , @_);
1236            
1237             Carp::croak "need pid" unless $args{pid};
1238             Carp::croak "need dsID" unless $args{dsID};
1239             Carp::croak "need dsState" unless $args{dsState};
1240            
1241             my $pid = $args{pid};
1242             my $dsID = $args{dsID};
1243            
1244             delete $args{pid};
1245             delete $args{dsID};
1246            
1247             my %defaults = ();
1248            
1249             my %values = (%defaults,%args);
1250             my $form_data = [];
1251            
1252             for my $name (keys %values) {
1253             push @$form_data , { $name => $values{$name} };
1254             }
1255            
1256             return Catmandu::FedoraCommons::Response->factory(
1257             'setDatastreamState' , $self->_PUT('/objects/' . $pid . '/datastreams/' . $dsID, $form_data)
1258             );
1259             }
1260              
1261             =head2 setDatastreamVersionable(pid => $pid, dsID => $dsID, versionable => $versionable)
1262              
1263             This method updates the versionable state of a data stream. Required parameters are the $pid of the object,
1264             the $dsID of the data stream and the new $versionable (true|false) state.
1265             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::datastreamProfile> model.
1266              
1267             Example:
1268            
1269             $fedora->setDatastreamVersionable(pid => 'demo:29' , dsID => 'url' , versionable => 'false');
1270            
1271             =cut
1272             sub setDatastreamVersionable {
1273             my $self = shift;
1274             my %args = (pid => undef , dsID => undef, versionable => undef , @_);
1275            
1276             Carp::croak "need pid" unless $args{pid};
1277             Carp::croak "need dsID" unless $args{dsID};
1278             Carp::croak "need versionable" unless $args{versionable};
1279            
1280             my $pid = $args{pid};
1281             my $dsID = $args{dsID};
1282            
1283             delete $args{pid};
1284             delete $args{dsID};
1285            
1286             my %defaults = ();
1287            
1288             my %values = (%defaults,%args);
1289             my $form_data = [];
1290            
1291             for my $name (keys %values) {
1292             push @$form_data , { $name => $values{$name} };
1293             }
1294            
1295             return Catmandu::FedoraCommons::Response->factory(
1296             'setDatastreamVersionable' , $self->_PUT('/objects/' . $pid . '/datastreams/' . $dsID, $form_data)
1297             );
1298             }
1299              
1300             =head2 validate(pid => $pid)
1301              
1302             This method can be used to validate the content of an object. Required parameter is the $pid of the object.
1303             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::validate> model.
1304              
1305             Example:
1306            
1307             my $obj = $fedora->validate(pid => 'demo:29')->parse_content;
1308            
1309             print "Is valid: %s\n" , $obj->{valid};
1310            
1311             =cut
1312             sub validate {
1313             my $self = shift;
1314             my %args = (pid => undef , @_);
1315            
1316             Carp::croak "need pid" unless $args{pid};
1317            
1318             my $pid = $args{pid};
1319            
1320             delete $args{pid};
1321            
1322             my %defaults = ();
1323            
1324             my %values = (%defaults,%args);
1325             my $form_data = [];
1326            
1327             for my $name (keys %values) {
1328             push @$form_data , { $name => $values{$name} };
1329             }
1330            
1331             return Catmandu::FedoraCommons::Response->factory(
1332             'validate' , $self->_GET('/objects/' . $pid . '/validate', $form_data)
1333             );
1334             }
1335              
1336             =head2 upload(file => $file)
1337              
1338             This method uploads a file to the Fedora Server. Required parameter is the $file name.
1339             This method returns a L<Catmandu::FedoraCommons::Response> object with a L<Catmandu::FedoraCommons::Model::upload-> model.
1340              
1341             Example:
1342            
1343             my $obj = $fedora->upload(file => 't/marc.xml')->parse_content;
1344            
1345             print "Upload id: %s\n" , $obj->{id};
1346            
1347             =cut
1348             sub upload {
1349             my $self = shift;
1350             my %args = (file => undef , @_);
1351            
1352             Carp::croak "need file" unless $args{file};
1353            
1354             my $file = $args{file};
1355              
1356             delete $args{file};
1357            
1358             my $form_data = [ { file => [ "$file"] }];
1359            
1360             return Catmandu::FedoraCommons::Response->factory(
1361             'upload' , $self->_POST('/upload', $form_data)
1362             );
1363             }
1364              
1365              
1366             =head1 SEE ALSO
1367              
1368             L<Catmandu::FedoraCommons::Response>,
1369             L<Catmandu::Model::findObjects>,
1370             L<Catmandu::Model::getObjectHistory>,
1371             L<Catmandu::Model::getObjectProfile>,
1372             L<Catmandu::Model::listDatastreams>,
1373             L<Catmandu::Model::listMethods>
1374              
1375             =head1 AUTHOR
1376              
1377             =over
1378              
1379             =item * Patrick Hochstenbach, C<< <patrick.hochstenbach at ugent.be> >>
1380              
1381             =back
1382              
1383             =head1 LICENSE AND COPYRIGHT
1384              
1385             This program is free software; you can redistribute it and/or modify it under the terms
1386             of either: the GNU General Public License as published by the Free Software Foundation;
1387             or the Artistic License.
1388              
1389             See L<http://dev.perl.org/licenses/> for more information.
1390              
1391             =cut
1392              
1393              
1394             1;