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