execute method

Future<ValidationRuleResult> execute({
  1. required DataValueSet dataValueSet,
  2. required String dataSet,
  3. DataValue? changedDataValue,
})

Implementation

Future<ValidationRuleResult> execute(
    {required DataValueSet dataValueSet,
    required String dataSet,
    DataValue? changedDataValue}) async {
  List<ValidationRuleAction> validationRuleActions = [];

  List<ValidationRule> validationRules =
      await ValidationRuleQuery(database: database)
          .where(attribute: 'dataSet', value: dataSet)
          .get();

  List<DataValue> dataValues = await DataValueQuery(database: database)
      .where(attribute: 'dataValueSet', value: dataValueSet.id)
      .get();

  final dataValueEntities =
      DataValueEntities.fromAggregateDataValues(dataValues);

  final nonTotalEvaluationContext =
      ValidationRuleEngine._getEvaluationContext(dataValueEntities);

  final totalEvaluationContext = ValidationRuleEngine._getEvaluationContext(
      dataValueEntities,
      totalOnly: true);

  validationRules.forEach((validationRule) {
    final leftSide = jsonDecode(json.decode(validationRule.leftSide));

    String leftSideConditionForEvaluation = leftSide['expression']
        .replaceAll("#{", "")
        .replaceAll("}", "")
        .replaceAll(".", "");

    List<String> leftSideElements = leftSide['expression']
        .replaceAll("#{", ",")
        .replaceAll("}", ",")
        .split(',')
        .where((String id) => id.length > 0)
        .toList();

    final rightSide = jsonDecode(json.decode(validationRule.rightSide));
    String rightSideConditionForEvaluation = rightSide['expression']
        .replaceAll("#{", "")
        .replaceAll("}", "")
        .replaceAll(".", "");

    List<String> rightSideElements = rightSide['expression']
        .replaceAll("#{", ",")
        .replaceAll("}", ",")
        .split(',')
        .where((String id) => id.length > 0)
        .toList();

    nonTotalEvaluationContext.keys.forEach((key) {
      final value = nonTotalEvaluationContext[key];

      leftSideConditionForEvaluation =
          leftSideConditionForEvaluation.replaceAll(key, value);
      rightSideConditionForEvaluation =
          rightSideConditionForEvaluation.replaceAll(key, value);
    });

    totalEvaluationContext.keys.forEach((key) {
      final value = totalEvaluationContext[key];

      leftSideConditionForEvaluation =
          leftSideConditionForEvaluation.replaceAll(key, value);
      rightSideConditionForEvaluation =
          rightSideConditionForEvaluation.replaceAll(key, value);
    });

    bool skipLeftSideExpression = false;
    try {
      Expression leftSideExpression =
          Expression.parse(leftSideConditionForEvaluation);
      final leftSideEvaluator = const ExpressionEvaluator();
      leftSideEvaluator.eval(leftSideExpression, nonTotalEvaluationContext);
    } catch (e) {
      skipLeftSideExpression =
          leftSide['missingValueStrategy'] == 'SKIP_IF_ANY_VALUE_MISSING';
    }

    bool skipRightSideExpression = false;
    try {
      Expression rightSideExpression =
          Expression.parse(rightSideConditionForEvaluation);
      final rightSideEvaluator = const ExpressionEvaluator();
      rightSideEvaluator.eval(rightSideExpression, nonTotalEvaluationContext);
    } catch (e) {
      skipRightSideExpression =
          rightSide['missingValueStrategy'] == 'SKIP_IF_ANY_VALUE_MISSING';
    }

    if (!(skipLeftSideExpression || skipRightSideExpression)) {
      String ruleExpressionForEvaluation =
          '$leftSideConditionForEvaluation ${ValidationRuleEngine._getRuleMathOperator(validationRule.operator)} $rightSideConditionForEvaluation';

      try {
        Expression expression = Expression.parse(ruleExpressionForEvaluation);

        final evaluator = const ExpressionEvaluator();
        var evaluationResult =
            evaluator.eval(expression, nonTotalEvaluationContext);

        if (evaluationResult == false) {
          validationRuleActions.add(ValidationRuleAction(
              instruction: (validationRule.displayInstruction ??
                  validationRule.instruction ??
                  validationRule.name) as String,
              dataElements: [...leftSideElements, ...rightSideElements],
              action: 'SHOWWARNING'));
        }
      } catch (e) {}
    }
  });

  return ValidationRuleResult(
      dataValueSet: dataValueSet,
      validationRuleActions: validationRuleActions);
}