data-met.lua /size: 5518 b    last modification: 2020-07-01 14:35
1if not modules then modules = { } end modules ['data-met'] = {
2    version   = 1.100,
3    comment   = "companion to luat-lib.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9local type = type
10local find = string.find
11local addurlscheme, urlhashed = url.addscheme, url.hashed
12local collapsepath, joinfile = file.collapsepath, file.join
13
14local report_methods = logs.reporter("resolvers","methods")
15
16local trace_locating = false
17local trace_methods  = false
18
19trackers.register("resolvers.locating", function(v) trace_methods = v end)
20trackers.register("resolvers.methods",  function(v) trace_methods = v end)
21
22local allocate   = utilities.storage.allocate
23local resolvers  = resolvers
24
25local registered = { }
26
27local function splitmethod(filename) -- todo: filetype in specification
28    if not filename then
29        return {
30            scheme   = "unknown",
31            original = filename,
32        }
33    end
34    if type(filename) == "table" then
35        return filename -- already split
36    end
37    filename = collapsepath(filename,".") -- hm, we should keep ./ in some cases
38    if not find(filename,"://",1,true) then
39        return {
40            scheme   = "file",
41            path     = filename,
42            original = filename,
43            filename = filename,
44        }
45    end
46    local specification = urlhashed(filename)
47    if not specification.scheme or specification.scheme == "" then
48        return {
49            scheme   = "file",
50            path     = filename,
51            original = filename,
52            filename = filename,
53        }
54    else
55        return specification
56    end
57end
58
59-- local function splitmethod(filename) -- todo: filetype in specification
60--     if not filename then
61--         return { scheme = "unknown", original = filename }
62--     end
63--     if type(filename) == "table" then
64--         return filename -- already split
65--     end
66--     return urlhashed(filename)
67-- end
68
69resolvers.splitmethod = splitmethod -- bad name but ok
70
71-- the second argument is always analyzed (saves time later on) and the original
72-- gets passed as original but also as argument
73
74local function methodhandler(what,first,...) -- filename can be nil or false
75    local method = registered[what]
76    if method then
77        local how       = method.how
78        local namespace = method.namespace
79        if how == "uri" or how == "url" then
80            local specification = splitmethod(first)
81            local scheme        = specification.scheme
82            local resolver      = namespace and namespace[scheme]
83            if resolver then
84                if trace_methods then
85                    report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,scheme,first)
86                end
87                return resolver(specification,...)
88            else
89                resolver = namespace.default or namespace.file
90                if resolver then
91                    if trace_methods then
92                        report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"default",first)
93                    end
94                    return resolver(specification,...)
95                elseif trace_methods then
96                    report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"unset")
97                end
98            end
99        elseif how == "tag" then
100            local resolver = namespace and namespace[first]
101            if resolver then
102                if trace_methods then
103                    report_methods("resolving, method %a, how %a, tag %a",what,how,first)
104                end
105                return resolver(...)
106            else
107                resolver = namespace.default or namespace.file
108                if resolver then
109                    if trace_methods then
110                        report_methods("resolving, method %a, how %a, tag %a",what,how,"default")
111                    end
112                    return resolver(...)
113                elseif trace_methods then
114                    report_methods("resolving, method %a, how %a, tag %a",what,how,"unset")
115                end
116            end
117        end
118    else
119        report_methods("resolving, invalid method %a")
120    end
121end
122
123resolvers.methodhandler = methodhandler
124
125function resolvers.registermethod(name,namespace,how)
126    registered[name] = {
127        how       = how or "tag",
128        namespace = namespace
129    }
130    namespace["byscheme"] = function(scheme,filename,...)
131        if scheme == "file" then
132            return methodhandler(name,filename,...)
133        else
134            return methodhandler(name,addurlscheme(filename,scheme),...)
135        end
136    end
137end
138
139local concatinators = allocate { notfound = joinfile        }  -- concatinate paths
140local locators      = allocate { notfound = function() end  }  -- locate databases
141local hashers       = allocate { notfound = function() end  }  -- load databases
142local generators    = allocate { notfound = function() end  }  -- generate databases
143
144resolvers.concatinators = concatinators
145resolvers.locators      = locators
146resolvers.hashers       = hashers
147resolvers.generators    = generators
148
149local registermethod = resolvers.registermethod
150
151registermethod("concatinators",concatinators,"tag")
152registermethod("locators",     locators,     "uri")
153registermethod("hashers",      hashers,      "uri")
154registermethod("generators",   generators,   "uri")
155