Skip to content

Commit

Permalink
refactor: rework parsing of additional fields
Browse files Browse the repository at this point in the history
  • Loading branch information
JKRhb committed Sep 26, 2022
1 parent 975e120 commit 75009b8
Show file tree
Hide file tree
Showing 19 changed files with 220 additions and 150 deletions.
8 changes: 4 additions & 4 deletions lib/src/definitions/additional_expected_response.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// SPDX-License-Identifier: BSD-3-Clause

import 'package:collection/collection.dart';
import 'package:curie/curie.dart';
import 'package:meta/meta.dart';

import 'extensions/json_parser.dart';
Expand All @@ -26,17 +27,16 @@ class AdditionalExpectedResponse {
factory AdditionalExpectedResponse.fromJson(
Map<String, dynamic> json,
String formContentType,
PrefixMapping prefixMapping,
) {
final Set<String> parsedFields = {};

final contentType =
json.parseField<String>('contentType', parsedFields) ?? formContentType;
final success = json.parseField<bool>('success', parsedFields);
final schema = json.parseField<String>('schema', parsedFields);

final additionalFields = Map.fromEntries(
json.entries.where((entry) => !parsedFields.contains(entry.key)),
);
final additionalFields =
json.parseAdditionalFields(prefixMapping, parsedFields);

return AdditionalExpectedResponse(
contentType,
Expand Down
31 changes: 14 additions & 17 deletions lib/src/definitions/expected_response.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
//
// SPDX-License-Identifier: BSD-3-Clause

import 'package:curie/curie.dart';

import 'extensions/json_parser.dart';

/// Communication metadata describing the expected response message for the
Expand All @@ -18,23 +20,18 @@ class ExpectedResponse {
);

/// Creates an [ExpectedResponse] from a [json] object.
static ExpectedResponse? fromJson(
Map<String, dynamic> json, [
Set<String>? parsedFields,
]) {
final responseJson = json['response'];
parsedFields?.add('response');

if (responseJson is! Map<String, dynamic>) {
return null;
}

return ExpectedResponse(
responseJson.parseRequiredField<String>('contentType'),
additionalFields: Map.fromEntries(
responseJson.entries.where((element) => element.key != 'contentType'),
),
);
factory ExpectedResponse.fromJson(
Map<String, dynamic> json,
PrefixMapping prefixMapping,
) {
final Set<String> parsedFields = {};

final contentType =
json.parseRequiredField<String>('contentType', parsedFields);
final additionalFields =
json.parseAdditionalFields(prefixMapping, parsedFields);

return ExpectedResponse(contentType, additionalFields: additionalFields);
}

/// The [contentType] of this [ExpectedResponse] object.
Expand Down
96 changes: 93 additions & 3 deletions lib/src/definitions/extensions/json_parser.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'package:curie/curie.dart';

import '../additional_expected_response.dart';
import '../data_schema.dart';
import '../expected_response.dart';
import '../form.dart';
import '../interaction_affordances/action.dart';
import '../interaction_affordances/event.dart';
Expand Down Expand Up @@ -209,7 +211,7 @@ extension ParseField on Map<String, dynamic> {

return fieldValue
.whereType<Map<String, dynamic>>()
.map((e) => Form.fromJson(e, interactionAffordance))
.map((e) => Form.fromJson(e, interactionAffordance, prefixMapping))
.toList();
}

Expand All @@ -228,7 +230,7 @@ extension ParseField on Map<String, dynamic> {

return fieldValue
.whereType<Map<String, dynamic>>()
.map(Link.fromJson)
.map((e) => Link.fromJson(e, prefixMapping))
.toList();
}

Expand All @@ -252,7 +254,7 @@ extension ParseField on Map<String, dynamic> {
for (final securityDefinition in fieldValue.entries) {
final dynamic value = securityDefinition.value;
if (value is Map<String, dynamic>) {
final securityScheme = SecurityScheme.fromJson(value);
final securityScheme = SecurityScheme.fromJson(value, prefixMapping);
if (securityScheme != null) {
result[securityDefinition.key] = securityScheme;
}
Expand Down Expand Up @@ -342,4 +344,92 @@ extension ParseField on Map<String, dynamic> {

return result;
}

/// Parses [ExpectedResponse]s contained in this JSON object.
///
/// Adds the key `events` to the set of [parsedFields], if defined.
ExpectedResponse? parseExpectedResponse(
PrefixMapping prefixMapping, [
Set<String>? parsedFields,
]) {
final fieldValue = parseMapField<dynamic>('response', parsedFields);

if (fieldValue == null) {
return null;
}

return ExpectedResponse.fromJson(fieldValue, prefixMapping);
}

/// Parses [ExpectedResponse]s contained in this JSON object.
///
/// Adds the key `events` to the set of [parsedFields], if defined.
List<AdditionalExpectedResponse>? parseAdditionalExpectedResponse(
PrefixMapping prefixMapping,
String formContentType, [
Set<String>? parsedFields,
]) {
final fieldValue = parseArrayField<Map<String, dynamic>>(
'additionalResponses',
parsedFields,
);

if (fieldValue == null) {
return null;
}

return fieldValue
.map(
(e) => AdditionalExpectedResponse.fromJson(
e,
formContentType,
prefixMapping,
),
)
.toList();
}

/// Parses and filters the remaining fields in this JSON object.
///
/// The additional fields are determined by the [Set] of [parsedFields].
Map<String, dynamic> parseAdditionalFields(
PrefixMapping prefixMapping,
Set<String> parsedFields,
) {
return Map.fromEntries(
entries.where((element) => !parsedFields.contains(element.key)),
).map(
(key, value) => MapEntry(
_expandCurieKey(key, prefixMapping),
_expandCurieValue(value, prefixMapping),
),
);
}

static String _expandCurieKey(String key, PrefixMapping prefixMapping) {
if (key.contains(':')) {
final prefix = key.split(':')[0];
if (prefixMapping.getPrefixValue(prefix) != null) {
return prefixMapping.expandCurieString(key);
}
}
return key;
}

static dynamic _expandCurieValue(dynamic value, PrefixMapping prefixMapping) {
if (value is String && value.contains(':')) {
final prefix = value.split(':')[0];
if (prefixMapping.getPrefixValue(prefix) != null) {
return prefixMapping.expandCurieString(value);
}
} else if (value is Map<String, dynamic>) {
return value.map<String, dynamic>((key, dynamic oldValue) {
final newKey = _expandCurieKey(key, prefixMapping);
final dynamic newValue = _expandCurieValue(oldValue, prefixMapping);
return MapEntry<String, dynamic>(newKey, newValue);
});
}

return value;
}
}
84 changes: 8 additions & 76 deletions lib/src/definitions/form.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class Form {
factory Form.fromJson(
Map<String, dynamic> json,
InteractionAffordance interactionAffordance,
PrefixMapping prefixMapping,
) {
final Set<String> parsedFields = {};
final href = json.parseRequiredUriField('href', parsedFields);
Expand All @@ -65,33 +66,17 @@ class Form {

final security = json.parseArrayField<String>('security', parsedFields);
final scopes = json.parseArrayField<String>('scopes', parsedFields);
final response = ExpectedResponse.fromJson(json, parsedFields);

List<AdditionalExpectedResponse>? additionalResponses;
if (json['additionalResponses'] != null) {
final dynamic jsonResponse =
_getJsonValue(json, 'additionalResponses', parsedFields);
if (jsonResponse is Map<String, dynamic>) {
additionalResponses = [
AdditionalExpectedResponse.fromJson(jsonResponse, contentType)
];
} else if (jsonResponse is List<dynamic>) {
additionalResponses = [];
for (final entry in jsonResponse) {
if (entry is Map<String, dynamic>) {
additionalResponses
.add(AdditionalExpectedResponse.fromJson(entry, contentType));
}
}
}
}
final response = json.parseExpectedResponse(prefixMapping, parsedFields);

final additionalFields = _parseAdditionalFields(
json,
final additionalResponses = json.parseAdditionalExpectedResponse(
prefixMapping,
contentType,
parsedFields,
interactionAffordance.thingDescription.prefixMapping,
);

final additionalFields =
json.parseAdditionalFields(prefixMapping, parsedFields);

return Form(
href,
interactionAffordance,
Expand Down Expand Up @@ -231,59 +216,6 @@ class Form {
);
}

static dynamic _getJsonValue(
Map<String, dynamic> formJson,
String key,
Set<String> parsedJsonFields,
) {
parsedJsonFields.add(key);
return formJson[key];
}

static String _expandCurieKey(String key, PrefixMapping prefixMapping) {
if (key.contains(':')) {
final prefix = key.split(':')[0];
if (prefixMapping.getPrefixValue(prefix) != null) {
return prefixMapping.expandCurieString(key);
}
}
return key;
}

static dynamic _expandCurieValue(dynamic value, PrefixMapping prefixMapping) {
if (value is String && value.contains(':')) {
final prefix = value.split(':')[0];
if (prefixMapping.getPrefixValue(prefix) != null) {
return prefixMapping.expandCurieString(value);
}
} else if (value is Map<String, dynamic>) {
return value.map<String, dynamic>((key, dynamic oldValue) {
final newKey = _expandCurieKey(key, prefixMapping);
final dynamic newValue = _expandCurieValue(oldValue, prefixMapping);
return MapEntry<String, dynamic>(newKey, newValue);
});
}

return value;
}

static Map<String, dynamic> _parseAdditionalFields(
Map<String, dynamic> formJson,
Set<String> parsedFields,
PrefixMapping prefixMapping,
) {
final additionalFields = <String, dynamic>{};
for (final entry in formJson.entries) {
if (!parsedFields.contains(entry.key)) {
final String key = _expandCurieKey(entry.key, prefixMapping);
final dynamic value = _expandCurieValue(entry.value, prefixMapping);

additionalFields[key] = value;
}
}
return additionalFields;
}

/// Creates a deep copy of this [Form].
Form _copy(Uri newHref) {
// TODO(JKRhb): Make deep copies of security, scopes, and response.
Expand Down
5 changes: 2 additions & 3 deletions lib/src/definitions/interaction_affordances/action.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,8 @@ class Action extends InteractionAffordance {
);

action.forms.addAll(json.parseForms(action, prefixMapping, parsedFields));
action.additionalFields.addEntries(
json.entries.where((entry) => !parsedFields.contains(entry.key)),
);
action.additionalFields
.addAll(json.parseAdditionalFields(prefixMapping, parsedFields));

return action;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/src/definitions/interaction_affordances/event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ class Event extends InteractionAffordance {
);

event.forms.addAll(json.parseForms(event, prefixMapping));
event.additionalFields.addEntries(
json.entries.where((entry) => !parsedFields.contains(entry.key)),
event.additionalFields.addAll(
json.parseAdditionalFields(prefixMapping, parsedFields),
);

return event;
Expand Down
4 changes: 2 additions & 2 deletions lib/src/definitions/interaction_affordances/property.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ class Property extends InteractionAffordance implements DataSchema {
);

property.forms.addAll(json.parseForms(property, prefixMapping));
property.additionalFields.addEntries(
json.entries.where((element) => !parsedFields.contains(element.key)),
property.additionalFields.addAll(
json.parseAdditionalFields(prefixMapping, parsedFields),
);

return property;
Expand Down
11 changes: 5 additions & 6 deletions lib/src/definitions/link.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
//
// SPDX-License-Identifier: BSD-3-Clause

import 'package:curie/curie.dart';

import 'extensions/json_parser.dart';

/// Represents an element of the `links` array in a Thing Description.
Expand All @@ -29,7 +31,7 @@ class Link {
}

/// Creates a new [Link] from a [json] object.
Link.fromJson(Map<String, dynamic> json) {
Link.fromJson(Map<String, dynamic> json, PrefixMapping prefixMapping) {
final Set<String> parsedFields = {};

href = json.parseRequiredUriField('href', parsedFields);
Expand All @@ -40,11 +42,8 @@ class Link {
sizes = json.parseField<String>('sizes', parsedFields);
hreflang = json.parseArrayField<String>('hreflang', parsedFields);

additionalFields.addAll(
Map.fromEntries(
json.entries.where((element) => !parsedFields.contains(element.key)),
),
);
additionalFields
.addAll(json.parseAdditionalFields(prefixMapping, parsedFields));
}

/// Target IRI of a link or submission target of a form.
Expand Down
Loading

0 comments on commit 75009b8

Please sign in to comment.