create or replace package PKG_P8PANELS_PE as

  /* Список аргументов пользовательской процедуры */
  procedure USERPROCS_DESC
  (
    SCODE                   in varchar2, -- Мнемокод пользовательской процедуры
    COUT                    out clob     -- Сериализованный список аргументов
  );

end PKG_P8PANELS_PE;
/
create or replace package body PKG_P8PANELS_PE as

  /* Описание пользовательской процедуры */
  procedure USERPROCS_DESC
  (
    SCODE                   in varchar2,     -- Мнемокод пользовательской процедуры
    COUT                    out clob         -- Сериализованный список аргументов
  )
  is
    SRESP_ARG               PKG_STD.TSTRING; -- Имя выходного визуализируемого параметра
  begin
    /* Обращаемся к процедуре */
    for C in (select T.RN       NRN,
                     T.PROCNAME SPROC_NAME,
                     T.PROCTYPE NPROC_TYPE
                from USERPROCS T
               where T.CODE = SCODE)
    loop
      /* Проверим возможность использования ПП в качестве источника данных */
      if (C.NPROC_TYPE <> 0) then
        P_EXCEPTION(0,
                    'Пользовательская процедура "%s" не может быть использована в качестве источника данных: должна иметь тип "Хранимая процедура".',
                    SCODE);
      end if;
      if (C.SPROC_NAME is null) then
        P_EXCEPTION(0,
                    'Пользовательская процедура "%s" не может быть использована в качестве источника данных: не указана хранимая процедура.',
                    SCODE);
      end if;
      /* Начинаем формирование XML */
      PKG_XFAST.PROLOGUE(ITYPE => PKG_XFAST.CONTENT_);
      /* Открываем корень */
      PKG_XFAST.DOWN_NODE(SNAME => 'XDATA');
      /* Открываем описание процедуры */
      PKG_XFAST.DOWN_NODE(SNAME => 'XUSERPROC');
      /* Обходим параметры */
      for P in (select T.PARAMTYPE NTYPE,
                       T.PARAMNAME SNAME,
                       T.NAME SCAPTION,
                       T.DATATYPE NDATA_TYPE,
                       case T.DATATYPE
                         when 0 then
                          'STR'
                         when 1 then
                          'NUMB'
                         when 2 then
                          'DATE'
                         else
                          null
                       end SDATA_TYPE,
                       T.MANDATORY NREQ,
                       T.VISUALIZE NVISUALIZE
                  from USERPROCSPARAMS T
                 where T.PRN = C.NRN
                 order by T.POSITION)
      loop
        /* В результирующий список забираем только входные поддерживаемого типа */
        if ((P.NTYPE = 0) and (P.SDATA_TYPE is not null)) then
          /* Открываем описание аргумента */
          PKG_XFAST.DOWN_NODE(SNAME => 'arguments');
          /* Описываем аргумент */
          PKG_XFAST.ATTR(SNAME => 'name', SVALUE => P.SNAME);
          PKG_XFAST.ATTR(SNAME => 'caption', SVALUE => P.SCAPTION);
          PKG_XFAST.ATTR(SNAME => 'dataType', SVALUE => P.SDATA_TYPE);
          PKG_XFAST.ATTR(SNAME  => 'req',
                         BVALUE => case P.NREQ
                                     when 1 then
                                      true
                                     else
                                      false
                                   end);
          /* Закрываем описание аргумента */
          PKG_XFAST.UP();
        end if;
        /* Если встретился визуализируемый параметр типа CLOB */
        if ((P.NVISUALIZE = 1) and (P.NDATA_TYPE = 4)) then
          if (SRESP_ARG is null) then
            SRESP_ARG := P.SNAME;
          else
            /* Это уже второй такой - ошибка */
            P_EXCEPTION(0,
                        'Пользовательская процедура "%s" не может быть использована в качестве источника данных: имеет более одного выходного параметра типа "Текстовые данные" с признаком "Визуализировать после выполнения".',
                        SCODE);
          end if;
        end if;
      end loop;
      /* Сформируем описание хранимой процедуры */
      PKG_XFAST.DOWN_NODE(SNAME => 'stored');
      PKG_XFAST.ATTR(SNAME => 'name', SVALUE => C.SPROC_NAME);
      PKG_XFAST.ATTR(SNAME => 'respArg', SVALUE => SRESP_ARG);
      PKG_XFAST.UP();
      /* Закрываем описание процедуры */
      PKG_XFAST.UP();
      /* Закрываем описание корня */
      PKG_XFAST.UP();
      /* Сериализуем */
      COUT := PKG_XFAST.SERIALIZE_TO_CLOB();
      /* Завершаем формирование XML */
      PKG_XFAST.EPILOGUE();
    end loop;
    /* Если ничего не нашли */
    if (COUT is null) then
      P_EXCEPTION(0,
                  'Пользовательская процедура "%s" не определена.',
                  COALESCE(SCODE, '<НЕ УКАЗАНА>'));
    end if;
    /* Проверим возможность использования ПП в качестве источника данных - должен быть выходной визуализируемый параметр типа CLOB */
    if (SRESP_ARG is null) then
      P_EXCEPTION(0,
                  'Пользовательская процедура "%s" не может быть использована в качестве источника данных: должна иметь выходной параметр типа "Текстовые данные" с признаком "Визуализировать после выполнения".',
                  SCODE);
    end if;
  end USERPROCS_DESC;

end PKG_P8PANELS_PE;
/
