CVULookupController.dart 37.18 KiB
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(