Skip to content

Commit

Permalink
feat: Added ModelUri and ModelGeoValue.
Browse files Browse the repository at this point in the history
  • Loading branch information
mathrunet committed Jun 5, 2023
1 parent d49a756 commit 176a98e
Show file tree
Hide file tree
Showing 12 changed files with 1,735 additions and 87 deletions.
34 changes: 17 additions & 17 deletions packages/katana_model/example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: "405666cd3cf0ee0a48d21ec67e65406aad2c726d9fa58840d3375e7bdcd32a07"
sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
url: "https://pub.dev"
source: hosted
version: "60.0.0"
version: "61.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "1952250bd005bacb895a01bf1b4dc00e3ba1c526cf47dca54dfe24979c65f5b3"
sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
url: "https://pub.dev"
source: hosted
version: "5.12.0"
version: "5.13.0"
args:
dependency: transitive
description:
Expand Down Expand Up @@ -93,10 +93,10 @@ packages:
dependency: transitive
description:
name: build_runner_core
sha256: "30859c90e9ddaccc484f56303931f477b1f1ba2bab74aa32ed5d6ce15870f8cf"
sha256: "88a57f2ac99849362e73878334caa9f06ee25f31d2adced882b8337838c84e1e"
url: "https://pub.dev"
source: hosted
version: "7.2.8"
version: "7.2.9"
built_collection:
dependency: transitive
description:
Expand All @@ -109,10 +109,10 @@ packages:
dependency: transitive
description:
name: built_value
sha256: "2f17434bd5d52a26762043d6b43bb53b3acd029b4d9071a329f46d67ef297e6d"
sha256: "7dd62d9faf105c434f3d829bbe9c4be02ec67f5ed94832222116122df67c5452"
url: "https://pub.dev"
source: hosted
version: "8.5.0"
version: "8.6.0"
characters:
dependency: transitive
description:
Expand Down Expand Up @@ -260,18 +260,18 @@ packages:
dependency: transitive
description:
name: glob
sha256: "4515b5b6ddb505ebdd242a5f2cc5d22d3d6a80013789debfbda7777f47ea308c"
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
version: "2.1.2"
graphs:
dependency: transitive
description:
name: graphs
sha256: "772db3d53d23361d4ffcf5a9bb091cf3ee9b22f2be52cd107cd7a2683a89ba0e"
sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
url: "https://pub.dev"
source: hosted
version: "2.3.0"
version: "2.3.1"
http:
dependency: transitive
description:
Expand Down Expand Up @@ -356,7 +356,7 @@ packages:
path: ".."
relative: true
source: path
version: "2.0.1"
version: "2.0.2"
lints:
dependency: transitive
description:
Expand All @@ -369,10 +369,10 @@ packages:
dependency: transitive
description:
name: logging
sha256: "04094f2eb032cbb06c6f6e8d3607edcfcb0455e2bb6cbc010cb01171dcb64e6d"
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
version: "1.2.0"
matcher:
dependency: transitive
description:
Expand Down Expand Up @@ -449,10 +449,10 @@ packages:
dependency: transitive
description:
name: path_provider_linux
sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1"
sha256: ffbb8cc9ed2c9ec0e4b7a541e56fd79b138e8f47d2fb86815f15358a349b3b57
url: "https://pub.dev"
source: hosted
version: "2.1.10"
version: "2.1.11"
path_provider_platform_interface:
dependency: transitive
description:
Expand Down
1 change: 1 addition & 0 deletions packages/katana_model/lib/katana_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ part 'src/collection_base.dart';
part 'src/listenable_listener.dart';
part 'src/model_transaction.dart';
part 'src/model_field_value.dart';
part 'src/model_geo_value.dart';
248 changes: 248 additions & 0 deletions packages/katana_model/lib/src/model_field_value.dart
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ abstract class ModelFieldValue<T> {
static final Set<ModelFieldValueConverter> _converters = {
const ModelCounterConverter(),
const ModelTimestampConverter(),
const ModelGeoValueConverter(),
const ModelUriConverter(),
const ModelRefConverter(),
};

Expand All @@ -147,6 +149,8 @@ abstract class ModelFieldValue<T> {
static final Set<ModelFieldValueFilter> _filters = {
const ModelCounterFilter(),
const ModelTimestampFilter(),
const ModelGeoValueFilter(),
const ModelUriFilter(),
const ModelRefFilter(),
};

Expand Down Expand Up @@ -984,3 +988,247 @@ class ModelTimestampFilter extends ModelFieldValueFilter<ModelTimestamp> {
return null;
}
}

/// Define the field as a URI.
///
/// The base value is given as [value]. An empty [Uri] is defined.
///
/// Use [ModelUri] if you want to be sure to define it as a URI.
///
/// フィールドをURIとして定義します。
///
/// ベースの値を[value]として与えます。空の[Uri]が定義されます。
///
/// 必ずURIとしての定義を行いたい場合は[ModelUri]を利用してください。
@immutable
class ModelUri extends ModelFieldValue<Uri> {
/// Define the field as a URI.
///
/// The base value is given as [value]. An empty [Uri] is defined.
///
/// Use [ModelUri] if you want to be sure to define it as a URI.
///
/// フィールドをURIとして定義します。
///
/// ベースの値を[value]として与えます。空の[Uri]が定義されます。
///
/// 必ずURIとしての定義を行いたい場合は[ModelUri]を利用してください。
const factory ModelUri([Uri? value]) = _ModelUri;

/// Define the field as a URI.
///
/// The base value is given as [value]. An empty [Uri] is defined.
///
/// Use [ModelUri] if you want to be sure to define it as a URI.
///
/// フィールドをURIとして定義します。
///
/// ベースの値を[value]として与えます。空の[Uri]が定義されます。
///
/// 必ずURIとしての定義を行いたい場合は[ModelUri]を利用してください。
factory ModelUri.parse([String? value]) {
return ModelUri(value == null ? null : Uri.parse(value));
}

/// Used to disguise the retrieval of data from the server.
///
/// Use for testing purposes.
///
/// サーバーからのデータの取得に偽装するために利用します。
///
/// テスト用途で用いてください。
const factory ModelUri.fromServer([Uri? value]) = _ModelUri.fromServer;

/// Convert from [json] map to [ModelUri].
///
/// [json]のマップから[ModelUri]に変換します。
factory ModelUri.fromJson(DynamicMap json) {
final uri = json.get(kUriKey, "");
return ModelUri.fromServer(
Uri.tryParse(uri),
);
}

const ModelUri._([
Uri? value,
ModelFieldValueSource source = ModelFieldValueSource.user,
]) : _value = value,
_source = source;

/// Key to save time.
///
/// 時間を保存しておくキー。
static const kUriKey = "@uri";

/// Key to store the data source.
///
/// データソースを保存しておくキー。
static const kSourceKey = "@source";

@override
Uri get value => _value ?? Uri();
final Uri? _value;

final ModelFieldValueSource _source;

@override
String toString() {
return value.toString();
}

@override
DynamicMap toJson() => {
kTypeFieldKey: (ModelUri).toString(),
kUriKey: value.toString(),
kSourceKey: _source.name,
};

@override
bool operator ==(Object other) => hashCode == other.hashCode;

@override
int get hashCode => _value.hashCode;
}

@immutable
class _ModelUri extends ModelUri with ModelFieldValueAsMapMixin<Uri> {
const _ModelUri([
Uri? value,
ModelFieldValueSource source = ModelFieldValueSource.user,
]) : super._(value, source);
const _ModelUri.fromServer([Uri? value])
: super._(value, ModelFieldValueSource.server);
}

/// [ModelFieldValueConverter] to enable automatic conversion of [ModelUri] as [ModelFieldValue].
///
/// [ModelUri][ModelFieldValue]として自動変換できるようにするための[ModelFieldValueConverter]
@immutable
class ModelUriConverter extends ModelFieldValueConverter<ModelUri> {
/// [ModelFieldValueConverter] to enable automatic conversion of [ModelUri] as [ModelFieldValue].
///
/// [ModelUri][ModelFieldValue]として自動変換できるようにするための[ModelFieldValueConverter]
const ModelUriConverter();

@override
ModelUri fromJson(Map<String, Object?> map) {
return ModelUri.fromJson(map);
}

@override
Map<String, Object?> toJson(ModelUri value) {
return value.toJson();
}
}

/// Filter class to make [ModelUri] available to [ModelQuery.filters].
///
/// [ModelUri][ModelQuery.filters]で利用できるようにするためのフィルタークラス。
@immutable
class ModelUriFilter extends ModelFieldValueFilter<ModelUri> {
/// Filter class to make [ModelUri] available to [ModelQuery.filters].
///
/// [ModelUri][ModelQuery.filters]で利用できるようにするためのフィルタークラス。
const ModelUriFilter();

@override
int? compare(dynamic a, dynamic b) {
return _hasMatch(a, b, (a, b) => a.toString().compareTo(b.toString()));
}

@override
bool? hasMatch(ModelQueryFilter filter, dynamic source) {
final target = filter.value;
switch (filter.type) {
case ModelQueryFilterType.equalTo:
return _hasMatch(source, target, (source, target) => source == target);
case ModelQueryFilterType.notEqualTo:
return _hasMatch(source, target, (source, target) => source != target);
case ModelQueryFilterType.lessThan:
case ModelQueryFilterType.greaterThan:
case ModelQueryFilterType.lessThanOrEqualTo:
case ModelQueryFilterType.greaterThanOrEqualTo:
return null;
case ModelQueryFilterType.arrayContains:
if (source is List) {
if (source.any((s) =>
_hasMatch(s, target, (source, target) => source == target) ??
false)) {
return true;
}
}
break;
case ModelQueryFilterType.arrayContainsAny:
if (source is List && target is List && target.isNotEmpty) {
if (source.any((s) => target.any((t) =>
_hasMatch(s, t, (source, target) => source == target) ??
false))) {
return true;
}
}
break;
case ModelQueryFilterType.whereIn:
if (target is List && target.isNotEmpty) {
final matches = target.mapAndRemoveEmpty((t) =>
_hasMatch(source, t, (source, target) => source == target));
if (matches.isNotEmpty) {
return matches.any((element) => element);
}
}
break;
case ModelQueryFilterType.whereNotIn:
if (target is List && target.isNotEmpty) {
final matches = target.mapAndRemoveEmpty((t) =>
_hasMatch(source, t, (source, target) => source == target));
if (matches.isNotEmpty) {
return !matches.any((element) => element);
}
}
break;
default:
return null;
}
return null;
}

T? _hasMatch<T>(
dynamic source,
dynamic target,
T Function(Uri source, Uri target) filter,
) {
if (source is ModelUri && target is ModelUri) {
return filter(source.value, target.value);
} else if (source is ModelUri && target is Uri) {
return filter(source.value, target);
} else if (source is Uri && target is ModelUri) {
return filter(source, target.value);
} else if (source is ModelUri && target is String) {
final uri = Uri.tryParse(target);
if (uri == null) {
return null;
}
return filter(source.value, uri);
} else if (source is String && target is ModelUri) {
final uri = Uri.tryParse(source);
if (uri == null) {
return null;
}
return filter(uri, target.value);
} else if (source is ModelUri &&
target is DynamicMap &&
target.get(kTypeFieldKey, "") == (ModelUri).toString()) {
return filter(source.value, ModelUri.fromJson(target).value);
} else if (source is DynamicMap &&
target is ModelUri &&
source.get(kTypeFieldKey, "") == (ModelUri).toString()) {
return filter(ModelUri.fromJson(source).value, target.value);
} else if (source is DynamicMap &&
target is DynamicMap &&
source.get(kTypeFieldKey, "") == (ModelUri).toString() &&
target.get(kTypeFieldKey, "") == (ModelUri).toString()) {
return filter(
ModelUri.fromJson(source).value, ModelUri.fromJson(target).value);
}
return null;
}
}
Loading

0 comments on commit 176a98e

Please sign in to comment.