/**
  * Displays an information bubble pointing to an ExecuteProcess operator to indicate a {@link
  * UserError} occurred inside the process executed by the operator.
  *
  * @param userError the error instance
  * @return the {@link OperatorInfoBubble} instance, never {@code null}
  */
 public static OperatorInfoBubble displayUserErrorInExecutedProcess(
     final ProcessExecutionUserErrorError userError) {
   String referencedOperatorName = userError.getUserError().getOperator().getName();
   return displayUserErrorInExecutedProcess(
       userError,
       "executed_process_usererror",
       referencedOperatorName,
       userError.getUserError().getDetails());
 }
  /**
   * Displays the best machting error bubble depending on the given {@link UserError}. If no
   * explicit match can be found, displays a generic error bubble.
   *
   * @param error the error in question, must not be {@code null}
   * @return the bubble instance, never {@code null}
   */
  public static BubbleWindow displayBubbleForUserError(final UserError error) {
    if (error == null) {
      throw new IllegalArgumentException("userError must not be null!");
    }

    if (error instanceof PortUserError) {
      PortUserError userError = (PortUserError) error;
      if (userError.getCode() == 149) {
        // for "no data" errors we display an error bubble instead of a dialog
        return displayInputPortNoDataInformation(userError.getPort());
      } else if (userError.getCode() == 156) {
        return displayInputPortWrongTypeInformation(
            userError.getPort(), userError.getExpectedType(), userError.getActualType());
      } else {
        return displayGenericPortError(userError);
      }
    } else if (error.getClass().equals(UndefinedParameterError.class)) {
      UndefinedParameterError userError = (UndefinedParameterError) error;
      if (userError.getCode() == 205 || userError.getCode() == 217) {
        // for "missing mandatory parameter" errors we display an error bubble
        // instead of a dialog
        Operator op = userError.getOperator();
        ParameterType param = op != null ? op.getParameterType(userError.getKey()) : null;
        if (op != null && param != null) {
          return displayMissingMandatoryParameterInformation(op, param);
        } else {
          return displayGenericUserError(error);
        }
      } else {
        Operator op = userError.getOperator();
        ParameterType param = op != null ? op.getParameterType(userError.getKey()) : null;
        if (op != null && param != null) {
          return displayMissingMandatoryParameterInformation(op, param);
        } else {
          return displayGenericUserError(error);
        }
      }
    } else if (error instanceof ParameterError) {
      ParameterError userError = (ParameterError) error;
      Operator op = userError.getOperator();
      ParameterType param = op != null ? op.getParameterType(userError.getKey()) : null;
      if (op != null && param != null) {
        return displayGenericParameterError(userError);
      } else {
        return displayGenericUserError(error);
      }
    } else if (error instanceof AttributeNotFoundError) {
      AttributeNotFoundError userError = (AttributeNotFoundError) error;
      Operator op = userError.getOperator();
      ParameterType param = op != null ? op.getParameterType(userError.getKey()) : null;
      if (op != null && param != null) {
        return displayAttributeNotFoundParameterInformation(userError);
      } else {
        return displayGenericUserError(error);
      }
    } else if (error instanceof ProcessExecutionUserErrorError) {
      ProcessExecutionUserErrorError userError = (ProcessExecutionUserErrorError) error;
      if (userError.getUserError() != null && userError.getUserError().getOperator() != null) {
        return displayUserErrorInExecutedProcess(userError);
      } else {
        return displayGenericUserError(error);
      }
    } else {
      return displayGenericUserError(error);
    }
  }