| 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 part of gcloud.db; | 5 part of gcloud.db; |
| 6 | 6 |
| 7 /// Annotation used to mark dart classes which can be stored into datastore. | 7 /// Annotation used to mark dart classes which can be stored into datastore. |
| 8 /// | 8 /// |
| 9 /// The `Kind` annotation on a class as well as other `Property` annotations on | 9 /// The `Kind` annotation on a class as well as other `Property` annotations on |
| 10 /// fields or getters of the class itself (and any of it's superclasses) up to | 10 /// fields or getters of the class itself (and any of it's superclasses) up to |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 /// `true`. | 81 /// `true`. |
| 82 final bool indexed; | 82 final bool indexed; |
| 83 | 83 |
| 84 const Property({this.propertyName, this.required: false, this.indexed: true}); | 84 const Property({this.propertyName, this.required: false, this.indexed: true}); |
| 85 | 85 |
| 86 bool validate(ModelDB db, Object value) { | 86 bool validate(ModelDB db, Object value) { |
| 87 if (required && value == null) return false; | 87 if (required && value == null) return false; |
| 88 return true; | 88 return true; |
| 89 } | 89 } |
| 90 | 90 |
| 91 Object encodeValue(ModelDB db, Object value); | 91 Object encodeValue(ModelDB db, Object value, {bool forComparison: false}); |
| 92 | 92 |
| 93 Object decodePrimitiveValue(ModelDB db, Object value); | 93 Object decodePrimitiveValue(ModelDB db, Object value); |
| 94 } | 94 } |
| 95 | 95 |
| 96 /// An abstract base class for primitive properties which can e.g. be used | 96 /// An abstract base class for primitive properties which can e.g. be used |
| 97 /// within a composed `ListProperty`. | 97 /// within a composed `ListProperty`. |
| 98 abstract class PrimitiveProperty extends Property { | 98 abstract class PrimitiveProperty extends Property { |
| 99 const PrimitiveProperty( | 99 const PrimitiveProperty( |
| 100 {String propertyName, bool required: false, bool indexed: true}) | 100 {String propertyName, bool required: false, bool indexed: true}) |
| 101 : super(propertyName: propertyName, required: required, indexed: indexed); | 101 : super(propertyName: propertyName, required: required, indexed: indexed); |
| 102 | 102 |
| 103 Object encodeValue(ModelDB db, Object value) => value; | 103 Object encodeValue(ModelDB db, Object value, {bool forComparison: false}) => v
alue; |
| 104 | 104 |
| 105 Object decodePrimitiveValue(ModelDB db, Object value) => value; | 105 Object decodePrimitiveValue(ModelDB db, Object value) => value; |
| 106 } | 106 } |
| 107 | 107 |
| 108 /// A boolean [Property]. | 108 /// A boolean [Property]. |
| 109 /// | 109 /// |
| 110 /// It will validate that values are booleans before writing them to the | 110 /// It will validate that values are booleans before writing them to the |
| 111 /// datastore and when reading them back. | 111 /// datastore and when reading them back. |
| 112 class BoolProperty extends PrimitiveProperty { | 112 class BoolProperty extends PrimitiveProperty { |
| 113 const BoolProperty( | 113 const BoolProperty( |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 /// It will validate that values are keys before writing them to the | 162 /// It will validate that values are keys before writing them to the |
| 163 /// datastore and when reading them back. | 163 /// datastore and when reading them back. |
| 164 class ModelKeyProperty extends PrimitiveProperty { | 164 class ModelKeyProperty extends PrimitiveProperty { |
| 165 const ModelKeyProperty( | 165 const ModelKeyProperty( |
| 166 {String propertyName, bool required: false, bool indexed: true}) | 166 {String propertyName, bool required: false, bool indexed: true}) |
| 167 : super(propertyName: propertyName, required: required, indexed: indexed); | 167 : super(propertyName: propertyName, required: required, indexed: indexed); |
| 168 | 168 |
| 169 bool validate(ModelDB db, Object value) | 169 bool validate(ModelDB db, Object value) |
| 170 => super.validate(db, value) && (value == null || value is Key); | 170 => super.validate(db, value) && (value == null || value is Key); |
| 171 | 171 |
| 172 Object encodeValue(ModelDB db, Object value) { | 172 Object encodeValue(ModelDB db, Object value, {bool forComparison: false}) { |
| 173 if (value == null) return null; | 173 if (value == null) return null; |
| 174 return db.toDatastoreKey(value); | 174 return db.toDatastoreKey(value); |
| 175 } | 175 } |
| 176 | 176 |
| 177 Object decodePrimitiveValue(ModelDB db, Object value) { | 177 Object decodePrimitiveValue(ModelDB db, Object value) { |
| 178 if (value == null) return null; | 178 if (value == null) return null; |
| 179 return db.fromDatastoreKey(value as datastore.Key); | 179 return db.fromDatastoreKey(value as datastore.Key); |
| 180 } | 180 } |
| 181 } | 181 } |
| 182 | 182 |
| 183 /// A binary blob [Property]. | 183 /// A binary blob [Property]. |
| 184 /// | 184 /// |
| 185 /// It will validate that values are blobs before writing them to the | 185 /// It will validate that values are blobs before writing them to the |
| 186 /// datastore and when reading them back. Blob values will be represented by | 186 /// datastore and when reading them back. Blob values will be represented by |
| 187 /// List<int>. | 187 /// List<int>. |
| 188 class BlobProperty extends PrimitiveProperty { | 188 class BlobProperty extends PrimitiveProperty { |
| 189 const BlobProperty({String propertyName, bool required: false}) | 189 const BlobProperty({String propertyName, bool required: false}) |
| 190 : super(propertyName: propertyName, required: required, indexed: false); | 190 : super(propertyName: propertyName, required: required, indexed: false); |
| 191 | 191 |
| 192 // NOTE: We don't validate that the entries of the list are really integers | 192 // NOTE: We don't validate that the entries of the list are really integers |
| 193 // of the range 0..255! | 193 // of the range 0..255! |
| 194 // If an untyped list was created the type check will always succeed. i.e. | 194 // If an untyped list was created the type check will always succeed. i.e. |
| 195 // "[1, true, 'bar'] is List<int>" evaluates to `true` | 195 // "[1, true, 'bar'] is List<int>" evaluates to `true` |
| 196 bool validate(ModelDB db, Object value) | 196 bool validate(ModelDB db, Object value) |
| 197 => super.validate(db, value) && (value == null || value is List<int>); | 197 => super.validate(db, value) && (value == null || value is List<int>); |
| 198 | 198 |
| 199 Object encodeValue(ModelDB db, Object value) { | 199 Object encodeValue(ModelDB db, Object value, {bool forComparison: false}) { |
| 200 if (value == null) return null; | 200 if (value == null) return null; |
| 201 return new datastore.BlobValue(value); | 201 return new datastore.BlobValue(value); |
| 202 } | 202 } |
| 203 | 203 |
| 204 Object decodePrimitiveValue(ModelDB db, Object value) { | 204 Object decodePrimitiveValue(ModelDB db, Object value) { |
| 205 if (value == null) return null; | 205 if (value == null) return null; |
| 206 | 206 |
| 207 datastore.BlobValue blobValue = value; | 207 datastore.BlobValue blobValue = value; |
| 208 return blobValue.bytes; | 208 return blobValue.bytes; |
| 209 } | 209 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 | 247 |
| 248 bool validate(ModelDB db, Object value) { | 248 bool validate(ModelDB db, Object value) { |
| 249 if (!super.validate(db, value) || value is! List) return false; | 249 if (!super.validate(db, value) || value is! List) return false; |
| 250 | 250 |
| 251 for (var entry in value) { | 251 for (var entry in value) { |
| 252 if (!subProperty.validate(db, entry)) return false; | 252 if (!subProperty.validate(db, entry)) return false; |
| 253 } | 253 } |
| 254 return true; | 254 return true; |
| 255 } | 255 } |
| 256 | 256 |
| 257 Object encodeValue(ModelDB db, Object value) { | 257 Object encodeValue(ModelDB db, Object value, {bool forComparison: false}) { |
| 258 if (forComparison) { |
| 259 // If we have comparison of list properties (i.e. repeated property names) |
| 260 // the comparison object must not be a list, but the value itself. |
| 261 // i.e. |
| 262 // |
| 263 // class Article { |
| 264 // ... |
| 265 // @ListProperty(StringProperty()) |
| 266 // List<String> tags; |
| 267 // ... |
| 268 // } |
| 269 // |
| 270 // should be queried via |
| 271 // |
| 272 // await db.query(Article, 'tags=', "Dart").toList(); |
| 273 // |
| 274 // So the [value] for the comparison is of type `String` and not |
| 275 // `List<String>`! |
| 276 return subProperty.encodeValue(db, value, forComparison: true); |
| 277 } |
| 278 |
| 258 if (value == null) return null; | 279 if (value == null) return null; |
| 259 List list = value; | 280 List list = value; |
| 260 if (list.length == 0) return null; | 281 if (list.length == 0) return null; |
| 261 if (list.length == 1) return subProperty.encodeValue(db, list[0]); | 282 if (list.length == 1) return subProperty.encodeValue(db, list[0]); |
| 262 return list.map( | 283 return list.map( |
| 263 (value) => subProperty.encodeValue(db, value)).toList(); | 284 (value) => subProperty.encodeValue(db, value)).toList(); |
| 264 } | 285 } |
| 265 | 286 |
| 266 Object decodePrimitiveValue(ModelDB db, Object value) { | 287 Object decodePrimitiveValue(ModelDB db, Object value) { |
| 267 if (value == null) return []; | 288 if (value == null) return []; |
| 268 if (value is! List) return [subProperty.decodePrimitiveValue(db, value)]; | 289 if (value is! List) return [subProperty.decodePrimitiveValue(db, value)]; |
| 269 return (value as List) | 290 return (value as List) |
| 270 .map((entry) => subProperty.decodePrimitiveValue(db, entry)) | 291 .map((entry) => subProperty.decodePrimitiveValue(db, entry)) |
| 271 .toList(); | 292 .toList(); |
| 272 } | 293 } |
| 273 } | 294 } |
| 274 | 295 |
| 275 /// A convenience [Property] for list of strings. | 296 /// A convenience [Property] for list of strings. |
| 276 class StringListProperty extends ListProperty { | 297 class StringListProperty extends ListProperty { |
| 277 const StringListProperty({String propertyName, bool indexed: true}) | 298 const StringListProperty({String propertyName, bool indexed: true}) |
| 278 : super(const StringProperty(), | 299 : super(const StringProperty(), |
| 279 propertyName: propertyName, indexed: indexed); | 300 propertyName: propertyName, indexed: indexed); |
| 280 } | 301 } |
| OLD | NEW |