validateCommandSet function

NmCommandValidationResult validateCommandSet(
  1. NmCommandSet value,
  2. NmTelecomL10n l10n, {
  3. Iterable<String> otherIds = const [],
})

Validate command set.

Implementation

NmCommandValidationResult validateCommandSet(NmCommandSet value, NmTelecomL10n l10n, {Iterable<String> otherIds = const []}) {
  final issues = <NmCommandFieldIssue>[];
  if (value.id.isEmpty || value.id.length > 64 || !_safeId.hasMatch(value.id)) {
    issues.add(NmCommandFieldIssue('metadata.id', l10n.cmdSetValIdCharset));
  }
  if (otherIds.contains(value.id)) {
    issues.add(NmCommandFieldIssue('metadata.id', l10n.cmdSetValIdDuplicate));
  }
  if (value.name.trim().isEmpty || value.name.length > 100) {
    issues.add(NmCommandFieldIssue('metadata.name', l10n.cmdSetValNameRequired));
  }
  if (value.operatorName.trim().isEmpty || value.operatorName.length > 80) {
    issues.add(NmCommandFieldIssue('metadata.operator', l10n.cmdSetValOperatorRequired));
  }
  if (!RegExp(r'^[A-Z]{2}$').hasMatch(value.countryCode)) {
    issues.add(NmCommandFieldIssue('metadata.country', l10n.cmdSetValCountryCodeFormat));
  }
  if (value.countryName.trim().isEmpty) {
    issues.add(NmCommandFieldIssue('metadata.country', l10n.cmdSetValCountryNameRequired));
  }
  if ((value.region?.length ?? 0) > 80) {
    issues.add(NmCommandFieldIssue('metadata.region', l10n.cmdSetValRegionTooLong));
  }

  final commandIds = <String>{};
  for (final command in value.commands) {
    final base = 'commands.${command.id}';
    if (!commandIds.add(command.id) || !_safeId.hasMatch(command.id)) {
      issues.add(NmCommandFieldIssue('$base.id', l10n.cmdSetValCommandIdUnique));
    }
    if (command.name.trim().isEmpty) {
      issues.add(NmCommandFieldIssue('$base.name', l10n.cmdSetValCommandNameRequired));
    }
    if (command.operations.isEmpty) {
      issues.add(NmCommandFieldIssue('$base.operations', l10n.cmdSetValCommandNeedsOperation));
    }
    final parameterKeys = command.parameters.map((p) => p.key).toSet();
    final operationIds = <String>{};
    for (final operation in command.operations) {
      final opPath = '$base.operations.${operation.id}';
      if (!operationIds.add(operation.id) || !_safeId.hasMatch(operation.id)) {
        issues.add(NmCommandFieldIssue('$opPath.id', l10n.cmdSetValOperationIdUnique));
      }
      if (operation is NmUssdDialogOperation) {
        _validateTemplate(operation.start.payloadTemplate, parameterKeys, '$opPath.start.payload', issues, l10n, emptyMessage: l10n.cmdSetValUssdStartRequired);
        final replyIds = <String>{};
        for (final reply in operation.replies) {
          final replyPath = '$opPath.replies.${reply.id}';
          if (!replyIds.add(reply.id)) {
            issues.add(NmCommandFieldIssue('$replyPath.id', l10n.cmdSetValReplyIdUnique));
          }
          _validateTemplate(reply.payloadTemplate, parameterKeys, '$replyPath.payload', issues, l10n, emptyMessage: l10n.cmdSetValUssdReplyRequired);
          final fallback = reply.fallbackAfterSeconds;
          if (fallback != null && (fallback < 1 || fallback > 300)) {
            issues.add(NmCommandFieldIssue('$replyPath.fallback', l10n.cmdSetValFallbackRange));
          }
        }
      } else if (operation is NmSendSmsOperation) {
        _validateTemplate(
          operation.destinationTemplate,
          parameterKeys,
          '$opPath.destination',
          issues,
          l10n,
          emptyMessage: l10n.cmdSetValSmsDestinationRequired,
        );
        _validateTemplate(operation.messageTemplate, parameterKeys, '$opPath.message', issues, l10n, emptyMessage: l10n.cmdSetValSmsTextRequired);
      } else if (operation is NmPlaceCallOperation) {
        _validateTemplate(operation.numberTemplate, parameterKeys, '$opPath.number', issues, l10n, emptyMessage: l10n.cmdSetValPhoneNumberRequired);
      } else if (operation is NmSendAtOperation) {
        _validateTemplate(operation.commandTemplate, parameterKeys, '$opPath.command', issues, l10n, emptyMessage: l10n.cmdSetValAtCommandRequired);
      }
    }
  }

  final ruleIds = <String>{};
  for (final rule in value.responseRules) {
    final base = 'rules.${rule.id}';
    if (!ruleIds.add(rule.id) || !_safeId.hasMatch(rule.id)) {
      issues.add(NmCommandFieldIssue('$base.id', l10n.cmdSetValRuleIdUnique));
    }
    if (rule.name.trim().isEmpty) {
      issues.add(NmCommandFieldIssue('$base.name', l10n.cmdSetValRuleNameRequired));
    }
    if (rule.matcher.pattern.isEmpty) {
      issues.add(NmCommandFieldIssue('$base.pattern', l10n.cmdSetValPatternRequired));
    }
    if (rule.matcher.mode == NmResponseMatchMode.regularExpression && rule.matcher.pattern.isNotEmpty) {
      try {
        RegExp(rule.matcher.pattern, caseSensitive: rule.matcher.caseSensitive);
      } on FormatException {
        issues.add(NmCommandFieldIssue('$base.pattern', l10n.cmdSetValRegexInvalid));
      }
    }
    if (rule.effects.isEmpty && rule.outcome == null) {
      issues.add(NmCommandFieldIssue('$base.effects', l10n.cmdSetValRuleNeedsEffect));
    }
    final destinations = <NmResponseField>{};
    for (var i = 0; i < rule.effects.length; i++) {
      final effect = rule.effects[i];
      final effectPath = '$base.effects.$i';
      if (!destinations.add(effect.field)) {
        issues.add(NmCommandFieldIssue('$effectPath.field', l10n.cmdSetValFieldAlreadyUsed));
      }
      if (effect.source == NmParameterValueSource.fixedValue && (effect.fixedValue?.isEmpty ?? true)) {
        issues.add(NmCommandFieldIssue('$effectPath.value', l10n.cmdSetValFixedValueRequired));
      }
      if (effect.source == NmParameterValueSource.capture) {
        final capture = effect.captureNameOrIndex;
        if (capture == null || capture.isEmpty) {
          issues.add(NmCommandFieldIssue('$effectPath.capture', l10n.cmdSetValCaptureRequired));
        } else if (!RegExp(r'^(?:[1-9][0-9]*|[A-Za-z_][A-Za-z0-9_]*)$').hasMatch(capture)) {
          issues.add(NmCommandFieldIssue('$effectPath.capture', l10n.cmdSetValCaptureFormat));
        }
      }
    }
  }
  return NmCommandValidationResult(issues);
}