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