supply entire client-provided object if discovery doc does not describe structure
[arvados.git] / sdk / perl / lib / Arvados / ResourceMethod.pm
1 package Arvados::ResourceMethod;
2 use Carp;
3 use Data::Dumper;
4
5 sub new
6 {
7     my $class = shift;
8     my $self = {};
9     bless ($self, $class);
10     return $self->_init(@_);
11 }
12
13 sub _init
14 {
15     my $self = shift;
16     $self->{'resourceAccessor'} = shift;
17     $self->{'method'} = shift;
18     return $self;
19 }
20
21 sub execute
22 {
23     my $self = shift;
24     my $method = $self->{'method'};
25
26     my $path = $method->{'path'};
27
28     my %body_params;
29     my %given_params = @_;
30     while (my ($param_name, $param) = each %{$method->{'parameters'}}) {
31         if ($param->{'required'} && !exists $given_params{$param_name}) {
32             croak("Required parameter not supplied: $param_name");
33         }
34         elsif ($param->{'location'} eq 'path') {
35             $path =~ s/{\Q$param_name\E}/$given_params{$param_name}/eg;
36         }
37         elsif (!exists $given_params{$param_name}) {
38             ;
39         }
40         elsif ($param->{'type'} eq 'object') {
41             my %param_value;
42             my ($p, $v);
43             if (exists $param->{'properties'}) {
44                 while (my ($property_name, $property) =
45                        each %{$param->{'properties'}}) {
46                     # if the discovery doc specifies object structure,
47                     # convert to true/false depending on supplied type
48                     if (!exists $given_params{$param_name}->{$property_name}) {
49                         ;
50                     }
51                     elsif ($given_params{$param_name}->{$property_name} eq undef) {
52                         $param_value{$property_name} = JSON::null;
53                     }
54                     elsif ($property->{'type'} eq 'boolean') {
55                         $param_value{$property_name} = $given_params{$param_name}->{$property_name} ? JSON::true : JSON::false;
56                     }
57                     else {
58                         $param_value{$property_name} = $given_params{$param_name}->{$property_name};
59                     }
60                 }
61             }
62             else {
63                 while (my ($property_name, $property) =
64                        each %{$given_params{$param_name}}) {
65                     if (ref $property eq '' || $property eq undef) {
66                         $param_value{$property_name} = $property;
67                     }
68                 }
69             }
70             $body_params{$param_name} = \%param_value;
71         } elsif ($param->{'type'} eq 'boolean') {
72             $body_params{$param_name} = $given_params{$param_name} ? JSON::true : JSON::false;
73         } else {
74             $body_params{$param_name} = $given_params{$param_name};
75         }
76     }
77     my $r = $self->{'resourceAccessor'}->{'api'}->new_request;
78     $r->set_uri($self->{'resourceAccessor'}->{'api'}->{'discoveryDocument'}->{'baseUrl'} . "/" . $path);
79     $r->set_method($method->{'httpMethod'});
80     $r->set_auth_token($self->{'resourceAccessor'}->{'api'}->{'authToken'});
81     $r->set_query_params(\%body_params) if %body_params;
82     $r->process_request();
83     my $data, $headers;
84     my ($status_number, $status_phrase) = $r->get_status();
85     if ($status_number != 200) {
86         croak("API call failed: $status_number $status_phrase\n". $r->get_body());
87     }
88     $data = $r->get_body();
89     $headers = $r->get_headers();
90     my $result = JSON::decode_json($data);
91     if ($method->{'response'}->{'$ref'} =~ /List$/) {
92         Arvados::ResourceProxyList->new($result, $self->{'resourceAccessor'});
93     } else {
94         Arvados::ResourceProxy->new($result, $self->{'resourceAccessor'});
95     }
96 }
97
98 1;