relatives property

  1. @override
Future<Iterable<Tuple2<Relation, Node>>> relatives
override

Relatives of this node that can be generated if/when needed. Subclasses must implement this getter, while making sure each generated Relation either starts or ends at this Node.

Implementation

@override
Future<Iterable<Tuple2<Relation, Node>>> get relatives async {
  var result = <Tuple2<Relation, Node>>[];
  final client = http.Client();

  var response = await client.get(
    Uri.parse(
        "https://www.wikidata.org/wiki/Special:EntityData/$entityId.json"),
  );

  if (response.statusCode != 200) return result;

  final data = jsonDecode(response.body);

  List<String> claimKeys = (data["entities"][entityId]["claims"] as Map)
      .keys
      .map<String>((e) => e)
      .toList();

  var claims = <String, List<String>>{};
  for (var claim in claimKeys) {
    final claimItems = (data["entities"][entityId]["claims"][claim] as List)
        .map((claimItem) {
          try {
            return claimItem["mainsnak"]["datavalue"]["value"]["id"];
          } catch (_) {}
        })
        .where((element) => element != null)
        .toList();
    claims[claim] = claimItems.cast<String>();
  }

  final futureResults = <Future>[];
  for (final claim in claims.entries) {
    for (final node in claim.value) {
      final f = Future.microtask(() async {
        final toNode = await WikiDataEntityNode.tryFromWikidata(node);
        if (toNode == null) {
          return;
        }
        final relation = await WikiDataUtils.tryFromWikidata(
          this,
          toNode,
          claim.key,
        );
        if (relation == null) {
          return;
        }
        result.add(Tuple2(relation, toNode));
      });
      futureResults.add(f);
    }
  }

  await Future.wait(futureResults);

  return result;
}