| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # | 
| 2 |  |  |  |  |  |  | # Web::DataService::Request | 
| 3 |  |  |  |  |  |  | # | 
| 4 |  |  |  |  |  |  | # A base class that implements a data service for the PaleoDB.  This can be | 
| 5 |  |  |  |  |  |  | # subclassed to produce any necessary data service.  For examples, see | 
| 6 |  |  |  |  |  |  | # TaxonQuery.pm and CollectionQuery.pm. | 
| 7 |  |  |  |  |  |  | # | 
| 8 |  |  |  |  |  |  | # Author: Michael McClennen | 
| 9 |  |  |  |  |  |  |  | 
| 10 | 2 |  |  | 2 |  | 15 | use strict; | 
|  | 2 |  |  |  |  | 20 |  | 
|  | 2 |  |  |  |  | 87 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | package Web::DataService::Request; | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 2 |  |  | 2 |  | 13 | use Carp 'croak'; | 
|  | 2 |  |  |  |  | 6 |  | 
|  | 2 |  |  |  |  | 112 |  | 
| 15 |  |  |  |  |  |  |  | 
| 16 | 2 |  |  | 2 |  | 1213 | use Moo; | 
|  | 2 |  |  |  |  | 5658 |  | 
|  | 2 |  |  |  |  | 10 |  | 
| 17 | 2 |  |  | 2 |  | 4070 | use namespace::clean; | 
|  | 2 |  |  |  |  | 20103 |  | 
|  | 2 |  |  |  |  | 14 |  | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | # The required attribute 'ds' is the data service with which this request is | 
| 21 |  |  |  |  |  |  | # associated. | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | has ds => ( is => 'ro', isa => \&is_dataservice_object, required => 1 ); | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | # The required attribute 'outer' is the request object generated by the | 
| 26 |  |  |  |  |  |  | # foundation framework. | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | has outer => ( is => 'ro', required => 1 ); | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | # The attribute 'path' selects the data service node which will be used to | 
| 31 |  |  |  |  |  |  | # process the request.  If not given explicitly, it will be retrieved from the | 
| 32 |  |  |  |  |  |  | # 'outer' request object. | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | has path => ( is => 'rw', trigger => \&_match_node ); | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | # The following argument can be specified separately, or you can let it be | 
| 37 |  |  |  |  |  |  | # extracted from the value of 'path'.  But note that if 'path' does not | 
| 38 |  |  |  |  |  |  | # correspond to a defined node, then 'rest_path' will be modified | 
| 39 |  |  |  |  |  |  | # accordingly. | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | has rest_path => ( is => 'ro' ); | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | # The attribute 'http_method' selects the HTTP method which will be used to | 
| 44 |  |  |  |  |  |  | # process the request. If not given explicitly, it will be retrieved from the | 
| 45 |  |  |  |  |  |  | # 'outer' request object. | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | has http_method => ( is => 'rw' ); | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | # The following attributes will be determined automatically by | 
| 50 |  |  |  |  |  |  | # Web::DataService, unless explicitly defined at initialization time or | 
| 51 |  |  |  |  |  |  | # explicitly overridden later. | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | has is_invalid_request => ( is => 'rw' ); | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | has is_doc_request => ( is => 'rw' ); | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | has output_format => ( is => 'rw' ); | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | has output_vocab => ( is => 'rw' ); | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | has output_linebreak => ( is => 'rw' ); | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | has result_limit => ( is => 'rw' ); | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | has result_offset => ( is => 'rw' ); | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | has display_header => ( is => 'rw' ); #, lazy => 1, builder => sub { $_[0]->_init_value('header') } ); | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | has display_datainfo => ( is => 'rw' ); | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | has display_counts => ( is => 'rw' ); | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | has save_output => ( is => 'rw' ); | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | has save_filename => ( is => 'rw' ); | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | has do_not_stream => ( is => 'rw' ); | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | # The following attributes will be determined automatically by | 
| 80 |  |  |  |  |  |  | # Web::DataService and should not be overridden. | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | has node_path => ( is => 'ro', init_arg => '_node_path' ); | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | has is_node_path => ( is => 'ro', init_arg => undef ); | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  |  | 
| 87 |  |  |  |  |  |  | # BUILD ( ) | 
| 88 |  |  |  |  |  |  | # | 
| 89 |  |  |  |  |  |  | # Finish generating a new request object.  This involves determining the "node | 
| 90 |  |  |  |  |  |  | # path" from the "raw path" that was specified when this object was | 
| 91 |  |  |  |  |  |  | # initialized.  Depending upon the features enabled for this data service, the | 
| 92 |  |  |  |  |  |  | # path may be processed in different ways. | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | sub BUILD { | 
| 95 |  |  |  |  |  |  |  | 
| 96 | 0 |  |  | 0 | 0 |  | my ($self) = @_; | 
| 97 |  |  |  |  |  |  |  | 
| 98 | 0 |  |  |  |  |  | my $ds = $self->{ds}; | 
| 99 |  |  |  |  |  |  | } | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | sub is_dataservice_object { | 
| 103 |  |  |  |  |  |  |  | 
| 104 | 0 | 0 | 0 | 0 | 0 |  | die "must be an object of class Web::DataService" | 
| 105 |  |  |  |  |  |  | unless ref $_[0] && $_[0]->isa('Web::DataService'); | 
| 106 |  |  |  |  |  |  | } | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | sub _init_value { | 
| 110 |  |  |  |  |  |  |  | 
| 111 | 0 |  |  | 0 |  |  | my ($self, $attr) = @_; | 
| 112 |  |  |  |  |  |  |  | 
| 113 | 0 | 0 |  |  |  |  | if ( my $special = $self->special_value($attr) ) | 
|  |  | 0 |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | { | 
| 115 | 0 |  |  |  |  |  | return $special; | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | elsif ( my $default = $self->{ds}->node_attr("default_$attr") ) | 
| 119 |  |  |  |  |  |  | { | 
| 120 | 0 |  |  |  |  |  | return $default; | 
| 121 |  |  |  |  |  |  | } | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | else | 
| 124 |  |  |  |  |  |  | { | 
| 125 | 0 |  |  |  |  |  | return; | 
| 126 |  |  |  |  |  |  | } | 
| 127 |  |  |  |  |  |  | } | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | # _match_node ( ) | 
| 131 |  |  |  |  |  |  | # | 
| 132 |  |  |  |  |  |  | # This routine will be called whenever the 'path' attribute of this request is | 
| 133 |  |  |  |  |  |  | # set.  It determines the closest matching 'node_path' and sets some other | 
| 134 |  |  |  |  |  |  | # attributes. | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | sub _match_node { | 
| 137 |  |  |  |  |  |  |  | 
| 138 | 0 |  |  | 0 |  |  | my ($self) = @_; | 
| 139 |  |  |  |  |  |  |  | 
| 140 | 0 |  |  |  |  |  | local($Carp::CarpLevel) = 1;	# We shouldn't have to do this, but | 
| 141 |  |  |  |  |  |  | # Moo and Carp don't play well together. | 
| 142 |  |  |  |  |  |  |  | 
| 143 | 0 |  |  |  |  |  | my $ds = $self->{ds}; | 
| 144 | 0 |  |  |  |  |  | my $raw_path = $self->{path}; | 
| 145 | 0 |  |  |  |  |  | my $suffix_is_missing; | 
| 146 |  |  |  |  |  |  |  | 
| 147 |  |  |  |  |  |  | # We start with the raw path and trim it in various ways to find the | 
| 148 |  |  |  |  |  |  | # closest matching data service node. | 
| 149 |  |  |  |  |  |  |  | 
| 150 | 0 |  |  |  |  |  | my $node_path = $raw_path; | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  | # If the raw path exactly matches any node, we just use that.  Otherwise, | 
| 153 |  |  |  |  |  |  | # apply any applicable path transformations. | 
| 154 |  |  |  |  |  |  |  | 
| 155 | 0 | 0 |  |  |  |  | if ( exists $ds->{node_attrs}{$raw_path} ) | 
| 156 |  |  |  |  |  |  | { | 
| 157 | 0 |  |  |  |  |  | $self->{is_node_path} = 1; | 
| 158 | 0 | 0 |  |  |  |  | $self->{is_doc_request} = 1 if $ds->has_feature('format_suffix'); | 
| 159 |  |  |  |  |  |  | } | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | else | 
| 162 |  |  |  |  |  |  | { | 
| 163 |  |  |  |  |  |  | # If the feature 'format_suffix' is enabled and the specified path has | 
| 164 |  |  |  |  |  |  | # a suffix, split it off. | 
| 165 |  |  |  |  |  |  |  | 
| 166 | 0 | 0 |  |  |  |  | if ( $ds->has_feature('format_suffix') ) | 
| 167 |  |  |  |  |  |  | { | 
| 168 | 0 | 0 |  |  |  |  | if ( $node_path =~ qr{ ^ (.+) [.] (.+) }xs ) | 
| 169 |  |  |  |  |  |  | { | 
| 170 | 0 |  |  |  |  |  | $node_path = $1; | 
| 171 | 0 |  |  |  |  |  | $self->output_format($2); | 
| 172 |  |  |  |  |  |  | } | 
| 173 |  |  |  |  |  |  |  | 
| 174 |  |  |  |  |  |  | else | 
| 175 |  |  |  |  |  |  | { | 
| 176 | 0 |  |  |  |  |  | $suffix_is_missing = 1; | 
| 177 |  |  |  |  |  |  | } | 
| 178 |  |  |  |  |  |  | } | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | # If the feature 'doc_paths' is enabled and the specified path ends in | 
| 181 |  |  |  |  |  |  | # '_doc', remove that string and set the 'is_doc_request' flag for this | 
| 182 |  |  |  |  |  |  | # request.  Under this feature, the path "abc/def_doc" indicates a | 
| 183 |  |  |  |  |  |  | # request for doumentation about the path "abc/def". | 
| 184 |  |  |  |  |  |  |  | 
| 185 | 0 | 0 |  |  |  |  | if ( $ds->has_feature('doc_paths') ) | 
|  |  | 0 |  |  |  |  |  | 
| 186 |  |  |  |  |  |  | { | 
| 187 | 0 | 0 | 0 |  |  |  | if ( $node_path eq '' ) | 
|  |  | 0 | 0 |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 188 |  |  |  |  |  |  | { | 
| 189 | 0 |  |  |  |  |  | $self->{is_doc_request} = 1; | 
| 190 |  |  |  |  |  |  | } | 
| 191 |  |  |  |  |  |  |  | 
| 192 |  |  |  |  |  |  | elsif ( ref $ds->{doc_path_regex} eq 'Regexp' && $node_path =~ $ds->{doc_path_regex} ) | 
| 193 |  |  |  |  |  |  | { | 
| 194 | 0 |  |  |  |  |  | $node_path = $1; | 
| 195 | 0 |  |  |  |  |  | $self->{is_doc_request} = 1; | 
| 196 |  |  |  |  |  |  | } | 
| 197 |  |  |  |  |  |  |  | 
| 198 |  |  |  |  |  |  | elsif ( $ds->{doc_index} && $node_path eq $ds->{doc_index} ) | 
| 199 |  |  |  |  |  |  | { | 
| 200 | 0 |  |  |  |  |  | $node_path = ''; | 
| 201 | 0 |  |  |  |  |  | $self->{is_doc_request} = 1; | 
| 202 |  |  |  |  |  |  | } | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | elsif ( $suffix_is_missing ) | 
| 205 |  |  |  |  |  |  | { | 
| 206 | 0 |  |  |  |  |  | $self->{is_doc_request} = 1; | 
| 207 |  |  |  |  |  |  | } | 
| 208 |  |  |  |  |  |  | } | 
| 209 |  |  |  |  |  |  |  | 
| 210 |  |  |  |  |  |  | # Otherwise, if the special parameter 'document' is enabled and | 
| 211 |  |  |  |  |  |  | # present then set the 'is_doc_request' flag for this request. | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | elsif ( my $document_param = $ds->special_param('document') ) | 
| 214 |  |  |  |  |  |  | { | 
| 215 | 0 |  |  |  |  |  | my $params = $Web::DataService::FOUNDATION->get_params($self->{outer}); | 
| 216 |  |  |  |  |  |  |  | 
| 217 | 0 | 0 |  |  |  |  | $self->{is_doc_request} = 1 if defined $params->{$document_param}; | 
| 218 |  |  |  |  |  |  | } | 
| 219 |  |  |  |  |  |  |  | 
| 220 |  |  |  |  |  |  | # We then lop off components as necessary until we get to a node that has | 
| 221 |  |  |  |  |  |  | # attributes or until we reach the empty string.  We set the 'is_node_path' | 
| 222 |  |  |  |  |  |  | # flag to 0 (unless it has already been set) to indicate that the request | 
| 223 |  |  |  |  |  |  | # path does not fully match a defined node. | 
| 224 |  |  |  |  |  |  |  | 
| 225 | 0 |  |  |  |  |  | while ( $node_path ne '' ) | 
| 226 |  |  |  |  |  |  | { | 
| 227 |  |  |  |  |  |  | # If we find a node with attributes, stop here. | 
| 228 |  |  |  |  |  |  |  | 
| 229 | 0 | 0 |  |  |  |  | last if exists $ds->{node_attrs}{$node_path}; | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | # If this is a documentation request and a template exists that | 
| 232 |  |  |  |  |  |  | # would correspond to the current node path, then create the node | 
| 233 |  |  |  |  |  |  | # and stop here. | 
| 234 |  |  |  |  |  |  |  | 
| 235 | 0 | 0 | 0 |  |  |  | if ( $self->{is_doc_request} and my $doc_path = $ds->check_for_template($node_path) ) | 
| 236 |  |  |  |  |  |  | { | 
| 237 | 0 |  |  |  |  |  | $ds->make_doc_node($node_path, $doc_path); | 
| 238 | 0 |  |  |  |  |  | last; | 
| 239 |  |  |  |  |  |  | } | 
| 240 |  |  |  |  |  |  |  | 
| 241 |  |  |  |  |  |  | # Otherwise, lop off the last path component and try again. | 
| 242 |  |  |  |  |  |  |  | 
| 243 | 0 |  | 0 |  |  |  | $self->{is_node_path} //= 0; | 
| 244 |  |  |  |  |  |  |  | 
| 245 | 0 | 0 |  |  |  |  | if ( $node_path =~ qr{ ^ (.*) / (.*) }xs ) | 
| 246 |  |  |  |  |  |  | { | 
| 247 | 0 |  |  |  |  |  | $node_path = $1; | 
| 248 |  |  |  |  |  |  | } | 
| 249 |  |  |  |  |  |  |  | 
| 250 |  |  |  |  |  |  | else | 
| 251 |  |  |  |  |  |  | { | 
| 252 | 0 |  |  |  |  |  | $node_path = ''; | 
| 253 |  |  |  |  |  |  | } | 
| 254 |  |  |  |  |  |  | } | 
| 255 |  |  |  |  |  |  | } | 
| 256 |  |  |  |  |  |  |  | 
| 257 |  |  |  |  |  |  | # An empty path should always produce documentation.  In fact, it should | 
| 258 |  |  |  |  |  |  | # produce a "main documentation page" for this data service.  The data | 
| 259 |  |  |  |  |  |  | # service author should make sure that this is so. | 
| 260 |  |  |  |  |  |  |  | 
| 261 | 0 | 0 |  |  |  |  | if ( $node_path eq '' ) | 
|  |  | 0 |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | { | 
| 263 | 0 |  |  |  |  |  | $self->{is_doc_request} = 1; | 
| 264 |  |  |  |  |  |  | } | 
| 265 |  |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | # If the selected node is disabled, set the 'is_invalid_request' attribute. | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | elsif ( $ds->node_attr($node_path, 'disabled') ) | 
| 269 |  |  |  |  |  |  | { | 
| 270 | 0 |  |  |  |  |  | $self->{is_invalid_request} = 1; | 
| 271 |  |  |  |  |  |  | } | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  | # If 'is_node_path' has not yet been set, then we assume it should be 1. | 
| 274 |  |  |  |  |  |  |  | 
| 275 | 0 |  | 0 |  |  |  | $self->{is_node_path} //= 1; | 
| 276 |  |  |  |  |  |  |  | 
| 277 |  |  |  |  |  |  | # We save all of the characters removed from the raw path as $rest_path, | 
| 278 |  |  |  |  |  |  | # so that (for example) we can send a requested file. | 
| 279 |  |  |  |  |  |  |  | 
| 280 | 0 |  |  |  |  |  | $self->{rest_path} = substr($raw_path, length($node_path)); | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | # If we got an empty path, turn it into the root node path '/'. | 
| 283 |  |  |  |  |  |  |  | 
| 284 | 0 | 0 |  |  |  |  | $self->{node_path} = $node_path eq '' ? '/' : $node_path; | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | # If the node that we got has either the 'file_path' or 'file_dir' | 
| 287 |  |  |  |  |  |  | # attribute, then mark this request as 'is_file_path'.  If it has | 
| 288 |  |  |  |  |  |  | # 'file_path', then it is invalid unless $rest_path is empty.  If it has | 
| 289 |  |  |  |  |  |  | # 'file_dir', then it is invalid unless $rest_path is NOT empty. | 
| 290 |  |  |  |  |  |  |  | 
| 291 | 0 | 0 |  |  |  |  | if ( $ds->node_attr($self->{node_path}, 'file_dir') ) | 
|  |  | 0 |  |  |  |  |  | 
| 292 |  |  |  |  |  |  | { | 
| 293 | 0 |  |  |  |  |  | $self->{is_file_path} = 1; | 
| 294 |  |  |  |  |  |  | $self->{is_invalid_request} = 1 unless defined $self->{rest_path} && | 
| 295 | 0 | 0 | 0 |  |  |  | $self->{rest_path} ne ''; | 
| 296 |  |  |  |  |  |  | } | 
| 297 |  |  |  |  |  |  |  | 
| 298 |  |  |  |  |  |  | elsif ( $ds->node_attr($self->{node_path}, 'file_path' ) ) | 
| 299 |  |  |  |  |  |  | { | 
| 300 | 0 |  |  |  |  |  | $self->{is_file_path} = 1; | 
| 301 |  |  |  |  |  |  | $self->{is_invalid_request} = 1 if defined $self->{rest_path} && | 
| 302 | 0 | 0 | 0 |  |  |  | $self->{rest_path} ne ''; | 
| 303 |  |  |  |  |  |  | } | 
| 304 |  |  |  |  |  |  | } | 
| 305 |  |  |  |  |  |  |  | 
| 306 |  |  |  |  |  |  |  | 
| 307 |  |  |  |  |  |  | # execute ( ) | 
| 308 |  |  |  |  |  |  | # | 
| 309 |  |  |  |  |  |  | # Execute this request, and return the result. | 
| 310 |  |  |  |  |  |  |  | 
| 311 |  |  |  |  |  |  | sub execute { | 
| 312 |  |  |  |  |  |  |  | 
| 313 | 0 |  |  | 0 | 1 |  | return $_[0]->{ds}->execute_request($_[0]->{outer}); | 
| 314 |  |  |  |  |  |  | } | 
| 315 |  |  |  |  |  |  |  | 
| 316 |  |  |  |  |  |  |  | 
| 317 |  |  |  |  |  |  | # configure ( ) | 
| 318 |  |  |  |  |  |  | # | 
| 319 |  |  |  |  |  |  | # Configure this request for execution. | 
| 320 |  |  |  |  |  |  |  | 
| 321 |  |  |  |  |  |  | sub configure { | 
| 322 |  |  |  |  |  |  |  | 
| 323 | 0 |  |  | 0 | 0 |  | return $_[0]->{ds}->configure_request($_[0]->{outer}); | 
| 324 |  |  |  |  |  |  | } | 
| 325 |  |  |  |  |  |  |  | 
| 326 |  |  |  |  |  |  |  | 
| 327 |  |  |  |  |  |  | # Common methods needed for both execution and documentation | 
| 328 |  |  |  |  |  |  |  | 
| 329 |  |  |  |  |  |  | # request_url | 
| 330 |  |  |  |  |  |  | # | 
| 331 |  |  |  |  |  |  | # Return the raw (unparsed) request URL | 
| 332 |  |  |  |  |  |  |  | 
| 333 |  |  |  |  |  |  | sub request_url { | 
| 334 |  |  |  |  |  |  |  | 
| 335 | 0 |  |  | 0 | 1 |  | return $Web::DataService::FOUNDATION->get_request_url($_[0]->{outer}); | 
| 336 |  |  |  |  |  |  | } | 
| 337 |  |  |  |  |  |  |  | 
| 338 |  |  |  |  |  |  |  | 
| 339 |  |  |  |  |  |  | # base_url | 
| 340 |  |  |  |  |  |  | # | 
| 341 |  |  |  |  |  |  | # Return the base component of the URL for this request, of the form "http://some.host/". | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | sub base_url { | 
| 344 |  |  |  |  |  |  |  | 
| 345 | 0 |  |  | 0 | 1 |  | return $Web::DataService::FOUNDATION->get_base_url($_[0]->{outer}); | 
| 346 |  |  |  |  |  |  | } | 
| 347 |  |  |  |  |  |  |  | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | # root_url ( ) | 
| 350 |  |  |  |  |  |  | # | 
| 351 |  |  |  |  |  |  | # Return the base url plus the path prefix. | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | sub root_url { | 
| 354 |  |  |  |  |  |  |  | 
| 355 | 0 |  |  | 0 | 1 |  | return $Web::DataService::FOUNDATION->get_base_url($_[0]) . $_[0]->{ds}{path_prefix}; | 
| 356 |  |  |  |  |  |  | } | 
| 357 |  |  |  |  |  |  |  | 
| 358 |  |  |  |  |  |  |  | 
| 359 |  |  |  |  |  |  | # path_prefix ( ) | 
| 360 |  |  |  |  |  |  | # | 
| 361 |  |  |  |  |  |  | # Return the path prefix for this request. | 
| 362 |  |  |  |  |  |  |  | 
| 363 |  |  |  |  |  |  | sub path_prefix { | 
| 364 |  |  |  |  |  |  |  | 
| 365 | 0 |  |  | 0 | 1 |  | return $_[0]->{ds}{path_prefix}; | 
| 366 |  |  |  |  |  |  | } | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  |  | 
| 369 |  |  |  |  |  |  | # generate_url ( attrs ) | 
| 370 |  |  |  |  |  |  | # | 
| 371 |  |  |  |  |  |  | # Generate a URL based on the specified attributes.  This routine calls | 
| 372 |  |  |  |  |  |  | # Web::DataService::generate_url to create a site-relative URL, then applies | 
| 373 |  |  |  |  |  |  | # the base URL from the current request if asked to do so. | 
| 374 |  |  |  |  |  |  |  | 
| 375 |  |  |  |  |  |  | sub generate_url { | 
| 376 |  |  |  |  |  |  |  | 
| 377 | 0 |  |  | 0 | 1 |  | my ($self, $attrs) = @_; | 
| 378 |  |  |  |  |  |  |  | 
| 379 | 0 |  |  |  |  |  | return $self->{ds}->generate_site_url($attrs); | 
| 380 |  |  |  |  |  |  | } | 
| 381 |  |  |  |  |  |  |  | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | # data_info ( ) | 
| 384 |  |  |  |  |  |  | # | 
| 385 |  |  |  |  |  |  | # Return a hash of information about the request. | 
| 386 |  |  |  |  |  |  |  | 
| 387 |  |  |  |  |  |  | sub data_info { | 
| 388 |  |  |  |  |  |  |  | 
| 389 | 0 |  |  | 0 | 1 |  | my ($self) = @_; | 
| 390 |  |  |  |  |  |  |  | 
| 391 |  |  |  |  |  |  | # We start with the information provided by the data service, and add some | 
| 392 |  |  |  |  |  |  | # info specific to this request. | 
| 393 |  |  |  |  |  |  |  | 
| 394 | 0 |  |  |  |  |  | my $ds = $self->{ds}; | 
| 395 | 0 |  |  |  |  |  | my $info = $ds->data_info; | 
| 396 |  |  |  |  |  |  |  | 
| 397 | 0 |  |  |  |  |  | my $node_path = $self->node_path; | 
| 398 | 0 |  |  |  |  |  | my $base_url = $self->base_url; | 
| 399 |  |  |  |  |  |  |  | 
| 400 | 0 |  |  |  |  |  | my $doc_url = $self->generate_url({ node => $node_path }); | 
| 401 | 0 |  |  |  |  |  | $doc_url =~ s{^/}{}; | 
| 402 | 0 |  |  |  |  |  | my $data_url = $self->request_url; | 
| 403 | 0 |  |  |  |  |  | $data_url =~ s{^/}{}; | 
| 404 |  |  |  |  |  |  |  | 
| 405 | 0 | 0 |  |  |  |  | $info->{documentation_url} = $base_url . $doc_url if $ds->{feature}{documentation}; | 
| 406 | 0 |  |  |  |  |  | $info->{data_url} = $base_url . $data_url; | 
| 407 |  |  |  |  |  |  |  | 
| 408 | 0 |  |  |  |  |  | return $info; | 
| 409 |  |  |  |  |  |  | } | 
| 410 |  |  |  |  |  |  |  | 
| 411 |  |  |  |  |  |  |  | 
| 412 |  |  |  |  |  |  | sub data_info_keys { | 
| 413 |  |  |  |  |  |  |  | 
| 414 | 0 |  |  | 0 | 1 |  | return $_[0]->{ds}->data_info_keys; | 
| 415 |  |  |  |  |  |  | } | 
| 416 |  |  |  |  |  |  |  | 
| 417 |  |  |  |  |  |  |  | 
| 418 |  |  |  |  |  |  | # contact_info ( ) | 
| 419 |  |  |  |  |  |  | # | 
| 420 |  |  |  |  |  |  | # Return a hash of information indicating who to contact about this data service. | 
| 421 |  |  |  |  |  |  |  | 
| 422 |  |  |  |  |  |  | sub contact_info { | 
| 423 |  |  |  |  |  |  |  | 
| 424 | 0 |  |  | 0 | 1 |  | my ($self) = @_; | 
| 425 |  |  |  |  |  |  |  | 
| 426 | 0 |  |  |  |  |  | my $ds = $self->{ds}; | 
| 427 | 0 |  |  |  |  |  | return $ds->contact_info; | 
| 428 |  |  |  |  |  |  | } | 
| 429 |  |  |  |  |  |  |  | 
| 430 |  |  |  |  |  |  |  | 
| 431 |  |  |  |  |  |  | # node_attr ( ) | 
| 432 |  |  |  |  |  |  | # | 
| 433 |  |  |  |  |  |  | # Return the specified attribute of the node that matches this request. | 
| 434 |  |  |  |  |  |  |  | 
| 435 |  |  |  |  |  |  | sub node_attr { | 
| 436 |  |  |  |  |  |  |  | 
| 437 | 0 |  |  | 0 | 1 |  | my ($self, $attr) = @_; | 
| 438 |  |  |  |  |  |  |  | 
| 439 | 0 |  |  |  |  |  | my $ds = $self->{ds}; | 
| 440 | 0 |  |  |  |  |  | my $path = $self->node_path; | 
| 441 |  |  |  |  |  |  |  | 
| 442 | 0 |  |  |  |  |  | return $ds->node_attr($path, $attr); | 
| 443 |  |  |  |  |  |  | } | 
| 444 |  |  |  |  |  |  |  | 
| 445 |  |  |  |  |  |  | # special_value ( param ) | 
| 446 |  |  |  |  |  |  | # | 
| 447 |  |  |  |  |  |  | # Return the value of the specified special param, if it is enabled, and if | 
| 448 |  |  |  |  |  |  | # it was specified.  Return undefined otherwise. | 
| 449 |  |  |  |  |  |  |  | 
| 450 |  |  |  |  |  |  | sub special_value { | 
| 451 |  |  |  |  |  |  |  | 
| 452 | 0 |  |  | 0 | 1 |  | my ($self, $param) = @_; | 
| 453 |  |  |  |  |  |  |  | 
| 454 | 0 |  |  |  |  |  | my $ds = $self->{ds}; | 
| 455 |  |  |  |  |  |  |  | 
| 456 | 0 |  | 0 |  |  |  | my $param_name = $ds->special_param($param) || return; | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  | # If we have already passed the params through HTTP::Validate, return the | 
| 459 |  |  |  |  |  |  | # cleaned value. | 
| 460 |  |  |  |  |  |  |  | 
| 461 | 0 | 0 |  |  |  |  | if ( ref $self->{valid} ) | 
| 462 |  |  |  |  |  |  | { | 
| 463 | 0 |  |  |  |  |  | my $value = $self->{valid}->value($param_name); | 
| 464 | 0 | 0 |  |  |  |  | return @$value if ref $value eq 'ARRAY'; | 
| 465 | 0 | 0 |  |  |  |  | return $value if defined $value; | 
| 466 | 0 |  |  |  |  |  | return; # otherwise | 
| 467 |  |  |  |  |  |  | } | 
| 468 |  |  |  |  |  |  |  | 
| 469 |  |  |  |  |  |  | # Otherwise, return the raw value if it exists and undefined otherwise. | 
| 470 |  |  |  |  |  |  |  | 
| 471 | 0 |  |  |  |  |  | return $self->{raw_params}{$param_name}; | 
| 472 |  |  |  |  |  |  | } | 
| 473 |  |  |  |  |  |  |  | 
| 474 |  |  |  |  |  |  |  | 
| 475 |  |  |  |  |  |  | # special_given ( param ) | 
| 476 |  |  |  |  |  |  | # | 
| 477 |  |  |  |  |  |  | # Return true if the given special parameter was specified in the request, | 
| 478 |  |  |  |  |  |  | # regardless of its value. | 
| 479 |  |  |  |  |  |  |  | 
| 480 |  |  |  |  |  |  | sub special_given { | 
| 481 |  |  |  |  |  |  |  | 
| 482 | 0 |  |  | 0 | 1 |  | my ($self, $param) = @_; | 
| 483 |  |  |  |  |  |  |  | 
| 484 | 0 |  |  |  |  |  | my $ds = $self->{ds}; | 
| 485 | 0 |  | 0 |  |  |  | my $param_name = $ds->special_param($param) || return; | 
| 486 |  |  |  |  |  |  |  | 
| 487 | 0 |  |  |  |  |  | return exists $self->{raw_params}{$param_name}; | 
| 488 |  |  |  |  |  |  | } | 
| 489 |  |  |  |  |  |  |  | 
| 490 |  |  |  |  |  |  |  | 
| 491 |  |  |  |  |  |  | # default_limit ( ) | 
| 492 |  |  |  |  |  |  | # | 
| 493 |  |  |  |  |  |  | # Return the default result limit, if any.  Return undefined otherwise. | 
| 494 |  |  |  |  |  |  |  | 
| 495 |  |  |  |  |  |  | sub default_limit { | 
| 496 |  |  |  |  |  |  |  | 
| 497 | 0 |  |  | 0 | 1 |  | my ($self) = @_; | 
| 498 |  |  |  |  |  |  |  | 
| 499 | 0 |  |  |  |  |  | my $path = $self->{node_path}; | 
| 500 | 0 |  |  |  |  |  | return $self->{ds}->node_attr($path, 'default_limit'); | 
| 501 |  |  |  |  |  |  | } | 
| 502 |  |  |  |  |  |  |  | 
| 503 |  |  |  |  |  |  |  | 
| 504 |  |  |  |  |  |  | sub set_scratch { | 
| 505 |  |  |  |  |  |  |  | 
| 506 | 0 |  |  | 0 | 0 |  | my ($self, $key, $value) = @_; | 
| 507 |  |  |  |  |  |  |  | 
| 508 | 0 |  |  |  |  |  | return $self->{ds}->set_scratch($key, $value); | 
| 509 |  |  |  |  |  |  | } | 
| 510 |  |  |  |  |  |  |  | 
| 511 |  |  |  |  |  |  |  | 
| 512 |  |  |  |  |  |  | sub get_scratch { | 
| 513 |  |  |  |  |  |  |  | 
| 514 | 0 |  |  | 0 | 0 |  | my ($self, $key) = @_; | 
| 515 |  |  |  |  |  |  |  | 
| 516 | 0 |  |  |  |  |  | return $self->{ds}->get_scratch($key); | 
| 517 |  |  |  |  |  |  | } | 
| 518 |  |  |  |  |  |  |  | 
| 519 |  |  |  |  |  |  |  | 
| 520 |  |  |  |  |  |  | sub add_warning { | 
| 521 |  |  |  |  |  |  |  | 
| 522 | 0 |  |  | 0 | 1 |  | my ($self, $warn_msg) = @_; | 
| 523 |  |  |  |  |  |  |  | 
| 524 | 0 | 0 |  |  |  |  | $self->{warnings} = [] unless ref $self->{warnings} eq 'ARRAY'; | 
| 525 | 0 |  |  |  |  |  | push @{$self->{warnings}}, $warn_msg; | 
|  | 0 |  |  |  |  |  |  | 
| 526 |  |  |  |  |  |  | } | 
| 527 |  |  |  |  |  |  |  | 
| 528 |  |  |  |  |  |  |  | 
| 529 |  |  |  |  |  |  | sub warnings { | 
| 530 |  |  |  |  |  |  |  | 
| 531 | 0 |  |  | 0 | 1 |  | my ($self) = @_; | 
| 532 |  |  |  |  |  |  |  | 
| 533 | 0 | 0 |  |  |  |  | return @{$self->{warnings}} if ref $self->{warnings} eq 'ARRAY'; | 
|  | 0 |  |  |  |  |  |  | 
| 534 | 0 |  |  |  |  |  | return; | 
| 535 |  |  |  |  |  |  | } | 
| 536 |  |  |  |  |  |  |  | 
| 537 |  |  |  |  |  |  |  | 
| 538 |  |  |  |  |  |  | sub errors { | 
| 539 |  |  |  |  |  |  |  | 
| 540 | 0 |  |  | 0 | 1 |  | my ($self) = @_; | 
| 541 |  |  |  |  |  |  |  | 
| 542 | 0 | 0 |  |  |  |  | return @{$self->{errors}} if ref $self->{errors} eq 'ARRAY'; | 
|  | 0 |  |  |  |  |  |  | 
| 543 | 0 |  |  |  |  |  | return; | 
| 544 |  |  |  |  |  |  | } | 
| 545 |  |  |  |  |  |  |  | 
| 546 |  |  |  |  |  |  |  | 
| 547 |  |  |  |  |  |  | sub cautions { | 
| 548 |  |  |  |  |  |  |  | 
| 549 | 0 |  |  | 0 | 1 |  | my ($self) = @_; | 
| 550 |  |  |  |  |  |  |  | 
| 551 | 0 | 0 |  |  |  |  | return {@$self->{cautions}} if ref $self->{cautions} eq 'ARRAY'; | 
| 552 | 0 |  |  |  |  |  | return; | 
| 553 |  |  |  |  |  |  | } | 
| 554 |  |  |  |  |  |  |  | 
| 555 |  |  |  |  |  |  |  | 
| 556 |  |  |  |  |  |  | sub error_result { | 
| 557 |  |  |  |  |  |  |  | 
| 558 | 0 |  |  | 0 | 1 |  | my ($self, $error) = @_; | 
| 559 |  |  |  |  |  |  |  | 
| 560 | 0 |  |  |  |  |  | return $self->{ds}->error_result($error, $self); | 
| 561 |  |  |  |  |  |  | } | 
| 562 |  |  |  |  |  |  |  | 
| 563 |  |  |  |  |  |  | =head1 NAME | 
| 564 |  |  |  |  |  |  |  | 
| 565 |  |  |  |  |  |  | Web::DataService::Request - object class for data service requests | 
| 566 |  |  |  |  |  |  |  | 
| 567 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 568 |  |  |  |  |  |  |  | 
| 569 |  |  |  |  |  |  | As each incoming request is handled by the Web::DataService framework, a | 
| 570 |  |  |  |  |  |  | request object is created to represent it.  This object is blessed into a | 
| 571 |  |  |  |  |  |  | subclass of Web::DataService::Request which provides the methods listed here | 
| 572 |  |  |  |  |  |  | and also includes one or more L with methods that you have | 
| 573 |  |  |  |  |  |  | written for evaluating the request and doing the appropriate fetching/storing | 
| 574 |  |  |  |  |  |  | on the backend data system. | 
| 575 |  |  |  |  |  |  |  | 
| 576 |  |  |  |  |  |  | The simplest way for the main application to handle a request is as follows: | 
| 577 |  |  |  |  |  |  |  | 
| 578 |  |  |  |  |  |  | Web::DataService->handle_request(request); | 
| 579 |  |  |  |  |  |  |  | 
| 580 |  |  |  |  |  |  | This call uses the C function provided by the foundation framework | 
| 581 |  |  |  |  |  |  | (L) to get the "outer" object representing this request from the point | 
| 582 |  |  |  |  |  |  | of view of the foundation framework, and then passes it to the | 
| 583 |  |  |  |  |  |  | L | 
| 584 |  |  |  |  |  |  | method of Web::DataService.  In the process of handling the request, a new | 
| 585 |  |  |  |  |  |  | "inner" request object is generated and blessed into an appropriate subclass | 
| 586 |  |  |  |  |  |  | of Web::DataService::Request. | 
| 587 |  |  |  |  |  |  |  | 
| 588 |  |  |  |  |  |  | If you wish more control over this process, you can substitute the following: | 
| 589 |  |  |  |  |  |  |  | 
| 590 |  |  |  |  |  |  | my $inner = Web::DataService->new_request(request); | 
| 591 |  |  |  |  |  |  |  | 
| 592 |  |  |  |  |  |  | # You can put code here to check the attributes of $inner and possibly | 
| 593 |  |  |  |  |  |  | # alter them... | 
| 594 |  |  |  |  |  |  |  | 
| 595 |  |  |  |  |  |  | $inner->execute; | 
| 596 |  |  |  |  |  |  |  | 
| 597 |  |  |  |  |  |  | Whichever of these code fragments you use should go into a Dancer L | 
| 598 |  |  |  |  |  |  | handler|Dancer/"USAGE">. | 
| 599 |  |  |  |  |  |  |  | 
| 600 |  |  |  |  |  |  | =head2 Request handling process | 
| 601 |  |  |  |  |  |  |  | 
| 602 |  |  |  |  |  |  | The request handling process carried out by | 
| 603 |  |  |  |  |  |  | L works | 
| 604 |  |  |  |  |  |  | as follows: | 
| 605 |  |  |  |  |  |  |  | 
| 606 |  |  |  |  |  |  | =over | 
| 607 |  |  |  |  |  |  |  | 
| 608 |  |  |  |  |  |  | =item 1. | 
| 609 |  |  |  |  |  |  |  | 
| 610 |  |  |  |  |  |  | The request URL path and parameters are parsed according to the active set of | 
| 611 |  |  |  |  |  |  | data service features and special parameters. Depending upon the set of data | 
| 612 |  |  |  |  |  |  | service features that are active, the path may be processed before moving on | 
| 613 |  |  |  |  |  |  | to the next step.  The following is not an exhaustive list, but illustrates | 
| 614 |  |  |  |  |  |  | the kinds of processing that are done: | 
| 615 |  |  |  |  |  |  |  | 
| 616 |  |  |  |  |  |  | =over | 
| 617 |  |  |  |  |  |  |  | 
| 618 |  |  |  |  |  |  | =item * | 
| 619 |  |  |  |  |  |  |  | 
| 620 |  |  |  |  |  |  | If more than one data service is defined, the appropriate one is selected to | 
| 621 |  |  |  |  |  |  | handle this request. | 
| 622 |  |  |  |  |  |  |  | 
| 623 |  |  |  |  |  |  | =item * | 
| 624 |  |  |  |  |  |  |  | 
| 625 |  |  |  |  |  |  | If the data service has the attribute "path_prefix", this prefix is removed | 
| 626 |  |  |  |  |  |  | from the path. | 
| 627 |  |  |  |  |  |  |  | 
| 628 |  |  |  |  |  |  | =item * | 
| 629 |  |  |  |  |  |  |  | 
| 630 |  |  |  |  |  |  | If the feature 'format_suffix' is active and the path ends in a format suffix | 
| 631 |  |  |  |  |  |  | such as C<.json>, then that suffix is removed and later used to set the | 
| 632 |  |  |  |  |  |  | "format" attribute of the request. | 
| 633 |  |  |  |  |  |  |  | 
| 634 |  |  |  |  |  |  | =item * | 
| 635 |  |  |  |  |  |  |  | 
| 636 |  |  |  |  |  |  | If the feature 'doc_paths' is active and the path ends in '_doc' or in | 
| 637 |  |  |  |  |  |  | '/index' then this suffix is removed and the "is_doc_request" attribute of the | 
| 638 |  |  |  |  |  |  | request is set. | 
| 639 |  |  |  |  |  |  |  | 
| 640 |  |  |  |  |  |  | =item * | 
| 641 |  |  |  |  |  |  |  | 
| 642 |  |  |  |  |  |  | If the special parameter 'document' is active and this parameter was included | 
| 643 |  |  |  |  |  |  | with the request, then the "is_doc_request" attribute of the request is set. | 
| 644 |  |  |  |  |  |  |  | 
| 645 |  |  |  |  |  |  | =back | 
| 646 |  |  |  |  |  |  |  | 
| 647 |  |  |  |  |  |  | =item 2. | 
| 648 |  |  |  |  |  |  |  | 
| 649 |  |  |  |  |  |  | The modified request path is matched against the set of data service node | 
| 650 |  |  |  |  |  |  | paths.  Nodes with either of the attributes C or C | 
| 651 |  |  |  |  |  |  | match as prefixes, all others must match exactly.  If none of the nodes match, | 
| 652 |  |  |  |  |  |  | then the request is rejected with a HTTP 404 error.  Otherwise, a new request | 
| 653 |  |  |  |  |  |  | object is created and configured using the attributes of the matching node. | 
| 654 |  |  |  |  |  |  |  | 
| 655 |  |  |  |  |  |  | =back | 
| 656 |  |  |  |  |  |  |  | 
| 657 |  |  |  |  |  |  | If you used L | 
| 658 |  |  |  |  |  |  | instead of L | 
| 659 |  |  |  |  |  |  | ] )">, then you get control at this point and can modify the request before | 
| 660 |  |  |  |  |  |  | calling C<< $request->execute >> to finish the process. | 
| 661 |  |  |  |  |  |  |  | 
| 662 |  |  |  |  |  |  | =over | 
| 663 |  |  |  |  |  |  |  | 
| 664 |  |  |  |  |  |  | =item 3. | 
| 665 |  |  |  |  |  |  |  | 
| 666 |  |  |  |  |  |  | If the matching node has the C attribute, then the contents of the | 
| 667 |  |  |  |  |  |  | specified file are returned using the foundation framework (i.e. Dancer).  If | 
| 668 |  |  |  |  |  |  | the node has the C attribute instead, then the remainder of the | 
| 669 |  |  |  |  |  |  | request path is applied as a relative path to that directory.  The result of | 
| 670 |  |  |  |  |  |  | the request will be either the contents of a matching file or a HTTP 404 | 
| 671 |  |  |  |  |  |  | error. | 
| 672 |  |  |  |  |  |  |  | 
| 673 |  |  |  |  |  |  | =item 4. | 
| 674 |  |  |  |  |  |  |  | 
| 675 |  |  |  |  |  |  | Otherwise, the new request will be blessed into an automatically generated | 
| 676 |  |  |  |  |  |  | subclass of Web::DataService::Request.  These subclasses are generated | 
| 677 |  |  |  |  |  |  | according to the value of the "role" attribute of the matching node.  Each | 
| 678 |  |  |  |  |  |  | different role generates two subclasses, one for documentation requests and | 
| 679 |  |  |  |  |  |  | one for operation requests.  These classes are composed so that they contain | 
| 680 |  |  |  |  |  |  | the necessary methods for documentation rendering and operation execution, | 
| 681 |  |  |  |  |  |  | respectively, along with all of the definitions from the primary role (this | 
| 682 |  |  |  |  |  |  | role module must be written by the application author). | 
| 683 |  |  |  |  |  |  |  | 
| 684 |  |  |  |  |  |  | =item 5. | 
| 685 |  |  |  |  |  |  |  | 
| 686 |  |  |  |  |  |  | If the "is_doc_request" attribute has been set, or if the matching node does | 
| 687 |  |  |  |  |  |  | not have a value for the "method" attribute, then the documentation directory | 
| 688 |  |  |  |  |  |  | is checked for a template corresponding to the matching node.  If not found, | 
| 689 |  |  |  |  |  |  | the appropriate default template is used.  This template is rendered to | 
| 690 |  |  |  |  |  |  | produce a documentation page, which is returned as the result of the request. | 
| 691 |  |  |  |  |  |  |  | 
| 692 |  |  |  |  |  |  | =item 6. | 
| 693 |  |  |  |  |  |  |  | 
| 694 |  |  |  |  |  |  | Otherwise, we can assume that the node has a "method" attribute.  The request | 
| 695 |  |  |  |  |  |  | parameters are then checked against the ruleset named by the "ruleset" | 
| 696 |  |  |  |  |  |  | attribute, or the ruleset corresponding to the node path if this attribute is | 
| 697 |  |  |  |  |  |  | not set. | 
| 698 |  |  |  |  |  |  |  | 
| 699 |  |  |  |  |  |  | =item 7. | 
| 700 |  |  |  |  |  |  |  | 
| 701 |  |  |  |  |  |  | The output is then configured according to the output blocks(s) indicated by the | 
| 702 |  |  |  |  |  |  | "output" attribute plus those indicated by "optional_output" in conjunction | 
| 703 |  |  |  |  |  |  | with the special parameter "show". | 
| 704 |  |  |  |  |  |  |  | 
| 705 |  |  |  |  |  |  | =item 8. | 
| 706 |  |  |  |  |  |  |  | 
| 707 |  |  |  |  |  |  | The method specified by the node attribute "method" is then called.  This | 
| 708 |  |  |  |  |  |  | method (which must be written by the application author) is responsible for | 
| 709 |  |  |  |  |  |  | fetching and/or storing data using the backend system and specifying what the | 
| 710 |  |  |  |  |  |  | result of the operation should be. | 
| 711 |  |  |  |  |  |  |  | 
| 712 |  |  |  |  |  |  | =item 9. | 
| 713 |  |  |  |  |  |  |  | 
| 714 |  |  |  |  |  |  | If the result of the operation is one or more data records, these records are | 
| 715 |  |  |  |  |  |  | processed according to the specification contained in the selected output | 
| 716 |  |  |  |  |  |  | block(s), and are then serialized by the module corresponding to the selected | 
| 717 |  |  |  |  |  |  | output format.  If "count" or "datainfo" were requested, or if any warnings or | 
| 718 |  |  |  |  |  |  | errors were generated during the execution of the request, this material is | 
| 719 |  |  |  |  |  |  | included in an appropriate way by the serialization module.  The resulting | 
| 720 |  |  |  |  |  |  | response body is returned using the foundation framework. | 
| 721 |  |  |  |  |  |  |  | 
| 722 |  |  |  |  |  |  | =item 10. | 
| 723 |  |  |  |  |  |  |  | 
| 724 |  |  |  |  |  |  | If the result of the operation is instead a piece of non-record data (i.e. an | 
| 725 |  |  |  |  |  |  | image or other binary data), it is returned as the response body using the | 
| 726 |  |  |  |  |  |  | foundation framework. | 
| 727 |  |  |  |  |  |  |  | 
| 728 |  |  |  |  |  |  | =back | 
| 729 |  |  |  |  |  |  |  | 
| 730 |  |  |  |  |  |  | =head1 METHODS | 
| 731 |  |  |  |  |  |  |  | 
| 732 |  |  |  |  |  |  | =head2 Constructor | 
| 733 |  |  |  |  |  |  |  | 
| 734 |  |  |  |  |  |  | =head3 new ( attributes... ) | 
| 735 |  |  |  |  |  |  |  | 
| 736 |  |  |  |  |  |  | You will not need to call this method directly; instead, you should call the | 
| 737 |  |  |  |  |  |  | L | 
| 738 |  |  |  |  |  |  | method of Web::DataService, which calls it internally after carrying out other | 
| 739 |  |  |  |  |  |  | processing. | 
| 740 |  |  |  |  |  |  |  | 
| 741 |  |  |  |  |  |  | =head2 Execution | 
| 742 |  |  |  |  |  |  |  | 
| 743 |  |  |  |  |  |  | =head3 execute ( ) | 
| 744 |  |  |  |  |  |  |  | 
| 745 |  |  |  |  |  |  | Executes this request, and returns the serialized response data.  If your main | 
| 746 |  |  |  |  |  |  | application uses C, then you will not need to call this | 
| 747 |  |  |  |  |  |  | method because C calls it internally. | 
| 748 |  |  |  |  |  |  |  | 
| 749 |  |  |  |  |  |  | =head3 error_result ( error ) | 
| 750 |  |  |  |  |  |  |  | 
| 751 |  |  |  |  |  |  | Aborts processing of the request and causes a HTTP error response to be | 
| 752 |  |  |  |  |  |  | returned to the client.  You will probably not need to call this method, since | 
| 753 |  |  |  |  |  |  | the preferred way of generating an error condition is to call | 
| 754 |  |  |  |  |  |  | L.  The parameter can be any of the following: | 
| 755 |  |  |  |  |  |  |  | 
| 756 |  |  |  |  |  |  | =over | 
| 757 |  |  |  |  |  |  |  | 
| 758 |  |  |  |  |  |  | =item * | 
| 759 |  |  |  |  |  |  |  | 
| 760 |  |  |  |  |  |  | A HTTP error code, such as "404" or "500". | 
| 761 |  |  |  |  |  |  |  | 
| 762 |  |  |  |  |  |  | =item * | 
| 763 |  |  |  |  |  |  |  | 
| 764 |  |  |  |  |  |  | An error message, which will be written to the log.  For security reasons, the | 
| 765 |  |  |  |  |  |  | client will just get back a HTTP 500 response that tells them a server error | 
| 766 |  |  |  |  |  |  | occurred and they should contact the server administrator. | 
| 767 |  |  |  |  |  |  |  | 
| 768 |  |  |  |  |  |  | =item * | 
| 769 |  |  |  |  |  |  |  | 
| 770 |  |  |  |  |  |  | A validation result object from L.  The client will get back a | 
| 771 |  |  |  |  |  |  | HTTP 400 response containing the error and warning messages contained within | 
| 772 |  |  |  |  |  |  | it. | 
| 773 |  |  |  |  |  |  |  | 
| 774 |  |  |  |  |  |  | =back | 
| 775 |  |  |  |  |  |  |  | 
| 776 |  |  |  |  |  |  | =head2 Attribute accessors | 
| 777 |  |  |  |  |  |  |  | 
| 778 |  |  |  |  |  |  | =head3 ds | 
| 779 |  |  |  |  |  |  |  | 
| 780 |  |  |  |  |  |  | Returns a reference to the data service instance with which this request is | 
| 781 |  |  |  |  |  |  | associated. | 
| 782 |  |  |  |  |  |  |  | 
| 783 |  |  |  |  |  |  | =head3 outer | 
| 784 |  |  |  |  |  |  |  | 
| 785 |  |  |  |  |  |  | Returns a reference to the "outer" request object defined by the foundation | 
| 786 |  |  |  |  |  |  | framework. | 
| 787 |  |  |  |  |  |  |  | 
| 788 |  |  |  |  |  |  | =head3 path | 
| 789 |  |  |  |  |  |  |  | 
| 790 |  |  |  |  |  |  | Returns the raw path associated with the request. | 
| 791 |  |  |  |  |  |  |  | 
| 792 |  |  |  |  |  |  | =head3 node_path | 
| 793 |  |  |  |  |  |  |  | 
| 794 |  |  |  |  |  |  | Returns the path of the node that matches this request. | 
| 795 |  |  |  |  |  |  |  | 
| 796 |  |  |  |  |  |  | =head3 rest_path | 
| 797 |  |  |  |  |  |  |  | 
| 798 |  |  |  |  |  |  | If the node path matches the processed request path as a prefix, this accessor returns | 
| 799 |  |  |  |  |  |  | the remainder of the path.  Otherwise, it returns C. | 
| 800 |  |  |  |  |  |  |  | 
| 801 |  |  |  |  |  |  | =head3 is_invalid_request | 
| 802 |  |  |  |  |  |  |  | 
| 803 |  |  |  |  |  |  | Returns true if this request could not be matched to a node, or is otherwise | 
| 804 |  |  |  |  |  |  | invalid.  Returns false otherwise. | 
| 805 |  |  |  |  |  |  |  | 
| 806 |  |  |  |  |  |  | =head3 is_doc_request | 
| 807 |  |  |  |  |  |  |  | 
| 808 |  |  |  |  |  |  | Returns true if this request has been determined to be a request for | 
| 809 |  |  |  |  |  |  | documentation, according to the features and special parameters enabled for | 
| 810 |  |  |  |  |  |  | this data service.  Returns false otherwise. | 
| 811 |  |  |  |  |  |  |  | 
| 812 |  |  |  |  |  |  | =head3 is_node_path | 
| 813 |  |  |  |  |  |  |  | 
| 814 |  |  |  |  |  |  | Returns true if the request path I matches the path of a data service | 
| 815 |  |  |  |  |  |  | node, false otherwise. | 
| 816 |  |  |  |  |  |  |  | 
| 817 |  |  |  |  |  |  | =head3 http_method | 
| 818 |  |  |  |  |  |  |  | 
| 819 |  |  |  |  |  |  | Returns (or sets) the HTTP method associated with the request. | 
| 820 |  |  |  |  |  |  |  | 
| 821 |  |  |  |  |  |  | =head3 request_url | 
| 822 |  |  |  |  |  |  |  | 
| 823 |  |  |  |  |  |  | Returns the complete request URL. | 
| 824 |  |  |  |  |  |  |  | 
| 825 |  |  |  |  |  |  | =head3 base_url | 
| 826 |  |  |  |  |  |  |  | 
| 827 |  |  |  |  |  |  | Returns the base component of the request URL, of the form | 
| 828 |  |  |  |  |  |  | "http://some.host/" or something similar. | 
| 829 |  |  |  |  |  |  |  | 
| 830 |  |  |  |  |  |  | =head3 root_url | 
| 831 |  |  |  |  |  |  |  | 
| 832 |  |  |  |  |  |  | Returns the base URL plus the path prefix (if any) for this data service. | 
| 833 |  |  |  |  |  |  |  | 
| 834 |  |  |  |  |  |  | =head3 path_prefix | 
| 835 |  |  |  |  |  |  |  | 
| 836 |  |  |  |  |  |  | Returns the path prefix (if any) for this data service. | 
| 837 |  |  |  |  |  |  |  | 
| 838 |  |  |  |  |  |  | =head3 data_info | 
| 839 |  |  |  |  |  |  |  | 
| 840 |  |  |  |  |  |  | Returns a hash containing information about the request and the data to be | 
| 841 |  |  |  |  |  |  | returned.  The hash keys will include some or all of the following, depending | 
| 842 |  |  |  |  |  |  | upon the configuration of the data service. | 
| 843 |  |  |  |  |  |  |  | 
| 844 |  |  |  |  |  |  | =over | 
| 845 |  |  |  |  |  |  |  | 
| 846 |  |  |  |  |  |  | =item title, data_provider, data_source, data_license, license_url | 
| 847 |  |  |  |  |  |  |  | 
| 848 |  |  |  |  |  |  | The values of these keys will be the corresponding attributes of the data | 
| 849 |  |  |  |  |  |  | service.  They may be undefined if no value was specified for them either when | 
| 850 |  |  |  |  |  |  | the data service was instantiated or in the configuration file maintained by | 
| 851 |  |  |  |  |  |  | the foundation framework. | 
| 852 |  |  |  |  |  |  |  | 
| 853 |  |  |  |  |  |  | =item access_time | 
| 854 |  |  |  |  |  |  |  | 
| 855 |  |  |  |  |  |  | The current time. | 
| 856 |  |  |  |  |  |  |  | 
| 857 |  |  |  |  |  |  | =item data_url | 
| 858 |  |  |  |  |  |  |  | 
| 859 |  |  |  |  |  |  | The complete request URL. | 
| 860 |  |  |  |  |  |  |  | 
| 861 |  |  |  |  |  |  | =item documentation_url | 
| 862 |  |  |  |  |  |  |  | 
| 863 |  |  |  |  |  |  | A URL that will return a documentation page describing the selected data | 
| 864 |  |  |  |  |  |  | service node. | 
| 865 |  |  |  |  |  |  |  | 
| 866 |  |  |  |  |  |  | =back | 
| 867 |  |  |  |  |  |  |  | 
| 868 |  |  |  |  |  |  | =head3 data_info_keys | 
| 869 |  |  |  |  |  |  |  | 
| 870 |  |  |  |  |  |  | Returns a list of the keys documented for C, in a canonical order | 
| 871 |  |  |  |  |  |  | for use by the serialization modules. | 
| 872 |  |  |  |  |  |  |  | 
| 873 |  |  |  |  |  |  | =head3 contact_info | 
| 874 |  |  |  |  |  |  |  | 
| 875 |  |  |  |  |  |  | Returns a hash whose keys are C and C.  The values will be the | 
| 876 |  |  |  |  |  |  | values of the data service attributes C and C, | 
| 877 |  |  |  |  |  |  | respectively. | 
| 878 |  |  |  |  |  |  |  | 
| 879 |  |  |  |  |  |  | =head3 generate_url ( attrs ) | 
| 880 |  |  |  |  |  |  |  | 
| 881 |  |  |  |  |  |  | This method returns a URL generated from the specified attributes, which must be given | 
| 882 |  |  |  |  |  |  | either as a hashref or as a string: | 
| 883 |  |  |  |  |  |  |  | 
| 884 |  |  |  |  |  |  | # either of the following: | 
| 885 |  |  |  |  |  |  |  | 
| 886 |  |  |  |  |  |  | $url = $request->generate_url( { op => 'abc/def', format => 'json', params => 'foo=1' } ); | 
| 887 |  |  |  |  |  |  | $url = $request->generate_url( "op:abc/def.json?foo=1" ); | 
| 888 |  |  |  |  |  |  |  | 
| 889 |  |  |  |  |  |  | The attributes are as follows: | 
| 890 |  |  |  |  |  |  |  | 
| 891 |  |  |  |  |  |  | =over | 
| 892 |  |  |  |  |  |  |  | 
| 893 |  |  |  |  |  |  | =item node | 
| 894 |  |  |  |  |  |  |  | 
| 895 |  |  |  |  |  |  | Generate a URL which will request documentation using the node path given by | 
| 896 |  |  |  |  |  |  | the value of this attribute.  In the string form, this is represented by a | 
| 897 |  |  |  |  |  |  | prefix of "node:". | 
| 898 |  |  |  |  |  |  |  | 
| 899 |  |  |  |  |  |  | =item op | 
| 900 |  |  |  |  |  |  |  | 
| 901 |  |  |  |  |  |  | Generate a URL which will request a data service operation using the node path | 
| 902 |  |  |  |  |  |  | given by the value of this attribute.  In the string form, this is represented | 
| 903 |  |  |  |  |  |  | by a prefix of "op:". | 
| 904 |  |  |  |  |  |  |  | 
| 905 |  |  |  |  |  |  | =item path | 
| 906 |  |  |  |  |  |  |  | 
| 907 |  |  |  |  |  |  | Generate a URL which will request the exact path given.  This is used to | 
| 908 |  |  |  |  |  |  | generate URLs for requesting files, such as CSS files.  In the string form, | 
| 909 |  |  |  |  |  |  | this is represented by a prefix of "path:". | 
| 910 |  |  |  |  |  |  |  | 
| 911 |  |  |  |  |  |  | =item format | 
| 912 |  |  |  |  |  |  |  | 
| 913 |  |  |  |  |  |  | The generated URL will request output in the specified format.  Depending upon | 
| 914 |  |  |  |  |  |  | the features enabled for this data service, that may mean either adding the | 
| 915 |  |  |  |  |  |  | specified value as a suffix to the URL path, or adding a special parameter. | 
| 916 |  |  |  |  |  |  | In the string form, this is represented by adding '.' followed by the format | 
| 917 |  |  |  |  |  |  | to the path (this syntax is fixed no matter which data service features are | 
| 918 |  |  |  |  |  |  | enabled). | 
| 919 |  |  |  |  |  |  |  | 
| 920 |  |  |  |  |  |  | =item params | 
| 921 |  |  |  |  |  |  |  | 
| 922 |  |  |  |  |  |  | Configure the URL to include the specified parameters.  The value of this | 
| 923 |  |  |  |  |  |  | attribute must be either an arrayref with an even number of elements or a | 
| 924 |  |  |  |  |  |  | single URL parameter string such as C<"foo=1&bar=2">.  In the string form, | 
| 925 |  |  |  |  |  |  | this is represented by a '?' followed by the parameter string. | 
| 926 |  |  |  |  |  |  |  | 
| 927 |  |  |  |  |  |  | =item type | 
| 928 |  |  |  |  |  |  |  | 
| 929 |  |  |  |  |  |  | The value of this attribute must be either C, C, or C.  If | 
| 930 |  |  |  |  |  |  | "abs" is given, then the generated URL will begin with | 
| 931 |  |  |  |  |  |  | "http[s]://hostname[:port]/.  If "site", then the generated URL will begin | 
| 932 |  |  |  |  |  |  | with "/" followed by the path prefix for this data service (if any).  If | 
| 933 |  |  |  |  |  |  | "relative", no prefix will be added to the generated URL.  In this case, you | 
| 934 |  |  |  |  |  |  | must make sure to specify a path that will work properly relative to the URL | 
| 935 |  |  |  |  |  |  | of the page on which you intend to display it. | 
| 936 |  |  |  |  |  |  |  | 
| 937 |  |  |  |  |  |  | If this attribute is not specified, it defaults to "site".  In the string | 
| 938 |  |  |  |  |  |  | form, this is represented by modifying the prefix, i.e. "oprel:" or "opabs:" | 
| 939 |  |  |  |  |  |  | instead of just "op:". | 
| 940 |  |  |  |  |  |  |  | 
| 941 |  |  |  |  |  |  | =back | 
| 942 |  |  |  |  |  |  |  | 
| 943 |  |  |  |  |  |  | =head3 node_attr ( name ) | 
| 944 |  |  |  |  |  |  |  | 
| 945 |  |  |  |  |  |  | Returns the value of the specified attribute of the node matching this | 
| 946 |  |  |  |  |  |  | request, or I if the attribute is not defined for that node. | 
| 947 |  |  |  |  |  |  |  | 
| 948 |  |  |  |  |  |  | =head3 special_value ( param ) | 
| 949 |  |  |  |  |  |  |  | 
| 950 |  |  |  |  |  |  | Returns the value of the specified special parameter, if it is enabled for | 
| 951 |  |  |  |  |  |  | this data service and if it was included with this request.  Returns I | 
| 952 |  |  |  |  |  |  | otherwise. | 
| 953 |  |  |  |  |  |  |  | 
| 954 |  |  |  |  |  |  | =head3 special_given ( param ) | 
| 955 |  |  |  |  |  |  |  | 
| 956 |  |  |  |  |  |  | Returns true if the specified special parameter was included in this request | 
| 957 |  |  |  |  |  |  | and is enabled for this data service, regardless of its value.  Returns false | 
| 958 |  |  |  |  |  |  | otherwise. | 
| 959 |  |  |  |  |  |  |  | 
| 960 |  |  |  |  |  |  | =head3 default_limit | 
| 961 |  |  |  |  |  |  |  | 
| 962 |  |  |  |  |  |  | Returns the default result limit, if any.  This is used in generating | 
| 963 |  |  |  |  |  |  | documentation. | 
| 964 |  |  |  |  |  |  |  | 
| 965 |  |  |  |  |  |  | =head2 Documentation methods | 
| 966 |  |  |  |  |  |  |  | 
| 967 |  |  |  |  |  |  | The following methods are only available with documentation requests.  They can | 
| 968 |  |  |  |  |  |  | be called from documentation templates as follows: | 
| 969 |  |  |  |  |  |  |  | 
| 970 |  |  |  |  |  |  | <% result = request.method_name(args) %> | 
| 971 |  |  |  |  |  |  |  | 
| 972 |  |  |  |  |  |  | or, to include the result directly in the rendered output: | 
| 973 |  |  |  |  |  |  |  | 
| 974 |  |  |  |  |  |  | <% request.method_name(args) %> | 
| 975 |  |  |  |  |  |  |  | 
| 976 |  |  |  |  |  |  | In either case, "request" is a variable automatically provided to the | 
| 977 |  |  |  |  |  |  | templating engine.  The string "result" should be replaced by whatever | 
| 978 |  |  |  |  |  |  | variable you wish to assign the result to, and "method_name" and "args" by the | 
| 979 |  |  |  |  |  |  | desired method and arguments. | 
| 980 |  |  |  |  |  |  |  | 
| 981 |  |  |  |  |  |  | These methods are all packaged up in blocks defined by doc_defs.tt, so you | 
| 982 |  |  |  |  |  |  | will not need to call them directly unless you want to make substantive | 
| 983 |  |  |  |  |  |  | changes to the look of the documentation pages. | 
| 984 |  |  |  |  |  |  |  | 
| 985 |  |  |  |  |  |  | =head3 document_node | 
| 986 |  |  |  |  |  |  |  | 
| 987 |  |  |  |  |  |  | Returns the documentation string for the node matching this request, or the | 
| 988 |  |  |  |  |  |  | empty string if none was defined. | 
| 989 |  |  |  |  |  |  |  | 
| 990 |  |  |  |  |  |  | =head3 list_navtrail | 
| 991 |  |  |  |  |  |  |  | 
| 992 |  |  |  |  |  |  | Returns a list of navigation trail components for the current request, in Pod | 
| 993 |  |  |  |  |  |  | format.  These are generated componentwise from the node path. | 
| 994 |  |  |  |  |  |  |  | 
| 995 |  |  |  |  |  |  | =head3 document_usage | 
| 996 |  |  |  |  |  |  |  | 
| 997 |  |  |  |  |  |  | Returns a string in Pod format listing the URLs generated from the node | 
| 998 |  |  |  |  |  |  | attribute "usage", if any were given for this node. | 
| 999 |  |  |  |  |  |  |  | 
| 1000 |  |  |  |  |  |  | =head3 list_subnodes | 
| 1001 |  |  |  |  |  |  |  | 
| 1002 |  |  |  |  |  |  | Returns a list of the node paths corresponding to all subnodes of the current | 
| 1003 |  |  |  |  |  |  | one for which the C attribute was set. | 
| 1004 |  |  |  |  |  |  |  | 
| 1005 |  |  |  |  |  |  | =head3 document_subnodes | 
| 1006 |  |  |  |  |  |  |  | 
| 1007 |  |  |  |  |  |  | Returns a string in Pod format documenting the subnodes of the current one for | 
| 1008 |  |  |  |  |  |  | which the C attribute was set. | 
| 1009 |  |  |  |  |  |  |  | 
| 1010 |  |  |  |  |  |  | =head3 document_params | 
| 1011 |  |  |  |  |  |  |  | 
| 1012 |  |  |  |  |  |  | Returns a string in Pod format documenting the parameters available for this | 
| 1013 |  |  |  |  |  |  | request.  This is automatically generated from the corresponding ruleset, if | 
| 1014 |  |  |  |  |  |  | one was defined. | 
| 1015 |  |  |  |  |  |  |  | 
| 1016 |  |  |  |  |  |  | =head3 list_http_methods | 
| 1017 |  |  |  |  |  |  |  | 
| 1018 |  |  |  |  |  |  | Returns a list of HTTP methods that are allowed for this request path. | 
| 1019 |  |  |  |  |  |  |  | 
| 1020 |  |  |  |  |  |  | =head3 document_http_methods | 
| 1021 |  |  |  |  |  |  |  | 
| 1022 |  |  |  |  |  |  | Returns a string in Pod format documenting the HTTP methods that are allowed | 
| 1023 |  |  |  |  |  |  | for this request path. | 
| 1024 |  |  |  |  |  |  |  | 
| 1025 |  |  |  |  |  |  | =head3 document_response | 
| 1026 |  |  |  |  |  |  |  | 
| 1027 |  |  |  |  |  |  | Returns a string in Pod format documenting the all of the fields that might be | 
| 1028 |  |  |  |  |  |  | included in the result. | 
| 1029 |  |  |  |  |  |  |  | 
| 1030 |  |  |  |  |  |  | =head3 output_label | 
| 1031 |  |  |  |  |  |  |  | 
| 1032 |  |  |  |  |  |  | Returns the value of the node attribute "output_label", or the default value | 
| 1033 |  |  |  |  |  |  | "basic" if none was defined. | 
| 1034 |  |  |  |  |  |  |  | 
| 1035 |  |  |  |  |  |  | =head3 optional_output | 
| 1036 |  |  |  |  |  |  |  | 
| 1037 |  |  |  |  |  |  | Returns the value of the node attribute "optional_output", if this attribute | 
| 1038 |  |  |  |  |  |  | was defined. | 
| 1039 |  |  |  |  |  |  |  | 
| 1040 |  |  |  |  |  |  | =head3 document_formats ( options ) | 
| 1041 |  |  |  |  |  |  |  | 
| 1042 |  |  |  |  |  |  | Returns a string in Pod format documenting the formats allowed for this | 
| 1043 |  |  |  |  |  |  | node.  If a parameter is specified, it must be a hashref.  If this includes | 
| 1044 |  |  |  |  |  |  | the key 'all' with a true value, then all formats defined for this | 
| 1045 |  |  |  |  |  |  | data service are included.  If it includes the key 'extended' with a true value, then | 
| 1046 |  |  |  |  |  |  | a description of each format is included. | 
| 1047 |  |  |  |  |  |  |  | 
| 1048 |  |  |  |  |  |  | =head3 default_format | 
| 1049 |  |  |  |  |  |  |  | 
| 1050 |  |  |  |  |  |  | Return the name of the default format (if any was specified) for this node. | 
| 1051 |  |  |  |  |  |  |  | 
| 1052 |  |  |  |  |  |  | =head3 document_vocabs ( options ) | 
| 1053 |  |  |  |  |  |  |  | 
| 1054 |  |  |  |  |  |  | Return a string in Pod format documenting the vocabularies allowed for this | 
| 1055 |  |  |  |  |  |  | node.  If a parameter is specified, it must be a hashref.  If this includes | 
| 1056 |  |  |  |  |  |  | the key 'all' with a true value, then all vocabularies defined for this | 
| 1057 |  |  |  |  |  |  | data service are included.  If it includes the key 'extended' with a true value, then | 
| 1058 |  |  |  |  |  |  | a description of each vocabulary is included. | 
| 1059 |  |  |  |  |  |  |  | 
| 1060 |  |  |  |  |  |  | =head3 output_format | 
| 1061 |  |  |  |  |  |  |  | 
| 1062 |  |  |  |  |  |  | You can use this method to check whether the response is to be rendered into | 
| 1063 |  |  |  |  |  |  | HTML or returned as Pod text.  The values returned are C and | 
| 1064 |  |  |  |  |  |  | respectively. | 
| 1065 |  |  |  |  |  |  |  | 
| 1066 |  |  |  |  |  |  | =head2 Operation methods | 
| 1067 |  |  |  |  |  |  |  | 
| 1068 |  |  |  |  |  |  | The following methods are only available with operation requests.  They can be | 
| 1069 |  |  |  |  |  |  | called from any of the operation methods included in the application role | 
| 1070 |  |  |  |  |  |  | module(s). | 
| 1071 |  |  |  |  |  |  |  | 
| 1072 |  |  |  |  |  |  | =head3 get_connection | 
| 1073 |  |  |  |  |  |  |  | 
| 1074 |  |  |  |  |  |  | This method can only be used if you explicitly specified a backend plugin when | 
| 1075 |  |  |  |  |  |  | instantiating the data service, or if the module L | 
| 1076 |  |  |  |  |  |  | was required in your main application before Web::DataService. | 
| 1077 |  |  |  |  |  |  |  | 
| 1078 |  |  |  |  |  |  | Assuming that the proper connection information is present in the application | 
| 1079 |  |  |  |  |  |  | configuration file, this method will return a connection to your backend data | 
| 1080 |  |  |  |  |  |  | store. | 
| 1081 |  |  |  |  |  |  |  | 
| 1082 |  |  |  |  |  |  | =head3 exception ( code, message ) | 
| 1083 |  |  |  |  |  |  |  | 
| 1084 |  |  |  |  |  |  | Returns an exception object encoding the specified HTTP result code and a message to go with | 
| 1085 |  |  |  |  |  |  | it. This exception object can be used as an argument to 'die'. Its type is | 
| 1086 |  |  |  |  |  |  | C. | 
| 1087 |  |  |  |  |  |  |  | 
| 1088 |  |  |  |  |  |  | =head3 debug | 
| 1089 |  |  |  |  |  |  |  | 
| 1090 |  |  |  |  |  |  | Returns true if the data service process is running under debug mode. This can be used to output | 
| 1091 |  |  |  |  |  |  | extra debugging information as appropriate. | 
| 1092 |  |  |  |  |  |  |  | 
| 1093 |  |  |  |  |  |  | =head3 debug_line ( text ) | 
| 1094 |  |  |  |  |  |  |  | 
| 1095 |  |  |  |  |  |  | Print the specified text to standard error, followed by a newline, if debug mode is enabled for | 
| 1096 |  |  |  |  |  |  | this data service process. This can be used, for example, to output the text of SQL statements | 
| 1097 |  |  |  |  |  |  | executed on the underlying database, and similar information, for debugging purposes. For example: | 
| 1098 |  |  |  |  |  |  |  | 
| 1099 |  |  |  |  |  |  | $request->debug_line($sql) if $request->debug; | 
| 1100 |  |  |  |  |  |  |  | 
| 1101 |  |  |  |  |  |  | =head3 param_keys ( ) | 
| 1102 |  |  |  |  |  |  |  | 
| 1103 |  |  |  |  |  |  | Returns a list of the parameter keys corresponding to the request parameters. | 
| 1104 |  |  |  |  |  |  | These will generally be the same as the parameter names, but may | 
| 1105 |  |  |  |  |  |  | be different if you include the keys C and/or C in the parameter | 
| 1106 |  |  |  |  |  |  | validation rulesets (see L). | 
| 1107 |  |  |  |  |  |  |  | 
| 1108 |  |  |  |  |  |  | =head3 clean_param ( param ) | 
| 1109 |  |  |  |  |  |  |  | 
| 1110 |  |  |  |  |  |  | Returns the cleaned value of the specified parameter, or undefined if the | 
| 1111 |  |  |  |  |  |  | parameter was not included in the request.  If more than one parameter value was | 
| 1112 |  |  |  |  |  |  | given, the result will be an array ref. | 
| 1113 |  |  |  |  |  |  |  | 
| 1114 |  |  |  |  |  |  | =head3 clean_param_list ( param ) | 
| 1115 |  |  |  |  |  |  |  | 
| 1116 |  |  |  |  |  |  | Returns a list of all the cleaned values of the specified parameter (one or | 
| 1117 |  |  |  |  |  |  | more), or empty if the parameter was not included in the request. | 
| 1118 |  |  |  |  |  |  |  | 
| 1119 |  |  |  |  |  |  | =head3 clean_param_hash ( param ) | 
| 1120 |  |  |  |  |  |  |  | 
| 1121 |  |  |  |  |  |  | Returns a hashref whose keys are all of the cleaned values of the specified | 
| 1122 |  |  |  |  |  |  | parameter, or an empty hashref if the parameter was not included in the | 
| 1123 |  |  |  |  |  |  | request. | 
| 1124 |  |  |  |  |  |  |  | 
| 1125 |  |  |  |  |  |  | =head3 param_given ( param ) | 
| 1126 |  |  |  |  |  |  |  | 
| 1127 |  |  |  |  |  |  | Returns true if the specified parameter was included in there request, whether | 
| 1128 |  |  |  |  |  |  | or not it had a valid value.  Returns false otherwise. | 
| 1129 |  |  |  |  |  |  |  | 
| 1130 |  |  |  |  |  |  | =head3 params_for_display | 
| 1131 |  |  |  |  |  |  |  | 
| 1132 |  |  |  |  |  |  | Returns a list of (parameter, value) pairs for use in responding to the | 
| 1133 |  |  |  |  |  |  | 'datainfo' special parameter.  This result list leaves out any special | 
| 1134 |  |  |  |  |  |  | parameters that do not affect the content of the result.  Multiple values are | 
| 1135 |  |  |  |  |  |  | concatenated together using commas. | 
| 1136 |  |  |  |  |  |  |  | 
| 1137 |  |  |  |  |  |  | =head3 validate_params ( ruleset_name, param... ) | 
| 1138 |  |  |  |  |  |  |  | 
| 1139 |  |  |  |  |  |  | Validates the specified parameters (which may be hash or list refs of parameters and values) to | 
| 1140 |  |  |  |  |  |  | the specified ruleset. Returns the result, which will be an object of type HTTP::Validate::Result | 
| 1141 |  |  |  |  |  |  | that can then be queried for success or failure, error messages, etc. The primary purpose for this | 
| 1142 |  |  |  |  |  |  | method is to allow validation of data records before they are added to the underlying database. | 
| 1143 |  |  |  |  |  |  |  | 
| 1144 |  |  |  |  |  |  | =head3 raw_body | 
| 1145 |  |  |  |  |  |  |  | 
| 1146 |  |  |  |  |  |  | Returns the request body as an un-decoded string. If the request does not contain a body, returns | 
| 1147 |  |  |  |  |  |  | the empty string. The primary purpose for this method is to accept data for addition to the | 
| 1148 |  |  |  |  |  |  | underlying database. | 
| 1149 |  |  |  |  |  |  |  | 
| 1150 |  |  |  |  |  |  | =head3 decode_body | 
| 1151 |  |  |  |  |  |  |  | 
| 1152 |  |  |  |  |  |  | Attempts to decode the request body, if it is in a known format. Currently, the only two formats | 
| 1153 |  |  |  |  |  |  | understood are JSON and text. A JSON body will be decoded into a Perl data structure, while a text | 
| 1154 |  |  |  |  |  |  | body will be split into a list of lines. If no body exists, the undefined value is returned. If an | 
| 1155 |  |  |  |  |  |  | error occurs during JSON decoding, it will be returned as a second item. Consequently, the return | 
| 1156 |  |  |  |  |  |  | value of this method should be assigned to a two-element list. | 
| 1157 |  |  |  |  |  |  |  | 
| 1158 |  |  |  |  |  |  | =head3 has_block ( block ) | 
| 1159 |  |  |  |  |  |  |  | 
| 1160 |  |  |  |  |  |  | Returns true if the specified output block was selected for this request.  The | 
| 1161 |  |  |  |  |  |  | parameter can be either the name of the block or the parameter value by which | 
| 1162 |  |  |  |  |  |  | it would be selected. | 
| 1163 |  |  |  |  |  |  |  | 
| 1164 |  |  |  |  |  |  | =head3 select_list ( subst ) | 
| 1165 |  |  |  |  |  |  |  | 
| 1166 |  |  |  |  |  |  | Returns a list of strings derived from the 'select' configuration records | 
| 1167 |  |  |  |  |  |  | found in the output blocks selected for this request.  You can use these | 
| 1168 |  |  |  |  |  |  | records to specify which fields need to be retrieved from the backend data | 
| 1169 |  |  |  |  |  |  | store.  Any given string will only appear once in the list, even if it occurs | 
| 1170 |  |  |  |  |  |  | in multiple 'select' records. | 
| 1171 |  |  |  |  |  |  |  | 
| 1172 |  |  |  |  |  |  | The optional argument should be a hashref, indicating substitutions to be | 
| 1173 |  |  |  |  |  |  | made.  For example, given the following code, | 
| 1174 |  |  |  |  |  |  |  | 
| 1175 |  |  |  |  |  |  | $ds->define_block( 'block1' => | 
| 1176 |  |  |  |  |  |  | { select => '$a.name', '$a.value', 'c.size' }, | 
| 1177 |  |  |  |  |  |  | ... ); | 
| 1178 |  |  |  |  |  |  |  | 
| 1179 |  |  |  |  |  |  | # ...and in a different subroutine... | 
| 1180 |  |  |  |  |  |  |  | 
| 1181 |  |  |  |  |  |  | my @fields = $request->select_list( { a => 'table1', b => 'table2' } ) | 
| 1182 |  |  |  |  |  |  |  | 
| 1183 |  |  |  |  |  |  | The result will include C, C, and C. | 
| 1184 |  |  |  |  |  |  |  | 
| 1185 |  |  |  |  |  |  | If you are using an SQL-based backend, and if you set up the 'select' records | 
| 1186 |  |  |  |  |  |  | properly, you can use this method (or see C below) to build a | 
| 1187 |  |  |  |  |  |  | SELECT statement that will fetch exactly the information needed for the | 
| 1188 |  |  |  |  |  |  | selected set of output blocks.  This is important if your application allows | 
| 1189 |  |  |  |  |  |  | optional output blocks that can be selected arbitrarily by the client.  If you | 
| 1190 |  |  |  |  |  |  | are using a non-SQL backend, you are free to use this in any way that makes | 
| 1191 |  |  |  |  |  |  | sense given the backend interface. | 
| 1192 |  |  |  |  |  |  |  | 
| 1193 |  |  |  |  |  |  | =head3 select_hash ( subst ) | 
| 1194 |  |  |  |  |  |  |  | 
| 1195 |  |  |  |  |  |  | Returns the same set of strings as C, but as the keys in a | 
| 1196 |  |  |  |  |  |  | hash. The values will all be 1. | 
| 1197 |  |  |  |  |  |  |  | 
| 1198 |  |  |  |  |  |  | =head3 select_string ( subst ) | 
| 1199 |  |  |  |  |  |  |  | 
| 1200 |  |  |  |  |  |  | Returns the same set of strings as C, but joined into a single | 
| 1201 |  |  |  |  |  |  | string with each item separated by a comma and a space. | 
| 1202 |  |  |  |  |  |  |  | 
| 1203 |  |  |  |  |  |  | =head3 substitute_select ( variable => value, variable => value ... ) | 
| 1204 |  |  |  |  |  |  |  | 
| 1205 |  |  |  |  |  |  | Make substitutions in the select list. For example, if passed the arguments 'v => xt', then | 
| 1206 |  |  |  |  |  |  | anywhere the string '$v' appears in the select list, that string will be replaced by 'xt'. This | 
| 1207 |  |  |  |  |  |  | method should be called before 'select_list' or 'select_string'. The intended use is to select | 
| 1208 |  |  |  |  |  |  | between one or more alternate database tables. | 
| 1209 |  |  |  |  |  |  |  | 
| 1210 |  |  |  |  |  |  | =head3 tables_hash | 
| 1211 |  |  |  |  |  |  |  | 
| 1212 |  |  |  |  |  |  | Returns a hashref whose keys are derived from the 'select' configuration | 
| 1213 |  |  |  |  |  |  | records found in the output blocks selected for this request.  The keys from | 
| 1214 |  |  |  |  |  |  | this hash will be the values specified by any 'tables' attributes in those | 
| 1215 |  |  |  |  |  |  | configuration records.  The values will all be 1. | 
| 1216 |  |  |  |  |  |  |  | 
| 1217 |  |  |  |  |  |  | If you are using an SQL-based backend, and if you set up the 'select' records | 
| 1218 |  |  |  |  |  |  | properly, you can use this method to keep track of which database tables will | 
| 1219 |  |  |  |  |  |  | be needed in order to build a query that can satisfy all of the data blocks | 
| 1220 |  |  |  |  |  |  | included in this request.  You can use the set of keys to constuct an | 
| 1221 |  |  |  |  |  |  | appropriate list of table joins.  If you are using a non-SQL backend, you can | 
| 1222 |  |  |  |  |  |  | use this in any way that makes sense given the backend interface. | 
| 1223 |  |  |  |  |  |  |  | 
| 1224 |  |  |  |  |  |  | If you call this method multiple times, you will get a reference to the same | 
| 1225 |  |  |  |  |  |  | hash each time.  This means that you can safely add and remove keys during | 
| 1226 |  |  |  |  |  |  | your own processing. | 
| 1227 |  |  |  |  |  |  |  | 
| 1228 |  |  |  |  |  |  | =head3 add_table ( alias, [full_name] ) | 
| 1229 |  |  |  |  |  |  |  | 
| 1230 |  |  |  |  |  |  | Add an extra key to the tables hash. The optional second parameter can be the full name of the | 
| 1231 |  |  |  |  |  |  | table to be included, but this is ignored. Note that adding a table to the table hash will I | 
| 1232 |  |  |  |  |  |  | automatically include that table in any SQL statements. You need to check the table hash and add | 
| 1233 |  |  |  |  |  |  | it yourself if the appropriate key is found. | 
| 1234 |  |  |  |  |  |  |  | 
| 1235 |  |  |  |  |  |  | =head3 filter_hash | 
| 1236 |  |  |  |  |  |  |  | 
| 1237 |  |  |  |  |  |  | Returns a hashref whose keys are derived from the 'filter' configuration | 
| 1238 |  |  |  |  |  |  | records found in the output blocks selected for this request.  The values will | 
| 1239 |  |  |  |  |  |  | all be 1. | 
| 1240 |  |  |  |  |  |  |  | 
| 1241 |  |  |  |  |  |  | If you are using an SQL-based backend, and if you set up the 'filter' records | 
| 1242 |  |  |  |  |  |  | properly, you can use this method to get a list of (unique) filter expressions | 
| 1243 |  |  |  |  |  |  | to use in building a query that can satisfy all of the data blocks included in | 
| 1244 |  |  |  |  |  |  | this request.  (Note: you will almost always need to add other filter | 
| 1245 |  |  |  |  |  |  | expressions derived from parameter values as well).  If you are using a | 
| 1246 |  |  |  |  |  |  | non-SQL backend, you can use this in any way that makes sense given the | 
| 1247 |  |  |  |  |  |  | backend interface. | 
| 1248 |  |  |  |  |  |  |  | 
| 1249 |  |  |  |  |  |  | If you call this method multiple times, you will get a reference to the same | 
| 1250 |  |  |  |  |  |  | hash each time.  This means that you can safely add and remove keys during | 
| 1251 |  |  |  |  |  |  | your own processing. | 
| 1252 |  |  |  |  |  |  |  | 
| 1253 |  |  |  |  |  |  | =head3 output_field_list | 
| 1254 |  |  |  |  |  |  |  | 
| 1255 |  |  |  |  |  |  | This method returns the output field list for the current request. This is the actual list, not a | 
| 1256 |  |  |  |  |  |  | copy, so it can be manipulated. This is a real hack, which will probably be removed from a future | 
| 1257 |  |  |  |  |  |  | version of this module. But for the time being, you can use it (for example) to go through the | 
| 1258 |  |  |  |  |  |  | list and prune fields that will not be used. | 
| 1259 |  |  |  |  |  |  |  | 
| 1260 |  |  |  |  |  |  | =head3 delete_output_field ( field ) | 
| 1261 |  |  |  |  |  |  |  | 
| 1262 |  |  |  |  |  |  | Remove the specified output field from the list. The first field whose name (not label) matches | 
| 1263 |  |  |  |  |  |  | the argument is removed, regardless of what output block it occurs in. If no fields match, nothing | 
| 1264 |  |  |  |  |  |  | will be removed. | 
| 1265 |  |  |  |  |  |  |  | 
| 1266 |  |  |  |  |  |  | =head3 result_limit | 
| 1267 |  |  |  |  |  |  |  | 
| 1268 |  |  |  |  |  |  | Returns the result limit specified for this request, or undefined if none was | 
| 1269 |  |  |  |  |  |  | given or if C was specified.  Even though Web::DataService will always | 
| 1270 |  |  |  |  |  |  | truncate the result set if a limit was given, you may want to include this | 
| 1271 |  |  |  |  |  |  | limit value in any queries you make to the backend so as to prevent your | 
| 1272 |  |  |  |  |  |  | server from doing unnecessary work. | 
| 1273 |  |  |  |  |  |  |  | 
| 1274 |  |  |  |  |  |  | =head3 result_offset ( will_handle ) | 
| 1275 |  |  |  |  |  |  |  | 
| 1276 |  |  |  |  |  |  | Returns true if a result offset was specified for this request, or zero if | 
| 1277 |  |  |  |  |  |  | none was specified.  If the argument value is true, then Web::DataService | 
| 1278 |  |  |  |  |  |  | assumes that you will handle the process of offsetting the data result, | 
| 1279 |  |  |  |  |  |  | e.g. by using modifying your backend query appropriately (see | 
| 1280 |  |  |  |  |  |  | C below). | 
| 1281 |  |  |  |  |  |  |  | 
| 1282 |  |  |  |  |  |  | If the argument is false, or if you never call either this method or | 
| 1283 |  |  |  |  |  |  | C, then (if an offset was specified for this request) | 
| 1284 |  |  |  |  |  |  | Web::DataService will automatically discard the corresponding number of | 
| 1285 |  |  |  |  |  |  | records from the beginning of the result set before serializing the results. | 
| 1286 |  |  |  |  |  |  |  | 
| 1287 |  |  |  |  |  |  | =head3 sql_limit_clause ( will_handle ) | 
| 1288 |  |  |  |  |  |  |  | 
| 1289 |  |  |  |  |  |  | Returns a string whose value is an LIMIT clause that can be added to an SQL | 
| 1290 |  |  |  |  |  |  | query to generate a result set in accordance with result limit and offset (if | 
| 1291 |  |  |  |  |  |  | any) specified for this request.  If the argument is true, then | 
| 1292 |  |  |  |  |  |  | Web::DataService assumes that you will actually do this. | 
| 1293 |  |  |  |  |  |  |  | 
| 1294 |  |  |  |  |  |  | If the argument is false, or if you never call either this method or | 
| 1295 |  |  |  |  |  |  | C, then (if an offset was specified for this request) | 
| 1296 |  |  |  |  |  |  | Web::DataService will automatically discard the corresponding number of | 
| 1297 |  |  |  |  |  |  | records from the beginning of the result set before serializing the results. | 
| 1298 |  |  |  |  |  |  |  | 
| 1299 |  |  |  |  |  |  | If a result limit was specified for this request, and if the result set you | 
| 1300 |  |  |  |  |  |  | generate exceeds this size, Web::DataService will always truncate it to match | 
| 1301 |  |  |  |  |  |  | the specified limit. | 
| 1302 |  |  |  |  |  |  |  | 
| 1303 |  |  |  |  |  |  | =head3 sql_count_clause ( ) | 
| 1304 |  |  |  |  |  |  |  | 
| 1305 |  |  |  |  |  |  | Returns a string that can be added to an SQL statement to generate a result | 
| 1306 |  |  |  |  |  |  | count in accordance with the request parameters.  If the special parameter | 
| 1307 |  |  |  |  |  |  | "count" was specified for this request, the result will be | 
| 1308 |  |  |  |  |  |  | C.  Otherwise, it will be the empty string. | 
| 1309 |  |  |  |  |  |  |  | 
| 1310 |  |  |  |  |  |  | If you are using a non-SQL backend, you can still use this as a boolean | 
| 1311 |  |  |  |  |  |  | variable to determine if the result should include a count of the number of | 
| 1312 |  |  |  |  |  |  | records found. | 
| 1313 |  |  |  |  |  |  |  | 
| 1314 |  |  |  |  |  |  | =head3 sql_count_rows ( ) | 
| 1315 |  |  |  |  |  |  |  | 
| 1316 |  |  |  |  |  |  | Execute the SQL statement "SELECT FOUND ROWS" and store the result for use in generating the | 
| 1317 |  |  |  |  |  |  | response header. But only do this if the request parameters specify that result counts should | 
| 1318 |  |  |  |  |  |  | be returned. | 
| 1319 |  |  |  |  |  |  |  | 
| 1320 |  |  |  |  |  |  | =head3 set_result_count ( count ) | 
| 1321 |  |  |  |  |  |  |  | 
| 1322 |  |  |  |  |  |  | Use this method to tell Web::DataService the result count if you are using | 
| 1323 |  |  |  |  |  |  | C.  In this case, you will generally need to execute a separate query | 
| 1324 |  |  |  |  |  |  | such as "SELECT FOUND_ROWS()" after your main query. | 
| 1325 |  |  |  |  |  |  |  | 
| 1326 |  |  |  |  |  |  | =head3 output_format | 
| 1327 |  |  |  |  |  |  |  | 
| 1328 |  |  |  |  |  |  | Returns the name of the response format selected for this request. | 
| 1329 |  |  |  |  |  |  |  | 
| 1330 |  |  |  |  |  |  | =head3 output_vocab | 
| 1331 |  |  |  |  |  |  |  | 
| 1332 |  |  |  |  |  |  | Returns the name of the response vocabulary selected for this request.  If no | 
| 1333 |  |  |  |  |  |  | vocabularies have been defined for this data service, it will return "null", | 
| 1334 |  |  |  |  |  |  | the name of the default vocabulary. | 
| 1335 |  |  |  |  |  |  |  | 
| 1336 |  |  |  |  |  |  | =head3 output_linebreak | 
| 1337 |  |  |  |  |  |  |  | 
| 1338 |  |  |  |  |  |  | Returns the string to be inserted between output lines in text-based response | 
| 1339 |  |  |  |  |  |  | formats.  This will be either a carriage return, a linefeed, or both. | 
| 1340 |  |  |  |  |  |  |  | 
| 1341 |  |  |  |  |  |  | =head3 result_limit | 
| 1342 |  |  |  |  |  |  |  | 
| 1343 |  |  |  |  |  |  | Returns the limit (if any) specified for the size of the result set. | 
| 1344 |  |  |  |  |  |  |  | 
| 1345 |  |  |  |  |  |  | =head3 result_offset | 
| 1346 |  |  |  |  |  |  |  | 
| 1347 |  |  |  |  |  |  | Returns the offset (if any) specified for the start of the result set. | 
| 1348 |  |  |  |  |  |  |  | 
| 1349 |  |  |  |  |  |  | =head3 display_header | 
| 1350 |  |  |  |  |  |  |  | 
| 1351 |  |  |  |  |  |  | Returns true if header material is to be displayed in text-based response | 
| 1352 |  |  |  |  |  |  | formats, false otherwise. | 
| 1353 |  |  |  |  |  |  |  | 
| 1354 |  |  |  |  |  |  | =head3 display_datainfo | 
| 1355 |  |  |  |  |  |  |  | 
| 1356 |  |  |  |  |  |  | Returns true if a description of the dataset is to be included in | 
| 1357 |  |  |  |  |  |  | the response, false otherwise. | 
| 1358 |  |  |  |  |  |  |  | 
| 1359 |  |  |  |  |  |  | =head3 display_counts | 
| 1360 |  |  |  |  |  |  |  | 
| 1361 |  |  |  |  |  |  | Returns true if result counts and elapsed time are to be included in the | 
| 1362 |  |  |  |  |  |  | response, false otherwise. | 
| 1363 |  |  |  |  |  |  |  | 
| 1364 |  |  |  |  |  |  | =head3 save_output | 
| 1365 |  |  |  |  |  |  |  | 
| 1366 |  |  |  |  |  |  | Returns true if the special parameter 'save' was included in the request. | 
| 1367 |  |  |  |  |  |  |  | 
| 1368 |  |  |  |  |  |  | =head3 get_config | 
| 1369 |  |  |  |  |  |  |  | 
| 1370 |  |  |  |  |  |  | Returns a hashref providing access to the attributes defined in the | 
| 1371 |  |  |  |  |  |  | application configuration file.  Allows you to include application-specific | 
| 1372 |  |  |  |  |  |  | directives in the file and retrieve them as needed from your operation | 
| 1373 |  |  |  |  |  |  | methods. | 
| 1374 |  |  |  |  |  |  |  | 
| 1375 |  |  |  |  |  |  | =head3 set_content_type | 
| 1376 |  |  |  |  |  |  |  | 
| 1377 |  |  |  |  |  |  | Specify the value for the "Content-type" HTTP response header.  You will | 
| 1378 |  |  |  |  |  |  | probably not need to call this, since it is set automatically based on the | 
| 1379 |  |  |  |  |  |  | selected response format. | 
| 1380 |  |  |  |  |  |  |  | 
| 1381 |  |  |  |  |  |  | =h3ad3 exception ( code, message ) | 
| 1382 |  |  |  |  |  |  |  | 
| 1383 |  |  |  |  |  |  | Returns an exception object which can be used as an argument to C.  This | 
| 1384 |  |  |  |  |  |  | will abort processing of the current request and generate an HTTP error | 
| 1385 |  |  |  |  |  |  | result.  The first argument must be a valid HTTP error code. | 
| 1386 |  |  |  |  |  |  |  | 
| 1387 |  |  |  |  |  |  | =head2 Result methods | 
| 1388 |  |  |  |  |  |  |  | 
| 1389 |  |  |  |  |  |  | These methods are also available with operation requests.  I | 
| 1390 |  |  |  |  |  |  | call at least one of them from each of your operation methods.>  These methods | 
| 1391 |  |  |  |  |  |  | are how you tell Web::DataService the result of each operation. | 
| 1392 |  |  |  |  |  |  |  | 
| 1393 |  |  |  |  |  |  | You can make more than one of these calls from a single operation, but note | 
| 1394 |  |  |  |  |  |  | that each call (except for C in some cases) wipes out any result | 
| 1395 |  |  |  |  |  |  | specified by previous calls. | 
| 1396 |  |  |  |  |  |  |  | 
| 1397 |  |  |  |  |  |  | =head3 single_result ( record ) | 
| 1398 |  |  |  |  |  |  |  | 
| 1399 |  |  |  |  |  |  | The argument must be a hashref representing a single data record.  The result | 
| 1400 |  |  |  |  |  |  | of this operation will be that single record. | 
| 1401 |  |  |  |  |  |  |  | 
| 1402 |  |  |  |  |  |  | =head3 list_result ( record... ) | 
| 1403 |  |  |  |  |  |  |  | 
| 1404 |  |  |  |  |  |  | You can call this method either with a single arrayref argument whose members | 
| 1405 |  |  |  |  |  |  | are hashrefs, or with a list of hashrefs.  Either way, the result of this | 
| 1406 |  |  |  |  |  |  | operation will be the specified list of records. | 
| 1407 |  |  |  |  |  |  |  | 
| 1408 |  |  |  |  |  |  | =head3 add_result ( record... ) | 
| 1409 |  |  |  |  |  |  |  | 
| 1410 |  |  |  |  |  |  | Adds the specified record(s) to a result set previously specified by | 
| 1411 |  |  |  |  |  |  | C.  All arguments must be hashrefs. | 
| 1412 |  |  |  |  |  |  |  | 
| 1413 |  |  |  |  |  |  | =head3 sth_result ( sth ) | 
| 1414 |  |  |  |  |  |  |  | 
| 1415 |  |  |  |  |  |  | The argument must be a valid DBI statement handle that has already been | 
| 1416 |  |  |  |  |  |  | executed.  Once your operation method returns, Web::DataService will then | 
| 1417 |  |  |  |  |  |  | fetch the result records from this sth one by one, process them according to | 
| 1418 |  |  |  |  |  |  | the selected set of output blocks for this request, and serialize the result. | 
| 1419 |  |  |  |  |  |  |  | 
| 1420 |  |  |  |  |  |  | If you use this result method, you will need to call either C | 
| 1421 |  |  |  |  |  |  | or C to determine if a result count is needed.  If so, | 
| 1422 |  |  |  |  |  |  | execute a "SELECT FOUND_ROWS()" query (or the equivalent) and use | 
| 1423 |  |  |  |  |  |  | C to tell Web::DataService how many records were found. | 
| 1424 |  |  |  |  |  |  |  | 
| 1425 |  |  |  |  |  |  | =head3 data_result ( data ) | 
| 1426 |  |  |  |  |  |  |  | 
| 1427 |  |  |  |  |  |  | The argument must be either a scalar or a reference to a scalar.  In either | 
| 1428 |  |  |  |  |  |  | case, this data will be returned as the result of the operation without any | 
| 1429 |  |  |  |  |  |  | further processing.  You can use this, for example, to return images or other | 
| 1430 |  |  |  |  |  |  | binary data.  You can use C to set the result content type, | 
| 1431 |  |  |  |  |  |  | or you can rely on the suffix of the URL path if appropriate. | 
| 1432 |  |  |  |  |  |  |  | 
| 1433 |  |  |  |  |  |  | =head3 clear_result | 
| 1434 |  |  |  |  |  |  |  | 
| 1435 |  |  |  |  |  |  | This call clears any results that have been specified for this operation by | 
| 1436 |  |  |  |  |  |  | any of the other methods in this section. | 
| 1437 |  |  |  |  |  |  |  | 
| 1438 |  |  |  |  |  |  | =head3 add_warning ( message ) | 
| 1439 |  |  |  |  |  |  |  | 
| 1440 |  |  |  |  |  |  | Add the specified warning message to this request.  The warnings will be | 
| 1441 |  |  |  |  |  |  | automatically included in the result, in a manner appropriate for the selected | 
| 1442 |  |  |  |  |  |  | response format. | 
| 1443 |  |  |  |  |  |  |  | 
| 1444 |  |  |  |  |  |  | =head3 warnings ( ) | 
| 1445 |  |  |  |  |  |  |  | 
| 1446 |  |  |  |  |  |  | Return a list of the warning messages (if any) that have been added to this | 
| 1447 |  |  |  |  |  |  | request. | 
| 1448 |  |  |  |  |  |  |  | 
| 1449 |  |  |  |  |  |  | =head3 add_caution ( message ) | 
| 1450 |  |  |  |  |  |  |  | 
| 1451 |  |  |  |  |  |  | Add the specified caution message to this request. The caution messages will be automatically | 
| 1452 |  |  |  |  |  |  | included in the result, in a manner appropriate for the selected response format. | 
| 1453 |  |  |  |  |  |  |  | 
| 1454 |  |  |  |  |  |  | =head3 cautions ( ) | 
| 1455 |  |  |  |  |  |  |  | 
| 1456 |  |  |  |  |  |  | Return a list of the caution messages (if any) that have been added to this request. | 
| 1457 |  |  |  |  |  |  |  | 
| 1458 |  |  |  |  |  |  | =head3 add_error ( message ) | 
| 1459 |  |  |  |  |  |  |  | 
| 1460 |  |  |  |  |  |  | Add the specified error message to this request. The error messages will be automatically | 
| 1461 |  |  |  |  |  |  | included in the result, in a manner appropriate for the selected response format. | 
| 1462 |  |  |  |  |  |  |  | 
| 1463 |  |  |  |  |  |  | =head3 errors ( ) | 
| 1464 |  |  |  |  |  |  |  | 
| 1465 |  |  |  |  |  |  | Return a list of the error messages (if any) that have been added to this request. | 
| 1466 |  |  |  |  |  |  |  | 
| 1467 |  |  |  |  |  |  | =head1 AUTHOR | 
| 1468 |  |  |  |  |  |  |  | 
| 1469 |  |  |  |  |  |  | mmcclenn "at" cpan.org | 
| 1470 |  |  |  |  |  |  |  | 
| 1471 |  |  |  |  |  |  | =head1 BUGS | 
| 1472 |  |  |  |  |  |  |  | 
| 1473 |  |  |  |  |  |  | Please report any bugs or feature requests to C, or through | 
| 1474 |  |  |  |  |  |  | the web interface at L.  I will be notified, and then you'll | 
| 1475 |  |  |  |  |  |  | automatically be notified of progress on your bug as I make changes. | 
| 1476 |  |  |  |  |  |  |  | 
| 1477 |  |  |  |  |  |  | =head1 COPYRIGHT & LICENSE | 
| 1478 |  |  |  |  |  |  |  | 
| 1479 |  |  |  |  |  |  | Copyright 2014 Michael McClennen, all rights reserved. | 
| 1480 |  |  |  |  |  |  |  | 
| 1481 |  |  |  |  |  |  | This program is free software; you can redistribute it and/or modify it | 
| 1482 |  |  |  |  |  |  | under the same terms as Perl itself. | 
| 1483 |  |  |  |  |  |  |  | 
| 1484 |  |  |  |  |  |  | =cut | 
| 1485 |  |  |  |  |  |  |  | 
| 1486 |  |  |  |  |  |  | 1; |