public void showNotification(final @NotNull ProjectSystemId externalSystemId,
                               final @NotNull NotificationData notificationData,
                               @Nullable Key<String> notificationKey) {
    Disposer.register(this, notificationData);
    if (ApplicationManager.getApplication().isHeadlessEnvironment()) {
      if (notificationData.getNotificationCategory() == NotificationCategory.INFO) {
        LOG.debug(notificationData.getMessage());
      } else {
        LOG.warn(notificationData.getMessage());
      }
    }

    if (ApplicationManager.getApplication().isUnitTestMode()) {
      @SuppressWarnings("UseOfSystemOutOrSystemErr")
      PrintStream out = notificationData.getNotificationCategory() == NotificationCategory.INFO ? System.out : System.err;
      out.println(notificationData.getMessage());
      return;
    }

    if (notificationKey != null && isNotificationActive(notificationKey)) return;
    myUpdateQueue.queue(new Update(new Object()) {

      @Override
      public void run() {
        if (isDisposedOrNotOpen()) return;
        assert myProject != null;
        Project project = myProject;

        final Application app = ApplicationManager.getApplication();
        Runnable action = () -> {
          if (!initializedExternalSystem.contains(externalSystemId)) {
            app.runWriteAction(() -> {
              if (isDisposedOrNotOpen()) return;
              ExternalSystemUtil.ensureToolWindowContentInitialized(project, externalSystemId);
              initializedExternalSystem.add(externalSystemId);
            });
          }
          if (isDisposedOrNotOpen()) return;
          NotificationGroup group;
          if (notificationData.getBalloonGroup() == null) {
            ExternalProjectsView externalProjectsView =
              ExternalProjectsManagerImpl.getInstance(project).getExternalProjectsView(externalSystemId);
            group = externalProjectsView instanceof ExternalProjectsViewImpl ?
                    ((ExternalProjectsViewImpl)externalProjectsView).getNotificationGroup() : null;
          }
          else {
            group = notificationData.getBalloonGroup();
          }
          if (group == null) return;

          final Notification notification = group
            .createNotification(notificationData.getTitle(), notificationData.getMessage(), notificationData.getNotificationCategory().getNotificationType())
            .setListener(notificationData.getListener());

          if (notificationKey == null) {
            myNotifications.add(notification);
          }
          else {
            Notification oldNotification = myUniqueNotifications.put(notificationKey, notification);
            if (oldNotification != null) {
              oldNotification.expire();
            }
          }

          if (notificationData.isBalloonNotification()) {
            applyNotification(notification);
          }
          else {
            addMessage(notification, externalSystemId, notificationData);
          }
        };
        app.invokeLater(action, ModalityState.defaultModalityState(), project.getDisposed());
      }
    });
  }
public void showNotification(final @NotNull ProjectSystemId externalSystemId,
                               final @NotNull NotificationData notificationData,
                               @Nullable Key<String> notificationKey)