Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library protocol; | 5 library protocol; |
| 6 | 6 |
| 7 import 'dart:convert' show JsonDecoder; | 7 import 'dart:convert' show JsonDecoder; |
| 8 | 8 |
| 9 /** | 9 /** |
| 10 * Instances of the class [Request] represent a request that was received. | 10 * Instances of the class [Request] represent a request that was received. |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 87 } else if (params != null) { | 87 } else if (params != null) { |
| 88 return null; | 88 return null; |
| 89 } | 89 } |
| 90 return request; | 90 return request; |
| 91 } catch (exception) { | 91 } catch (exception) { |
| 92 return null; | 92 return null; |
| 93 } | 93 } |
| 94 } | 94 } |
| 95 | 95 |
| 96 /** | 96 /** |
| 97 * Return the value of the parameter with the given [name], or `null` if there | 97 * Return the value of the parameter with the given [name], or defaultValue |
|
Brian Wilkerson
2014/04/21 22:12:32
"defaultValue" --> "[defaultValue]"
Paul Berry
2014/04/21 22:22:21
Done.
| |
| 98 * is no such parameter associated with this request. | 98 * if there is no such parameter associated with this request. |
| 99 */ | 99 */ |
| 100 Object getParameter(String name) => params[name]; | 100 RequestDatum getParameter(String name, dynamic defaultValue) { |
|
Brian Wilkerson
2014/04/21 22:12:32
Do we want a default default value, such as
Requ
Paul Berry
2014/04/21 22:22:21
I don't know. Currently there's not really a need
| |
| 101 Object value = params[name]; | |
| 102 if (value == null) { | |
| 103 return new RequestDatum(this, "default for $name", defaultValue); | |
| 104 } | |
| 105 return new RequestDatum(this, name, params[name]); | |
| 106 } | |
| 101 | 107 |
| 102 /** | 108 /** |
| 103 * Return the value of the parameter with the given [name], or throw a | 109 * Return the value of the parameter with the given [name], or throw a |
| 104 * [RequestFailure] exception with an appropriate error message if there is no | 110 * [RequestFailure] exception with an appropriate error message if there is no |
| 105 * such parameter associated with this request. | 111 * such parameter associated with this request. |
| 106 */ | 112 */ |
| 107 Object getRequiredParameter(String name) { | 113 RequestDatum getRequiredParameter(String name) { |
| 108 Object value = params[name]; | 114 Object value = params[name]; |
| 109 if (value == null) { | 115 if (value == null) { |
| 110 throw new RequestFailure(new Response.missingRequiredParameter(this, name) ); | 116 throw new RequestFailure(new Response.missingRequiredParameter(this, name) ); |
| 111 } | 117 } |
| 112 return value; | 118 return new RequestDatum(this, name, value); |
| 113 } | 119 } |
| 114 | 120 |
| 115 /** | 121 /** |
| 116 * Set the value of the parameter with the given [name] to the given [value]. | 122 * Set the value of the parameter with the given [name] to the given [value]. |
| 117 */ | 123 */ |
| 118 void setParameter(String name, Object value) { | 124 void setParameter(String name, Object value) { |
| 119 params[name] = value; | 125 params[name] = value; |
| 120 } | 126 } |
| 121 | 127 |
| 122 /** | 128 /** |
| 123 * Convert the given [value] to a boolean, or throw a [RequestFailure] | |
| 124 * exception if the [value] could not be converted. | |
| 125 * | |
| 126 * The value is typically the result of invoking either [getParameter] or | |
| 127 * [getRequiredParameter]. | |
| 128 */ | |
| 129 bool toBool(Object value) { | |
| 130 if (value is bool) { | |
| 131 return value; | |
| 132 } else if (value is String) { | |
| 133 return value == 'true'; | |
| 134 } | |
| 135 throw new RequestFailure(new Response.expectedBoolean(this, value)); | |
| 136 } | |
| 137 | |
| 138 /** | |
| 139 * Convert the given [value] to an integer, or throw a [RequestFailure] | |
| 140 * exception if the [value] could not be converted. | |
| 141 * | |
| 142 * The value is typically the result of invoking either [getParameter] or | |
| 143 * [getRequiredParameter]. | |
| 144 */ | |
| 145 int toInt(Object value) { | |
| 146 if (value is int) { | |
| 147 return value; | |
| 148 } else if (value is String) { | |
| 149 return int.parse(value, onError: (String value) { | |
| 150 throw new RequestFailure(new Response.expectedInteger(this, value)); | |
| 151 }); | |
| 152 } | |
| 153 throw new RequestFailure(new Response.expectedInteger(this, value)); | |
| 154 } | |
| 155 | |
| 156 /** | |
| 157 * Return a table representing the structure of the Json object that will be | 129 * Return a table representing the structure of the Json object that will be |
| 158 * sent to the client to represent this response. | 130 * sent to the client to represent this response. |
| 159 */ | 131 */ |
| 160 Map<String, Object> toJson() { | 132 Map<String, Object> toJson() { |
| 161 Map<String, Object> jsonObject = new Map<String, Object>(); | 133 Map<String, Object> jsonObject = new Map<String, Object>(); |
| 162 jsonObject[ID] = id; | 134 jsonObject[ID] = id; |
| 163 jsonObject[METHOD] = method; | 135 jsonObject[METHOD] = method; |
| 164 if (params.isNotEmpty) { | 136 if (params.isNotEmpty) { |
| 165 jsonObject[PARAMS] = params; | 137 jsonObject[PARAMS] = params; |
| 166 } | 138 } |
| 167 return jsonObject; | 139 return jsonObject; |
| 168 } | 140 } |
| 169 } | 141 } |
| 170 | 142 |
| 143 /** | |
| 144 * Instances of the class [RequestDatum] wrap a piece of data from a | |
| 145 * request parameter, and contain accessor methods which automatically validate | |
| 146 * and convert the data into the appropriate form. | |
| 147 */ | |
| 148 class RequestDatum { | |
| 149 /** | |
| 150 * Request object that should be referred to in any errors that are | |
| 151 * generated. | |
| 152 */ | |
| 153 final Request request; | |
| 154 | |
| 155 /** | |
| 156 * String description of how [datum] was obtained from the request. | |
| 157 */ | |
| 158 final String path; | |
| 159 | |
| 160 /** | |
| 161 * Value to be decoded and validated. | |
| 162 */ | |
| 163 final dynamic datum; | |
| 164 | |
| 165 /** | |
| 166 * Create a RequestDatum for decoding and validating [datum], which refers to | |
| 167 * [request] in any errors it reports. | |
| 168 */ | |
| 169 RequestDatum(this.request, this.path, this.datum); | |
| 170 | |
| 171 /** | |
| 172 * Validate that the datum is a Map containing the given [key], and return | |
| 173 * a [RequestDatum] containing the corresponding value. | |
| 174 */ | |
| 175 RequestDatum operator [](String key) { | |
| 176 if (datum is! Map<String, dynamic>) { | |
| 177 throw new RequestFailure(new Response.invalidParameter(request, path, | |
| 178 "be a map")); | |
| 179 } | |
| 180 if (!datum.containsKey(key)) { | |
| 181 throw new RequestFailure(new Response.invalidParameter(request, path, | |
| 182 "contain key '$key'")); | |
| 183 } | |
| 184 return new RequestDatum(request, "$path.$key", datum[key]); | |
| 185 } | |
| 186 | |
| 187 /** | |
| 188 * Validate that the datum is a Map whose keys are strings, and call [f] on | |
| 189 * each key/value pair in the map. | |
| 190 */ | |
| 191 void forEachMap(void f(String key, RequestDatum value)) { | |
| 192 if (datum is! Map<String, dynamic>) { | |
| 193 throw new RequestFailure(new Response.invalidParameter(request, path, | |
| 194 "be a map")); | |
| 195 } | |
| 196 datum.forEach((String key, dynamic value) { | |
| 197 f(key, new RequestDatum(request, "$path.$key", value)); | |
| 198 }); | |
| 199 } | |
| 200 | |
| 201 /** | |
| 202 * Validate that the datum is an integer (or a string that can be parsed | |
| 203 * as an integer), and return the int. | |
| 204 */ | |
| 205 int asInt() { | |
| 206 if (datum is int) { | |
| 207 return datum; | |
| 208 } else if (datum is String) { | |
| 209 return int.parse(datum, onError: (String value) { | |
| 210 throw new RequestFailure(new Response.invalidParameter(request, path, | |
| 211 "be an integer")); | |
| 212 }); | |
| 213 } | |
| 214 throw new RequestFailure(new Response.invalidParameter(request, path, | |
| 215 "be an integer")); | |
| 216 } | |
| 217 | |
| 218 /** | |
| 219 * Validate that the datum is a boolean (or a string that can be parsed | |
| 220 * as a boolean), and return the bool. | |
| 221 * | |
| 222 * The value is typically the result of invoking either [getParameter] or | |
| 223 * [getRequiredParameter]. | |
| 224 */ | |
| 225 bool asBool() { | |
| 226 if (datum is bool) { | |
| 227 return datum; | |
| 228 } else if (datum == 'true') { | |
| 229 return datum == 'true'; | |
| 230 } else if (datum == 'false') { | |
| 231 return datum == 'false'; | |
| 232 } | |
| 233 throw new RequestFailure(new Response.invalidParameter(request, datum, | |
| 234 "be a boolean")); | |
| 235 } | |
| 236 | |
| 237 /** | |
| 238 * Validate that the datum is a string, and return it. | |
| 239 */ | |
| 240 String asString() { | |
| 241 if (datum is! String) { | |
| 242 throw new RequestFailure(new Response.invalidParameter(request, path, | |
| 243 "be a string")); | |
| 244 } | |
| 245 return datum; | |
| 246 } | |
| 247 | |
| 248 /** | |
| 249 * Validate that the datum is a list of strings, and return it. | |
| 250 */ | |
| 251 List<String> asStringList() { | |
| 252 if (datum is! List<String>) { | |
| 253 throw new RequestFailure(new Response.invalidParameter(request, path, | |
| 254 "be a list of strings")); | |
| 255 } | |
| 256 return datum; | |
| 257 } | |
| 258 | |
| 259 /** | |
| 260 * Validate that the datum is a map from strings to strings, and return it. | |
| 261 */ | |
| 262 Map<String, String> asStringMap() { | |
| 263 if (datum is! Map<String, String>) { | |
| 264 throw new RequestFailure(new Response.invalidParameter(request, path, | |
| 265 "be a string map")); | |
| 266 } | |
| 267 return datum; | |
| 268 } | |
| 269 } | |
| 270 | |
| 171 /** | 271 /** |
| 172 * Instances of the class [Response] represent a response to a request. | 272 * Instances of the class [Response] represent a response to a request. |
| 173 */ | 273 */ |
| 174 class Response { | 274 class Response { |
| 175 /** | 275 /** |
| 176 * The name of the JSON attribute containing the id of the request for which | 276 * The name of the JSON attribute containing the id of the request for which |
| 177 * this is a response. | 277 * this is a response. |
| 178 */ | 278 */ |
| 179 static const String ID = 'id'; | 279 static const String ID = 'id'; |
| 180 | 280 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 215 | 315 |
| 216 /** | 316 /** |
| 217 * Initialize a newly created instance to represent an error condition caused | 317 * Initialize a newly created instance to represent an error condition caused |
| 218 * by a [request] referencing a context that does not exist. | 318 * by a [request] referencing a context that does not exist. |
| 219 */ | 319 */ |
| 220 Response.contextDoesNotExist(Request request) | 320 Response.contextDoesNotExist(Request request) |
| 221 : this(request.id, new RequestError(-1, 'Context does not exist')); | 321 : this(request.id, new RequestError(-1, 'Context does not exist')); |
| 222 | 322 |
| 223 /** | 323 /** |
| 224 * Initialize a newly created instance to represent an error condition caused | 324 * Initialize a newly created instance to represent an error condition caused |
| 225 * by a [request] that was expected to have a boolean-valued parameter but was | 325 * by a [request] that had invalid parameter. [path] is the path to the |
| 226 * passed a non-boolean value. | 326 * invalid parameter, in Javascript notation (e.g. "foo.bar" means that the |
| 327 * parameter "foo" contained a key "bar" whose value was the wrong type). | |
| 328 * [expectation] is a description of the type of data that was expected. | |
| 227 */ | 329 */ |
| 228 Response.expectedBoolean(Request request, Object value) | 330 Response.invalidParameter(Request request, String path, String expectation) |
| 229 : this(request.id, new RequestError(-2, 'Expected a boolean value, but found "$value"')); | 331 : this(request.id, new RequestError(-2, |
| 332 "Expected parameter $path to $expectation")); | |
| 230 | 333 |
| 231 /** | 334 /** |
| 232 * Initialize a newly created instance to represent an error condition caused | 335 * Initialize a newly created instance to represent an error condition caused |
| 233 * by a [request] that was expected to have a integer-valued parameter but was | |
| 234 * passed a non-integer value. | |
| 235 */ | |
| 236 Response.expectedInteger(Request request, Object value) | |
| 237 : this(request.id, new RequestError(-3, 'Expected an integer value, but foun d "$value"')); | |
| 238 | |
| 239 /** | |
| 240 * Initialize a newly created instance to represent an error condition caused | |
| 241 * by a malformed request. | 336 * by a malformed request. |
| 242 */ | 337 */ |
| 243 Response.invalidRequestFormat() | 338 Response.invalidRequestFormat() |
| 244 : this('', new RequestError(-4, 'Invalid request')); | 339 : this('', new RequestError(-4, 'Invalid request')); |
| 245 | 340 |
| 246 /** | 341 /** |
| 247 * Initialize a newly created instance to represent an error condition caused | 342 * Initialize a newly created instance to represent an error condition caused |
| 248 * by a [request] that does not have a required parameter. | 343 * by a [request] that does not have a required parameter. |
| 249 */ | 344 */ |
| 250 Response.missingRequiredParameter(Request request, String parameterName) | 345 Response.missingRequiredParameter(Request request, String parameterName) |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 600 /** | 695 /** |
| 601 * The response to be returned as a result of the failure. | 696 * The response to be returned as a result of the failure. |
| 602 */ | 697 */ |
| 603 final Response response; | 698 final Response response; |
| 604 | 699 |
| 605 /** | 700 /** |
| 606 * Initialize a newly created exception to return the given reponse. | 701 * Initialize a newly created exception to return the given reponse. |
| 607 */ | 702 */ |
| 608 RequestFailure(this.response); | 703 RequestFailure(this.response); |
| 609 } | 704 } |
| OLD | NEW |