-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
156 lines (129 loc) · 3.95 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
var namespaces = require('./namespaces');
var util = require('util');
/*
- URIs that we know about are minimized into URNs
http://vocab.getty.com/thing/1234?v=1 ~> 'urn:hg:tgn:v=1,thing=1234'
- URIs that we dont know are left as-is.
- Histograph identifiers (e.g. `dataset1/123`) are mapped to internal-only URNs
dataset1/123 ~> urn:hgid:dataset1/123
- Dataset-internal identifiers (without dataset scope, e.g. `123`) are mapped to scoped internal-only URNs
123 ~> urn:hgid:dataset1/123 - To do this, a dataset identifier is needed
*/
// match if this string looks like a URI
var URI_PATTERN = /^[a-zA-Z][a-zA-Z0-9+-\.]*:.*$/;
// match `a/b` HG identifiers
var HGID_PATTERN = /^([a-zA-Z0-9\.+-_]+)\/([a-zA-Z0-9\.+-_]+)$/;
// match normal identifiers
var ID_PATTERN = /^([a-zA-Z0-9\.+-_]+)$/;
exports.normalize = function(s, nid) {
// normalize URIs
if (URI_PATTERN.test(s)) {
try {
return exports.URLtoURN(s);
} catch (e) {
return s;
}
}
// it is (or, should be) a HGID
return exports.normalizeHGID(s, nid);
};
// normalize dataset names; `KOEKwous.floes.tozz` ~> `koekwous`
exports.normalizeSourceID = function(sourceid) {
if (sourceid) {
return sourceid.split('.')[0].toLowerCase();
} else {
return undefined;
}
};
exports.parseHGID = function(s, sourceId) {
// the case `a/x`
var ax = HGID_PATTERN.exec(s);
if (ax) {
return [ax[1], ax[2]];
}
// the case `x`
var x = ID_PATTERN.exec(s);
if (x) {
return [sourceId, x[1]];
} else {
return undefined;
}
};
// normalize HG identifiers; `fOE.bar/234` ~> `urn:hgid:foo/123`
exports.normalizeHGID = function(hgid, sourceId) {
// split `a/b` into a and b
var hgidParts = exports.parseHGID(hgid, sourceId);
// string doesn't parse as HGID (only alphanum, etc)
if (!hgidParts) {
return hgidParts;
}
// turn 'foo.bar.baz' into foo
hgidParts[0] = exports.normalizeSourceID(hgidParts[0]);
if (hgidParts[0]) {
// namespace 'foo' is known in `urn:hg` namespace
if (namespaces[hgidParts[0]])
return util.format('urn:hg:%s:%s', hgidParts[0], hgidParts[1]);
// HGID namespace
return util.format('urn:hgid:%s/%s', hgidParts[0], hgidParts[1]);
} else {
// HGID of the form `x` but no sourceId was given
return undefined;
}
};
exports.URLtoURN = function(url, nid) {
if (nid !== undefined && namespaces[nid]) {
var namespace = namespaces[nid];
return namespace.URLtoURN(url);
} else {
for (var n in namespaces) {
var urlMatch = function(url, baseUrl) {
return url.toLowerCase().indexOf(baseUrl) === 0;
};
var urlMatched = namespaces[n].urlMatch ? namespaces[n].urlMatch(url) : urlMatch(url, namespaces[n].baseUrl);
if (urlMatched) {
return namespaces[n].URLtoURN(url);
}
}
throw new Error('No namespace found for URL: ' + url);
}
};
exports.URNtoURL = function(urn) {
var parts = urn.split(':');
if (parts[0] === 'urn') {
var hg = parts[1];
var nid = parts[2];
var nss = parts.splice(3).join(':');
if (hg === 'hg' && nid !== undefined && namespaces[nid]) {
var namespace = namespaces[nid];
return namespace.URNtoURL(nid, nss);
} else {
throw new Error('No namespace found for URN: ' + urn);
}
} else {
throw new Error('Invalid URN: ' + urn);
}
};
exports.addNamespace = function(nid, namespace) {
if (!nid) {
throw new Error('Invalid namespace: ' + nid);
}
if (!namespaces[nid]) {
var namespaceValid = namespace.baseUrl &&
namespace.URLtoURN &&
namespace.URNtoURL;
if (namespaceValid) {
namespaces[nid] = namespace;
} else {
throw new Error('Namespace namespace not valid, should include baseUrl, URLtoURN and URNtoURL');
}
} else {
throw new Error('Namespace already exists: ' + nid);
}
};
exports.removeNamespace = function(nid) {
if (namespaces[nid]) {
delete namespaces[nid];
} else {
throw new Error('Namespace does not exist: ' + nid);
}
};