local ss = analiz.libs.serv
local tick = CreateTimeServ()

local finn_serv = analiz.mix.finnova.serv
finn_serv.mt_parser = CreateMTParser()
local mem = ss.CreateMemItem(8000)
local base64 = require("ee5_base64")
-- patch_validator:igrore:ru
local function all_trim(s)
    if s == nil then
        ss.l("all_trim:nill!!")
        s = ""
    end
    return s:match("^%s*(.-)%s*$")
end

-- ----------------------------------------------------------------
local function find_(str, start_tag, end_tag, pos)
    if str == nil then
        ss.l("failed: str is null ")
        ss.l(debug.traceback())
    end
    local i = str:find(start_tag, pos)
    if i == nil then return nil, 0 end
    local iend = str:find(end_tag, i)
    if iend == nil then
        ss.l("iend is nil")
        ss.l("end_tag:" .. end_tag)
        return nil, 0
    end
    local s = i + start_tag:len()
    --    ss.l("find.c:"..s)
    --    ss.l("find.iend:"..ss.def(iend,"<nil>"))
    local x = str:sub(s, iend - 1)
    return x, iend + end_tag:len()
end
-- ----------------------------------------------------------------
local function find_xml_(str, tag, pos)

    local v, p = find_(str, "<" .. tag .. ">", "</" .. tag .. ">", pos)
    --    ss.l("find_xml_:"..ss.def(v,"nil")..":"..ss.def(p,"<nil>"))
    return v, p
end
-- ----------------------------------------------------------------
local function ExtractAdrLine(xml, tag, pos_start)
    -- ss.l("ExtractAdrLine.start:"..xml:sub(pos_start,300))
    local res = nil
    local old = -1
    local v, p = find_xml_(xml, tag, pos_start)
    local i = 1
    while v ~= nil do
        if i == 1 then
            res = ""
        else
            res = res .. "\n"
        end
        --       if i==1 then res = "" else res=res.." " end
        res = res .. v
        --    ss.l(i..":"..p.."val:"..res)
        v, p = find_xml_(xml, tag, p)
        if p == old then
            ss.l("ExtractAdrLine.warning:p=" .. p .. ":xml=" .. xml)
            break
        end
        old = p
        i = i + 1
        if i > 100 then
            ss.l("ExtractAdrLine.warning100:p=" .. p .. ":xml=" .. xml)
            break
        end
    end
    --   ss.l("ExtractAdrLine.end:"..res)
    return res, p + 1
end

local function find_xml_ex_(str, tags_str, pos_start, default_value, default_pos)
    local tags = ss.mysplit(tags_str, "\\")
    local pos = nil
    local xx = str
    local len = #tags
    for i = 1, len do
        --     ss.l("t:"..tags[i])
        if i == len and tags[i] == "AdrLine" then
            local res, p = ExtractAdrLine(xx, tags[i], pos_start)
            return res, p
        end
        local xxx, pos1 = find_xml_(xx, tags[i], pos_start)
        pos_start = 1
        if xxx == nil then
            ss.l("not found: " .. tags[i])
            return default_value, default_pos
        end
        if pos == nil then pos = pos1 --[[ss.l("new pos:"..pos)--]] end
        xx = xxx
    end
    return xx, pos
end
-- ----------------------------------------------------------------
-- ----------------------------
local function ExtractAmountVer1(o, xml_str) -- 008,009

    local amount_full =
        find_(xml_str, "<IntrBkSttlmAmt", "</IntrBkSttlmAmt>", 1)
    if amount_full ~= nil then
        o.amountlocalcur = find_(amount_full .. "</", '">', "</", 1)
        o.currency = find_(amount_full, 'Ccy="', '">', 1)
    end

    if o.currency == nil then o.currency = "UNDEF" end
    if o.amountlocalcur == nil then o.amountlocalcur = "-1" end
end

local function ExtractAmountVer2(o, xml_str) -- 004
    -- этот вариант не потвержден что правильный
    -- там еще есть место где есть валюта
    local str = find_xml_ex_(xml_str, "TxInf", 1, "")
    local amount_full = find_(str, "<RtrdIntrBkSttlmAmt",
                              "</RtrdIntrBkSttlmAmt>", 1)
    if amount_full ~= nil then
        o.amountlocalcur = find_(amount_full .. "</", '">', "</", 1)
        o.currency = find_(amount_full, 'Ccy="', '">', 1)
    end

    if o.currency == nil then o.currency = "UNDEF" end
    if o.amountlocalcur == nil then o.amountlocalcur = "-1" end

end

local function ExtractAmountVer3(o, xml_str, doc_writer) -- 004
    -- в этом варианте пишем amountlocalcur в amount
    -- получается что у нас есть валюта и сумма (в ver2 были две суммы и одно наименование валюты)
    -- 
    local str = find_xml_ex_(xml_str, "TxInf", 1, "")
    local amount_full = find_(str, "<RtrdIntrBkSttlmAmt",
                              "</RtrdIntrBkSttlmAmt>", 1)
    if amount_full ~= nil then
        o.amount = find_(amount_full .. "</", '">', "</", 1)
        o.currency = find_(amount_full, 'Ccy="', '">', 1)
    end

    if o.currency == nil then o.currency = "UNDEF" end
    if o.amount == nil then o.amount = "-1" end

    if doc_writer == nil then return end
    doc_writer:write("RtrdIntrBkSttlmAmt", "amount",
                     "ExtractAmountVer3().amount", "-1")
    doc_writer:write("RtrdIntrBkSttlmAmt.Ccy", "currency",
                     "ExtractAmountVer3().currency", "-1")

end

-- ----------------------------
local function ExtractAmountVer1v2(o, xml_str, doc_writer) -- 008,009

    local amount_full =
        find_(xml_str, "<IntrBkSttlmAmt", "</IntrBkSttlmAmt>", 1)
    if amount_full ~= nil then
        o.amount = find_(amount_full .. "</", '">', "</", 1)
        o.currency = find_(amount_full, 'Ccy="', '">', 1)
    end

    if o.currency == nil then o.currency = "UNDEF" end
    if o.amount == nil then o.amount = "-1" end

    if doc_writer == nil then return end
    doc_writer:write("IntrBkSttlmAmt", "amount", "ExtractAmountVer1v2().amount",
                     "-1")
    doc_writer:write("IntrBkSttlmAmt.Ccy", "currency",
                     "ExtractAmountVer1v2().currency", "-1")
end

-- ------------------------------------------------------------------------------------------------------------
-- ------------------------------------------------------------------------------------------------------------
-- ------------------------------------------------------------------------------------------------------------
local function out_name_doc(ii)
    if ii.obj == nil then return ii.name end
    return ii.obj .. "." .. ii.name
end

local function from_name_doc(ii)
    if type(ii) == "string" then return ii end
    if ii == nil then
        ss.l("failed.ii=nul")
        ss.l(debug.traceback())
    end
    ss.tprint(ii)
    if ii.value_is_null == true then return "=nil" end
    if ii.from_obj == nil then return ii.from end
    return ii.from_obj .. "." .. ii.from
end

local function add_val(o, ii, val)
    if ii.obj ~= nil then
        local obj = o[ii.obj]
        if obj == nil then
            obj = {}
            o[ii.obj] = obj
        end
        obj[ii.name] = val
    else
        o[ii.name] = val
    end
end
local function get_val(o, ii)
    if type(ii) == "string" then return o[ii] end
    if ii.value_is_null == true then return nil end

    if ii.from_obj ~= nil then
        local v = o[ii.from_obj]
        if v == nil then return nil end
        return v[ii.from]
    end
    return o[ii.from]
end

-- ------------------------------------------------------------------------------------------------------------
-- ------------------------------------------------------------------------------------------------------------
-- ------------------------------------------------------------------------------------------------------------

local function ExtractLastName_incoming(xml_str, doc_i)
    if doc_i.writer ~= nil then

        doc_i.writer:write("<Dbtr><Nm>", out_name_doc(doc_i.obj),
                           "ExtractLastName_incoming")
    end

    local pos = xml_str:find("<Dbtr><Nm>")
    local x = find_xml_(xml_str, "Dbtr", pos)
    if x == nil then return o end

    return find_xml_(x, "Nm", 1)
end
-- ------------------------------------------------------
local function ExtractLastName(xml_str, doc_i)
    if doc_i.writer ~= nil then
        doc_i.writer:write("<Cdtr><Nm>", out_name_doc(doc_i.obj),
                           "ExtractLastName")
    end

    local pos = xml_str:find("<Cdtr><Nm>")
    local x = find_xml_(xml_str, "Cdtr", pos)
    if x == nil then return o end

    return find_xml_(x, "Nm", 1)
end
-- -------------------
local function ExtractAddr(x)
    local l, pos = find_xml_(x, "AdrLine", 1)

    local buf = ss.CreateStringBuffer()

    while l ~= nil do
        if not buf:isempty() then buf:add("#;#") end
        buf:add(l)
        l, pos = find_xml_(x, "AdrLine", pos)
    end

    return buf:to_string()
end

local function ExtractPstlAdr_v2(xml_str, doc_i)
    if doc_i.writer ~= nil then
        doc_i.writer:write(doc_i.obj.pattern, out_name_doc(doc_i.obj),
                           "ExtractPstlAdr_v2")
    end
    -- from ao: if AdrLine is found then use the old logic
    local l_old, pos =
        find_xml_ex_(xml_str, doc_i.obj.pattern .. "\\AdrLine", 1)
    if ss.def(l_old, "") ~= "" then return l_old end

    -- new logic:
    local l, pos = find_xml_ex_(xml_str, doc_i.obj.pattern, 1)
    if l == nil then return "" end

    ss.l("ExtractPstlAdr_v2.start")
    -- ss.l("l:"..l..":"..ss.def(pos,"nil"))ss.l("---")ss.l("xml_str.size="..(xml_str:len()))
    -- local xml = xml_str:sub(l,pos)
    local xml = l

    local function replace_(xml, tag, rr, rr2)
        local start_tag = "<" .. tag .. ">"
        if xml:find(start_tag, 1, true) == nil then return xml end

        xml = ss.ReplaceValue(xml, start_tag, rr)
        xml = ss.ReplaceValue(xml, "</" .. tag .. ">", rr2)

        return xml
    end

    -- xml = replace_(xml,"AdrLine","##;##","")

    xml = replace_(xml, "TwnNm", "  ", " ")
    xml = replace_(xml, "StrtNm", "  ", " ")
    xml = replace_(xml, "PstCd", " ", " ")
    xml = replace_(xml, "Ctry", " ", " ")
    xml = replace_(xml, "BldgNb", " ", " ")

    xml = replace_(xml, "AdrTp", " ", " ")
    xml = replace_(xml, "Dept", " ", " ")
    xml = replace_(xml, "SubDept", " ", " ")
    xml = replace_(xml, "CtrySubDvsn", " ", " ")

    xml = ss.ReplaceValue(xml, "<AdrLine></AdrLine>", "")
    if xml == "" then return "" end

    ss.l("ExtractPstlAdr_v2.res:" .. xml)
    return "#" .. all_trim(xml)
end
local function ExtractPstlAdr(xml_str, doc_i)

    if doc_i.writer ~= nil then
        doc_i.writer:write("PstlAdr\\AdrLine", out_name_doc(doc_i.obj),
                           "ExtractPstlAdr")
    end

    local l, pos = find_xml_ex_(xml_str, "PstlAdr\\AdrLine", 1)
    if l == nil then return "" end
    ss.l(l .. ":" .. ss.def(pos, "nil"))

    local buf = ss.CreateStringBuffer()
    local old = -1

    while l ~= nil do
        if not buf:isempty() then buf:add("#;#") end

        buf:add(l)
        l, pos = find_xml_ex_(xml_str, "PstlAdr\\AdrLine", pos)
        if pos == old then break end
        old = pos
    end

    return buf:to_string()
end

local function alter_swift_code_pacs(o, ii)
    local op = ii.option
    ss.l("alter_swift_code_pacs.start:" .. op.obj)

    local swift_code_tag = {from_obj = op.obj, from = op.name}
    local swift_code = get_val(o, swift_code_tag)
    if ss.def(swift_code, "") ~= "" then
        ss.l("swift_code:" .. swift_code)
        return
    end

    local CLRNAME =
        ss.def(get_val(o, {from_obj = op.obj, from = "CLRNAME"}), "")
    local MMBNAME =
        ss.def(get_val(o, {from_obj = op.obj, from = "MMBNAME"}), "")
    ss.l("CLRNAME:" .. CLRNAME)
    ss.l("MMBNAME:" .. MMBNAME)

    local account = get_val(o, op.account)
    local isaccount_correct = checkFormat_account_(account)
    if not (isaccount_correct) then account = "XX" end

    local val = ""

    if MMBNAME ~= "" then
        val = "CLR:" .. account:sub(1, 2) .. ":" .. CLRNAME .. ":" .. MMBNAME
    elseif account ~= "XX" then
        val = "NON:" .. account:sub(1, 2)

    end

    ss.l("val:" .. val)
    add_val(o, op, val)
end

-- -----------------------------------------------
-- -----------------------------------------------
-- -----------------------------------------------

local function copy_sub_type1(o, options)
    if options.sub_type == "incoming" then
        o.lastname = o.dbtr.lastname
        o.address = o.dbtr.address
        o.swift_code = o.dbtr.swift_code
    else
        o.lastname = o.cdtr.lastname
        o.address = o.cdtr.address
        o.swift_code = o.cdtr.swift_code
    end
end
local function copy_sub_type2(o, options)
    if options.sub_type == "outgoing" then
        o.lastname = o.cdtr.lastname
        o.address = o.cdtr.address
    else
        o.lastname = o.dbtr.lastname
    end

end

local function copy_sub_type3(o, options)
    -- 9.04.2019 mail:https://mail.google.com/mail/u/0/?tab=wm#sent/CllgCJlLWxtVXbvvdRjBqsLmTtqGVwdJjrgXKGSWvFGwRjgwnswqRFnlQbDqnKFtNgcgQcsznPL
    if options.sub_type == "incoming" then
        o.swift_code = o.dbtr.swift_code
    else
        o.swift_code = o.cdtr.swift_code
    end
end

local function ExtractLastName009(xml_str, doc_i)
    if doc_i.writer ~= nil then
        doc_i.writer:write("Cdtr\\BIC,CdtrAgt\\BIC", out_name_doc(doc_i.obj),
                           "ExtractLastName009")
    end

    local str = find_xml_ex_(xml_str, "Cdtr\\BIC", 1, "")
    if str == "" then str = find_xml_ex_(xml_str, "CdtrAgt\\BIC", 1, "") end

    return str

end

local function load_item(o, xml_str, ii, options, profile_info)
    local ttype = ss.def(ii.ttype, "std")
    local doc_writer = profile_info.profile_full.advanced_.xml_doc_writer
    local doc_i = {writer = doc_writer, obj = ii}
    local op = ii.option
    if op == nil then op = {} end
    if ttype == "std" then
        local val = find_xml_ex_(xml_str, ii.pattern, ii.start_pos, ii.def_val)
        if (val == nil or val == "") and op.altern_pattern ~= nil then
            ss.l("check alter pattern:" .. op.altern_pattern)
            val = find_xml_ex_(xml_str, op.altern_pattern, ii.start_pos,
                               ii.def_val)
        end
        if val ~= nil and val ~= "" then
            ss.l(i .. ss.def(ii.name, "<null>") .. ":" ..
                     ss.def(ii.pattern, "<null>") .. "res:" ..
                     seclevel:get("load", ii.pattern, ss.def(val, "<null>")))
        end
        local rule_name = ""
        if op.trim == true then
            val = all_trim(val)
            rule_name = rule_name .. "trim"
        end
        if doc_writer then
            doc_writer:write(ii.pattern, out_name_doc(ii), rule)
        end

        add_val(o, ii, val)
    elseif ttype == "alter_swift_code_pacs" then
        alter_swift_code_pacs(o, ii)
    elseif ttype == "incoming/outgoing" then

        local data = ii.option.data
        ss.l("incoming/outgoing:" .. #data .. ":" .. options.sub_type)
        for i = 1, #data do
            local d = data[i]
            if d.name=="lastname" then 
            if doc_writer ~= nil then
                local doc_o = from_name_doc(d.outgoing)
                local doc_i = from_name_doc(d.incoming)
                local doc_formula= "if (prop.F_PAYMENT_SYSTEM=='INST') then return "..doc_o.." || "..doc_i
                doc_formula=doc_formula.." elseif direct=='outgoing' then return "..doc_o.." else return "..doc_i.." end"
                doc_writer:write("", out_name_doc(d), doc_formula, "")

            end
             local F_PAYMENT_SYSTEM= options.properies.F_PAYMENT_SYSTEM
             if F_PAYMENT_SYSTEM=="INST" then 
                local val_o = get_val(o, d.outgoing)
                local val_i = get_val(o,d.incoming)
                local fo=ss.def(val_o,"")~=""
                local fi=ss.def(val_i,"")~=""
                local val=""
                if fo and fi then val=val_o.."#;#"..val_i
                elseif fo then  val=val_o
                elseif fi then  val=val_i
                end
                add_val(o, d, val)
               return
             end
            end
            
            local from = d.outgoing
            if options.sub_type == "incoming" then from = d.incoming end

            local val = get_val(o, from)
            --        ss.tprint(from)
            --      ss.l("_o_")

            --       ss.l(d.name..":"..ss.def(val,"nil"))
            add_val(o, d, val)
            if doc_writer ~= nil then
                doc_writer:write("", out_name_doc(d), from_name_doc(from), "")
            end
            

        end
    elseif ttype == "ExtractAmountVer1v2" then
        ExtractAmountVer1v2(o, xml_str, doc_writer)
    elseif ttype == "ExtractAmountVer3" then
        ExtractAmountVer3(o, xml_str, doc_writer)
    elseif ttype == "ExtractLastName_incoming" then
        local val = ExtractLastName_incoming(xml_str, doc_i)
        add_val(o, ii, val)
    elseif ttype == "ExtractLastName009" then
        local val = ExtractLastName009(xml_str, doc_i)
        add_val(o, ii, val)
    elseif ttype == "ExtractPstlAdr" then
        local val = ExtractPstlAdr(xml_str, doc_i)
        add_val(o, ii, val)
    elseif ttype == "ExtractPstlAdr_v2" then
        local val = ExtractPstlAdr_v2(xml_str, doc_i)
        add_val(o, ii, val)
    elseif ttype == "ExtractLastName" then
        local val = ExtractLastName(xml_str, doc_i)
        add_val(o, ii, val)
    elseif ttype == "alias" then
        local val = get_val(o, ii)
        add_val(o, ii, val)
        if doc_writer ~= nil then
            doc_writer:write("", out_name_doc(ii), from_name_doc(ii), "")
        end
    elseif ttype == "copy_sub_type1" then
        copy_sub_type1(o, options, doc_writer)
    elseif ttype == "copy_sub_type2" then
        copy_sub_type2(o, options, doc_writer)
    elseif ttype == "copy_sub_type3" then
        copy_sub_type3(o, options, doc_writer)
    else
        ss.l("failed.ttype")
        ss.tprint(ii)
        ss.l("tracestack:")
        ss.l(debug.traceback())
        ss.e("sleep sec 15")
        ss.e("abort 1")
    end

end

local function std_parse_(o, xml_str, ttype, options, profile_info)
    ss.l("std_parse_.start. type=")
    local t = finn_serv.parser_config[ttype]
    if t == nil then ss.l("std_parse_.failed.not found type:" .. ttype) end
    ss.l("std_parse_.start")
    for i = 1, #t.items do
        ss.l("item:"..i)
        local ii = t.items[i]
        ss.tprint(ii)
        ss.l("__________________")
        load_item(o, xml_str, ii, options, profile_info)
    end
    ss.l("std_parse_.end")
end

-- ----------------------------
function finn_serv.ParsePACS009(o, xml_str, prop, sub_type, profile_info,properies)
    -- F:\p\FINNIOVA_PRJs\V5\finnova_examples\Example4.multi\pac009decode\readme.txt

    local options = {}
    options.sub_type  = sub_type
    options.properies = properies

    std_parse_(o, xml_str, "pacs009", options, profile_info)
end

function finn_serv.ParsePACS008(o, xml_str, prop, sub_type, profile_info,properies)
    ss.l("finn_serv.ParsePACS008.sub_type:" .. ss.def(sub_type, "nil"))

    local options = {}
    options.sub_type = sub_type
    options.properies = properies

    std_parse_(o, xml_str, "pacs008", options, profile_info)

end
-- -----------------------------------------------
function finn_serv.ParsePACS003(o, xml_str, prop, sub_type, profile_info,properies)
    ss.l("finn_serv.ParsePACS003.sub_type:" .. ss.def(sub_type, "nil"))

    local options = {}
    options.sub_type = sub_type
    options.properies = properies

    std_parse_(o, xml_str, "pacs003", options, profile_info)

end
-- -----------------------------------------------

function finn_serv.ParsePACS004(o, xml_str, prop, sub_type, profile_info,properies)
    -- 9.1.2019  ExtractAmountVer2(o,xml_str)
    local options = {}

    options.sub_type = sub_type
    options.properies = properies

    std_parse_(o, xml_str, "pacs004", options, profile_info)
end

-- -----------------------------------------------
function finn_serv.ParseKundenstamm(o, xml_string, cache)

    --      local binary = base64.decode(xml_string)
    local binary = xml_string
    mem:truncate()
    mem:set_string(binary)
    local res = mem:read_obj()

    local function g(name, e)
        local v1 = res[name]
        local v2 = cache[name]
        if v1 ~= v2 then
            local msg = "ParseKundenstamm.failed:" .. name .. " cache:" ..
                            ss.def(v2, "<nil>") .. " base64:" ..
                            ss.def(v1, "<nil>")
            ss.l(msg)
            e.emessage = e.emessage .. ";" .. msg
        end
        return v2
    end
    local err = {emessage = ""}
    local cfg = finn_serv.parser_config["kundenstamm"]
    for i = 1, #cfg.items do
        local ii = cfg.items[i]
        o[ii.name] = g(ii.patern, err)
    end
    --[[ move to transactionParserConfig.lua2.3.2020
  o.firstname=g("F_CUSTOMER_NAME",err)
  o.lastname= g("F_CUSTOMER_SURNAME",err)
  o.ADD_NAME1       = g("F_CUSTOMER_OTHER_NAMES",err)
  o.BIRTHDAY        = g("F_BIRTHDAY",err)
  o.BIRTHYEAR       = g("F_BIRTHYEAR",err)
  o.GENDER          = g("F_GENDER",err)
  o.NATIONALITY     = g("F_NATIONALITY",err)
  o.ADDRESS_STREET  = g("F_ADDRESS_STREET",err)
  o.ADDRESS_ZIP     = g("F_ADDRESS_ZIP",err)
  o.ADDRESS_CITY    = g("F_ADDRESS_CITY",err)
  o.ADDRESS_COUNTRY = g("F_ADDRESS_COUNTRY",err)
--]]
    do -- only test
        for k, v in pairs(cache) do g(k, err) end
    end

    if err.emessage ~= "" then
        ss.l("e.details:")
        ss.l("cache:")
        ss.tprint(cache)
        ss.l("bin:" .. base64.encode(xml_string))
        ss.l("bin.decode:")
        ss.tprint(res)
    end
end

function finn_serv.RemoveLn(nc)
    local function r(name, replace_str)
        local v = nc[name]
        if v == nil then return end
        if type(v) ~= "string" then return end
        if v:find("\n") == nil then return end
        local v2 = ss.ReplaceValue(v, "\n", replace_str)
        ss.l(
            "finn_serv.RemoveLn. replace:" .. name .. " old:" .. v .. " new:" ..
                v2)
        nc[name] = v2
    end

    r("swift_code", '')
    r("swift_code_dbtr", '')
    r("swift_code_cdtr", '')
    r("amount", '')
    r("currency", '')
    r("GENDER", '')
    r("NATIONALITY", '')
    r("BIRTHDAY", '')
    r("BIRTHYEAR", '')
end

function finn_serv.ParseXml(xml_str, prop, F_PROCESS_CODE, properies,
                            profile_info)
    local nc = finn_serv.ParseXml_(xml_str, prop, F_PROCESS_CODE, properies,
                                   profile_info)
    finn_serv.RemoveLn(nc) -- Андрей попросил добавить удаление enter-ов из атрибутов 14.05.2019
    return nc
end

function finn_serv.ParseXml_(xml_str, prop, F_PROCESS_CODE, properies,
                             profile_info)
    --  ss.l("finn_serv.ParseXml_")
    --  ss.tprint(profile_info)
    if properies == nil then properies = {} end

    local o = {
        firstname = "",
        lastname = "",
        dob = "",
        countries_filter = "",
        address = "",
        PAYMENT_TYPE = "",
        remittance = ""
    }

    local ltype = prop:lower()
    -- ss.l(prop)
    -- ss.a(10)
    if ltype == "kundenstamm" then
        finn_serv.ParseKundenstamm(o, xml_str, properies)
        return o
    end

    do -- for debug
        if ltype == "mt540" or ltype == "mt542" or ltype == "mt586" or ltype ==
            "mt599" or ltype == "mt940" then
            local sub_type = "incoming" -- ????
            finn_serv.mt_parser:ParseMT(o, xml_str, ltype, sub_type,
                                        profile_info)
            return o
        end
    end

    if F_PROCESS_CODE == "2" then
        -- Incoming Payment
        local sub_type = "incoming"
        if ltype == "pacs008" then
            finn_serv.ParsePACS008(o, xml_str, ltype, sub_type, profile_info,properies) -- ok --checkXml
        elseif ltype == "pacs003" then
            finn_serv.ParsePACS003(o, xml_str, ltype, sub_type, profile_info,properies) -- ok --checkXml
        elseif ltype == "pacs009" then
            finn_serv.ParsePACS009(o, xml_str, ltype, sub_type, profile_info,properies) -- ok --checkXml
        elseif ltype == "pacs004" then
            finn_serv.ParsePACS004(o, xml_str, ltype, sub_type, profile_info,properies) -- ok
        elseif ltype == "mt101" then
            finn_serv.mt_parser:ParseMT(o, xml_str, ltype, sub_type,
                                        profile_info) -- ok  --checkXml
        elseif ltype == "mt103" then
            finn_serv.mt_parser:ParseMT(o, xml_str, ltype, sub_type,
                                        profile_info) -- ok --checkXml
        elseif ltype == "mt200" then
            finn_serv.mt_parser:ParseMT(o, xml_str, ltype, sub_type,
                                        profile_info) -- ok --checkXml
        elseif ltype == "mt202" then
            finn_serv.mt_parser:ParseMT(o, xml_str, ltype, sub_type,
                                        profile_info) -- ok --checkXml
        elseif ltype == "mt202cov" then
            finn_serv.mt_parser:ParseMT(o, xml_str, ltype, sub_type,
                                        profile_info) -- ok --checkXml

        else
            o.error_message = "failed." .. sub_type ..
                                  ". unknown document type:" ..
                                  ss.def(prop, "<nil>")
        end

    else
        -- Outgoing Payment
        local sub_type = "outgoing"
        if ltype == "pacs008" then
            finn_serv.ParsePACS008(o, xml_str, ltype, sub_type, profile_info,properies) -- ok --checkXml
        elseif ltype == "pacs003" then
            finn_serv.ParsePACS003(o, xml_str, ltype, sub_type, profile_info,properies) -- ok --checkXml
        elseif ltype == "pacs009" then
            finn_serv.ParsePACS009(o, xml_str, ltype, sub_type, profile_info,properies) -- ok --checkXml
        elseif ltype == "pacs004" then
            finn_serv.ParsePACS004(o, xml_str, ltype, sub_type, profile_info,properies) -- ok --checkXml
        elseif ltype == "mt110" then
            finn_serv.mt_parser:ParseMT(o, xml_str, ltype, sub_type,
                                        profile_info) -- ok--checkXml
        elseif ltype == "mt200" then
            finn_serv.mt_parser:ParseMT(o, xml_str, ltype, sub_type,
                                        profile_info) -- no spec
        else
            o.error_message = "failed." .. sub_type ..
                                  ". unknown document type:" ..
                                  ss.def(prop, "<nil>")
        end
    end

    if o.error_message ~= nil then ss.l(o.error_message) end

    return o
end





