Fix 2.4.2 upgrade notes formatting refs #19330
[arvados.git] / sdk / perl / lib / Arvados / ResourceMethod.pm
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: Apache-2.0
4
5 package Arvados::ResourceMethod;
6 use Carp;
7 use Data::Dumper;
8
9 sub new
10 {
11     my $class = shift;
12     my $self = {};
13     bless ($self, $class);
14     return $self->_init(@_);
15 }
16
17 sub _init
18 {
19     my $self = shift;
20     $self->{'resourceAccessor'} = shift;
21     $self->{'method'} = shift;
22     return $self;
23 }
24
25 sub execute
26 {
27     my $self = shift;
28     my $method = $self->{'method'};
29
30     my $path = $method->{'path'};
31
32     my %body_params;
33     my %given_params = @_;
34     my %extra_params = %given_params;
35     my %method_params = %{$method->{'parameters'}};
36     if ($method->{'request'}->{'properties'}) {
37         while (my ($prop_name, $prop_value) =
38                each %{$method->{'request'}->{'properties'}}) {
39             if (ref($prop_value) eq 'HASH' && $prop_value->{'$ref'}) {
40                 $method_params{$prop_name} = { 'type' => 'object' };
41             }
42         }
43     }
44     while (my ($param_name, $param) = each %method_params) {
45         delete $extra_params{$param_name};
46         if ($param->{'required'} && !exists $given_params{$param_name}) {
47             croak("Required parameter not supplied: $param_name");
48         }
49         elsif ($param->{'location'} eq 'path') {
50             $path =~ s/{\Q$param_name\E}/$given_params{$param_name}/eg;
51         }
52         elsif (!exists $given_params{$param_name}) {
53             ;
54         }
55         elsif ($param->{'type'} eq 'object') {
56             my %param_value;
57             my ($p, $v);
58             if (exists $param->{'properties'}) {
59                 while (my ($property_name, $property) =
60                        each %{$param->{'properties'}}) {
61                     # if the discovery doc specifies object structure,
62                     # convert to true/false depending on supplied type
63                     if (!exists $given_params{$param_name}->{$property_name}) {
64                         ;
65                     }
66                     elsif (!defined $given_params{$param_name}->{$property_name}) {
67                         $param_value{$property_name} = JSON::null;
68                     }
69                     elsif ($property->{'type'} eq 'boolean') {
70                         $param_value{$property_name} = $given_params{$param_name}->{$property_name} ? JSON::true : JSON::false;
71                     }
72                     else {
73                         $param_value{$property_name} = $given_params{$param_name}->{$property_name};
74                     }
75                 }
76             }
77             else {
78                 while (my ($property_name, $property) =
79                        each %{$given_params{$param_name}}) {
80                     if (ref $property eq '' || $property eq undef) {
81                         $param_value{$property_name} = $property;
82                     }
83                     elsif (ref $property eq 'HASH') {
84                         $param_value{$property_name} = {};
85                         while (my ($k, $v) = each %$property) {
86                             $param_value{$property_name}->{$k} = $v;
87                         }
88                     }
89                 }
90             }
91             $body_params{$param_name} = \%param_value;
92         } elsif ($param->{'type'} eq 'boolean') {
93             $body_params{$param_name} = $given_params{$param_name} ? JSON::true : JSON::false;
94         } else {
95             $body_params{$param_name} = $given_params{$param_name};
96         }
97     }
98     if (%extra_params) {
99         croak("Unsupported parameter(s) passed to API call /$path: \"" . join('", "', keys %extra_params) . '"');
100     }
101     my $r = $self->{'resourceAccessor'}->{'api'}->new_request;
102     my $base_uri = $self->{'resourceAccessor'}->{'api'}->{'discoveryDocument'}->{'baseUrl'};
103     $base_uri =~ s:/$::;
104     $r->set_uri($base_uri . "/" . $path);
105     $r->set_method($method->{'httpMethod'});
106     $r->set_auth_token($self->{'resourceAccessor'}->{'api'}->{'authToken'});
107     $r->set_query_params(\%body_params) if %body_params;
108     $r->process_request();
109     my $data, $headers;
110     my ($status_number, $status_phrase) = $r->get_status();
111     if ($status_number != 200) {
112         croak("API call /$path failed: $status_number $status_phrase\n". $r->get_body());
113     }
114     $data = $r->get_body();
115     $headers = $r->get_headers();
116     my $result = JSON::decode_json($data);
117     if ($method->{'response'}->{'$ref'} =~ /List$/) {
118         Arvados::ResourceProxyList->new($result, $self->{'resourceAccessor'});
119     } else {
120         Arvados::ResourceProxy->new($result, $self->{'resourceAccessor'});
121     }
122 }
123
124 1;