parseAdxString static method

Adif parseAdxString(
  1. String str, {
  2. bool ignoreIllegals = true,
})

Parse from ADX strings.

  • @param str The ADX string to be parsed
  • @param ignoreIllegals Whether to ignore illegal data. When this argument is set to true, the method ignores all illegal fields (they won't be parsed anyway), otherwise it throws an exception.

Set ignoreIllegals to true does not mean it never throws an exception. When the ADX string is broken severely (eg. even not a valid XML string), exceptions may occur.

Implementation

static Adif parseAdxString(String str, {bool ignoreIllegals = true}) {
  final document = XmlDocument.parse(str);
  final XmlElement adx =
      document.getElement('ADX') ?? (throw Exception("Not a valid ADX file"));

  // Parse the header.
  final header = adx.getElement('HEADER');
  final adifVer = header?.getElement('ADIF_VER');
  final programId = header?.getElement('PROGRAMID');
  final programVersion = header?.getElement('PROGRAMVERSION');
  final userdefIterables = header?.findAllElements('USERDEF') ?? [];
  final userdefMetas = userdefIterables.map((e) {
    // final fieldId = int.parse(e.getAttribute('FIELDID') ?? '0');
    final fieldName = e.innerText;
    final type = e.getAttribute('TYPE') ?? 'S';
    final enumsStr = e.getAttribute('ENUM');
    final enums =
        enumsStr
            ?.substring(1, enumsStr.length - 1)
            .split(',')
            .map((e) => e.trim())
            .toList();
    final rangeStr = e.getAttribute('RANGE');
    final range =
        rangeStr
            ?.substring(1, rangeStr.length - 1)
            .split(':')
            .map((e) => double.parse(e.trim()))
            .toList();
    try {
      return UserdefMeta(
        fieldName,
        type,
        enums: enums,
        range:
            range != null && range.length == 2 ? (range[0], range[1]) : null,
      );
    } catch (e) {
      if (ignoreIllegals) {
        return null;
      } else {
        rethrow;
      }
    }
  });

  // Parse the records.
  final records = adx.getElement('RECORDS');
  final qsos =
      records?.findElements('RECORD').map((record) {
        final fields = record.children.whereType<XmlElement>().map((field) {
          final fieldName = field.name.local;

          // App-defined fields.
          if (fieldName == 'APP') {
            final programId = field.getAttribute('PROGRAMID');
            final customFieldName = field.getAttribute('FIELDNAME');
            final type = field.getAttribute('TYPE');
            final value = field.innerText;
            final (enums, range) = parseEnumsAndRanges(
              field.getAttribute('ENUMS'),
              field.getAttribute('RANGE'),
            );
            try {
              return Appdef.generate(
                programId ?? 'unknown',
                customFieldName ??
                    (throw Exception("APP-defined field without FIELDNAME")),
                type ?? 'S',
                value,
                enums: enums,
                range: range,
              );
            } catch (e) {
              if (ignoreIllegals) {
                return null;
              } else {
                rethrow;
              }
            }
          }

          // User-defined fields.
          if (fieldName == 'USERDEF') {
            final customFieldName = field.getAttribute('FIELDNAME');
            final value = field.innerText;
            try {
              // Get the metadata.
              final metadata =
                  userdefMetas.firstWhere(
                    (userdefMeta) => userdefMeta?.name == customFieldName,
                  ) ??
                  (throw Exception("USERDEF field undefined"));
              return Userdef.generate(
                customFieldName ??
                    (throw Exception("USERDEF field without FIELDNAME")),
                metadata.type,
                value,
                enums: metadata.enums,
                range: metadata.range,
              );
            } catch (e) {
              if (ignoreIllegals) {
                return null;
              } else {
                rethrow;
              }
            }
          }

          // Any other fields are regarded as ADIF-defined fields.
          final value = field.innerText;
          try {
            return adifFieldFactory(fieldName, value);
          } catch (e) {
            if (ignoreIllegals) {
              return null;
            } else {
              rethrow;
            }
          }
        });
        return Qso(
          fields.whereType<AdifField>().toList(),
          fields.whereType<Appdef>().toList(),
          fields.whereType<Userdef>().toList(),
        );
      }).toList() ??
      [];

  return Adif(
    programId?.innerText ?? 'unknown',
    programVersion?.innerText ?? '',
    qsos,
    adifVer: adifVer?.innerText,
  );
}