-
Azat Alimov authored0326ab05
import 'package:html/parser.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUValue.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUValue_Constant.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUValue_Expression.dart';
import 'package:memri/MemriApp/CVU/definitions/CVUValue_LookupNode.dart';
import 'package:memri/MemriApp/Controllers/Database/DatabaseController.dart';
import 'package:memri/MemriApp/Controllers/Database/ItemPropertyRecord.dart';
import 'package:memri/MemriApp/Controllers/Database/ItemRecord.dart';
import 'package:memri/MemriApp/Controllers/Database/PropertyDatabaseValue.dart';
import 'package:memri/MemriApp/Controllers/Database/Schema.dart';
import 'package:memri/MemriApp/Helpers/Binding.dart';
import 'CVUContext.dart';
import 'CVUViewArguments.dart';
/// This struct can be used to _resolve CVU values to a final value of the desired type.
/// For lookups you must provide a CVUContext which contains required information on the default item, viewArguments, etc to be used in the lookup.
class CVULookupController {
LookupMock? lookupMockMode;
CVULookupController([this.lookupMockMode]);
Future<T?> resolve<T>(
{CVUValue? value,
List<CVULookupNode>? nodes,
String? edge,
ItemRecord? item,
String? property,
CVUExpressionNode? expression,
CVUContext? context,
dynamic? defaultValue,
DatabaseController? db}) async {
switch (T) {
case double:
if (nodes != null) {
return await _resolveNodesDouble(nodes, context!, db!) as T?;
} else if (expression != null) {
return await _resolveExpressionDouble(expression, context!, db!) as T?;
}
return await _resolveDouble(value!, context!, db!) as T?;
case String:
if (nodes != null) {
return await _resolveNodesString(nodes, context!, db!) as T?;
} else if (expression != null) {
return await _resolveExpressionString(expression, context!, db!) as T?;
}
return await _resolveString(value!, context!, db!) as T?;
case bool:
if (nodes != null) {
return await _resolveNodesBool(nodes, context!, db!) as T?;
} else if (expression != null) {
return await _resolveExpressionBool(expression, context!, db!) as T?;
}
return await _resolveBool(value!, context!, db!) as T?;
case DateTime:
return await _resolveDate(value!, context!, db!) as T?;
case ItemRecord:
if (edge != null) {
return await _resolveEdgeItemRecord(edge, item!, db!) as T?;
} else if (nodes != null) {
return await _resolveNodesItemRecord(nodes, context!, db!) as T?;
} else if (expression != null) {
return await _resolveExpressionItemRecord(expression, context!, db!) as T?;
}
return await _resolveItemRecord(value!, context!, db!) as T?;
case List: //TODO this wouldn't work @anijanyan
if (edge != null) {
return await _resolveEdgeItemRecordArray(edge, item!, db!) as T?;
} else if (nodes != null) {
return await _resolveNodesItemRecordArray(nodes, context!, db!) as T?;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
} else if (expression != null) {
return await _resolveExpressionItemRecordArray(expression, context!, db!) as T?;
}
return await _resolveItemRecordArray(value!, context!, db!) as T?;
case Binding:
return await _resolveBinding(value!, context!, db!, defaultValue) as T?;
case LookupStep:
return await _resolveLookupStep(nodes!, context!, db!) as T?;
case PropertyDatabaseValue:
return await _resolvePropertyDatabaseValue(property!, item!, db!) as T?;
default:
throw Exception("Type is required");
}
}
Future<double?> _resolveDouble(CVUValue value, CVUContext context, DatabaseController db) async {
if (value is CVUValueConstant) {
return value.value.asNumber();
} else if (value is CVUValueExpression) {
return await resolve<double>(expression: value.value, context: context, db: db);
} else {
return null;
}
}
Future<String?> _resolveString(CVUValue value, CVUContext context, DatabaseController db) async {
if (value is CVUValueConstant) {
return value.value.asString();
} else if (value is CVUValueExpression) {
return await resolve<String>(expression: value.value, context: context, db: db);
} else {
return null;
}
}
Future<bool?> _resolveBool(CVUValue value, CVUContext context, DatabaseController db) async {
if (value is CVUValueConstant) {
return value.value.asBool();
} else if (value is CVUValueExpression) {
return await resolve<bool>(expression: value.value, context: context, db: db);
} else {
return null;
}
}
Future<DateTime?> _resolveDate(CVUValue value, CVUContext context, DatabaseController db) async {
if (value is CVUValueConstant) {
return DateTime.fromMicrosecondsSinceEpoch(
int.parse(value.value.asNumber().toString()) * 1000); //TODO is this right? @anijanyan
} else if (value is CVUValueExpression) {
return await resolve<DateTime>(expression: value.value, context: context, db: db);
} else {
return null;
}
}
Future<ItemRecord?> _resolveItemRecord(
CVUValue value, CVUContext context, DatabaseController db) async {
if (value is CVUValueConstant) {
return null;
} else if (value is CVUValueItem) {
return ItemRecord.fetchWithUID(value.value, db);
} else if (value is CVUValueExpression) {
return await resolve<ItemRecord>(expression: value.value, context: context, db: db);
} else {
return null;
}
}
Future<List<ItemRecord>> _resolveItemRecordArray(