diff --git a/db/UDO_PKG_EXS_TEST.pck b/db/UDO_PKG_EXS_TEST.pck index a236073..8993bb4 100644 --- a/db/UDO_PKG_EXS_TEST.pck +++ b/db/UDO_PKG_EXS_TEST.pck @@ -37,11 +37,131 @@ create or replace package UDO_PKG_EXS_TEST as NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена ); - + + /* Электронная инвентаризация - аутентификация */ + procedure INV_CHECKAUTH_XML + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + + /* Электронная инвентаризация - считывание пользователей */ + procedure INV_GETUSERS_XML + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ); + end; / create or replace package body UDO_PKG_EXS_TEST as + /* Тип данных для коллекции шаблонов вспомогательных слов поиска */ + type THELPER_PATTERNS is table of varchar2(4000); + + /* Проверка на присутствие слова в списке вспомогательных */ + function UTL_HELPER_CHECK + ( + SWORD in varchar2, -- Проверяемое слово + HELPER_PATTERNS in THELPER_PATTERNS -- Коллекция шаблонов вспомогательных слов + ) + return boolean -- Резульата проверки + is + BRES boolean; -- Буфер для результата + begin + /* Инициализируем буфер */ + BRES := false; + /* Если коллекция не пуста */ + if ((HELPER_PATTERNS is not null) and (HELPER_PATTERNS.COUNT > 0)) then + /* Обходим её */ + for I in HELPER_PATTERNS.FIRST .. HELPER_PATTERNS.LAST + loop + /* Если слово есть в коллекции */ + if (LOWER(SWORD) like LOWER(HELPER_PATTERNS(I))) then + /* Выставим флаг присутствия и завершим поиск */ + BRES := true; + exit; + end if; + end loop; + end if; + /* Возвращаем ответ */ + return BRES; + end UTL_HELPER_CHECK; + + /* Инициализация общих вспомогательных поисковых фраз */ + procedure UTL_HELPER_INIT_COMMON + ( + HELPER_PATTERNS in out THELPER_PATTERNS -- Коллекция шаблонов вспомогательных слов + ) + is + begin + /* Создадим пустую коллекцию если надо */ + if (HELPER_PATTERNS is null) then + HELPER_PATTERNS := THELPER_PATTERNS(); + end if; + /* Наполним её общими поисковыми вспомогательными фразами */ + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'расскажи'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'про'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'о'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'об'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'по'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'сведения'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'информацию'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'информация'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'информации'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'инфы'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'инфу'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'дай'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'нарой'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'запроси'; + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'найди'; + end UTL_HELPER_INIT_COMMON; + + /* Подготовка поисковой фразы к участию в выборке */ + function UTL_SEARCH_STR_PREPARE + ( + SSEARCH_STR in varchar2, -- Поисковая фраза + SDELIM in varchar2, -- Разделитель слов в поисковой фразе + HELPER_PATTERNS in THELPER_PATTERNS -- Коллекция шаблонов вспомогательных слов + ) + return varchar2 -- Подготовленная поисковая фраза + is + SRES varchar2(32000); -- Результат работы + begin + /* Обходим слова поисковой фразы */ + for W in (select REGEXP_SUBSTR(T.STR, '[^' || SDELIM || ']+', 1, level) SWRD + from (select replace(replace(SSEARCH_STR, ',', ''), '.', '') STR from DUAL) T + connect by INSTR(T.STR, SDELIM, 1, level - 1) > 0) + loop + /* Если слово не в списке вспомогательных */ + if (not UTL_HELPER_CHECK(SWORD => W.SWRD, HELPER_PATTERNS => HELPER_PATTERNS)) then + /* Оставляем его в итоговой выборке */ + SRES := SRES || '%' || W.SWRD; + end if; + end loop; + /* Уберем лишние пробелы и готовим для поиска */ + SRES := '%' || trim(SRES) || '%'; + /* Вернем ответ */ + return SRES; + end UTL_SEARCH_STR_PREPARE; + /* Запросить контрагента */ procedure RECIVE_AGENT ( @@ -188,58 +308,66 @@ create or replace package body UDO_PKG_EXS_TEST as NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена ) is + HELPER_PATTERNS THELPER_PATTERNS; -- Коллекция шаблонов вспомогательных слов поиска REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди CTMP clob; -- Буфер для конвертации CRESP clob; -- Данные для ответа RCTMP sys_refcursor; -- Буфер для измененной позиции очереди - begin - /* Считаем запись очереди */ - REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); - /* Забираем данные сообщения и конвертируем в кодировку БД */ - CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.MSG, SCHARSET => 'UTF8'); - /* Кладём конвертированное обратно (просто для удобства мониторинга) */ - PKG_EXS.QUEUE_MSG_SET(NEXSQUEUE => REXSQUEUE.RN, BMSG => CLOB2BLOB(LCDATA => CTMP), RCQUEUE => RCTMP); - /* Если есть что искать */ - if (CTMP is not null) then - /* Инициализируем ответ */ - CRESP := 'Контрагент "' || CTMP || '" не найден'; - /* Ищем запрошенного контрагента */ - for C in (select T.AGNNAME || - DECODE(T.AGNTYPE, 1, ', физическое лицо', ', юридическое лицо') SAGENT, - (select count(CN.RN) from CONTRACTS CN where CN.AGENT = T.RN) NCNT_CONTRACTS, - (select sum(CN.DOC_SUM) from CONTRACTS CN where CN.AGENT = T.RN) NSUM_CONTRACTS - from AGNLIST T - where ((STRINLIKE(LOWER(T.AGNABBR), '%' || LOWER(replace(CTMP, ' ', '% %')) || '%', ' ') <> 0) or - (STRINLIKE(LOWER(T.AGNNAME), '%' || LOWER(replace(CTMP, ' ', '% %')) || '%', ' ') <> 0)) - and ROWNUM <= 1) - loop - CRESP := C.SAGENT; - if (C.NCNT_CONTRACTS = 0) then - CRESP := CRESP || ', не имеет зарегистрированных в системе договоров'; - else - CRESP := CRESP || ', зарегистрировано договоров: ' || TO_CHAR(C.NCNT_CONTRACTS); - if (C.NSUM_CONTRACTS <> 0) then - CRESP := CRESP || ', на общую сумму: ' || TO_CHAR(C.NSUM_CONTRACTS) || ' руб.'; - end if; - end if; - end loop; - else - CRESP := 'Не указан поисковый запрос'; - end if; - /* Возвращаем ответ */ - PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, - SARG => PKG_EXS.SCONT_FLD_BRESP, - BVALUE => CLOB2BLOB(LCDATA => CRESP, SCHARSET => 'UTF8')); - end RESP_FIND_AGENT; + begin + /* Считаем запись очереди */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + /* Инициализируем коллекцию слов-помошников */ + UTL_HELPER_INIT_COMMON(HELPER_PATTERNS => HELPER_PATTERNS); + /* Наполняем её значениями индивидуальными для данного запроса */ + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'контрагент%'; + /* Забираем данные сообщения и конвертируем в кодировку БД */ + CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.MSG, SCHARSET => 'UTF8'); + /* Кладём конвертированное обратно (просто для удобства мониторинга) */ + PKG_EXS.QUEUE_MSG_SET(NEXSQUEUE => REXSQUEUE.RN, BMSG => CLOB2BLOB(LCDATA => CTMP), RCQUEUE => RCTMP); + /* Если есть что искать */ + if (CTMP is not null) then + /* Подготовим поисковую фразу */ + CTMP := UTL_SEARCH_STR_PREPARE(SSEARCH_STR => CTMP, SDELIM => ' ', HELPER_PATTERNS => HELPER_PATTERNS); + /* Инициализируем ответ */ + CRESP := 'Контрагент не найден'; + /* Ищем запрошенного контрагента */ + for C in (select T.AGNNAME || + DECODE(T.AGNTYPE, 1, ', физическое лицо', ', юридическое лицо') SAGENT, + (select count(CN.RN) from CONTRACTS CN where CN.AGENT = T.RN) NCNT_CONTRACTS, + (select sum(CN.DOC_SUM) from CONTRACTS CN where CN.AGENT = T.RN) NSUM_CONTRACTS + from AGNLIST T + where ((LOWER(T.AGNABBR) like LOWER(CTMP)) or (LOWER(T.AGNNAME) like LOWER(CTMP))) + and ROWNUM <= 1) + loop + CRESP := C.SAGENT; + if (C.NCNT_CONTRACTS = 0) then + CRESP := CRESP || ', не имеет зарегистрированных в системе договоров'; + else + CRESP := CRESP || ', зарегистрировано договоров: ' || TO_CHAR(C.NCNT_CONTRACTS); + if (C.NSUM_CONTRACTS <> 0) then + CRESP := CRESP || ', на общую сумму: ' || TO_CHAR(C.NSUM_CONTRACTS) || ' руб.'; + end if; + end if; + end loop; + else + CRESP := 'Не указан поисковый запрос'; + end if; + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, + SARG => PKG_EXS.SCONT_FLD_BRESP, + BVALUE => CLOB2BLOB(LCDATA => CRESP, SCHARSET => 'UTF8')); + end RESP_FIND_AGENT; /* Обработка запроса на поиск договора */ procedure RESP_FIND_CONTRACT ( - NIDENT in number, -- Идентификатор процесса - NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) - NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена ) is + HELPER_PATTERNS THELPER_PATTERNS; -- Коллекция шаблонов вспомогательных слов поиска REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди CTMP clob; -- Буфер для конвертации CRESP clob; -- Данные для ответа @@ -247,12 +375,19 @@ create or replace package body UDO_PKG_EXS_TEST as begin /* Считаем запись очереди */ REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + /* Инициализируем коллекцию слов-помошников */ + UTL_HELPER_INIT_COMMON(HELPER_PATTERNS => HELPER_PATTERNS); + /* Наполняем её значениями индивидуальными для данного запроса */ + HELPER_PATTERNS.EXTEND(); + HELPER_PATTERNS(HELPER_PATTERNS.LAST) := 'договор%'; /* Забираем данные сообщения и конвертируем в кодировку БД */ CTMP := BLOB2CLOB(LBDATA => REXSQUEUE.MSG, SCHARSET => 'UTF8'); /* Кладём конвертированное обратно (просто для удобства мониторинга) */ PKG_EXS.QUEUE_MSG_SET(NEXSQUEUE => REXSQUEUE.RN, BMSG => CLOB2BLOB(LCDATA => CTMP), RCQUEUE => RCTMP); /* Если есть что искать */ if (CTMP is not null) then + /* Подготовим поисковую фразу */ + CTMP := UTL_SEARCH_STR_PREPARE(SSEARCH_STR => CTMP, SDELIM => ' ', HELPER_PATTERNS => HELPER_PATTERNS); /* Ищем запрошенный договор */ begin select DECODE(T.INOUT_SIGN, 0, 'Входящий', 'Исходящий') || ' договор №' || @@ -264,16 +399,14 @@ create or replace package body UDO_PKG_EXS_TEST as from CONTRACTS T, AGNLIST AG, CURNAMES CN - where ((STRINLIKE(LOWER(T.EXT_NUMBER), '%' || LOWER(replace(CTMP, ' ', '% %')) || '%', ' ') <> 0) or - (STRINLIKE(LOWER(trim(T.DOC_PREF) || trim(T.DOC_NUMB)), - '%' || LOWER(replace(CTMP, ' ', '% %')) || '%', - ' ') <> 0)) + where ((LOWER(T.EXT_NUMBER) like LOWER(CTMP)) or + (LOWER(trim(T.DOC_PREF) || trim(T.DOC_NUMB)) like LOWER(CTMP))) and T.AGENT = AG.RN and T.CURRENCY = CN.RN and ROWNUM <= 1; exception when NO_DATA_FOUND then - CRESP := 'Договор "' || CTMP || '" не найден'; + CRESP := 'Договор не найден'; end; else CRESP := 'Не указан поисковый запрос'; @@ -283,6 +416,354 @@ create or replace package body UDO_PKG_EXS_TEST as SARG => PKG_EXS.SCONT_FLD_BRESP, BVALUE => CLOB2BLOB(LCDATA => CRESP, SCHARSET => 'UTF8')); end RESP_FIND_CONTRACT; + + /* Электронная инвентаризация - аутентификация */ + procedure INV_CHECKAUTH_XML + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ) + is + REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди + /**/ + SREQDEVICEID varchar2(30); + XCHECKAUTHRESPONSE DBMS_XMLDOM.DOMNODE; + XRESULT DBMS_XMLDOM.DOMNODE; + XNODE DBMS_XMLDOM.DOMNODE; + CRESPONSE clob; + XDOC DBMS_XMLDOM.DOMDOCUMENT; + /**/ + XMLPARCER DBMS_XMLPARSER.PARSER; + XENVELOPE DBMS_XMLDOM.DOMNODE; + XBODY DBMS_XMLDOM.DOMNODE; + XNODELIST DBMS_XMLDOM.DOMNODELIST; + XNODE_ROOT DBMS_XMLDOM.DOMNODE; + SNODE varchar2(100); + CREQ clob; + /**/ + STSD constant varchar2(20) := 'tsd'; + SCHECKAUTHRESPONSE constant varchar2(20) := 'CheckAuthResponse'; + SDEVICEID constant varchar2(20) := 'DeviceID'; + SRESULT constant varchar2(20) := 'Result'; + SSOAPENV constant varchar2(20) := 'soapenv'; + SENVELOPE constant varchar2(20) := 'Envelope'; + SHEADER constant varchar2(20) := 'Header'; + SBODY constant varchar2(20) := 'Body'; + /* Создание ветки XML */ + function CREATENODE + ( + STAG in varchar2, + SNS in varchar2 default null, + SVAL in varchar2 default null + ) return DBMS_XMLDOM.DOMNODE is + XEL DBMS_XMLDOM.DOMELEMENT; + XNODE DBMS_XMLDOM.DOMNODE; + XTEXT DBMS_XMLDOM.DOMNODE; + begin + if SNS is not null then + XEL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => STAG, NS => SNS); + XNODE := DBMS_XMLDOM.MAKENODE(XEL); + DBMS_XMLDOM.SETPREFIX(N => XNODE, PREFIX => SNS); + else + XEL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => STAG); + XNODE := DBMS_XMLDOM.MAKENODE(XEL); + end if; + if SVAL is not null then + XTEXT := DBMS_XMLDOM.APPENDCHILD(XNODE, DBMS_XMLDOM.MAKENODE(DBMS_XMLDOM.CREATETEXTNODE(XDOC, SVAL))); + end if; + return XNODE; + end; + /* Считывание значения ветки XML */ + function GETNODEVAL + ( + XROOTNODE in DBMS_XMLDOM.DOMNODE, + SPATTERN in varchar2 + ) return varchar2 is + XNODE DBMS_XMLDOM.DOMNODE; + SVAL varchar2(100); + begin + XNODE := DBMS_XSLPROCESSOR.SELECTSINGLENODE(N => XROOTNODE, PATTERN => SPATTERN); + if DBMS_XMLDOM.ISNULL(XNODE) then + return null; + end if; + SVAL := DBMS_XMLDOM.GETNODEVALUE(DBMS_XMLDOM.GETFIRSTCHILD(N => XNODE)); + return SVAL; + end GETNODEVAL; + /* Создание документа для ответа */ + procedure CREATERESPONSEDOC is + begin + XDOC := DBMS_XMLDOM.NEWDOMDOCUMENT; + DBMS_XMLDOM.SETVERSION(XDOC + ,'1.0" encoding="UTF-8'); + DBMS_XMLDOM.SETCHARSET(XDOC + ,'UTF-8'); + end; + /* Создание ответа */ + function CREATERESPONSE(XCONTENT in DBMS_XMLDOM.DOMNODE) return clob is + XMAIN_NODE DBMS_XMLDOM.DOMNODE; + XENVELOPE_EL DBMS_XMLDOM.DOMELEMENT; + XENVELOPE DBMS_XMLDOM.DOMNODE; + XHEADER DBMS_XMLDOM.DOMNODE; + XBODY DBMS_XMLDOM.DOMNODE; + XNODE DBMS_XMLDOM.DOMNODE; + CDATA clob; + begin + -- Document + XMAIN_NODE := DBMS_XMLDOM.MAKENODE(XDOC); + -- Envelope + XENVELOPE_EL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => SENVELOPE, NS => SSOAPENV); + DBMS_XMLDOM.SETATTRIBUTE(ELEM => XENVELOPE_EL, + name => 'xmlns:soapenv', + NEWVALUE => 'http://schemas.xmlsoap.org/soap/envelope/'); + DBMS_XMLDOM.SETATTRIBUTE(ELEM => XENVELOPE_EL, name => 'xmlns:tsd', NEWVALUE => 'http://www.example.org/TSDService/'); + XENVELOPE := DBMS_XMLDOM.MAKENODE(XENVELOPE_EL); + DBMS_XMLDOM.SETPREFIX(N => XENVELOPE, PREFIX => SSOAPENV); + XENVELOPE := DBMS_XMLDOM.APPENDCHILD(N => XMAIN_NODE, NEWCHILD => XENVELOPE); + -- Header + XHEADER := CREATENODE(SHEADER, SSOAPENV); + XHEADER := DBMS_XMLDOM.APPENDCHILD(N => XENVELOPE, NEWCHILD => XHEADER); + -- Body + XBODY := CREATENODE(SBODY, SSOAPENV); + XBODY := DBMS_XMLDOM.APPENDCHILD(N => XENVELOPE, NEWCHILD => XBODY); + XNODE := DBMS_XMLDOM.APPENDCHILD(N => XBODY, NEWCHILD => XCONTENT); + -- Создаем CLOB + DBMS_LOB.CREATETEMPORARY(LOB_LOC => CDATA, CACHE => true, DUR => DBMS_LOB.SESSION); + DBMS_XMLDOM.WRITETOCLOB(XDOC, CDATA, 'UTF-8'); + DBMS_XMLDOM.FREEDOCUMENT(DOC => XDOC); + return CDATA; + end; + begin + /* Считаем запись очереди */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + /* Конвертируем в кодировку БД */ + CREQ := BLOB2CLOB(LBDATA => REXSQUEUE.MSG); + -- Создаем инстанс XML парсера + XMLPARCER := DBMS_XMLPARSER.NEWPARSER; + -- Считываем XML из запроса + DBMS_XMLPARSER.PARSECLOB(XMLPARCER + ,CREQ); + -- Берем XML документ + XDOC := DBMS_XMLPARSER.GETDOCUMENT(XMLPARCER); + -- Считываем Корневой элемент + XENVELOPE := DBMS_XMLDOM.MAKENODE(DBMS_XMLDOM.GETDOCUMENTELEMENT(XDOC)); + -- Считываем элемент Body + XBODY := DBMS_XSLPROCESSOR.SELECTSINGLENODE(XENVELOPE + ,SBODY); + -- Считываем дочерние элементы к Body + XNODELIST := DBMS_XMLDOM.GETCHILDNODES(XBODY); + -- Берем первый дочерний элемент + XNODE_ROOT := DBMS_XMLDOM.ITEM(XNODELIST + ,0); + -- Считаем имя элемента + DBMS_XMLDOM.GETLOCALNAME(XNODE_ROOT + ,SNODE); + -- Считываем DeviceID + SREQDEVICEID := GETNODEVAL(XNODE_ROOT + ,SDEVICEID); + --CHECK_ID(SREQDEVICEID); + CREATERESPONSEDOC(); + if SREQDEVICEID is not null + then + XCHECKAUTHRESPONSE := CREATENODE(SCHECKAUTHRESPONSE + ,STSD); + XRESULT := CREATENODE(SRESULT + ,STSD + ,'true'); + XNODE := DBMS_XMLDOM.APPENDCHILD(N => XCHECKAUTHRESPONSE + ,NEWCHILD => XRESULT); + CRESPONSE := CREATERESPONSE(XCHECKAUTHRESPONSE); + end if; + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, + SARG => PKG_EXS.SCONT_FLD_BRESP, + BVALUE => CLOB2BLOB(LCDATA => CRESPONSE)); + end; + + /* Электронная инвентаризация - считывание пользователей */ + procedure INV_GETUSERS_XML + ( + NIDENT in number, -- Идентификатор процесса + NSRV_TYPE in number, -- Тип сервиса (см. константы PKG_EXS.NSRV_TYPE*) + NEXSQUEUE in number -- Регистрационный номер обрабатываемой позиции очереди обмена + ) + is + REXSQUEUE EXSQUEUE%rowtype; -- Запись позиции очереди + /**/ + SREQDEVICEID varchar2(30); + XGETUSERSRESPONSE DBMS_XMLDOM.DOMNODE; + XITEM DBMS_XMLDOM.DOMNODE; + XCODE DBMS_XMLDOM.DOMNODE; + XNAME DBMS_XMLDOM.DOMNODE; + XNODE DBMS_XMLDOM.DOMNODE; + CRESPONSE clob; + XDOC DBMS_XMLDOM.DOMDOCUMENT; + /**/ + XMLPARCER DBMS_XMLPARSER.PARSER; + XENVELOPE DBMS_XMLDOM.DOMNODE; + XBODY DBMS_XMLDOM.DOMNODE; + XNODELIST DBMS_XMLDOM.DOMNODELIST; + XNODE_ROOT DBMS_XMLDOM.DOMNODE; + SNODE varchar2(100); + CREQ clob; + /**/ + STSD constant varchar2(20) := 'tsd'; + SGETUSERSRESPONSE constant varchar2(20) := 'GetUsersResponse'; + SDEVICEID constant varchar2(20) := 'DeviceID'; + SRESULT constant varchar2(20) := 'Result'; + SSOAPENV constant varchar2(20) := 'soapenv'; + SENVELOPE constant varchar2(20) := 'Envelope'; + SHEADER constant varchar2(20) := 'Header'; + SBODY constant varchar2(20) := 'Body'; + SITEM constant varchar2(20) := 'Item'; + SCODE constant varchar2(20) := 'Code'; + SNAME constant varchar2(20) := 'Name'; + /* Создание ветки XML */ + function CREATENODE + ( + STAG in varchar2, + SNS in varchar2 default null, + SVAL in varchar2 default null + ) return DBMS_XMLDOM.DOMNODE is + XEL DBMS_XMLDOM.DOMELEMENT; + XNODE DBMS_XMLDOM.DOMNODE; + XTEXT DBMS_XMLDOM.DOMNODE; + begin + if SNS is not null then + XEL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => STAG, NS => SNS); + XNODE := DBMS_XMLDOM.MAKENODE(XEL); + DBMS_XMLDOM.SETPREFIX(N => XNODE, PREFIX => SNS); + else + XEL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => STAG); + XNODE := DBMS_XMLDOM.MAKENODE(XEL); + end if; + if SVAL is not null then + XTEXT := DBMS_XMLDOM.APPENDCHILD(XNODE, DBMS_XMLDOM.MAKENODE(DBMS_XMLDOM.CREATETEXTNODE(XDOC, SVAL))); + end if; + return XNODE; + end; + /* Считывание значения ветки XML */ + function GETNODEVAL + ( + XROOTNODE in DBMS_XMLDOM.DOMNODE, + SPATTERN in varchar2 + ) return varchar2 is + XNODE DBMS_XMLDOM.DOMNODE; + SVAL varchar2(100); + begin + XNODE := DBMS_XSLPROCESSOR.SELECTSINGLENODE(N => XROOTNODE, PATTERN => SPATTERN); + if DBMS_XMLDOM.ISNULL(XNODE) then + return null; + end if; + SVAL := DBMS_XMLDOM.GETNODEVALUE(DBMS_XMLDOM.GETFIRSTCHILD(N => XNODE)); + return SVAL; + end GETNODEVAL; + /* Создание документа для ответа */ + procedure CREATERESPONSEDOC is + begin + XDOC := DBMS_XMLDOM.NEWDOMDOCUMENT; + DBMS_XMLDOM.SETVERSION(XDOC + ,'1.0" encoding="UTF-8'); + DBMS_XMLDOM.SETCHARSET(XDOC + ,'UTF-8'); + end; + /* Создание ответа */ + function CREATERESPONSE(XCONTENT in DBMS_XMLDOM.DOMNODE) return clob is + XMAIN_NODE DBMS_XMLDOM.DOMNODE; + XENVELOPE_EL DBMS_XMLDOM.DOMELEMENT; + XENVELOPE DBMS_XMLDOM.DOMNODE; + XHEADER DBMS_XMLDOM.DOMNODE; + XBODY DBMS_XMLDOM.DOMNODE; + XNODE DBMS_XMLDOM.DOMNODE; + CDATA clob; + begin + -- Document + XMAIN_NODE := DBMS_XMLDOM.MAKENODE(XDOC); + -- Envelope + XENVELOPE_EL := DBMS_XMLDOM.CREATEELEMENT(DOC => XDOC, TAGNAME => SENVELOPE, NS => SSOAPENV); + DBMS_XMLDOM.SETATTRIBUTE(ELEM => XENVELOPE_EL, + name => 'xmlns:soapenv', + NEWVALUE => 'http://schemas.xmlsoap.org/soap/envelope/'); + DBMS_XMLDOM.SETATTRIBUTE(ELEM => XENVELOPE_EL, name => 'xmlns:tsd', NEWVALUE => 'http://www.example.org/TSDService/'); + XENVELOPE := DBMS_XMLDOM.MAKENODE(XENVELOPE_EL); + DBMS_XMLDOM.SETPREFIX(N => XENVELOPE, PREFIX => SSOAPENV); + XENVELOPE := DBMS_XMLDOM.APPENDCHILD(N => XMAIN_NODE, NEWCHILD => XENVELOPE); + -- Header + XHEADER := CREATENODE(SHEADER, SSOAPENV); + XHEADER := DBMS_XMLDOM.APPENDCHILD(N => XENVELOPE, NEWCHILD => XHEADER); + -- Body + XBODY := CREATENODE(SBODY, SSOAPENV); + XBODY := DBMS_XMLDOM.APPENDCHILD(N => XENVELOPE, NEWCHILD => XBODY); + XNODE := DBMS_XMLDOM.APPENDCHILD(N => XBODY, NEWCHILD => XCONTENT); + -- Создаем CLOB + DBMS_LOB.CREATETEMPORARY(LOB_LOC => CDATA, CACHE => true, DUR => DBMS_LOB.SESSION); + DBMS_XMLDOM.WRITETOCLOB(XDOC, CDATA, 'UTF-8'); + DBMS_XMLDOM.FREEDOCUMENT(DOC => XDOC); + return CDATA; + end; + begin + /* Считаем запись очереди */ + REXSQUEUE := GET_EXSQUEUE_ID(NFLAG_SMART => 0, NRN => NEXSQUEUE); + /* Конвертируем в кодировку БД */ + CREQ := BLOB2CLOB(LBDATA => REXSQUEUE.MSG); + -- Создаем инстанс XML парсера + XMLPARCER := DBMS_XMLPARSER.NEWPARSER; + -- Считываем XML из запроса + DBMS_XMLPARSER.PARSECLOB(XMLPARCER + ,CREQ); + -- Берем XML документ + XDOC := DBMS_XMLPARSER.GETDOCUMENT(XMLPARCER); + -- Считываем Корневой элемент + XENVELOPE := DBMS_XMLDOM.MAKENODE(DBMS_XMLDOM.GETDOCUMENTELEMENT(XDOC)); + -- Считываем элемент Body + XBODY := DBMS_XSLPROCESSOR.SELECTSINGLENODE(XENVELOPE + ,SBODY); + -- Считываем дочерние элементы к Body + XNODELIST := DBMS_XMLDOM.GETCHILDNODES(XBODY); + -- Берем первый дочерний элемент + XNODE_ROOT := DBMS_XMLDOM.ITEM(XNODELIST + ,0); + -- Считаем имя элемента + DBMS_XMLDOM.GETLOCALNAME(XNODE_ROOT + ,SNODE); + -- Считываем DeviceID + SREQDEVICEID := GETNODEVAL(XNODE_ROOT + ,SDEVICEID); + --CHECK_ID(SREQDEVICEID); + CREATERESPONSEDOC(); + if SREQDEVICEID is not null + then + XGETUSERSRESPONSE := CREATENODE(SGETUSERSRESPONSE + ,STSD); + for REC in (select T.RN + ,A.AGNABBR + from INVPERSONS T + ,AGNLIST A + where T.COMPANY = 136018 + and T.AGNLIST = A.RN) + loop + XITEM := CREATENODE(SITEM + ,STSD); + XCODE := CREATENODE(SCODE + ,STSD + ,REC.RN); + XNAME := CREATENODE(SNAME + ,STSD + ,REC.AGNABBR); + XNODE := DBMS_XMLDOM.APPENDCHILD(N => XITEM + ,NEWCHILD => XCODE); + XNODE := DBMS_XMLDOM.APPENDCHILD(N => XITEM + ,NEWCHILD => XNAME); + XNODE := DBMS_XMLDOM.APPENDCHILD(N => XGETUSERSRESPONSE + ,NEWCHILD => XITEM); + end loop; + CRESPONSE := CREATERESPONSE(XGETUSERSRESPONSE); + end if; + /* Возвращаем ответ */ + PKG_EXS.PRC_RESP_ARG_BLOB_SET(NIDENT => NIDENT, + SARG => PKG_EXS.SCONT_FLD_BRESP, + BVALUE => CLOB2BLOB(LCDATA => CRESPONSE, sCHARSET => 'UTF8')); + end; end; /