Skip to content

Commit

Permalink
feat: new "Barcodes" parameter; deprecated configurations (#538)
Browse files Browse the repository at this point in the history
New files:
* `BarcodeParameter.dart`: "Barcodes" search API parameter.
* `BoolMapParameter.dart`: Abstract map of `bool` as `Parameter`.

Impacted files:
* `AllergensParameter.dart`: refactored as `BoolMapParameter<AllergensTag>`
* `api_getToBeCompletedProducts_test.dart`: minor refactoring around a deprecated class
* `api_matchedProductV2_test.dart`: minor refactoring around a deprecated class
* `api_searchProducts_test.dart`: fixed test duration; refactoring
* `openfoodfacts.dart`: minor refactoring around a deprecated class
* `ProductListQueryConfiguration.dart`: deprecated
* `StatesTagsParameter.dart`: refactored as `BoolMapParameter<State>`
* `ToBeCompletedConfiguration.dart`: deprecated
  • Loading branch information
monsieurtanuki authored Aug 4, 2022
1 parent 3872351 commit 582775b
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 124 deletions.
26 changes: 6 additions & 20 deletions lib/model/parameter/AllergensParameter.dart
Original file line number Diff line number Diff line change
@@ -1,31 +1,17 @@
import 'package:openfoodfacts/interface/Parameter.dart';
import 'package:openfoodfacts/model/Allergens.dart';
import 'package:openfoodfacts/model/parameter/BoolMapParameter.dart';

/// List of allergens to filter in and out.
///
/// When we have several items, the results returned use a logical AND.
class AllergensParameter extends Parameter {
class AllergensParameter extends BoolMapParameter<AllergensTag> {
@override
String getName() => 'allergens_tags';

@override
String getValue() {
final List<String> result = <String>[];
if (include != null) {
for (final AllergensTag value in include!) {
result.add(value.tag);
}
}
if (exclude != null) {
for (final AllergensTag value in exclude!) {
result.add('-${value.tag}');
}
}
return result.join(',');
}
String getTag(final AllergensTag key, final bool value) =>
value ? key.tag : '-${key.tag}';

final Iterable<AllergensTag>? include;
final Iterable<AllergensTag>? exclude;

const AllergensParameter({this.include, this.exclude});
const AllergensParameter({required final Map<AllergensTag, bool> map})
: super(map: map);
}
16 changes: 16 additions & 0 deletions lib/model/parameter/BarcodeParameter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:openfoodfacts/interface/Parameter.dart';

/// "Barcodes" search API parameter.
class BarcodeParameter extends Parameter {
@override
String getName() => 'code';

@override
String getValue() => codes.join(',');

final List<String> codes;

BarcodeParameter(final String code) : this.list([code]);

const BarcodeParameter.list(this.codes);
}
28 changes: 28 additions & 0 deletions lib/model/parameter/BoolMapParameter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:openfoodfacts/interface/Parameter.dart';
import 'package:meta/meta.dart';
import 'package:openfoodfacts/openfoodfacts.dart';

/// Abstract map of [bool] as [Parameter].
///
/// Typical use-case with objects that have an on/off quality,
/// like "with/without gluten".
/// A query like "I want the products with eggs but without gluten" would be
/// something like "{'eggs': true, 'gluten': false}".
abstract class BoolMapParameter<T> extends Parameter {
const BoolMapParameter({required this.map});

final Map<T, bool> map;

@override
String getValue() {
final List<String> result = <String>[];
for (final MapEntry<T, bool> item in map.entries) {
result.add(getTag(item.key, item.value));
}
return result.join(',');
}

/// Returns the tag as on or off, like "gluten:with" or "gluten:without"
@protected
String getTag(final T key, final bool value);
}
22 changes: 5 additions & 17 deletions lib/model/parameter/StatesTagsParameter.dart
Original file line number Diff line number Diff line change
@@ -1,26 +1,14 @@
import 'package:openfoodfacts/interface/Parameter.dart';
import 'package:openfoodfacts/model/State.dart';
import 'package:openfoodfacts/model/parameter/BoolMapParameter.dart';

/// States Tags as completed or to-be-completed.
class StatesTagsParameter extends Parameter {
class StatesTagsParameter extends BoolMapParameter<State> {
@override
String getName() => 'states_tags';

@override
String getValue() {
final List<String> result = <String>[];
for (final MapEntry<State, bool> item in completed.entries) {
result.add(
item.value ? item.key.completedTag : item.key.toBeCompletedTag,
);
}
return result.join(',');
}
String getTag(final State key, final bool value) =>
value ? key.completedTag : key.toBeCompletedTag;

/// [State]s to be considered as completed (true) or to-be-completed (false).
///
/// When we have several items, the results returned use a logical AND.
final Map<State, bool> completed;

StatesTagsParameter({required this.completed});
StatesTagsParameter({required final Map<State, bool> map}) : super(map: map);
}
6 changes: 4 additions & 2 deletions lib/openfoodfacts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ import 'package:openfoodfacts/model/TaxonomyIngredient.dart';
import 'package:openfoodfacts/model/TaxonomyLabel.dart';
import 'package:openfoodfacts/model/TaxonomyLanguage.dart';
import 'package:openfoodfacts/model/TaxonomyPackaging.dart';
import 'package:openfoodfacts/model/parameter/BarcodeParameter.dart';
import 'package:openfoodfacts/utils/AbstractQueryConfiguration.dart';
import 'package:openfoodfacts/utils/CountryHelper.dart';
import 'package:openfoodfacts/utils/ImageHelper.dart';
import 'package:openfoodfacts/utils/OcrField.dart';
import 'package:openfoodfacts/utils/ProductFields.dart';
import 'package:openfoodfacts/utils/ProductListQueryConfiguration.dart';
import 'package:openfoodfacts/utils/ProductSearchQueryConfiguration.dart';
import 'package:openfoodfacts/utils/QueryType.dart';
import 'package:openfoodfacts/utils/TagType.dart';
import 'package:openfoodfacts/utils/TaxonomyQueryConfiguration.dart';
Expand Down Expand Up @@ -334,8 +336,8 @@ class OpenFoodAPIClient {
}) async {
final SearchResult searchResult = await searchProducts(
user,
ProductListQueryConfiguration(
barcodes,
ProductSearchQueryConfiguration(
parametersList: [BarcodeParameter.list(barcodes)],
language: language,
country: country,
fields: [
Expand Down
2 changes: 2 additions & 0 deletions lib/utils/ProductListQueryConfiguration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import 'package:openfoodfacts/utils/AbstractQueryConfiguration.dart';
import 'package:openfoodfacts/utils/CountryHelper.dart';

/// Query Configuration for multiple barcodes
// TODO: deprecated from 2022-08-03; remove when old enough
@Deprecated('Use ProductSearchQueryConfiguration with Barcodes instead')
class ProductListQueryConfiguration extends AbstractQueryConfiguration {
final List<String> barcodes;

Expand Down
3 changes: 3 additions & 0 deletions lib/utils/ToBeCompletedConfiguration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import 'package:openfoodfacts/utils/AbstractQueryConfiguration.dart';
import 'package:openfoodfacts/utils/CountryHelper.dart';

/// Query Configuration for all the to-be-completed products.
// TODO: deprecated from 2022-08-03; remove when old enough
@Deprecated(
'Use ProductSearchQueryConfiguration with StatesTagsParameter instead')
class ToBeCompletedQueryConfiguration extends AbstractQueryConfiguration {
ToBeCompletedQueryConfiguration({
final OpenFoodFactsLanguage? language,
Expand Down
6 changes: 5 additions & 1 deletion test/api_getProduct_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1502,7 +1502,11 @@ void main() {
containsAll(someExpectedKeys),
);
});
});
},
timeout: Timeout(
// some tests can be slow here
Duration(seconds: 300),
));

group('$OpenFoodAPIClient test ingredients', () {
const String barcode = BARCODE_DANISH_BUTTER_COOKIES;
Expand Down
12 changes: 8 additions & 4 deletions test/api_getToBeCompletedProducts_test.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import 'package:openfoodfacts/model/State.dart';
import 'package:openfoodfacts/model/parameter/StatesTagsParameter.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:openfoodfacts/utils/CountryHelper.dart';
import 'package:openfoodfacts/utils/OpenFoodAPIConfiguration.dart';
import 'package:openfoodfacts/utils/QueryType.dart';
import 'package:openfoodfacts/utils/ToBeCompletedConfiguration.dart';
import 'package:test/test.dart';

import 'test_constants.dart';

/// Integration tests related to [ToBeCompletedQueryConfiguration]
/// Integration tests related to the "to-be-completed" products
void main() {
OpenFoodAPIConfiguration.globalUser = TestConstants.PROD_USER;
OpenFoodAPIConfiguration.globalQueryType = QueryType.PROD;
Expand All @@ -18,14 +19,17 @@ void main() {
final OpenFoodFactsLanguage language,
) async {
final String reason = '($country, $language)';
final ToBeCompletedQueryConfiguration configuration =
ToBeCompletedQueryConfiguration(
final ProductSearchQueryConfiguration configuration =
ProductSearchQueryConfiguration(
country: country,
language: language,
fields: [
ProductField.BARCODE,
ProductField.STATES_TAGS,
],
parametersList: [
StatesTagsParameter(map: {State.COMPLETED: false}),
],
);

final SearchResult result;
Expand Down
6 changes: 3 additions & 3 deletions test/api_matchedProductV2_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:http/http.dart' as http;
import 'package:openfoodfacts/model/Attribute.dart';
import 'package:openfoodfacts/model/parameter/BarcodeParameter.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:openfoodfacts/personalized_search/available_attribute_groups.dart';
import 'package:openfoodfacts/personalized_search/available_preference_importances.dart';
Expand All @@ -10,7 +11,6 @@ import 'package:openfoodfacts/personalized_search/product_preferences_manager.da
import 'package:openfoodfacts/personalized_search/product_preferences_selection.dart';
import 'package:openfoodfacts/utils/CountryHelper.dart';
import 'package:openfoodfacts/utils/OpenFoodAPIConfiguration.dart';
import 'package:openfoodfacts/utils/ProductListQueryConfiguration.dart';
import 'package:openfoodfacts/utils/QueryType.dart';
import 'package:test/test.dart';

Expand Down Expand Up @@ -128,8 +128,8 @@ void main() {

final SearchResult result = await OpenFoodAPIClient.searchProducts(
OpenFoodAPIConfiguration.globalUser,
ProductListQueryConfiguration(
inputBarcodes,
ProductSearchQueryConfiguration(
parametersList: [BarcodeParameter.list(inputBarcodes)],
language: language,
fields: [ProductField.BARCODE, ProductField.ATTRIBUTE_GROUPS],
),
Expand Down
Loading

0 comments on commit 582775b

Please sign in to comment.