Apply usual parameter encoding logic to method[request] parameter too.
[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     my %extra_params = %given_params;
31     my %method_params = %{$method->{'parameters'}};
32     if ($method->{'request'}->{'properties'}) {
33         while (my ($prop_name, $prop_value) =
34                each %{$method->{'request'}->{'properties'}}) {
35             if (ref($prop_value) eq 'HASH' && $prop_value->{'$ref'}) {
36                 $method_params{$prop_name} = { 'type' => 'object' };
37             }
38         }
39     }
40     while (my ($param_name, $param) = each %method_params) {
41         delete $extra_params{$param_name};
42         if ($param->{'required'} && !exists $given_params{$param_name}) {
43             croak("Required parameter not supplied: $param_name");
44         }
45         elsif ($param->{'location'} eq 'path') {
46             $path =~ s/{\Q$param_name\E}/$given_params{$param_name}/eg;
47         }
48         elsif (!exists $given_params{$param_name}) {
49             ;
50         }
51         elsif ($param->{'type'} eq 'object') {
52             my %param_value;
53             my ($p, $v);
54             if (exists $param->{'properties'}) {
55                 while (my ($property_name, $property) =
56                        each %{$param->{'properties'}}) {
57                     # if the discovery doc specifies object structure,
58                     # convert to true/false depending on supplied type
59                     if (!exists $given_params{$param_name}->{$property_name}) {
60                         ;
61                     }
62                     elsif (!defined $given_params{$param_name}->{$property_name}) {
63                         $param_value{$property_name} = JSON::null;
64                     }
65                     elsif ($property->{'type'} eq 'boolean') {
66                         $param_value{$property_name} = $given_params{$param_name}->{$property_name} ? JSON::true : JSON::false;
67                     }
68                     else {
69                         $param_value{$property_name} = $given_params{$param_name}->{$property_name};
70                     }
71                 }
72             }
73             else {
74                 while (my ($property_name, $property) =
75                        each %{$given_params{$param_name}}) {
76                     if (ref $property eq '' || $property eq undef) {
77                         $param_value{$property_name} = $property;
78                     }
79                 }
80             }
81             $body_params{$param_name} = \%param_value;
82         } elsif ($param->{'type'} eq 'boolean') {
83             $body_params{$param_name} = $given_params{$param_name} ? JSON::true : JSON::false;
84         } else {
85             $body_params{$param_name} = $given_params{$param_name};
86         }
87     }
88     if (%extra_params) {
89         croak("Unsupported parameter(s) passed to API call /$path: \"" . join('", "', keys %extra_params) . '"');
90     }
91     my $r = $self->{'resourceAccessor'}->{'api'}->new_request;
92     my $base_uri = $self->{'resourceAccessor'}->{'api'}->{'discoveryDocument'}->{'baseUrl'};
93     $base_uri =~ s:/$::;
94     $r->set_uri($base_uri . "/" . $path);
95     $r->set_method($method->{'httpMethod'});
96     $r->set_auth_token($self->{'resourceAccessor'}->{'api'}->{'authToken'});
97     $r->set_query_params(\%body_params) if %body_params;
98     $r->process_request();
99     my $data, $headers;
100     my ($status_number, $status_phrase) = $r->get_status();
101     if ($status_number != 200) {
102         croak("API call /$path failed: $status_number $status_phrase\n". $r->get_body());
103     }
104     $data = $r->get_body();
105     $headers = $r->get_headers();
106     my $result = JSON::decode_json($data);
107     if ($method->{'response'}->{'$ref'} =~ /List$/) {
108         Arvados::ResourceProxyList->new($result, $self->{'resourceAccessor'});
109     } else {
110         Arvados::ResourceProxy->new($result, $self->{'resourceAccessor'});
111     }
112 }
113
114 1;