public static void parseLine(int lineNum, String line) throws IOException {
    MessageHeader msgHdr = new MessageHeader(line.substring(0, 12));
    MessageTypeHeader msgTypeHdr = new MessageTypeHeader(line.substring(12, 104));

    int declaredMessageLength = msgHdr.getMessageLength();
    int declaredRecordDataLength = msgTypeHdr.getRecordDataLength();

    // Validation to ensure the line contents match the lengths declaration.
    // 12 chars before the message length declaration.
    // 104 chars before the record data length declaration.
    if (declaredMessageLength + 12 == line.length()
        && declaredRecordDataLength + 104 == line.length()) {

      writeToLog(lineNum + ": " + "Declared lengths match the actual line length.");

      int currPos = 104;
      while (true) {

        RecordHeader rcdHdr = new RecordHeader(line.substring(currPos, currPos + 20));
        int recordLength = rcdHdr.getRecordLength();

        currPos = currPos + 20;

        Record record;

        if (keyMap.get(rcdHdr.getRecordType()) != null) {
          // String recordText = line.substring(currPos - 1, currPos + recordLength - 1);
          String recordText = line.substring(currPos, currPos + recordLength);
          String recordReferenceId = "|";

          // Build the reference identifier based on the record keys defined in the Key Map
          for (Key key : keyMap.get(rcdHdr.getRecordType())) {
            recordReferenceId =
                recordReferenceId
                    + recordText.substring(
                        key.getKeyPosition(), key.getKeyPosition() + key.getKeyLength())
                    + "|";
          }

          record =
              new Record(
                  rcdHdr.getRecordType(),
                  recordReferenceId,
                  rcdHdr.getRecordActionCode(),
                  recordText);
          writeToLog(record.getText().length() + ": " + record.getText());
          saveRecordToMap(record);

        } else {
          writeToLog("Record type " + rcdHdr.getRecordType() + " is not supported.");
        }

        currPos = currPos + recordLength;

        if (currPos >= line.length()) {
          break;
        }
      }

    } else {
      writeToLog(
          lineNum
              + ": "
              + "Line is invalid. Declared message lengths do not match the actual length.");
    }
  }