fromListToJson static method

List fromListToJson(
  1. List<String> lines, {
  2. bool allowEmptyLine = true,
})

Parse a list of icalendar object from a List<String>.

It will return a list containing at first the Map<String, dynamic> headData and at last the List<Map<String, dynamic>> data.

If allowEmptyLine is false the method will throw EmptyLineException.

Implementation

static List<dynamic> fromListToJson(
  List<String> lines, {
  bool allowEmptyLine = true,
}) {
  final data = <Map<String, dynamic>>[];
  final headData = <String, dynamic>{};
  final events = <Object?>[];
  Map<String, dynamic>? lastEvent = {};
  String? currentName;

  // Ensure first line is BEGIN:VCALENDAR
  if (lines.first.trim() != 'BEGIN:VCALENDAR') {
    throw ICalendarBeginException(
      'The first line must be BEGIN:VCALENDAR but was ${lines.first}.',
    );
  }

  // Ensure last line is END:VCALENDAR
  if (lines.last.trim() != 'END:VCALENDAR') {
    throw ICalendarEndException(
      'The last line must be END:VCALENDAR but was ${lines.last}.',
    );
  }

  for (var i = 0; i < lines.length; i++) {
    final line = StringBuffer(lines[i].trim());

    if (line.isEmpty && !allowEmptyLine) {
      throw const EmptyLineException();
    }

    final exp = RegExp('^ ');
    while (i + 1 < lines.length && exp.hasMatch(lines[i + 1])) {
      i += 1;
      line.write(lines[i].trim());
    }

    final dataLine = line.toString().split(':');
    if ((dataLine.length < 2 && !dataLine[0].contains(';')) ||
        (dataLine.isNotEmpty &&
            dataLine[0].toUpperCase() != dataLine[0] &&
            !dataLine[0].contains(';'))) {
      if (lastEvent != null && line.isNotEmpty && currentName != null) {
        final buffer = StringBuffer(lastEvent[currentName] as String)
          ..write(line.toString());
        lastEvent[currentName] = buffer.toString();
      }
      continue;
    }

    final dataName = dataLine[0].split(';');
    final name = dataName[0];
    dataName.removeRange(0, 1);

    final params = <String, String>{};
    for (final e in dataName) {
      final param = e.split('=');
      if (param.length == 2) params[param[0]] = param[1];
    }

    dataLine.removeRange(0, 1);
    final value = dataLine.join(':').replaceAll(RegExp(r'\\,'), ',');
    final nameFunc = _objects[name];
    if (_objects.containsKey(name) && nameFunc != null) {
      currentName = name.toLowerCase();
      if (name == 'END') {
        final func = nameFunc as ClosureFunction;
        currentName = null;
        lastEvent = func(value, params, events, lastEvent, data);
      } else {
        final func = nameFunc as SimpleParamFunction;
        lastEvent = func(value, params, events, lastEvent ?? headData);
      }
    }
  }
  if (!headData.containsKey('version')) {
    throw const ICalendarNoVersionException(
      'The body is missing the property VERSION',
    );
  } else if (!headData.containsKey('prodid')) {
    throw const ICalendarNoProdidException(
      'The body is missing the property PRODID',
    );
  }
  return [headData, data];
}