movieWithUserDataFromTurtle static method
- String ttlContent
Parses a single movie with user data from TTL content. Returns a map containing the movie, rating, and comment.
Implementation
static Map<String, dynamic>? movieWithUserDataFromTurtle(String ttlContent) {
try {
// First try to parse from JSON backup for compatibility.
final movieJsonMatch =
RegExp(r'# JSON_MOVIE_DATA: (.+)').firstMatch(ttlContent);
final userDataJsonMatch =
RegExp(r'# JSON_USER_DATA: (.+)').firstMatch(ttlContent);
if (movieJsonMatch != null && userDataJsonMatch != null) {
final movieJsonData = movieJsonMatch.group(1)!;
final userDataJsonData = userDataJsonMatch.group(1)!;
final movieData = jsonDecode(movieJsonData) as Map<String, dynamic>;
final userData = jsonDecode(userDataJsonData) as Map<String, dynamic>;
return {
'movie': Movie.fromJson(movieData),
'rating': userData['rating'],
'comment': userData['comment'],
};
}
// Parse using proper RDF if no JSON backup.
final triples = turtleToTripleMap(ttlContent);
Movie? movie;
double? rating;
String? comment;
// Find movie, rating, and comment resources.
for (final subject in triples.keys) {
final predicates = triples[subject]!;
final typeValues =
predicates['http://www.w3.org/1999/02/22-rdf-syntax-ns#type'] ?? [];
// Check for movie.
final isMovie = typeValues.any(
(type) =>
type.toString().contains('Movie') ||
type == 'http://schema.org/Movie' ||
type == '#Movie',
);
if (isMovie && movie == null) {
movie = _extractMovieFromTriples(predicates);
// Also check for rating and comment in the same movie resource (new ontology format).
if (rating == null) {
final contentRatingKey = predicates.keys.firstWhere(
(key) => key.toString().contains('contentRating'),
orElse: () => '',
);
if (contentRatingKey.isNotEmpty &&
predicates[contentRatingKey]!.isNotEmpty) {
final rawValue = predicates[contentRatingKey]!.first.toString();
rating = double.tryParse(rawValue);
}
}
if (comment == null) {
final commentKey = predicates.keys.firstWhere(
(key) => key.toString().contains('comment'),
orElse: () => '',
);
if (commentKey.isNotEmpty && predicates[commentKey]!.isNotEmpty) {
comment = predicates[commentKey]!.first.toString();
}
}
}
// Check for rating (old format compatibility).
final isRating = typeValues.any(
(type) => type.toString().contains('Rating') || type == '#Rating',
);
if (isRating && rating == null) {
final valueKey = predicates.keys.firstWhere(
(key) => key.toString().contains('value'),
orElse: () => '',
);
if (valueKey.isNotEmpty && predicates[valueKey]!.isNotEmpty) {
final rawValue = predicates[valueKey]!.first.toString();
rating = double.tryParse(rawValue);
}
}
// Check for comment (old format compatibility).
final isComment = typeValues.any(
(type) => type.toString().contains('Comment') || type == '#Comment',
);
if (isComment && comment == null) {
final textKey = predicates.keys.firstWhere(
(key) => key.toString().contains('text'),
orElse: () => '',
);
if (textKey.isNotEmpty && predicates[textKey]!.isNotEmpty) {
comment = predicates[textKey]!.first.toString();
}
}
}
if (movie != null) {
return {
'movie': movie,
'rating': rating,
'comment': comment,
};
}
return null;
} catch (e) {
// Don't log parsing errors - they're often due to expected empty/missing files.
return null;
}
}