pywebexec 2.1.15__py3-none-any.whl → 2.1.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pywebexec/pywebexec.py +1 -1
- pywebexec/static/css/form.css +1 -0
- pywebexec/static/js/executables.js +2 -0
- pywebexec/static/js/script.js +1 -1
- pywebexec/static/jsonform/deps/jsv.js +3700 -0
- pywebexec/templates/index.html +1 -0
- pywebexec/version.py +2 -2
- {pywebexec-2.1.15.dist-info → pywebexec-2.1.16.dist-info}/METADATA +1 -1
- {pywebexec-2.1.15.dist-info → pywebexec-2.1.16.dist-info}/RECORD +13 -12
- {pywebexec-2.1.15.dist-info → pywebexec-2.1.16.dist-info}/LICENSE +0 -0
- {pywebexec-2.1.15.dist-info → pywebexec-2.1.16.dist-info}/WHEEL +0 -0
- {pywebexec-2.1.15.dist-info → pywebexec-2.1.16.dist-info}/entry_points.txt +0 -0
- {pywebexec-2.1.15.dist-info → pywebexec-2.1.16.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,3700 @@
|
|
1
|
+
// This is a build of https://github.com/garycourt/JSV at 0aa11852537069b0830569ef1eab11a36b65b3ab with jsv.js, schema03 and URI.js appended.
|
2
|
+
// The build contains a few lines of custom code to handle format validation.
|
3
|
+
// Custom code is wrapped in comments that start with "JOSHFIRE"
|
4
|
+
(function(global, require) {
|
5
|
+
var exports = {};
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
/**
|
10
|
+
* URI.js
|
11
|
+
*
|
12
|
+
* @fileoverview An RFC 3986 compliant, scheme extendable URI parsing/validating/resolving library for JavaScript.
|
13
|
+
* @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
|
14
|
+
* @version 1.2
|
15
|
+
* @see http://github.com/garycourt/uri-js
|
16
|
+
* @license URI.js v1.2 (c) 2010 Gary Court. License: http://github.com/garycourt/uri-js
|
17
|
+
*/
|
18
|
+
|
19
|
+
/**
|
20
|
+
* Copyright 2010 Gary Court. All rights reserved.
|
21
|
+
*
|
22
|
+
* Redistribution and use in source and binary forms, with or without modification, are
|
23
|
+
* permitted provided that the following conditions are met:
|
24
|
+
*
|
25
|
+
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
26
|
+
* conditions and the following disclaimer.
|
27
|
+
*
|
28
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
29
|
+
* of conditions and the following disclaimer in the documentation and/or other materials
|
30
|
+
* provided with the distribution.
|
31
|
+
*
|
32
|
+
* THIS SOFTWARE IS PROVIDED BY GARY COURT ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
33
|
+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
34
|
+
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR
|
35
|
+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
36
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
37
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
38
|
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
39
|
+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
40
|
+
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
41
|
+
*
|
42
|
+
* The views and conclusions contained in the software and documentation are those of the
|
43
|
+
* authors and should not be interpreted as representing official policies, either expressed
|
44
|
+
* or implied, of Gary Court.
|
45
|
+
*/
|
46
|
+
|
47
|
+
/*jslint white: true, sub: true, onevar: true, undef: true, eqeqeq: true, newcap: true, immed: true, indent: 4 */
|
48
|
+
/*global exports:true, require:true */
|
49
|
+
|
50
|
+
if (typeof exports === "undefined") {
|
51
|
+
exports = {};
|
52
|
+
}
|
53
|
+
if (typeof require !== "function") {
|
54
|
+
require = function (id) {
|
55
|
+
return exports;
|
56
|
+
};
|
57
|
+
}
|
58
|
+
(function () {
|
59
|
+
var
|
60
|
+
/**
|
61
|
+
* @param {...string} sets
|
62
|
+
* @return {string}
|
63
|
+
*/
|
64
|
+
mergeSet = function (sets) {
|
65
|
+
var set = arguments[0],
|
66
|
+
x = 1,
|
67
|
+
nextSet = arguments[x];
|
68
|
+
|
69
|
+
while (nextSet) {
|
70
|
+
set = set.slice(0, -1) + nextSet.slice(1);
|
71
|
+
nextSet = arguments[++x];
|
72
|
+
}
|
73
|
+
|
74
|
+
return set;
|
75
|
+
},
|
76
|
+
|
77
|
+
/**
|
78
|
+
* @param {string} str
|
79
|
+
* @return {string}
|
80
|
+
*/
|
81
|
+
subexp = function (str) {
|
82
|
+
return "(?:" + str + ")";
|
83
|
+
},
|
84
|
+
|
85
|
+
ALPHA$$ = "[A-Za-z]",
|
86
|
+
CR$ = "[\\x0D]",
|
87
|
+
DIGIT$$ = "[0-9]",
|
88
|
+
DQUOTE$$ = "[\\x22]",
|
89
|
+
HEXDIG$$ = mergeSet(DIGIT$$, "[A-Fa-f]"), //case-insensitive
|
90
|
+
LF$$ = "[\\x0A]",
|
91
|
+
SP$$ = "[\\x20]",
|
92
|
+
PCT_ENCODED$ = subexp("%" + HEXDIG$$ + HEXDIG$$),
|
93
|
+
GEN_DELIMS$$ = "[\\:\\/\\?\\#\\[\\]\\@]",
|
94
|
+
SUB_DELIMS$$ = "[\\!\\$\\&\\'\\(\\)\\*\\+\\,\\;\\=]",
|
95
|
+
RESERVED$$ = mergeSet(GEN_DELIMS$$, SUB_DELIMS$$),
|
96
|
+
UNRESERVED$$ = mergeSet(ALPHA$$, DIGIT$$, "[\\-\\.\\_\\~]"),
|
97
|
+
SCHEME$ = subexp(ALPHA$$ + mergeSet(ALPHA$$, DIGIT$$, "[\\+\\-\\.]") + "*"),
|
98
|
+
USERINFO$ = subexp(subexp(PCT_ENCODED$ + "|" + mergeSet(UNRESERVED$$, SUB_DELIMS$$, "[\\:]")) + "*"),
|
99
|
+
DEC_OCTET$ = subexp(subexp("25[0-5]") + "|" + subexp("2[0-4]" + DIGIT$$) + "|" + subexp("1" + DIGIT$$ + DIGIT$$) + "|" + subexp("[1-9]" + DIGIT$$) + "|" + DIGIT$$),
|
100
|
+
IPV4ADDRESS$ = subexp(DEC_OCTET$ + "\\." + DEC_OCTET$ + "\\." + DEC_OCTET$ + "\\." + DEC_OCTET$),
|
101
|
+
H16$ = subexp(HEXDIG$$ + "{1,4}"),
|
102
|
+
LS32$ = subexp(subexp(H16$ + "\\:" + H16$) + "|" + IPV4ADDRESS$),
|
103
|
+
IPV6ADDRESS$ = subexp(mergeSet(UNRESERVED$$, SUB_DELIMS$$, "[\\:]") + "+"), //FIXME
|
104
|
+
IPVFUTURE$ = subexp("v" + HEXDIG$$ + "+\\." + mergeSet(UNRESERVED$$, SUB_DELIMS$$, "[\\:]") + "+"),
|
105
|
+
IP_LITERAL$ = subexp("\\[" + subexp(IPV6ADDRESS$ + "|" + IPVFUTURE$) + "\\]"),
|
106
|
+
REG_NAME$ = subexp(subexp(PCT_ENCODED$ + "|" + mergeSet(UNRESERVED$$, SUB_DELIMS$$)) + "*"),
|
107
|
+
HOST$ = subexp(IP_LITERAL$ + "|" + IPV4ADDRESS$ + "|" + REG_NAME$),
|
108
|
+
PORT$ = subexp(DIGIT$$ + "*"),
|
109
|
+
AUTHORITY$ = subexp(subexp(USERINFO$ + "@") + "?" + HOST$ + subexp("\\:" + PORT$) + "?"),
|
110
|
+
PCHAR$ = subexp(PCT_ENCODED$ + "|" + mergeSet(UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@]")),
|
111
|
+
SEGMENT$ = subexp(PCHAR$ + "*"),
|
112
|
+
SEGMENT_NZ$ = subexp(PCHAR$ + "+"),
|
113
|
+
SEGMENT_NZ_NC$ = subexp(subexp(PCT_ENCODED$ + "|" + mergeSet(UNRESERVED$$, SUB_DELIMS$$, "[\\@]")) + "+"),
|
114
|
+
PATH_ABEMPTY$ = subexp(subexp("\\/" + SEGMENT$) + "*"),
|
115
|
+
PATH_ABSOLUTE$ = subexp("\\/" + subexp(SEGMENT_NZ$ + PATH_ABEMPTY$) + "?"), //simplified
|
116
|
+
PATH_NOSCHEME$ = subexp(SEGMENT_NZ_NC$ + PATH_ABEMPTY$), //simplified
|
117
|
+
PATH_ROOTLESS$ = subexp(SEGMENT_NZ$ + PATH_ABEMPTY$), //simplified
|
118
|
+
PATH_EMPTY$ = subexp(""), //simplified
|
119
|
+
PATH$ = subexp(PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$),
|
120
|
+
QUERY$ = subexp(subexp(PCHAR$ + "|[\\/\\?]") + "*"),
|
121
|
+
FRAGMENT$ = subexp(subexp(PCHAR$ + "|[\\/\\?]") + "*"),
|
122
|
+
HIER_PART$ = subexp(subexp("\\/\\/" + AUTHORITY$ + PATH_ABEMPTY$) + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$),
|
123
|
+
URI$ = subexp(SCHEME$ + "\\:" + HIER_PART$ + subexp("\\?" + QUERY$) + "?" + subexp("\\#" + FRAGMENT$) + "?"),
|
124
|
+
RELATIVE_PART$ = subexp(subexp("\\/\\/" + AUTHORITY$ + PATH_ABEMPTY$) + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_EMPTY$),
|
125
|
+
RELATIVE_REF$ = subexp(RELATIVE_PART$ + subexp("\\?" + QUERY$) + "?" + subexp("\\#" + FRAGMENT$) + "?"),
|
126
|
+
URI_REFERENCE$ = subexp(URI$ + "|" + RELATIVE_REF$),
|
127
|
+
ABSOLUTE_URI$ = subexp(SCHEME$ + "\\:" + HIER_PART$ + subexp("\\?" + QUERY$) + "?"),
|
128
|
+
|
129
|
+
URI_REF = new RegExp("^" + subexp("(" + URI$ + ")|(" + RELATIVE_REF$ + ")") + "$"),
|
130
|
+
GENERIC_REF = new RegExp("^(" + SCHEME$ + ")\\:" + subexp(subexp("\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$ + ")") + subexp("\\?(" + QUERY$ + ")") + "?" + subexp("\\#(" + FRAGMENT$ + ")") + "?$"),
|
131
|
+
RELATIVE_REF = new RegExp("^(){0}" + subexp(subexp("\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_NOSCHEME$ + "|" + PATH_EMPTY$ + ")") + subexp("\\?(" + QUERY$ + ")") + "?" + subexp("\\#(" + FRAGMENT$ + ")") + "?$"),
|
132
|
+
ABSOLUTE_REF = new RegExp("^(" + SCHEME$ + ")\\:" + subexp(subexp("\\/\\/(" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?)") + "?(" + PATH_ABEMPTY$ + "|" + PATH_ABSOLUTE$ + "|" + PATH_ROOTLESS$ + "|" + PATH_EMPTY$ + ")") + subexp("\\?(" + QUERY$ + ")") + "?$"),
|
133
|
+
SAMEDOC_REF = new RegExp("^" + subexp("\\#(" + FRAGMENT$ + ")") + "?$"),
|
134
|
+
AUTHORITY = new RegExp("^" + subexp("(" + USERINFO$ + ")@") + "?(" + HOST$ + ")" + subexp("\\:(" + PORT$ + ")") + "?$"),
|
135
|
+
|
136
|
+
NOT_SCHEME = new RegExp(mergeSet("[^]", ALPHA$$, DIGIT$$, "[\\+\\-\\.]"), "g"),
|
137
|
+
NOT_USERINFO = new RegExp(mergeSet("[^\\%\\:]", UNRESERVED$$, SUB_DELIMS$$), "g"),
|
138
|
+
NOT_HOST = new RegExp(mergeSet("[^\\%]", UNRESERVED$$, SUB_DELIMS$$), "g"),
|
139
|
+
NOT_PATH = new RegExp(mergeSet("[^\\%\\/\\:\\@]", UNRESERVED$$, SUB_DELIMS$$), "g"),
|
140
|
+
NOT_PATH_NOSCHEME = new RegExp(mergeSet("[^\\%\\/\\@]", UNRESERVED$$, SUB_DELIMS$$), "g"),
|
141
|
+
NOT_QUERY = new RegExp(mergeSet("[^\\%]", UNRESERVED$$, SUB_DELIMS$$, "[\\:\\@\\/\\?]"), "g"),
|
142
|
+
NOT_FRAGMENT = NOT_QUERY,
|
143
|
+
ESCAPE = new RegExp(mergeSet("[^]", UNRESERVED$$, SUB_DELIMS$$), "g"),
|
144
|
+
UNRESERVED = new RegExp(UNRESERVED$$, "g"),
|
145
|
+
OTHER_CHARS = new RegExp(mergeSet("[^\\%]", UNRESERVED$$, RESERVED$$), "g"),
|
146
|
+
PCT_ENCODEDS = new RegExp(PCT_ENCODED$ + "+", "g"),
|
147
|
+
URI_PARSE = /^(?:([^:\/?#]+):)?(?:\/\/((?:([^\/?#@]*)@)?([^\/?#:]*)(?:\:(\d*))?))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/i,
|
148
|
+
RDS1 = /^\.\.?\//,
|
149
|
+
RDS2 = /^\/\.(\/|$)/,
|
150
|
+
RDS3 = /^\/\.\.(\/|$)/,
|
151
|
+
RDS4 = /^\.\.?$/,
|
152
|
+
RDS5 = /^\/?.*?(?=\/|$)/,
|
153
|
+
NO_MATCH_IS_UNDEFINED = ("").match(/(){0}/)[1] === undefined,
|
154
|
+
|
155
|
+
/**
|
156
|
+
* @param {string} chr
|
157
|
+
* @return {string}
|
158
|
+
*/
|
159
|
+
pctEncChar = function (chr) {
|
160
|
+
var c = chr.charCodeAt(0);
|
161
|
+
|
162
|
+
if (c < 128) {
|
163
|
+
return "%" + c.toString(16).toUpperCase();
|
164
|
+
}
|
165
|
+
else if ((c > 127) && (c < 2048)) {
|
166
|
+
return "%" + ((c >> 6) | 192).toString(16).toUpperCase() + "%" + ((c & 63) | 128).toString(16).toUpperCase();
|
167
|
+
}
|
168
|
+
else {
|
169
|
+
return "%" + ((c >> 12) | 224).toString(16).toUpperCase() + "%" + (((c >> 6) & 63) | 128).toString(16).toUpperCase() + "%" + ((c & 63) | 128).toString(16).toUpperCase();
|
170
|
+
}
|
171
|
+
},
|
172
|
+
|
173
|
+
/**
|
174
|
+
* @param {string} str
|
175
|
+
* @return {string}
|
176
|
+
*/
|
177
|
+
pctDecUnreserved = function (str) {
|
178
|
+
var newStr = "",
|
179
|
+
i = 0,
|
180
|
+
c, s;
|
181
|
+
|
182
|
+
while (i < str.length) {
|
183
|
+
c = parseInt(str.substr(i + 1, 2), 16);
|
184
|
+
|
185
|
+
if (c < 128) {
|
186
|
+
s = String.fromCharCode(c);
|
187
|
+
if (s.match(UNRESERVED)) {
|
188
|
+
newStr += s;
|
189
|
+
} else {
|
190
|
+
newStr += str.substr(i, 3);
|
191
|
+
}
|
192
|
+
i += 3;
|
193
|
+
}
|
194
|
+
else if ((c > 191) && (c < 224)) {
|
195
|
+
newStr += str.substr(i, 6);
|
196
|
+
i += 6;
|
197
|
+
}
|
198
|
+
else {
|
199
|
+
newStr += str.substr(i, 9);
|
200
|
+
i += 9;
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
return newStr;
|
205
|
+
},
|
206
|
+
|
207
|
+
/**
|
208
|
+
* @param {string} str
|
209
|
+
* @return {string}
|
210
|
+
*/
|
211
|
+
pctDecChars = function (str) {
|
212
|
+
var newStr = "",
|
213
|
+
i = 0,
|
214
|
+
c, c2, c3;
|
215
|
+
|
216
|
+
while (i < str.length) {
|
217
|
+
c = parseInt(str.substr(i + 1, 2), 16);
|
218
|
+
|
219
|
+
if (c < 128) {
|
220
|
+
newStr += String.fromCharCode(c);
|
221
|
+
i += 3;
|
222
|
+
}
|
223
|
+
else if ((c > 191) && (c < 224)) {
|
224
|
+
c2 = parseInt(str.substr(i + 4, 2), 16);
|
225
|
+
newStr += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
226
|
+
i += 6;
|
227
|
+
}
|
228
|
+
else {
|
229
|
+
c2 = parseInt(str.substr(i + 4, 2), 16);
|
230
|
+
c3 = parseInt(str.substr(i + 7, 2), 16);
|
231
|
+
newStr += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
232
|
+
i += 9;
|
233
|
+
}
|
234
|
+
}
|
235
|
+
|
236
|
+
return newStr;
|
237
|
+
},
|
238
|
+
|
239
|
+
/**
|
240
|
+
* @return {string}
|
241
|
+
*/
|
242
|
+
typeOf = function (o) {
|
243
|
+
return o === undefined ? "undefined" : (o === null ? "null" : Object.prototype.toString.call(o).split(" ").pop().split("]").shift().toLowerCase());
|
244
|
+
},
|
245
|
+
|
246
|
+
/**
|
247
|
+
* @constructor
|
248
|
+
* @implements URIComponents
|
249
|
+
*/
|
250
|
+
Components = function () {
|
251
|
+
this.errors = [];
|
252
|
+
},
|
253
|
+
|
254
|
+
/** @namespace */
|
255
|
+
URI = {};
|
256
|
+
|
257
|
+
/**
|
258
|
+
* Components
|
259
|
+
*/
|
260
|
+
|
261
|
+
Components.prototype = {
|
262
|
+
/**
|
263
|
+
* @type String
|
264
|
+
*/
|
265
|
+
|
266
|
+
scheme : undefined,
|
267
|
+
|
268
|
+
/**
|
269
|
+
* @type String
|
270
|
+
*/
|
271
|
+
|
272
|
+
authority : undefined,
|
273
|
+
|
274
|
+
/**
|
275
|
+
* @type String
|
276
|
+
*/
|
277
|
+
|
278
|
+
userinfo : undefined,
|
279
|
+
|
280
|
+
/**
|
281
|
+
* @type String
|
282
|
+
*/
|
283
|
+
|
284
|
+
host : undefined,
|
285
|
+
|
286
|
+
/**
|
287
|
+
* @type number
|
288
|
+
*/
|
289
|
+
|
290
|
+
port : undefined,
|
291
|
+
|
292
|
+
/**
|
293
|
+
* @type string
|
294
|
+
*/
|
295
|
+
|
296
|
+
path : undefined,
|
297
|
+
|
298
|
+
/**
|
299
|
+
* @type string
|
300
|
+
*/
|
301
|
+
|
302
|
+
query : undefined,
|
303
|
+
|
304
|
+
/**
|
305
|
+
* @type string
|
306
|
+
*/
|
307
|
+
|
308
|
+
fragment : undefined,
|
309
|
+
|
310
|
+
/**
|
311
|
+
* @type string
|
312
|
+
* @values "uri", "absolute", "relative", "same-document"
|
313
|
+
*/
|
314
|
+
|
315
|
+
reference : undefined,
|
316
|
+
|
317
|
+
/**
|
318
|
+
* @type Array
|
319
|
+
*/
|
320
|
+
|
321
|
+
errors : undefined
|
322
|
+
};
|
323
|
+
|
324
|
+
/**
|
325
|
+
* URI
|
326
|
+
*/
|
327
|
+
|
328
|
+
/**
|
329
|
+
* @namespace
|
330
|
+
*/
|
331
|
+
|
332
|
+
URI.SCHEMES = {};
|
333
|
+
|
334
|
+
/**
|
335
|
+
* @param {string} uriString
|
336
|
+
* @param {Options} [options]
|
337
|
+
* @returns {URIComponents}
|
338
|
+
*/
|
339
|
+
|
340
|
+
URI.parse = function (uriString, options) {
|
341
|
+
var matches,
|
342
|
+
components = new Components(),
|
343
|
+
schemeHandler;
|
344
|
+
|
345
|
+
uriString = uriString ? uriString.toString() : "";
|
346
|
+
options = options || {};
|
347
|
+
|
348
|
+
if (options.reference === "suffix") {
|
349
|
+
uriString = (options.scheme ? options.scheme + ":" : "") + "//" + uriString;
|
350
|
+
}
|
351
|
+
|
352
|
+
matches = uriString.match(URI_REF);
|
353
|
+
|
354
|
+
if (matches) {
|
355
|
+
if (matches[1]) {
|
356
|
+
//generic URI
|
357
|
+
matches = uriString.match(GENERIC_REF);
|
358
|
+
} else {
|
359
|
+
//relative URI
|
360
|
+
matches = uriString.match(RELATIVE_REF);
|
361
|
+
}
|
362
|
+
}
|
363
|
+
|
364
|
+
if (!matches) {
|
365
|
+
if (!options.tolerant) {
|
366
|
+
components.errors.push("URI is not strictly valid.");
|
367
|
+
}
|
368
|
+
matches = uriString.match(URI_PARSE);
|
369
|
+
}
|
370
|
+
|
371
|
+
if (matches) {
|
372
|
+
if (NO_MATCH_IS_UNDEFINED) {
|
373
|
+
//store each component
|
374
|
+
components.scheme = matches[1];
|
375
|
+
components.authority = matches[2];
|
376
|
+
components.userinfo = matches[3];
|
377
|
+
components.host = matches[4];
|
378
|
+
components.port = parseInt(matches[5], 10);
|
379
|
+
components.path = matches[6] || "";
|
380
|
+
components.query = matches[7];
|
381
|
+
components.fragment = matches[8];
|
382
|
+
|
383
|
+
//fix port number
|
384
|
+
if (isNaN(components.port)) {
|
385
|
+
components.port = matches[5];
|
386
|
+
}
|
387
|
+
} else { //IE FIX for improper RegExp matching
|
388
|
+
//store each component
|
389
|
+
components.scheme = matches[1] || undefined;
|
390
|
+
components.authority = (uriString.indexOf("//") !== -1 ? matches[2] : undefined);
|
391
|
+
components.userinfo = (uriString.indexOf("@") !== -1 ? matches[3] : undefined);
|
392
|
+
components.host = (uriString.indexOf("//") !== -1 ? matches[4] : undefined);
|
393
|
+
components.port = parseInt(matches[5], 10);
|
394
|
+
components.path = matches[6] || "";
|
395
|
+
components.query = (uriString.indexOf("?") !== -1 ? matches[7] : undefined);
|
396
|
+
components.fragment = (uriString.indexOf("#") !== -1 ? matches[8] : undefined);
|
397
|
+
|
398
|
+
//fix port number
|
399
|
+
if (isNaN(components.port)) {
|
400
|
+
components.port = (uriString.match(/\/\/.*\:(?:\/|\?|\#|$)/) ? matches[4] : undefined);
|
401
|
+
}
|
402
|
+
}
|
403
|
+
|
404
|
+
//determine reference type
|
405
|
+
if (!components.scheme && !components.authority && !components.path && !components.query) {
|
406
|
+
components.reference = "same-document";
|
407
|
+
} else if (!components.scheme) {
|
408
|
+
components.reference = "relative";
|
409
|
+
} else if (!components.fragment) {
|
410
|
+
components.reference = "absolute";
|
411
|
+
} else {
|
412
|
+
components.reference = "uri";
|
413
|
+
}
|
414
|
+
|
415
|
+
//check for reference errors
|
416
|
+
if (options.reference && options.reference !== "suffix" && options.reference !== components.reference) {
|
417
|
+
components.errors.push("URI is not a " + options.reference + " reference.");
|
418
|
+
}
|
419
|
+
|
420
|
+
//check if a handler for the scheme exists
|
421
|
+
schemeHandler = URI.SCHEMES[components.scheme || options.scheme];
|
422
|
+
if (schemeHandler && schemeHandler.parse) {
|
423
|
+
//perform extra parsing
|
424
|
+
schemeHandler.parse(components, options);
|
425
|
+
}
|
426
|
+
} else {
|
427
|
+
components.errors.push("URI can not be parsed.");
|
428
|
+
}
|
429
|
+
|
430
|
+
return components;
|
431
|
+
};
|
432
|
+
|
433
|
+
/**
|
434
|
+
* @private
|
435
|
+
* @param {URIComponents} components
|
436
|
+
* @returns {string|undefined}
|
437
|
+
*/
|
438
|
+
|
439
|
+
URI._recomposeAuthority = function (components) {
|
440
|
+
var uriTokens = [];
|
441
|
+
|
442
|
+
if (components.userinfo !== undefined || components.host !== undefined || typeof components.port === "number") {
|
443
|
+
if (components.userinfo !== undefined) {
|
444
|
+
uriTokens.push(components.userinfo.toString().replace(NOT_USERINFO, pctEncChar));
|
445
|
+
uriTokens.push("@");
|
446
|
+
}
|
447
|
+
if (components.host !== undefined) {
|
448
|
+
uriTokens.push(components.host.toString().toLowerCase().replace(NOT_HOST, pctEncChar));
|
449
|
+
}
|
450
|
+
if (typeof components.port === "number") {
|
451
|
+
uriTokens.push(":");
|
452
|
+
uriTokens.push(components.port.toString(10));
|
453
|
+
}
|
454
|
+
}
|
455
|
+
|
456
|
+
return uriTokens.length ? uriTokens.join("") : undefined;
|
457
|
+
};
|
458
|
+
|
459
|
+
/**
|
460
|
+
* @param {string} input
|
461
|
+
* @returns {string}
|
462
|
+
*/
|
463
|
+
|
464
|
+
URI.removeDotSegments = function (input) {
|
465
|
+
var output = [], s;
|
466
|
+
|
467
|
+
while (input.length) {
|
468
|
+
if (input.match(RDS1)) {
|
469
|
+
input = input.replace(RDS1, "");
|
470
|
+
} else if (input.match(RDS2)) {
|
471
|
+
input = input.replace(RDS2, "/");
|
472
|
+
} else if (input.match(RDS3)) {
|
473
|
+
input = input.replace(RDS3, "/");
|
474
|
+
output.pop();
|
475
|
+
} else if (input === "." || input === "..") {
|
476
|
+
input = "";
|
477
|
+
} else {
|
478
|
+
s = input.match(RDS5)[0];
|
479
|
+
input = input.slice(s.length);
|
480
|
+
output.push(s);
|
481
|
+
}
|
482
|
+
}
|
483
|
+
|
484
|
+
return output.join("");
|
485
|
+
};
|
486
|
+
|
487
|
+
/**
|
488
|
+
* @param {URIComponents} components
|
489
|
+
* @param {Options} [options]
|
490
|
+
* @returns {string}
|
491
|
+
*/
|
492
|
+
|
493
|
+
URI.serialize = function (components, options) {
|
494
|
+
var uriTokens = [],
|
495
|
+
schemeHandler,
|
496
|
+
s;
|
497
|
+
options = options || {};
|
498
|
+
|
499
|
+
//check if a handler for the scheme exists
|
500
|
+
schemeHandler = URI.SCHEMES[components.scheme || options.scheme];
|
501
|
+
if (schemeHandler && schemeHandler.serialize) {
|
502
|
+
//perform extra serialization
|
503
|
+
schemeHandler.serialize(components, options);
|
504
|
+
}
|
505
|
+
|
506
|
+
if (options.reference !== "suffix" && components.scheme) {
|
507
|
+
uriTokens.push(components.scheme.toString().toLowerCase().replace(NOT_SCHEME, ""));
|
508
|
+
uriTokens.push(":");
|
509
|
+
}
|
510
|
+
|
511
|
+
components.authority = URI._recomposeAuthority(components);
|
512
|
+
if (components.authority !== undefined) {
|
513
|
+
if (options.reference !== "suffix") {
|
514
|
+
uriTokens.push("//");
|
515
|
+
}
|
516
|
+
|
517
|
+
uriTokens.push(components.authority);
|
518
|
+
|
519
|
+
if (components.path && components.path.charAt(0) !== "/") {
|
520
|
+
uriTokens.push("/");
|
521
|
+
}
|
522
|
+
}
|
523
|
+
|
524
|
+
if (components.path) {
|
525
|
+
s = URI.removeDotSegments(components.path.toString().replace(/%2E/ig, "."));
|
526
|
+
|
527
|
+
if (components.scheme) {
|
528
|
+
s = s.replace(NOT_PATH, pctEncChar);
|
529
|
+
} else {
|
530
|
+
s = s.replace(NOT_PATH_NOSCHEME, pctEncChar);
|
531
|
+
}
|
532
|
+
|
533
|
+
if (components.authority === undefined) {
|
534
|
+
s = s.replace(/^\/\//, "/%2F"); //don't allow the path to start with "//"
|
535
|
+
}
|
536
|
+
uriTokens.push(s);
|
537
|
+
}
|
538
|
+
|
539
|
+
if (components.query) {
|
540
|
+
uriTokens.push("?");
|
541
|
+
uriTokens.push(components.query.toString().replace(NOT_QUERY, pctEncChar));
|
542
|
+
}
|
543
|
+
|
544
|
+
if (components.fragment) {
|
545
|
+
uriTokens.push("#");
|
546
|
+
uriTokens.push(components.fragment.toString().replace(NOT_FRAGMENT, pctEncChar));
|
547
|
+
}
|
548
|
+
|
549
|
+
return uriTokens
|
550
|
+
.join('') //merge tokens into a string
|
551
|
+
.replace(PCT_ENCODEDS, pctDecUnreserved) //undecode unreserved characters
|
552
|
+
//.replace(OTHER_CHARS, pctEncChar) //replace non-URI characters
|
553
|
+
.replace(/%[0-9A-Fa-f]{2}/g, function (str) { //uppercase percent encoded characters
|
554
|
+
return str.toUpperCase();
|
555
|
+
})
|
556
|
+
;
|
557
|
+
};
|
558
|
+
|
559
|
+
/**
|
560
|
+
* @param {URIComponents} base
|
561
|
+
* @param {URIComponents} relative
|
562
|
+
* @param {Options} [options]
|
563
|
+
* @param {boolean} [skipNormalization]
|
564
|
+
* @returns {URIComponents}
|
565
|
+
*/
|
566
|
+
|
567
|
+
URI.resolveComponents = function (base, relative, options, skipNormalization) {
|
568
|
+
var target = new Components();
|
569
|
+
|
570
|
+
if (!skipNormalization) {
|
571
|
+
base = URI.parse(URI.serialize(base, options), options); //normalize base components
|
572
|
+
relative = URI.parse(URI.serialize(relative, options), options); //normalize relative components
|
573
|
+
}
|
574
|
+
options = options || {};
|
575
|
+
|
576
|
+
if (!options.tolerant && relative.scheme) {
|
577
|
+
target.scheme = relative.scheme;
|
578
|
+
target.authority = relative.authority;
|
579
|
+
target.userinfo = relative.userinfo;
|
580
|
+
target.host = relative.host;
|
581
|
+
target.port = relative.port;
|
582
|
+
target.path = URI.removeDotSegments(relative.path);
|
583
|
+
target.query = relative.query;
|
584
|
+
} else {
|
585
|
+
if (relative.authority !== undefined) {
|
586
|
+
target.authority = relative.authority;
|
587
|
+
target.userinfo = relative.userinfo;
|
588
|
+
target.host = relative.host;
|
589
|
+
target.port = relative.port;
|
590
|
+
target.path = URI.removeDotSegments(relative.path);
|
591
|
+
target.query = relative.query;
|
592
|
+
} else {
|
593
|
+
if (!relative.path) {
|
594
|
+
target.path = base.path;
|
595
|
+
if (relative.query !== undefined) {
|
596
|
+
target.query = relative.query;
|
597
|
+
} else {
|
598
|
+
target.query = base.query;
|
599
|
+
}
|
600
|
+
} else {
|
601
|
+
if (relative.path.charAt(0) === "/") {
|
602
|
+
target.path = URI.removeDotSegments(relative.path);
|
603
|
+
} else {
|
604
|
+
if (base.authority !== undefined && !base.path) {
|
605
|
+
target.path = "/" + relative.path;
|
606
|
+
} else if (!base.path) {
|
607
|
+
target.path = relative.path;
|
608
|
+
} else {
|
609
|
+
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
|
610
|
+
}
|
611
|
+
target.path = URI.removeDotSegments(target.path);
|
612
|
+
}
|
613
|
+
target.query = relative.query;
|
614
|
+
}
|
615
|
+
target.authority = base.authority;
|
616
|
+
target.userinfo = base.userinfo;
|
617
|
+
target.host = base.host;
|
618
|
+
target.port = base.port;
|
619
|
+
}
|
620
|
+
target.scheme = base.scheme;
|
621
|
+
}
|
622
|
+
|
623
|
+
target.fragment = relative.fragment;
|
624
|
+
|
625
|
+
return target;
|
626
|
+
};
|
627
|
+
|
628
|
+
/**
|
629
|
+
* @param {string} baseURI
|
630
|
+
* @param {string} relativeURI
|
631
|
+
* @param {Options} [options]
|
632
|
+
* @returns {string}
|
633
|
+
*/
|
634
|
+
|
635
|
+
URI.resolve = function (baseURI, relativeURI, options) {
|
636
|
+
return URI.serialize(URI.resolveComponents(URI.parse(baseURI, options), URI.parse(relativeURI, options), options, true), options);
|
637
|
+
};
|
638
|
+
|
639
|
+
/**
|
640
|
+
* @param {string|URIComponents} uri
|
641
|
+
* @param {Options} options
|
642
|
+
* @returns {string|URIComponents}
|
643
|
+
*/
|
644
|
+
|
645
|
+
URI.normalize = function (uri, options) {
|
646
|
+
if (typeof uri === "string") {
|
647
|
+
return URI.serialize(URI.parse(uri, options), options);
|
648
|
+
} else if (typeOf(uri) === "object") {
|
649
|
+
return URI.parse(URI.serialize(uri, options), options);
|
650
|
+
}
|
651
|
+
|
652
|
+
return uri;
|
653
|
+
};
|
654
|
+
|
655
|
+
/**
|
656
|
+
* @param {string|URIComponents} uriA
|
657
|
+
* @param {string|URIComponents} uriB
|
658
|
+
* @param {Options} options
|
659
|
+
*/
|
660
|
+
|
661
|
+
URI.equal = function (uriA, uriB, options) {
|
662
|
+
if (typeof uriA === "string") {
|
663
|
+
uriA = URI.serialize(URI.parse(uriA, options), options);
|
664
|
+
} else if (typeOf(uriA) === "object") {
|
665
|
+
uriA = URI.serialize(uriA, options);
|
666
|
+
}
|
667
|
+
|
668
|
+
if (typeof uriB === "string") {
|
669
|
+
uriB = URI.serialize(URI.parse(uriB, options), options);
|
670
|
+
} else if (typeOf(uriB) === "object") {
|
671
|
+
uriB = URI.serialize(uriB, options);
|
672
|
+
}
|
673
|
+
|
674
|
+
return uriA === uriB;
|
675
|
+
};
|
676
|
+
|
677
|
+
/**
|
678
|
+
* @param {string} str
|
679
|
+
* @returns {string}
|
680
|
+
*/
|
681
|
+
|
682
|
+
URI.escapeComponent = function (str) {
|
683
|
+
return str && str.toString().replace(ESCAPE, pctEncChar);
|
684
|
+
};
|
685
|
+
|
686
|
+
/**
|
687
|
+
* @param {string} str
|
688
|
+
* @returns {string}
|
689
|
+
*/
|
690
|
+
|
691
|
+
URI.unescapeComponent = function (str) {
|
692
|
+
return str && str.toString().replace(PCT_ENCODEDS, pctDecChars);
|
693
|
+
};
|
694
|
+
|
695
|
+
//export API
|
696
|
+
exports.Components = Components;
|
697
|
+
exports.URI = URI;
|
698
|
+
|
699
|
+
//name-safe export API
|
700
|
+
exports["URI"] = {
|
701
|
+
"SCHEMES" : URI.SCHEMES,
|
702
|
+
"parse" : URI.parse,
|
703
|
+
"removeDotSegments" : URI.removeDotSegments,
|
704
|
+
"serialize" : URI.serialize,
|
705
|
+
"resolveComponents" : URI.resolveComponents,
|
706
|
+
"resolve" : URI.resolve,
|
707
|
+
"normalize" : URI.normalize,
|
708
|
+
"equal" : URI.equal,
|
709
|
+
"escapeComponent" : URI.escapeComponent,
|
710
|
+
"unescapeComponent" : URI.unescapeComponent
|
711
|
+
};
|
712
|
+
|
713
|
+
}());
|
714
|
+
|
715
|
+
|
716
|
+
|
717
|
+
/**
|
718
|
+
* JSV: JSON Schema Validator
|
719
|
+
*
|
720
|
+
* @fileOverview A JavaScript implementation of a extendable, fully compliant JSON Schema validator.
|
721
|
+
* @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
|
722
|
+
* @version 3.5
|
723
|
+
* @see http://github.com/garycourt/JSV
|
724
|
+
*/
|
725
|
+
|
726
|
+
/*
|
727
|
+
* Copyright 2010 Gary Court. All rights reserved.
|
728
|
+
*
|
729
|
+
* Redistribution and use in source and binary forms, with or without modification, are
|
730
|
+
* permitted provided that the following conditions are met:
|
731
|
+
*
|
732
|
+
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
733
|
+
* conditions and the following disclaimer.
|
734
|
+
*
|
735
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
736
|
+
* of conditions and the following disclaimer in the documentation and/or other materials
|
737
|
+
* provided with the distribution.
|
738
|
+
*
|
739
|
+
* THIS SOFTWARE IS PROVIDED BY GARY COURT ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
740
|
+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
741
|
+
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR
|
742
|
+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
743
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
744
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
745
|
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
746
|
+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
747
|
+
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
748
|
+
*
|
749
|
+
* The views and conclusions contained in the software and documentation are those of the
|
750
|
+
* authors and should not be interpreted as representing official policies, either expressed
|
751
|
+
* or implied, of Gary Court or the JSON Schema specification.
|
752
|
+
*/
|
753
|
+
|
754
|
+
/*jslint white: true, sub: true, onevar: true, undef: true, eqeqeq: true, newcap: true, immed: true, indent: 4 */
|
755
|
+
|
756
|
+
var exports = exports || this,
|
757
|
+
require = require || function () {
|
758
|
+
return exports;
|
759
|
+
};
|
760
|
+
|
761
|
+
(function () {
|
762
|
+
|
763
|
+
var URI = require("./uri/uri").URI,
|
764
|
+
O = {},
|
765
|
+
I2H = "0123456789abcdef".split(""),
|
766
|
+
mapArray, filterArray, searchArray,
|
767
|
+
|
768
|
+
JSV;
|
769
|
+
|
770
|
+
//
|
771
|
+
// Utility functions
|
772
|
+
//
|
773
|
+
|
774
|
+
function typeOf(o) {
|
775
|
+
return o === undefined ? "undefined" : (o === null ? "null" : Object.prototype.toString.call(o).split(" ").pop().split("]").shift().toLowerCase());
|
776
|
+
}
|
777
|
+
|
778
|
+
/** @inner */
|
779
|
+
function F() {}
|
780
|
+
|
781
|
+
function createObject(proto) {
|
782
|
+
F.prototype = proto || {};
|
783
|
+
return new F();
|
784
|
+
}
|
785
|
+
|
786
|
+
function mapObject(obj, func, scope) {
|
787
|
+
var newObj = {}, key;
|
788
|
+
for (key in obj) {
|
789
|
+
if (obj[key] !== O[key]) {
|
790
|
+
newObj[key] = func.call(scope, obj[key], key, obj);
|
791
|
+
}
|
792
|
+
}
|
793
|
+
return newObj;
|
794
|
+
}
|
795
|
+
|
796
|
+
/** @ignore */
|
797
|
+
mapArray = function (arr, func, scope) {
|
798
|
+
var x = 0, xl = arr.length, newArr = new Array(xl);
|
799
|
+
for (; x < xl; ++x) {
|
800
|
+
newArr[x] = func.call(scope, arr[x], x, arr);
|
801
|
+
}
|
802
|
+
return newArr;
|
803
|
+
};
|
804
|
+
|
805
|
+
if (Array.prototype.map) {
|
806
|
+
/** @ignore */
|
807
|
+
mapArray = function (arr, func, scope) {
|
808
|
+
return Array.prototype.map.call(arr, func, scope);
|
809
|
+
};
|
810
|
+
}
|
811
|
+
|
812
|
+
/** @ignore */
|
813
|
+
filterArray = function (arr, func, scope) {
|
814
|
+
var x = 0, xl = arr.length, newArr = [];
|
815
|
+
for (; x < xl; ++x) {
|
816
|
+
if (func.call(scope, arr[x], x, arr)) {
|
817
|
+
newArr[newArr.length] = arr[x];
|
818
|
+
}
|
819
|
+
}
|
820
|
+
return newArr;
|
821
|
+
};
|
822
|
+
|
823
|
+
if (Array.prototype.filter) {
|
824
|
+
/** @ignore */
|
825
|
+
filterArray = function (arr, func, scope) {
|
826
|
+
return Array.prototype.filter.call(arr, func, scope);
|
827
|
+
};
|
828
|
+
}
|
829
|
+
|
830
|
+
/** @ignore */
|
831
|
+
searchArray = function (arr, o) {
|
832
|
+
var x = 0, xl = arr.length;
|
833
|
+
for (; x < xl; ++x) {
|
834
|
+
if (arr[x] === o) {
|
835
|
+
return x;
|
836
|
+
}
|
837
|
+
}
|
838
|
+
return -1;
|
839
|
+
};
|
840
|
+
|
841
|
+
if (Array.prototype.indexOf) {
|
842
|
+
/** @ignore */
|
843
|
+
searchArray = function (arr, o) {
|
844
|
+
return Array.prototype.indexOf.call(arr, o);
|
845
|
+
};
|
846
|
+
}
|
847
|
+
|
848
|
+
function toArray(o) {
|
849
|
+
return o !== undefined && o !== null ? (o instanceof Array && !o.callee ? o : (typeof o.length !== "number" || o.split || o.setInterval || o.call ? [ o ] : Array.prototype.slice.call(o))) : [];
|
850
|
+
}
|
851
|
+
|
852
|
+
function keys(o) {
|
853
|
+
var result = [], key;
|
854
|
+
|
855
|
+
switch (typeOf(o)) {
|
856
|
+
case "object":
|
857
|
+
for (key in o) {
|
858
|
+
if (o[key] !== O[key]) {
|
859
|
+
result[result.length] = key;
|
860
|
+
}
|
861
|
+
}
|
862
|
+
break;
|
863
|
+
case "array":
|
864
|
+
for (key = o.length - 1; key >= 0; --key) {
|
865
|
+
result[key] = key;
|
866
|
+
}
|
867
|
+
break;
|
868
|
+
}
|
869
|
+
|
870
|
+
return result;
|
871
|
+
}
|
872
|
+
|
873
|
+
function pushUnique(arr, o) {
|
874
|
+
if (searchArray(arr, o) === -1) {
|
875
|
+
arr.push(o);
|
876
|
+
}
|
877
|
+
return arr;
|
878
|
+
}
|
879
|
+
|
880
|
+
function popFirst(arr, o) {
|
881
|
+
var index = searchArray(arr, o);
|
882
|
+
if (index > -1) {
|
883
|
+
arr.splice(index, 1);
|
884
|
+
}
|
885
|
+
return arr;
|
886
|
+
}
|
887
|
+
|
888
|
+
function randomUUID() {
|
889
|
+
return [
|
890
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
891
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
892
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
893
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
894
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
895
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
896
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
897
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
898
|
+
"-",
|
899
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
900
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
901
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
902
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
903
|
+
"-4", //set 4 high bits of time_high field to version
|
904
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
905
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
906
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
907
|
+
"-",
|
908
|
+
I2H[(Math.floor(Math.random() * 0x10) & 0x3) | 0x8], //specify 2 high bits of clock sequence
|
909
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
910
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
911
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
912
|
+
"-",
|
913
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
914
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
915
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
916
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
917
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
918
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
919
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
920
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
921
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
922
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
923
|
+
I2H[Math.floor(Math.random() * 0x10)],
|
924
|
+
I2H[Math.floor(Math.random() * 0x10)]
|
925
|
+
].join("");
|
926
|
+
}
|
927
|
+
|
928
|
+
function escapeURIComponent(str) {
|
929
|
+
return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A');
|
930
|
+
}
|
931
|
+
|
932
|
+
function formatURI(uri) {
|
933
|
+
if (typeof uri === "string" && uri.indexOf("#") === -1) {
|
934
|
+
uri += "#";
|
935
|
+
}
|
936
|
+
return uri;
|
937
|
+
}
|
938
|
+
|
939
|
+
/**
|
940
|
+
* Defines an error, found by a schema, with an instance.
|
941
|
+
* This class can only be instantiated by {@link Report#addError}.
|
942
|
+
*
|
943
|
+
* @name ValidationError
|
944
|
+
* @class
|
945
|
+
* @see Report#addError
|
946
|
+
*/
|
947
|
+
|
948
|
+
/**
|
949
|
+
* The URI of the instance that has the error.
|
950
|
+
*
|
951
|
+
* @name ValidationError.prototype.uri
|
952
|
+
* @type String
|
953
|
+
*/
|
954
|
+
|
955
|
+
/**
|
956
|
+
* The URI of the schema that generated the error.
|
957
|
+
*
|
958
|
+
* @name ValidationError.prototype.schemaUri
|
959
|
+
* @type String
|
960
|
+
*/
|
961
|
+
|
962
|
+
/**
|
963
|
+
* The name of the schema attribute that generated the error.
|
964
|
+
*
|
965
|
+
* @name ValidationError.prototype.attribute
|
966
|
+
* @type String
|
967
|
+
*/
|
968
|
+
|
969
|
+
/**
|
970
|
+
* An user-friendly (English) message about what failed to validate.
|
971
|
+
*
|
972
|
+
* @name ValidationError.prototype.message
|
973
|
+
* @type String
|
974
|
+
*/
|
975
|
+
|
976
|
+
/**
|
977
|
+
* The value of the schema attribute that generated the error.
|
978
|
+
*
|
979
|
+
* @name ValidationError.prototype.details
|
980
|
+
* @type Any
|
981
|
+
*/
|
982
|
+
|
983
|
+
/**
|
984
|
+
* Reports are returned from validation methods to describe the result of a validation.
|
985
|
+
*
|
986
|
+
* @name Report
|
987
|
+
* @class
|
988
|
+
* @see JSONSchema#validate
|
989
|
+
* @see Environment#validate
|
990
|
+
*/
|
991
|
+
|
992
|
+
function Report() {
|
993
|
+
/**
|
994
|
+
* An array of {@link ValidationError} objects that define all the errors generated by the schema against the instance.
|
995
|
+
*
|
996
|
+
* @name Report.prototype.errors
|
997
|
+
* @type Array
|
998
|
+
* @see Report#addError
|
999
|
+
*/
|
1000
|
+
this.errors = [];
|
1001
|
+
|
1002
|
+
/**
|
1003
|
+
* A hash table of every instance and what schemas were validated against it.
|
1004
|
+
* <p>
|
1005
|
+
* The key of each item in the table is the URI of the instance that was validated.
|
1006
|
+
* The value of this key is an array of strings of URIs of the schema that validated it.
|
1007
|
+
* </p>
|
1008
|
+
*
|
1009
|
+
* @name Report.prototype.validated
|
1010
|
+
* @type Object
|
1011
|
+
* @see Report#registerValidation
|
1012
|
+
* @see Report#isValidatedBy
|
1013
|
+
*/
|
1014
|
+
this.validated = {};
|
1015
|
+
|
1016
|
+
/**
|
1017
|
+
* If the report is generated by {@link Environment#validate}, this field is the generated instance.
|
1018
|
+
*
|
1019
|
+
* @name Report.prototype.instance
|
1020
|
+
* @type JSONInstance
|
1021
|
+
* @see Environment#validate
|
1022
|
+
*/
|
1023
|
+
|
1024
|
+
/**
|
1025
|
+
* If the report is generated by {@link Environment#validate}, this field is the generated schema.
|
1026
|
+
*
|
1027
|
+
* @name Report.prototype.schema
|
1028
|
+
* @type JSONSchema
|
1029
|
+
* @see Environment#validate
|
1030
|
+
*/
|
1031
|
+
|
1032
|
+
/**
|
1033
|
+
* If the report is generated by {@link Environment#validate}, this field is the schema's schema.
|
1034
|
+
* This value is the same as calling <code>schema.getSchema()</code>.
|
1035
|
+
*
|
1036
|
+
* @name Report.prototype.schemaSchema
|
1037
|
+
* @type JSONSchema
|
1038
|
+
* @see Environment#validate
|
1039
|
+
* @see JSONSchema#getSchema
|
1040
|
+
*/
|
1041
|
+
}
|
1042
|
+
|
1043
|
+
/**
|
1044
|
+
* Adds a {@link ValidationError} object to the <a href="#errors"><code>errors</code></a> field.
|
1045
|
+
*
|
1046
|
+
* @param {JSONInstance|String} instance The instance (or instance URI) that is invalid
|
1047
|
+
* @param {JSONSchema|String} schema The schema (or schema URI) that was validating the instance
|
1048
|
+
* @param {String} attr The attribute that failed to validated
|
1049
|
+
* @param {String} message A user-friendly message on why the schema attribute failed to validate the instance
|
1050
|
+
* @param {Any} details The value of the schema attribute
|
1051
|
+
*/
|
1052
|
+
|
1053
|
+
Report.prototype.addError = function (instance, schema, attr, message, details) {
|
1054
|
+
this.errors.push({
|
1055
|
+
uri : instance instanceof JSONInstance ? instance.getURI() : instance,
|
1056
|
+
schemaUri : schema instanceof JSONInstance ? schema.getURI() : schema,
|
1057
|
+
attribute : attr,
|
1058
|
+
message : message,
|
1059
|
+
details : details
|
1060
|
+
});
|
1061
|
+
};
|
1062
|
+
|
1063
|
+
/**
|
1064
|
+
* Registers that the provided instance URI has been validated by the provided schema URI.
|
1065
|
+
* This is recorded in the <a href="#validated"><code>validated</code></a> field.
|
1066
|
+
*
|
1067
|
+
* @param {String} uri The URI of the instance that was validated
|
1068
|
+
* @param {String} schemaUri The URI of the schema that validated the instance
|
1069
|
+
*/
|
1070
|
+
|
1071
|
+
Report.prototype.registerValidation = function (uri, schemaUri) {
|
1072
|
+
if (!this.validated[uri]) {
|
1073
|
+
this.validated[uri] = [ schemaUri ];
|
1074
|
+
} else {
|
1075
|
+
this.validated[uri].push(schemaUri);
|
1076
|
+
}
|
1077
|
+
};
|
1078
|
+
|
1079
|
+
/**
|
1080
|
+
* Returns if an instance with the provided URI has been validated by the schema with the provided URI.
|
1081
|
+
*
|
1082
|
+
* @param {String} uri The URI of the instance
|
1083
|
+
* @param {String} schemaUri The URI of a schema
|
1084
|
+
* @returns {Boolean} If the instance has been validated by the schema.
|
1085
|
+
*/
|
1086
|
+
|
1087
|
+
Report.prototype.isValidatedBy = function (uri, schemaUri) {
|
1088
|
+
return !!this.validated[uri] && searchArray(this.validated[uri], schemaUri) !== -1;
|
1089
|
+
};
|
1090
|
+
|
1091
|
+
/**
|
1092
|
+
* A wrapper class for binding an Environment, URI and helper methods to an instance.
|
1093
|
+
* This class is most commonly instantiated with {@link Environment#createInstance}.
|
1094
|
+
*
|
1095
|
+
* @name JSONInstance
|
1096
|
+
* @class
|
1097
|
+
* @param {Environment} env The environment this instance belongs to
|
1098
|
+
* @param {JSONInstance|Any} json The value of the instance
|
1099
|
+
* @param {String} [uri] The URI of the instance. If undefined, the URI will be a randomly generated UUID.
|
1100
|
+
* @param {String} [fd] The fragment delimiter for properties. If undefined, uses the environment default.
|
1101
|
+
*/
|
1102
|
+
|
1103
|
+
function JSONInstance(env, json, uri, fd) {
|
1104
|
+
if (json instanceof JSONInstance) {
|
1105
|
+
if (typeof fd !== "string") {
|
1106
|
+
fd = json._fd;
|
1107
|
+
}
|
1108
|
+
if (typeof uri !== "string") {
|
1109
|
+
uri = json._uri;
|
1110
|
+
}
|
1111
|
+
json = json._value;
|
1112
|
+
}
|
1113
|
+
|
1114
|
+
if (typeof uri !== "string") {
|
1115
|
+
uri = "urn:uuid:" + randomUUID() + "#";
|
1116
|
+
} else if (uri.indexOf(":") === -1) {
|
1117
|
+
uri = formatURI(URI.resolve("urn:uuid:" + randomUUID() + "#", uri));
|
1118
|
+
}
|
1119
|
+
|
1120
|
+
this._env = env;
|
1121
|
+
this._value = json;
|
1122
|
+
this._uri = uri;
|
1123
|
+
this._fd = fd || this._env._options["defaultFragmentDelimiter"];
|
1124
|
+
}
|
1125
|
+
|
1126
|
+
/**
|
1127
|
+
* Returns the environment the instance is bound to.
|
1128
|
+
*
|
1129
|
+
* @returns {Environment} The environment of the instance
|
1130
|
+
*/
|
1131
|
+
|
1132
|
+
JSONInstance.prototype.getEnvironment = function () {
|
1133
|
+
return this._env;
|
1134
|
+
};
|
1135
|
+
|
1136
|
+
/**
|
1137
|
+
* Returns the name of the type of the instance.
|
1138
|
+
*
|
1139
|
+
* @returns {String} The name of the type of the instance
|
1140
|
+
*/
|
1141
|
+
|
1142
|
+
JSONInstance.prototype.getType = function () {
|
1143
|
+
return typeOf(this._value);
|
1144
|
+
};
|
1145
|
+
|
1146
|
+
/**
|
1147
|
+
* Returns the JSON value of the instance.
|
1148
|
+
*
|
1149
|
+
* @returns {Any} The actual JavaScript value of the instance
|
1150
|
+
*/
|
1151
|
+
|
1152
|
+
JSONInstance.prototype.getValue = function () {
|
1153
|
+
return this._value;
|
1154
|
+
};
|
1155
|
+
|
1156
|
+
/**
|
1157
|
+
* Returns the URI of the instance.
|
1158
|
+
*
|
1159
|
+
* @returns {String} The URI of the instance
|
1160
|
+
*/
|
1161
|
+
|
1162
|
+
JSONInstance.prototype.getURI = function () {
|
1163
|
+
return this._uri;
|
1164
|
+
};
|
1165
|
+
|
1166
|
+
/**
|
1167
|
+
* Returns a resolved URI of a provided relative URI against the URI of the instance.
|
1168
|
+
*
|
1169
|
+
* @param {String} uri The relative URI to resolve
|
1170
|
+
* @returns {String} The resolved URI
|
1171
|
+
*/
|
1172
|
+
|
1173
|
+
JSONInstance.prototype.resolveURI = function (uri) {
|
1174
|
+
return formatURI(URI.resolve(this._uri, uri));
|
1175
|
+
};
|
1176
|
+
|
1177
|
+
/**
|
1178
|
+
* Returns an array of the names of all the properties.
|
1179
|
+
*
|
1180
|
+
* @returns {Array} An array of strings which are the names of all the properties
|
1181
|
+
*/
|
1182
|
+
|
1183
|
+
JSONInstance.prototype.getPropertyNames = function () {
|
1184
|
+
return keys(this._value);
|
1185
|
+
};
|
1186
|
+
|
1187
|
+
/**
|
1188
|
+
* Returns a {@link JSONInstance} of the value of the provided property name.
|
1189
|
+
*
|
1190
|
+
* @param {String} key The name of the property to fetch
|
1191
|
+
* @returns {JSONInstance} The instance of the property value
|
1192
|
+
*/
|
1193
|
+
|
1194
|
+
JSONInstance.prototype.getProperty = function (key) {
|
1195
|
+
var value = this._value ? this._value[key] : undefined;
|
1196
|
+
if (value instanceof JSONInstance) {
|
1197
|
+
return value;
|
1198
|
+
}
|
1199
|
+
//else
|
1200
|
+
return new JSONInstance(this._env, value, this._uri + this._fd + escapeURIComponent(key), this._fd);
|
1201
|
+
};
|
1202
|
+
|
1203
|
+
/**
|
1204
|
+
* Returns all the property instances of the target instance.
|
1205
|
+
* <p>
|
1206
|
+
* If the target instance is an Object, then the method will return a hash table of {@link JSONInstance}s of all the properties.
|
1207
|
+
* If the target instance is an Array, then the method will return an array of {@link JSONInstance}s of all the items.
|
1208
|
+
* </p>
|
1209
|
+
*
|
1210
|
+
* @returns {Object|Array|undefined} The list of instances for all the properties
|
1211
|
+
*/
|
1212
|
+
|
1213
|
+
JSONInstance.prototype.getProperties = function () {
|
1214
|
+
var type = typeOf(this._value),
|
1215
|
+
self = this;
|
1216
|
+
|
1217
|
+
if (type === "object") {
|
1218
|
+
return mapObject(this._value, function (value, key) {
|
1219
|
+
if (value instanceof JSONInstance) {
|
1220
|
+
return value;
|
1221
|
+
}
|
1222
|
+
return new JSONInstance(self._env, value, self._uri + self._fd + escapeURIComponent(key), self._fd);
|
1223
|
+
});
|
1224
|
+
} else if (type === "array") {
|
1225
|
+
return mapArray(this._value, function (value, key) {
|
1226
|
+
if (value instanceof JSONInstance) {
|
1227
|
+
return value;
|
1228
|
+
}
|
1229
|
+
return new JSONInstance(self._env, value, self._uri + self._fd + escapeURIComponent(key), self._fd);
|
1230
|
+
});
|
1231
|
+
}
|
1232
|
+
};
|
1233
|
+
|
1234
|
+
/**
|
1235
|
+
* Returns the JSON value of the provided property name.
|
1236
|
+
* This method is a faster version of calling <code>instance.getProperty(key).getValue()</code>.
|
1237
|
+
*
|
1238
|
+
* @param {String} key The name of the property
|
1239
|
+
* @returns {Any} The JavaScript value of the instance
|
1240
|
+
* @see JSONInstance#getProperty
|
1241
|
+
* @see JSONInstance#getValue
|
1242
|
+
*/
|
1243
|
+
|
1244
|
+
JSONInstance.prototype.getValueOfProperty = function (key) {
|
1245
|
+
if (this._value) {
|
1246
|
+
if (this._value[key] instanceof JSONInstance) {
|
1247
|
+
return this._value[key]._value;
|
1248
|
+
}
|
1249
|
+
return this._value[key];
|
1250
|
+
}
|
1251
|
+
};
|
1252
|
+
|
1253
|
+
/**
|
1254
|
+
* Return if the provided value is the same as the value of the instance.
|
1255
|
+
*
|
1256
|
+
* @param {JSONInstance|Any} instance The value to compare
|
1257
|
+
* @returns {Boolean} If both the instance and the value match
|
1258
|
+
*/
|
1259
|
+
|
1260
|
+
JSONInstance.prototype.equals = function (instance) {
|
1261
|
+
if (instance instanceof JSONInstance) {
|
1262
|
+
return this._value === instance._value;
|
1263
|
+
}
|
1264
|
+
//else
|
1265
|
+
return this._value === instance;
|
1266
|
+
};
|
1267
|
+
|
1268
|
+
/**
|
1269
|
+
* Warning: Not a generic clone function
|
1270
|
+
* Produces a JSV acceptable clone
|
1271
|
+
*/
|
1272
|
+
|
1273
|
+
function clone(obj, deep) {
|
1274
|
+
var newObj, x;
|
1275
|
+
|
1276
|
+
if (obj instanceof JSONInstance) {
|
1277
|
+
obj = obj.getValue();
|
1278
|
+
}
|
1279
|
+
|
1280
|
+
switch (typeOf(obj)) {
|
1281
|
+
case "object":
|
1282
|
+
if (deep) {
|
1283
|
+
newObj = {};
|
1284
|
+
for (x in obj) {
|
1285
|
+
if (obj[x] !== O[x]) {
|
1286
|
+
newObj[x] = clone(obj[x], deep);
|
1287
|
+
}
|
1288
|
+
}
|
1289
|
+
return newObj;
|
1290
|
+
} else {
|
1291
|
+
return createObject(obj);
|
1292
|
+
}
|
1293
|
+
break;
|
1294
|
+
case "array":
|
1295
|
+
if (deep) {
|
1296
|
+
newObj = new Array(obj.length);
|
1297
|
+
x = obj.length;
|
1298
|
+
while (--x >= 0) {
|
1299
|
+
newObj[x] = clone(obj[x], deep);
|
1300
|
+
}
|
1301
|
+
return newObj;
|
1302
|
+
} else {
|
1303
|
+
return Array.prototype.slice.call(obj);
|
1304
|
+
}
|
1305
|
+
break;
|
1306
|
+
default:
|
1307
|
+
return obj;
|
1308
|
+
}
|
1309
|
+
}
|
1310
|
+
|
1311
|
+
/**
|
1312
|
+
* This class binds a {@link JSONInstance} with a {@link JSONSchema} to provided context aware methods.
|
1313
|
+
*
|
1314
|
+
* @name JSONSchema
|
1315
|
+
* @class
|
1316
|
+
* @param {Environment} env The environment this schema belongs to
|
1317
|
+
* @param {JSONInstance|Any} json The value of the schema
|
1318
|
+
* @param {String} [uri] The URI of the schema. If undefined, the URI will be a randomly generated UUID.
|
1319
|
+
* @param {JSONSchema|Boolean} [schema] The schema to bind to the instance. If <code>undefined</code>, the environment's default schema will be used. If <code>true</code>, the instance's schema will be itself.
|
1320
|
+
* @extends JSONInstance
|
1321
|
+
*/
|
1322
|
+
|
1323
|
+
function JSONSchema(env, json, uri, schema) {
|
1324
|
+
var fr;
|
1325
|
+
JSONInstance.call(this, env, json, uri);
|
1326
|
+
|
1327
|
+
if (schema === true) {
|
1328
|
+
this._schema = this;
|
1329
|
+
} else if (json instanceof JSONSchema && !(schema instanceof JSONSchema)) {
|
1330
|
+
this._schema = json._schema; //TODO: Make sure cross environments don't mess everything up
|
1331
|
+
} else {
|
1332
|
+
this._schema = schema instanceof JSONSchema ? schema : this._env.getDefaultSchema() || JSONSchema.createEmptySchema(this._env);
|
1333
|
+
}
|
1334
|
+
|
1335
|
+
//determine fragment delimiter from schema
|
1336
|
+
fr = this._schema.getValueOfProperty("fragmentResolution");
|
1337
|
+
if (fr === "dot-delimited") {
|
1338
|
+
this._fd = ".";
|
1339
|
+
} else if (fr === "slash-delimited") {
|
1340
|
+
this._fd = "/";
|
1341
|
+
}
|
1342
|
+
}
|
1343
|
+
|
1344
|
+
JSONSchema.prototype = createObject(JSONInstance.prototype);
|
1345
|
+
|
1346
|
+
/**
|
1347
|
+
* Creates an empty schema.
|
1348
|
+
*
|
1349
|
+
* @param {Environment} env The environment of the schema
|
1350
|
+
* @returns {JSONSchema} The empty schema, who's schema is itself.
|
1351
|
+
*/
|
1352
|
+
|
1353
|
+
JSONSchema.createEmptySchema = function (env) {
|
1354
|
+
var schema = createObject(JSONSchema.prototype);
|
1355
|
+
JSONInstance.call(schema, env, {}, undefined, undefined);
|
1356
|
+
schema._schema = schema;
|
1357
|
+
return schema;
|
1358
|
+
};
|
1359
|
+
|
1360
|
+
/**
|
1361
|
+
* Returns the schema of the schema.
|
1362
|
+
*
|
1363
|
+
* @returns {JSONSchema} The schema of the schema
|
1364
|
+
*/
|
1365
|
+
|
1366
|
+
JSONSchema.prototype.getSchema = function () {
|
1367
|
+
return this._schema;
|
1368
|
+
};
|
1369
|
+
|
1370
|
+
/**
|
1371
|
+
* Returns the value of the provided attribute name.
|
1372
|
+
* <p>
|
1373
|
+
* This method is different from {@link JSONInstance#getProperty} as the named property
|
1374
|
+
* is converted using a parser defined by the schema's schema before being returned. This
|
1375
|
+
* makes the return value of this method attribute dependent.
|
1376
|
+
* </p>
|
1377
|
+
*
|
1378
|
+
* @param {String} key The name of the attribute
|
1379
|
+
* @param {Any} [arg] Some attribute parsers accept special arguments for returning resolved values. This is attribute dependent.
|
1380
|
+
* @returns {JSONSchema|Any} The value of the attribute
|
1381
|
+
*/
|
1382
|
+
|
1383
|
+
JSONSchema.prototype.getAttribute = function (key, arg) {
|
1384
|
+
var schemaProperty, parser, property, result;
|
1385
|
+
|
1386
|
+
if (!arg && this._attributes && this._attributes.hasOwnProperty(key)) {
|
1387
|
+
return this._attributes[key];
|
1388
|
+
}
|
1389
|
+
|
1390
|
+
schemaProperty = this._schema.getProperty("properties").getProperty(key);
|
1391
|
+
parser = schemaProperty.getValueOfProperty("parser");
|
1392
|
+
property = this.getProperty(key);
|
1393
|
+
if (typeof parser === "function") {
|
1394
|
+
result = parser(property, schemaProperty, arg);
|
1395
|
+
if (!arg && this._attributes) {
|
1396
|
+
this._attributes[key] = result;
|
1397
|
+
}
|
1398
|
+
return result;
|
1399
|
+
}
|
1400
|
+
//else
|
1401
|
+
return property.getValue();
|
1402
|
+
};
|
1403
|
+
|
1404
|
+
/**
|
1405
|
+
* Returns all the attributes of the schema.
|
1406
|
+
*
|
1407
|
+
* @returns {Object} A map of all parsed attribute values
|
1408
|
+
*/
|
1409
|
+
|
1410
|
+
JSONSchema.prototype.getAttributes = function () {
|
1411
|
+
var properties, schemaProperties, key, schemaProperty, parser;
|
1412
|
+
|
1413
|
+
if (!this._attributes && this.getType() === "object") {
|
1414
|
+
properties = this.getProperties();
|
1415
|
+
schemaProperties = this._schema.getProperty("properties");
|
1416
|
+
this._attributes = {};
|
1417
|
+
for (key in properties) {
|
1418
|
+
if (properties[key] !== O[key]) {
|
1419
|
+
schemaProperty = schemaProperties && schemaProperties.getProperty(key);
|
1420
|
+
parser = schemaProperty && schemaProperty.getValueOfProperty("parser");
|
1421
|
+
if (typeof parser === "function") {
|
1422
|
+
this._attributes[key] = parser(properties[key], schemaProperty);
|
1423
|
+
} else {
|
1424
|
+
this._attributes[key] = properties[key].getValue();
|
1425
|
+
}
|
1426
|
+
}
|
1427
|
+
}
|
1428
|
+
}
|
1429
|
+
|
1430
|
+
return clone(this._attributes, false);
|
1431
|
+
};
|
1432
|
+
|
1433
|
+
/**
|
1434
|
+
* Convenience method for retrieving a link or link object from a schema.
|
1435
|
+
* This method is the same as calling <code>schema.getAttribute("links", [rel, instance])[0];</code>.
|
1436
|
+
*
|
1437
|
+
* @param {String} rel The link relationship
|
1438
|
+
* @param {JSONInstance} [instance] The instance to resolve any URIs from
|
1439
|
+
* @returns {String|Object|undefined} If <code>instance</code> is provided, a string containing the resolve URI of the link is returned.
|
1440
|
+
* If <code>instance</code> is not provided, a link object is returned with details of the link.
|
1441
|
+
* If no link with the provided relationship exists, <code>undefined</code> is returned.
|
1442
|
+
* @see JSONSchema#getAttribute
|
1443
|
+
*/
|
1444
|
+
|
1445
|
+
JSONSchema.prototype.getLink = function (rel, instance) {
|
1446
|
+
var schemaLinks = this.getAttribute("links", [rel, instance]);
|
1447
|
+
if (schemaLinks && schemaLinks.length && schemaLinks[schemaLinks.length - 1]) {
|
1448
|
+
return schemaLinks[schemaLinks.length - 1];
|
1449
|
+
}
|
1450
|
+
};
|
1451
|
+
|
1452
|
+
/**
|
1453
|
+
* Validates the provided instance against the target schema and returns a {@link Report}.
|
1454
|
+
*
|
1455
|
+
* @param {JSONInstance|Any} instance The instance to validate; may be a {@link JSONInstance} or any JavaScript value
|
1456
|
+
* @param {Report} [report] A {@link Report} to concatenate the result of the validation to. If <code>undefined</code>, a new {@link Report} is created.
|
1457
|
+
* @param {JSONInstance} [parent] The parent/containing instance of the provided instance
|
1458
|
+
* @param {JSONSchema} [parentSchema] The schema of the parent/containing instance
|
1459
|
+
* @param {String} [name] The name of the parent object's property that references the instance
|
1460
|
+
* @returns {Report} The result of the validation
|
1461
|
+
*/
|
1462
|
+
|
1463
|
+
JSONSchema.prototype.validate = function (instance, report, parent, parentSchema, name) {
|
1464
|
+
var validator = this._schema.getValueOfProperty("validator");
|
1465
|
+
|
1466
|
+
if (!(instance instanceof JSONInstance)) {
|
1467
|
+
instance = this.getEnvironment().createInstance(instance);
|
1468
|
+
}
|
1469
|
+
|
1470
|
+
if (!(report instanceof Report)) {
|
1471
|
+
report = new Report();
|
1472
|
+
}
|
1473
|
+
|
1474
|
+
if (typeof validator === "function" && !report.isValidatedBy(instance.getURI(), this.getURI())) {
|
1475
|
+
report.registerValidation(instance.getURI(), this.getURI());
|
1476
|
+
validator(instance, this, this._schema, report, parent, parentSchema, name);
|
1477
|
+
}
|
1478
|
+
|
1479
|
+
return report;
|
1480
|
+
};
|
1481
|
+
|
1482
|
+
/**
|
1483
|
+
* Merges two schemas/instances together.
|
1484
|
+
*/
|
1485
|
+
|
1486
|
+
function inherits(base, extra, extension) {
|
1487
|
+
var baseType = typeOf(base),
|
1488
|
+
extraType = typeOf(extra),
|
1489
|
+
child, x;
|
1490
|
+
|
1491
|
+
if (extraType === "undefined") {
|
1492
|
+
return clone(base, true);
|
1493
|
+
} else if (baseType === "undefined" || extraType !== baseType) {
|
1494
|
+
return clone(extra, true);
|
1495
|
+
} else if (extraType === "object") {
|
1496
|
+
if (base instanceof JSONSchema) {
|
1497
|
+
base = base.getAttributes();
|
1498
|
+
}
|
1499
|
+
if (extra instanceof JSONSchema) {
|
1500
|
+
extra = extra.getAttributes();
|
1501
|
+
if (extra["extends"] && extension && extra["extends"] instanceof JSONSchema) {
|
1502
|
+
extra["extends"] = [ extra["extends"] ];
|
1503
|
+
}
|
1504
|
+
}
|
1505
|
+
child = clone(base, true); //this could be optimized as some properties get overwritten
|
1506
|
+
for (x in extra) {
|
1507
|
+
if (extra[x] !== O[x]) {
|
1508
|
+
child[x] = inherits(base[x], extra[x], extension);
|
1509
|
+
}
|
1510
|
+
}
|
1511
|
+
return child;
|
1512
|
+
} else {
|
1513
|
+
return clone(extra, true);
|
1514
|
+
}
|
1515
|
+
}
|
1516
|
+
|
1517
|
+
/**
|
1518
|
+
* An Environment is a sandbox of schemas thats behavior is different from other environments.
|
1519
|
+
*
|
1520
|
+
* @name Environment
|
1521
|
+
* @class
|
1522
|
+
*/
|
1523
|
+
|
1524
|
+
function Environment() {
|
1525
|
+
this._id = randomUUID();
|
1526
|
+
this._schemas = {};
|
1527
|
+
this._options = {};
|
1528
|
+
}
|
1529
|
+
|
1530
|
+
/**
|
1531
|
+
* Returns a clone of the target environment.
|
1532
|
+
*
|
1533
|
+
* @returns {Environment} A new {@link Environment} that is a exact copy of the target environment
|
1534
|
+
*/
|
1535
|
+
|
1536
|
+
Environment.prototype.clone = function () {
|
1537
|
+
var env = new Environment();
|
1538
|
+
env._schemas = createObject(this._schemas);
|
1539
|
+
env._options = createObject(this._options);
|
1540
|
+
|
1541
|
+
return env;
|
1542
|
+
};
|
1543
|
+
|
1544
|
+
/**
|
1545
|
+
* Returns a new {@link JSONInstance} of the provided data.
|
1546
|
+
*
|
1547
|
+
* @param {JSONInstance|Any} data The value of the instance
|
1548
|
+
* @param {String} [uri] The URI of the instance. If undefined, the URI will be a randomly generated UUID.
|
1549
|
+
* @returns {JSONInstance} A new {@link JSONInstance} from the provided data
|
1550
|
+
*/
|
1551
|
+
|
1552
|
+
Environment.prototype.createInstance = function (data, uri) {
|
1553
|
+
var instance;
|
1554
|
+
uri = formatURI(uri);
|
1555
|
+
|
1556
|
+
if (data instanceof JSONInstance && (!uri || data.getURI() === uri)) {
|
1557
|
+
return data;
|
1558
|
+
}
|
1559
|
+
//else
|
1560
|
+
instance = new JSONInstance(this, data, uri);
|
1561
|
+
|
1562
|
+
return instance;
|
1563
|
+
};
|
1564
|
+
|
1565
|
+
/**
|
1566
|
+
* Creates a new {@link JSONSchema} from the provided data, and registers it with the environment.
|
1567
|
+
*
|
1568
|
+
* @param {JSONInstance|Any} data The value of the schema
|
1569
|
+
* @param {JSONSchema|Boolean} [schema] The schema to bind to the instance. If <code>undefined</code>, the environment's default schema will be used. If <code>true</code>, the instance's schema will be itself.
|
1570
|
+
* @param {String} [uri] The URI of the schema. If undefined, the URI will be a randomly generated UUID.
|
1571
|
+
* @returns {JSONSchema} A new {@link JSONSchema} from the provided data
|
1572
|
+
* @throws {InitializationError} If a schema that is not registered with the environment is referenced
|
1573
|
+
*/
|
1574
|
+
|
1575
|
+
Environment.prototype.createSchema = function (data, schema, uri) {
|
1576
|
+
var instance,
|
1577
|
+
initializer;
|
1578
|
+
uri = formatURI(uri);
|
1579
|
+
|
1580
|
+
if (data instanceof JSONSchema && (!uri || data._uri === uri) && (!schema || data._schema.equals(schema))) {
|
1581
|
+
return data;
|
1582
|
+
}
|
1583
|
+
|
1584
|
+
instance = new JSONSchema(this, data, uri, schema);
|
1585
|
+
|
1586
|
+
initializer = instance.getSchema().getValueOfProperty("initializer");
|
1587
|
+
if (typeof initializer === "function") {
|
1588
|
+
instance = initializer(instance);
|
1589
|
+
}
|
1590
|
+
|
1591
|
+
//register schema
|
1592
|
+
this._schemas[instance._uri] = instance;
|
1593
|
+
this._schemas[uri] = instance;
|
1594
|
+
|
1595
|
+
//build & cache the rest of the schema
|
1596
|
+
instance.getAttributes();
|
1597
|
+
|
1598
|
+
return instance;
|
1599
|
+
};
|
1600
|
+
|
1601
|
+
/**
|
1602
|
+
* Creates an empty schema.
|
1603
|
+
*
|
1604
|
+
* @param {Environment} env The environment of the schema
|
1605
|
+
* @returns {JSONSchema} The empty schema, who's schema is itself.
|
1606
|
+
*/
|
1607
|
+
|
1608
|
+
Environment.prototype.createEmptySchema = function () {
|
1609
|
+
var schema = JSONSchema.createEmptySchema(this);
|
1610
|
+
this._schemas[schema._uri] = schema;
|
1611
|
+
return schema;
|
1612
|
+
};
|
1613
|
+
|
1614
|
+
/**
|
1615
|
+
* Returns the schema registered with the provided URI.
|
1616
|
+
*
|
1617
|
+
* @param {String} uri The absolute URI of the required schema
|
1618
|
+
* @returns {JSONSchema|undefined} The request schema, or <code>undefined</code> if not found
|
1619
|
+
*/
|
1620
|
+
|
1621
|
+
Environment.prototype.findSchema = function (uri) {
|
1622
|
+
return this._schemas[formatURI(uri)];
|
1623
|
+
};
|
1624
|
+
|
1625
|
+
/**
|
1626
|
+
* Sets the specified environment option to the specified value.
|
1627
|
+
*
|
1628
|
+
* @param {String} name The name of the environment option to set
|
1629
|
+
* @param {Any} value The new value of the environment option
|
1630
|
+
*/
|
1631
|
+
|
1632
|
+
Environment.prototype.setOption = function (name, value) {
|
1633
|
+
this._options[name] = value;
|
1634
|
+
};
|
1635
|
+
|
1636
|
+
/**
|
1637
|
+
* Returns the specified environment option.
|
1638
|
+
*
|
1639
|
+
* @param {String} name The name of the environment option to set
|
1640
|
+
* @returns {Any} The value of the environment option
|
1641
|
+
*/
|
1642
|
+
|
1643
|
+
Environment.prototype.getOption = function (name) {
|
1644
|
+
return this._options[name];
|
1645
|
+
};
|
1646
|
+
|
1647
|
+
/**
|
1648
|
+
* Sets the default fragment delimiter of the environment.
|
1649
|
+
*
|
1650
|
+
* @deprecated Use {@link Environment#setOption} with option "defaultFragmentDelimiter"
|
1651
|
+
* @param {String} fd The fragment delimiter character
|
1652
|
+
*/
|
1653
|
+
|
1654
|
+
Environment.prototype.setDefaultFragmentDelimiter = function (fd) {
|
1655
|
+
if (typeof fd === "string" && fd.length > 0) {
|
1656
|
+
this._options["defaultFragmentDelimiter"] = fd;
|
1657
|
+
}
|
1658
|
+
};
|
1659
|
+
|
1660
|
+
/**
|
1661
|
+
* Returns the default fragment delimiter of the environment.
|
1662
|
+
*
|
1663
|
+
* @deprecated Use {@link Environment#getOption} with option "defaultFragmentDelimiter"
|
1664
|
+
* @returns {String} The fragment delimiter character
|
1665
|
+
*/
|
1666
|
+
|
1667
|
+
Environment.prototype.getDefaultFragmentDelimiter = function () {
|
1668
|
+
return this._options["defaultFragmentDelimiter"];
|
1669
|
+
};
|
1670
|
+
|
1671
|
+
/**
|
1672
|
+
* Sets the URI of the default schema for the environment.
|
1673
|
+
*
|
1674
|
+
* @deprecated Use {@link Environment#setOption} with option "defaultSchemaURI"
|
1675
|
+
* @param {String} uri The default schema URI
|
1676
|
+
*/
|
1677
|
+
|
1678
|
+
Environment.prototype.setDefaultSchemaURI = function (uri) {
|
1679
|
+
if (typeof uri === "string") {
|
1680
|
+
this._options["defaultSchemaURI"] = formatURI(uri);
|
1681
|
+
}
|
1682
|
+
};
|
1683
|
+
|
1684
|
+
/**
|
1685
|
+
* Returns the default schema of the environment.
|
1686
|
+
*
|
1687
|
+
* @returns {JSONSchema} The default schema
|
1688
|
+
*/
|
1689
|
+
|
1690
|
+
Environment.prototype.getDefaultSchema = function () {
|
1691
|
+
return this.findSchema(this._options["defaultSchemaURI"]);
|
1692
|
+
};
|
1693
|
+
|
1694
|
+
/**
|
1695
|
+
* Validates both the provided schema and the provided instance, and returns a {@link Report}.
|
1696
|
+
* If the schema fails to validate, the instance will not be validated.
|
1697
|
+
*
|
1698
|
+
* @param {JSONInstance|Any} instanceJSON The {@link JSONInstance} or JavaScript value to validate.
|
1699
|
+
* @param {JSONSchema|Any} schemaJSON The {@link JSONSchema} or JavaScript value to use in the validation. This will also be validated againt the schema's schema.
|
1700
|
+
* @returns {Report} The result of the validation
|
1701
|
+
*/
|
1702
|
+
|
1703
|
+
Environment.prototype.validate = function (instanceJSON, schemaJSON) {
|
1704
|
+
var instance,
|
1705
|
+
schema,
|
1706
|
+
schemaSchema,
|
1707
|
+
report = new Report();
|
1708
|
+
|
1709
|
+
try {
|
1710
|
+
instance = this.createInstance(instanceJSON);
|
1711
|
+
report.instance = instance;
|
1712
|
+
} catch (e) {
|
1713
|
+
report.addError(e.uri, e.schemaUri, e.attribute, e.message, e.details);
|
1714
|
+
}
|
1715
|
+
|
1716
|
+
try {
|
1717
|
+
schema = this.createSchema(schemaJSON);
|
1718
|
+
report.schema = schema;
|
1719
|
+
|
1720
|
+
schemaSchema = schema.getSchema();
|
1721
|
+
report.schemaSchema = schemaSchema;
|
1722
|
+
} catch (e) {
|
1723
|
+
report.addError(e.uri, e.schemaUri, e.attribute, e.message, e.details);
|
1724
|
+
}
|
1725
|
+
|
1726
|
+
if (schemaSchema) {
|
1727
|
+
schemaSchema.validate(schema, report);
|
1728
|
+
}
|
1729
|
+
|
1730
|
+
if (report.errors.length) {
|
1731
|
+
return report;
|
1732
|
+
}
|
1733
|
+
|
1734
|
+
return schema.validate(instance, report);
|
1735
|
+
};
|
1736
|
+
|
1737
|
+
/**
|
1738
|
+
* @private
|
1739
|
+
*/
|
1740
|
+
|
1741
|
+
Environment.prototype._checkForInvalidInstances = function (stackSize, schemaURI) {
|
1742
|
+
var result = [],
|
1743
|
+
stack = [
|
1744
|
+
[schemaURI, this._schemas[schemaURI]]
|
1745
|
+
],
|
1746
|
+
counter = 0,
|
1747
|
+
item, uri, instance, schema, properties, key;
|
1748
|
+
|
1749
|
+
while (counter++ < stackSize && stack.length) {
|
1750
|
+
item = stack.shift();
|
1751
|
+
uri = item[0];
|
1752
|
+
instance = item[1];
|
1753
|
+
|
1754
|
+
if (instance instanceof JSONSchema) {
|
1755
|
+
if (this._schemas[instance._uri] !== instance) {
|
1756
|
+
result.push("Instance " + uri + " does not match " + instance._uri);
|
1757
|
+
} else {
|
1758
|
+
//schema = instance.getSchema();
|
1759
|
+
//stack.push([uri + "/{schema}", schema]);
|
1760
|
+
|
1761
|
+
properties = instance.getAttributes();
|
1762
|
+
for (key in properties) {
|
1763
|
+
if (properties[key] !== O[key]) {
|
1764
|
+
stack.push([uri + "/" + escapeURIComponent(key), properties[key]]);
|
1765
|
+
}
|
1766
|
+
}
|
1767
|
+
}
|
1768
|
+
} else if (typeOf(instance) === "object") {
|
1769
|
+
properties = instance;
|
1770
|
+
for (key in properties) {
|
1771
|
+
if (properties.hasOwnProperty(key)) {
|
1772
|
+
stack.push([uri + "/" + escapeURIComponent(key), properties[key]]);
|
1773
|
+
}
|
1774
|
+
}
|
1775
|
+
} else if (typeOf(instance) === "array") {
|
1776
|
+
properties = instance;
|
1777
|
+
for (key = 0; key < properties.length; ++key) {
|
1778
|
+
stack.push([uri + "/" + escapeURIComponent(key), properties[key]]);
|
1779
|
+
}
|
1780
|
+
}
|
1781
|
+
}
|
1782
|
+
|
1783
|
+
return result.length ? result : counter;
|
1784
|
+
};
|
1785
|
+
|
1786
|
+
/**
|
1787
|
+
* A globaly accessible object that provides the ability to create and manage {@link Environments},
|
1788
|
+
* as well as providing utility methods.
|
1789
|
+
*
|
1790
|
+
* @namespace
|
1791
|
+
*/
|
1792
|
+
|
1793
|
+
JSV = {
|
1794
|
+
_environments : {},
|
1795
|
+
_defaultEnvironmentID : "",
|
1796
|
+
|
1797
|
+
/**
|
1798
|
+
* Returns if the provide value is an instance of {@link JSONInstance}.
|
1799
|
+
*
|
1800
|
+
* @param o The value to test
|
1801
|
+
* @returns {Boolean} If the provide value is an instance of {@link JSONInstance}
|
1802
|
+
*/
|
1803
|
+
|
1804
|
+
isJSONInstance : function (o) {
|
1805
|
+
return o instanceof JSONInstance;
|
1806
|
+
},
|
1807
|
+
|
1808
|
+
/**
|
1809
|
+
* Returns if the provide value is an instance of {@link JSONSchema}.
|
1810
|
+
*
|
1811
|
+
* @param o The value to test
|
1812
|
+
* @returns {Boolean} If the provide value is an instance of {@link JSONSchema}
|
1813
|
+
*/
|
1814
|
+
|
1815
|
+
isJSONSchema : function (o) {
|
1816
|
+
return o instanceof JSONSchema;
|
1817
|
+
},
|
1818
|
+
|
1819
|
+
/**
|
1820
|
+
* Creates and returns a new {@link Environment} that is a clone of the environment registered with the provided ID.
|
1821
|
+
* If no environment ID is provided, the default environment is cloned.
|
1822
|
+
*
|
1823
|
+
* @param {String} [id] The ID of the environment to clone. If <code>undefined</code>, the default environment ID is used.
|
1824
|
+
* @returns {Environment} A newly cloned {@link Environment}
|
1825
|
+
* @throws {Error} If there is no environment registered with the provided ID
|
1826
|
+
*/
|
1827
|
+
|
1828
|
+
createEnvironment : function (id) {
|
1829
|
+
id = id || this._defaultEnvironmentID;
|
1830
|
+
|
1831
|
+
if (!this._environments[id]) {
|
1832
|
+
throw new Error("Unknown Environment ID");
|
1833
|
+
}
|
1834
|
+
//else
|
1835
|
+
return this._environments[id].clone();
|
1836
|
+
},
|
1837
|
+
|
1838
|
+
Environment : Environment,
|
1839
|
+
|
1840
|
+
/**
|
1841
|
+
* Registers the provided {@link Environment} with the provided ID.
|
1842
|
+
*
|
1843
|
+
* @param {String} id The ID of the environment
|
1844
|
+
* @param {Environment} env The environment to register
|
1845
|
+
*/
|
1846
|
+
|
1847
|
+
registerEnvironment : function (id, env) {
|
1848
|
+
id = id || (env || 0)._id;
|
1849
|
+
if (id && !this._environments[id] && env instanceof Environment) {
|
1850
|
+
env._id = id;
|
1851
|
+
this._environments[id] = env;
|
1852
|
+
}
|
1853
|
+
},
|
1854
|
+
|
1855
|
+
/**
|
1856
|
+
* Sets which registered ID is the default environment.
|
1857
|
+
*
|
1858
|
+
* @param {String} id The ID of the registered environment that is default
|
1859
|
+
* @throws {Error} If there is no registered environment with the provided ID
|
1860
|
+
*/
|
1861
|
+
|
1862
|
+
setDefaultEnvironmentID : function (id) {
|
1863
|
+
if (typeof id === "string") {
|
1864
|
+
if (!this._environments[id]) {
|
1865
|
+
throw new Error("Unknown Environment ID");
|
1866
|
+
}
|
1867
|
+
|
1868
|
+
this._defaultEnvironmentID = id;
|
1869
|
+
}
|
1870
|
+
},
|
1871
|
+
|
1872
|
+
/**
|
1873
|
+
* Returns the ID of the default environment.
|
1874
|
+
*
|
1875
|
+
* @returns {String} The ID of the default environment
|
1876
|
+
*/
|
1877
|
+
|
1878
|
+
getDefaultEnvironmentID : function () {
|
1879
|
+
return this._defaultEnvironmentID;
|
1880
|
+
},
|
1881
|
+
|
1882
|
+
//
|
1883
|
+
// Utility Functions
|
1884
|
+
//
|
1885
|
+
|
1886
|
+
/**
|
1887
|
+
* Returns the name of the type of the provided value.
|
1888
|
+
*
|
1889
|
+
* @event //utility
|
1890
|
+
* @param {Any} o The value to determine the type of
|
1891
|
+
* @returns {String} The name of the type of the value
|
1892
|
+
*/
|
1893
|
+
typeOf : typeOf,
|
1894
|
+
|
1895
|
+
/**
|
1896
|
+
* Return a new object that inherits all of the properties of the provided object.
|
1897
|
+
*
|
1898
|
+
* @event //utility
|
1899
|
+
* @param {Object} proto The prototype of the new object
|
1900
|
+
* @returns {Object} A new object that inherits all of the properties of the provided object
|
1901
|
+
*/
|
1902
|
+
createObject : createObject,
|
1903
|
+
|
1904
|
+
/**
|
1905
|
+
* Returns a new object with each property transformed by the iterator.
|
1906
|
+
*
|
1907
|
+
* @event //utility
|
1908
|
+
* @param {Object} obj The object to transform
|
1909
|
+
* @param {Function} iterator A function that returns the new value of the provided property
|
1910
|
+
* @param {Object} [scope] The value of <code>this</code> in the iterator
|
1911
|
+
* @returns {Object} A new object with each property transformed
|
1912
|
+
*/
|
1913
|
+
mapObject : mapObject,
|
1914
|
+
|
1915
|
+
/**
|
1916
|
+
* Returns a new array with each item transformed by the iterator.
|
1917
|
+
*
|
1918
|
+
* @event //utility
|
1919
|
+
* @param {Array} arr The array to transform
|
1920
|
+
* @param {Function} iterator A function that returns the new value of the provided item
|
1921
|
+
* @param {Object} scope The value of <code>this</code> in the iterator
|
1922
|
+
* @returns {Array} A new array with each item transformed
|
1923
|
+
*/
|
1924
|
+
mapArray : mapArray,
|
1925
|
+
|
1926
|
+
/**
|
1927
|
+
* Returns a new array that only contains the items allowed by the iterator.
|
1928
|
+
*
|
1929
|
+
* @event //utility
|
1930
|
+
* @param {Array} arr The array to filter
|
1931
|
+
* @param {Function} iterator The function that returns true if the provided property should be added to the array
|
1932
|
+
* @param {Object} scope The value of <code>this</code> within the iterator
|
1933
|
+
* @returns {Array} A new array that contains the items allowed by the iterator
|
1934
|
+
*/
|
1935
|
+
filterArray : filterArray,
|
1936
|
+
|
1937
|
+
/**
|
1938
|
+
* Returns the first index in the array that the provided item is located at.
|
1939
|
+
*
|
1940
|
+
* @event //utility
|
1941
|
+
* @param {Array} arr The array to search
|
1942
|
+
* @param {Any} o The item being searched for
|
1943
|
+
* @returns {Number} The index of the item in the array, or <code>-1</code> if not found
|
1944
|
+
*/
|
1945
|
+
searchArray : searchArray,
|
1946
|
+
|
1947
|
+
/**
|
1948
|
+
* Returns an array representation of a value.
|
1949
|
+
* <ul>
|
1950
|
+
* <li>For array-like objects, the value will be casted as an Array type.</li>
|
1951
|
+
* <li>If an array is provided, the function will simply return the same array.</li>
|
1952
|
+
* <li>For a null or undefined value, the result will be an empty Array.</li>
|
1953
|
+
* <li>For all other values, the value will be the first element in a new Array. </li>
|
1954
|
+
* </ul>
|
1955
|
+
*
|
1956
|
+
* @event //utility
|
1957
|
+
* @param {Any} o The value to convert into an array
|
1958
|
+
* @returns {Array} The value as an array
|
1959
|
+
*/
|
1960
|
+
toArray : toArray,
|
1961
|
+
|
1962
|
+
/**
|
1963
|
+
* Returns an array of the names of all properties of an object.
|
1964
|
+
*
|
1965
|
+
* @event //utility
|
1966
|
+
* @param {Object|Array} o The object in question
|
1967
|
+
* @returns {Array} The names of all properties
|
1968
|
+
*/
|
1969
|
+
keys : keys,
|
1970
|
+
|
1971
|
+
/**
|
1972
|
+
* Mutates the array by pushing the provided value onto the array only if it is not already there.
|
1973
|
+
*
|
1974
|
+
* @event //utility
|
1975
|
+
* @param {Array} arr The array to modify
|
1976
|
+
* @param {Any} o The object to add to the array if it is not already there
|
1977
|
+
* @returns {Array} The provided array for chaining
|
1978
|
+
*/
|
1979
|
+
pushUnique : pushUnique,
|
1980
|
+
|
1981
|
+
/**
|
1982
|
+
* Mutates the array by removing the first item that matches the provided value in the array.
|
1983
|
+
*
|
1984
|
+
* @event //utility
|
1985
|
+
* @param {Array} arr The array to modify
|
1986
|
+
* @param {Any} o The object to remove from the array
|
1987
|
+
* @returns {Array} The provided array for chaining
|
1988
|
+
*/
|
1989
|
+
popFirst : popFirst,
|
1990
|
+
|
1991
|
+
/**
|
1992
|
+
* Creates a copy of the target object.
|
1993
|
+
* <p>
|
1994
|
+
* This method will create a new instance of the target, and then mixin the properties of the target.
|
1995
|
+
* If <code>deep</code> is <code>true</code>, then each property will be cloned before mixin.
|
1996
|
+
* </p>
|
1997
|
+
* <p><b>Warning</b>: This is not a generic clone function, as it will only properly clone objects and arrays.</p>
|
1998
|
+
*
|
1999
|
+
* @event //utility
|
2000
|
+
* @param {Any} o The value to clone
|
2001
|
+
* @param {Boolean} [deep=false] If each property should be recursively cloned
|
2002
|
+
* @returns A cloned copy of the provided value
|
2003
|
+
*/
|
2004
|
+
clone : clone,
|
2005
|
+
|
2006
|
+
/**
|
2007
|
+
* Generates a pseudo-random UUID.
|
2008
|
+
*
|
2009
|
+
* @event //utility
|
2010
|
+
* @returns {String} A new universally unique ID
|
2011
|
+
*/
|
2012
|
+
randomUUID : randomUUID,
|
2013
|
+
|
2014
|
+
/**
|
2015
|
+
* Properly escapes a URI component for embedding into a URI string.
|
2016
|
+
*
|
2017
|
+
* @event //utility
|
2018
|
+
* @param {String} str The URI component to escape
|
2019
|
+
* @returns {String} The escaped URI component
|
2020
|
+
*/
|
2021
|
+
escapeURIComponent : escapeURIComponent,
|
2022
|
+
|
2023
|
+
/**
|
2024
|
+
* Returns a URI that is formated for JSV. Currently, this only ensures that the URI ends with a hash tag (<code>#</code>).
|
2025
|
+
*
|
2026
|
+
* @event //utility
|
2027
|
+
* @param {String} uri The URI to format
|
2028
|
+
* @returns {String} The URI formatted for JSV
|
2029
|
+
*/
|
2030
|
+
formatURI : formatURI,
|
2031
|
+
|
2032
|
+
/**
|
2033
|
+
* Merges two schemas/instance together.
|
2034
|
+
*
|
2035
|
+
* @event //utility
|
2036
|
+
* @param {JSONSchema|Any} base The old value to merge
|
2037
|
+
* @param {JSONSchema|Any} extra The new value to merge
|
2038
|
+
* @param {Boolean} extension If the merge is a JSON Schema extension
|
2039
|
+
* @return {Any} The modified base value
|
2040
|
+
*/
|
2041
|
+
|
2042
|
+
inherits : inherits
|
2043
|
+
};
|
2044
|
+
|
2045
|
+
this.JSV = JSV; //set global object
|
2046
|
+
exports.JSV = JSV; //export to CommonJS
|
2047
|
+
|
2048
|
+
require("./environments"); //load default environments
|
2049
|
+
|
2050
|
+
}());
|
2051
|
+
|
2052
|
+
|
2053
|
+
|
2054
|
+
|
2055
|
+
|
2056
|
+
/**
|
2057
|
+
* json-schema-draft-03 Environment
|
2058
|
+
*
|
2059
|
+
* @fileOverview Implementation of the third revision of the JSON Schema specification draft.
|
2060
|
+
* @author <a href="mailto:gary.court@gmail.com">Gary Court</a>
|
2061
|
+
* @version 1.3
|
2062
|
+
* @see http://github.com/garycourt/JSV
|
2063
|
+
*/
|
2064
|
+
|
2065
|
+
/*
|
2066
|
+
* Copyright 2010 Gary Court. All rights reserved.
|
2067
|
+
*
|
2068
|
+
* Redistribution and use in source and binary forms, with or without modification, are
|
2069
|
+
* permitted provided that the following conditions are met:
|
2070
|
+
*
|
2071
|
+
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
2072
|
+
* conditions and the following disclaimer.
|
2073
|
+
*
|
2074
|
+
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
2075
|
+
* of conditions and the following disclaimer in the documentation and/or other materials
|
2076
|
+
* provided with the distribution.
|
2077
|
+
*
|
2078
|
+
* THIS SOFTWARE IS PROVIDED BY GARY COURT ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
2079
|
+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
2080
|
+
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR
|
2081
|
+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
2082
|
+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
2083
|
+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
2084
|
+
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
2085
|
+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
2086
|
+
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2087
|
+
*
|
2088
|
+
* The views and conclusions contained in the software and documentation are those of the
|
2089
|
+
* authors and should not be interpreted as representing official policies, either expressed
|
2090
|
+
* or implied, of Gary Court or the JSON Schema specification.
|
2091
|
+
*/
|
2092
|
+
|
2093
|
+
/*jslint white: true, sub: true, onevar: true, undef: true, eqeqeq: true, newcap: true, immed: true, indent: 4 */
|
2094
|
+
/*global require */
|
2095
|
+
|
2096
|
+
(function () {
|
2097
|
+
var O = {},
|
2098
|
+
JSV = require('./jsv').JSV,
|
2099
|
+
InitializationError,
|
2100
|
+
TYPE_VALIDATORS,
|
2101
|
+
ENVIRONMENT,
|
2102
|
+
SCHEMA_00_JSON,
|
2103
|
+
HYPERSCHEMA_00_JSON,
|
2104
|
+
LINKS_00_JSON,
|
2105
|
+
SCHEMA_00,
|
2106
|
+
HYPERSCHEMA_00,
|
2107
|
+
LINKS_00,
|
2108
|
+
SCHEMA_01_JSON,
|
2109
|
+
HYPERSCHEMA_01_JSON,
|
2110
|
+
LINKS_01_JSON,
|
2111
|
+
SCHEMA_01,
|
2112
|
+
HYPERSCHEMA_01,
|
2113
|
+
LINKS_01,
|
2114
|
+
SCHEMA_02_JSON,
|
2115
|
+
HYPERSCHEMA_02_JSON,
|
2116
|
+
LINKS_02_JSON,
|
2117
|
+
SCHEMA_02,
|
2118
|
+
HYPERSCHEMA_02,
|
2119
|
+
LINKS_02,
|
2120
|
+
SCHEMA_03_JSON,
|
2121
|
+
HYPERSCHEMA_03_JSON,
|
2122
|
+
LINKS_03_JSON,
|
2123
|
+
SCHEMA_03,
|
2124
|
+
HYPERSCHEMA_03,
|
2125
|
+
LINKS_03;
|
2126
|
+
|
2127
|
+
InitializationError = function InitializationError(instance, schema, attr, message, details) {
|
2128
|
+
Error.call(this, message);
|
2129
|
+
|
2130
|
+
this.uri = instance.getURI();
|
2131
|
+
this.schemaUri = schema.getURI();
|
2132
|
+
this.attribute = attr;
|
2133
|
+
this.message = message;
|
2134
|
+
this.description = message; //IE
|
2135
|
+
this.details = details;
|
2136
|
+
}
|
2137
|
+
InitializationError.prototype = new Error();
|
2138
|
+
InitializationError.prototype.constructor = InitializationError;
|
2139
|
+
InitializationError.prototype.name = "InitializationError";
|
2140
|
+
|
2141
|
+
TYPE_VALIDATORS = {
|
2142
|
+
"string" : function (instance, report) {
|
2143
|
+
return instance.getType() === "string";
|
2144
|
+
},
|
2145
|
+
|
2146
|
+
"number" : function (instance, report) {
|
2147
|
+
return instance.getType() === "number";
|
2148
|
+
},
|
2149
|
+
|
2150
|
+
"integer" : function (instance, report) {
|
2151
|
+
return instance.getType() === "number" && instance.getValue() % 1 === 0;
|
2152
|
+
},
|
2153
|
+
|
2154
|
+
"boolean" : function (instance, report) {
|
2155
|
+
return instance.getType() === "boolean";
|
2156
|
+
},
|
2157
|
+
|
2158
|
+
"object" : function (instance, report) {
|
2159
|
+
return instance.getType() === "object";
|
2160
|
+
},
|
2161
|
+
|
2162
|
+
"array" : function (instance, report) {
|
2163
|
+
return instance.getType() === "array";
|
2164
|
+
},
|
2165
|
+
|
2166
|
+
"null" : function (instance, report) {
|
2167
|
+
return instance.getType() === "null";
|
2168
|
+
},
|
2169
|
+
|
2170
|
+
"any" : function (instance, report) {
|
2171
|
+
return true;
|
2172
|
+
}
|
2173
|
+
};
|
2174
|
+
|
2175
|
+
ENVIRONMENT = new JSV.Environment();
|
2176
|
+
ENVIRONMENT.setOption("strict", false);
|
2177
|
+
ENVIRONMENT.setOption("validateReferences", false); //updated later
|
2178
|
+
|
2179
|
+
//
|
2180
|
+
// draft-00
|
2181
|
+
//
|
2182
|
+
|
2183
|
+
SCHEMA_00_JSON = {
|
2184
|
+
"$schema" : "http://json-schema.org/draft-00/hyper-schema#",
|
2185
|
+
"id" : "http://json-schema.org/draft-00/schema#",
|
2186
|
+
"type" : "object",
|
2187
|
+
|
2188
|
+
"properties" : {
|
2189
|
+
"type" : {
|
2190
|
+
"type" : ["string", "array"],
|
2191
|
+
"items" : {
|
2192
|
+
"type" : ["string", {"$ref" : "#"}]
|
2193
|
+
},
|
2194
|
+
"optional" : true,
|
2195
|
+
"uniqueItems" : true,
|
2196
|
+
"default" : "any",
|
2197
|
+
|
2198
|
+
"parser" : function (instance, self) {
|
2199
|
+
var parser;
|
2200
|
+
|
2201
|
+
if (instance.getType() === "string") {
|
2202
|
+
return instance.getValue();
|
2203
|
+
} else if (instance.getType() === "object") {
|
2204
|
+
return instance.getEnvironment().createSchema(
|
2205
|
+
instance,
|
2206
|
+
self.getEnvironment().findSchema(self.resolveURI("#"))
|
2207
|
+
);
|
2208
|
+
} else if (instance.getType() === "array") {
|
2209
|
+
parser = self.getValueOfProperty("parser");
|
2210
|
+
return JSV.mapArray(instance.getProperties(), function (prop) {
|
2211
|
+
return parser(prop, self);
|
2212
|
+
});
|
2213
|
+
}
|
2214
|
+
//else
|
2215
|
+
return "any";
|
2216
|
+
},
|
2217
|
+
|
2218
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2219
|
+
var requiredTypes = JSV.toArray(schema.getAttribute("type")),
|
2220
|
+
x, xl, type, subreport, typeValidators;
|
2221
|
+
|
2222
|
+
//for instances that are required to be a certain type
|
2223
|
+
if (instance.getType() !== "undefined" && requiredTypes && requiredTypes.length) {
|
2224
|
+
typeValidators = self.getValueOfProperty("typeValidators") || {};
|
2225
|
+
|
2226
|
+
//ensure that type matches for at least one of the required types
|
2227
|
+
for (x = 0, xl = requiredTypes.length; x < xl; ++x) {
|
2228
|
+
type = requiredTypes[x];
|
2229
|
+
if (JSV.isJSONSchema(type)) {
|
2230
|
+
subreport = JSV.createObject(report);
|
2231
|
+
subreport.errors = [];
|
2232
|
+
subreport.validated = JSV.clone(report.validated);
|
2233
|
+
if (type.validate(instance, subreport, parent, parentSchema, name).errors.length === 0) {
|
2234
|
+
return true; //instance matches this schema
|
2235
|
+
}
|
2236
|
+
} else {
|
2237
|
+
if (typeValidators[type] !== O[type] && typeof typeValidators[type] === "function") {
|
2238
|
+
if (typeValidators[type](instance, report)) {
|
2239
|
+
return true; //type is valid
|
2240
|
+
}
|
2241
|
+
} else {
|
2242
|
+
return true; //unknown types are assumed valid
|
2243
|
+
}
|
2244
|
+
}
|
2245
|
+
}
|
2246
|
+
|
2247
|
+
//if we get to this point, type is invalid
|
2248
|
+
report.addError(instance, schema, "type", "Instance is not a required type", requiredTypes);
|
2249
|
+
return false;
|
2250
|
+
}
|
2251
|
+
//else, anything is allowed if no type is specified
|
2252
|
+
return true;
|
2253
|
+
},
|
2254
|
+
|
2255
|
+
"typeValidators" : TYPE_VALIDATORS
|
2256
|
+
},
|
2257
|
+
|
2258
|
+
"properties" : {
|
2259
|
+
"type" : "object",
|
2260
|
+
"additionalProperties" : {"$ref" : "#"},
|
2261
|
+
"optional" : true,
|
2262
|
+
"default" : {},
|
2263
|
+
|
2264
|
+
"parser" : function (instance, self, arg) {
|
2265
|
+
var env = instance.getEnvironment(),
|
2266
|
+
selfEnv = self.getEnvironment();
|
2267
|
+
if (instance.getType() === "object") {
|
2268
|
+
if (arg) {
|
2269
|
+
return env.createSchema(instance.getProperty(arg), selfEnv.findSchema(self.resolveURI("#")));
|
2270
|
+
} else {
|
2271
|
+
return JSV.mapObject(instance.getProperties(), function (instance) {
|
2272
|
+
return env.createSchema(instance, selfEnv.findSchema(self.resolveURI("#")));
|
2273
|
+
});
|
2274
|
+
}
|
2275
|
+
}
|
2276
|
+
//else
|
2277
|
+
return {};
|
2278
|
+
},
|
2279
|
+
|
2280
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2281
|
+
var propertySchemas, key;
|
2282
|
+
//this attribute is for object type instances only
|
2283
|
+
if (instance.getType() === "object") {
|
2284
|
+
//for each property defined in the schema
|
2285
|
+
propertySchemas = schema.getAttribute("properties");
|
2286
|
+
for (key in propertySchemas) {
|
2287
|
+
if (propertySchemas[key] !== O[key] && propertySchemas[key]) {
|
2288
|
+
//ensure that instance property is valid
|
2289
|
+
propertySchemas[key].validate(instance.getProperty(key), report, instance, schema, key);
|
2290
|
+
}
|
2291
|
+
}
|
2292
|
+
}
|
2293
|
+
}
|
2294
|
+
},
|
2295
|
+
|
2296
|
+
"items" : {
|
2297
|
+
"type" : [{"$ref" : "#"}, "array"],
|
2298
|
+
"items" : {"$ref" : "#"},
|
2299
|
+
"optional" : true,
|
2300
|
+
"default" : {},
|
2301
|
+
|
2302
|
+
"parser" : function (instance, self) {
|
2303
|
+
if (instance.getType() === "object") {
|
2304
|
+
return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
|
2305
|
+
} else if (instance.getType() === "array") {
|
2306
|
+
return JSV.mapArray(instance.getProperties(), function (instance) {
|
2307
|
+
return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
|
2308
|
+
});
|
2309
|
+
}
|
2310
|
+
//else
|
2311
|
+
return instance.getEnvironment().createEmptySchema();
|
2312
|
+
},
|
2313
|
+
|
2314
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2315
|
+
var properties, items, x, xl, itemSchema, additionalProperties;
|
2316
|
+
|
2317
|
+
if (instance.getType() === "array") {
|
2318
|
+
properties = instance.getProperties();
|
2319
|
+
items = schema.getAttribute("items");
|
2320
|
+
additionalProperties = schema.getAttribute("additionalProperties");
|
2321
|
+
|
2322
|
+
if (JSV.typeOf(items) === "array") {
|
2323
|
+
for (x = 0, xl = properties.length; x < xl; ++x) {
|
2324
|
+
itemSchema = items[x] || additionalProperties;
|
2325
|
+
if (itemSchema !== false) {
|
2326
|
+
itemSchema.validate(properties[x], report, instance, schema, x);
|
2327
|
+
} else {
|
2328
|
+
report.addError(instance, schema, "additionalProperties", "Additional items are not allowed", itemSchema);
|
2329
|
+
}
|
2330
|
+
}
|
2331
|
+
} else {
|
2332
|
+
itemSchema = items || additionalProperties;
|
2333
|
+
for (x = 0, xl = properties.length; x < xl; ++x) {
|
2334
|
+
itemSchema.validate(properties[x], report, instance, schema, x);
|
2335
|
+
}
|
2336
|
+
}
|
2337
|
+
}
|
2338
|
+
}
|
2339
|
+
},
|
2340
|
+
|
2341
|
+
"optional" : {
|
2342
|
+
"type" : "boolean",
|
2343
|
+
"optional" : true,
|
2344
|
+
"default" : false,
|
2345
|
+
|
2346
|
+
"parser" : function (instance, self) {
|
2347
|
+
return !!instance.getValue();
|
2348
|
+
},
|
2349
|
+
|
2350
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2351
|
+
if (instance.getType() === "undefined" && !schema.getAttribute("optional")) {
|
2352
|
+
report.addError(instance, schema, "optional", "Property is required", false);
|
2353
|
+
}
|
2354
|
+
},
|
2355
|
+
|
2356
|
+
"validationRequired" : true
|
2357
|
+
},
|
2358
|
+
|
2359
|
+
"additionalProperties" : {
|
2360
|
+
"type" : [{"$ref" : "#"}, "boolean"],
|
2361
|
+
"optional" : true,
|
2362
|
+
"default" : {},
|
2363
|
+
|
2364
|
+
"parser" : function (instance, self) {
|
2365
|
+
if (instance.getType() === "object") {
|
2366
|
+
return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
|
2367
|
+
} else if (instance.getType() === "boolean" && instance.getValue() === false) {
|
2368
|
+
return false;
|
2369
|
+
}
|
2370
|
+
//else
|
2371
|
+
return instance.getEnvironment().createEmptySchema();
|
2372
|
+
},
|
2373
|
+
|
2374
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2375
|
+
var additionalProperties, propertySchemas, properties, key;
|
2376
|
+
//we only need to check against object types as arrays do their own checking on this property
|
2377
|
+
if (instance.getType() === "object") {
|
2378
|
+
additionalProperties = schema.getAttribute("additionalProperties");
|
2379
|
+
propertySchemas = schema.getAttribute("properties") || {};
|
2380
|
+
properties = instance.getProperties();
|
2381
|
+
for (key in properties) {
|
2382
|
+
if (properties[key] !== O[key] && properties[key] && propertySchemas[key] === O[key]) {
|
2383
|
+
if (JSV.isJSONSchema(additionalProperties)) {
|
2384
|
+
additionalProperties.validate(properties[key], report, instance, schema, key);
|
2385
|
+
} else if (additionalProperties === false) {
|
2386
|
+
report.addError(instance, schema, "additionalProperties", "Additional properties are not allowed", additionalProperties);
|
2387
|
+
}
|
2388
|
+
}
|
2389
|
+
}
|
2390
|
+
}
|
2391
|
+
}
|
2392
|
+
},
|
2393
|
+
|
2394
|
+
"requires" : {
|
2395
|
+
"type" : ["string", {"$ref" : "#"}],
|
2396
|
+
"optional" : true,
|
2397
|
+
|
2398
|
+
"parser" : function (instance, self) {
|
2399
|
+
if (instance.getType() === "string") {
|
2400
|
+
return instance.getValue();
|
2401
|
+
} else if (instance.getType() === "object") {
|
2402
|
+
return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
|
2403
|
+
}
|
2404
|
+
},
|
2405
|
+
|
2406
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2407
|
+
var requires;
|
2408
|
+
if (instance.getType() !== "undefined" && parent && parent.getType() !== "undefined") {
|
2409
|
+
requires = schema.getAttribute("requires");
|
2410
|
+
if (typeof requires === "string") {
|
2411
|
+
if (parent.getProperty(requires).getType() === "undefined") {
|
2412
|
+
report.addError(instance, schema, "requires", 'Property requires sibling property "' + requires + '"', requires);
|
2413
|
+
}
|
2414
|
+
} else if (JSV.isJSONSchema(requires)) {
|
2415
|
+
requires.validate(parent, report); //WATCH: A "requires" schema does not support the "requires" attribute
|
2416
|
+
}
|
2417
|
+
}
|
2418
|
+
}
|
2419
|
+
},
|
2420
|
+
|
2421
|
+
"minimum" : {
|
2422
|
+
"type" : "number",
|
2423
|
+
"optional" : true,
|
2424
|
+
|
2425
|
+
"parser" : function (instance, self) {
|
2426
|
+
if (instance.getType() === "number") {
|
2427
|
+
return instance.getValue();
|
2428
|
+
}
|
2429
|
+
},
|
2430
|
+
|
2431
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2432
|
+
var minimum, minimumCanEqual;
|
2433
|
+
if (instance.getType() === "number") {
|
2434
|
+
minimum = schema.getAttribute("minimum");
|
2435
|
+
minimumCanEqual = schema.getAttribute("minimumCanEqual");
|
2436
|
+
if (typeof minimum === "number" && (instance.getValue() < minimum || (minimumCanEqual === false && instance.getValue() === minimum))) {
|
2437
|
+
report.addError(instance, schema, "minimum", "Number is less then the required minimum value", minimum);
|
2438
|
+
}
|
2439
|
+
}
|
2440
|
+
}
|
2441
|
+
},
|
2442
|
+
|
2443
|
+
"maximum" : {
|
2444
|
+
"type" : "number",
|
2445
|
+
"optional" : true,
|
2446
|
+
|
2447
|
+
"parser" : function (instance, self) {
|
2448
|
+
if (instance.getType() === "number") {
|
2449
|
+
return instance.getValue();
|
2450
|
+
}
|
2451
|
+
},
|
2452
|
+
|
2453
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2454
|
+
var maximum, maximumCanEqual;
|
2455
|
+
if (instance.getType() === "number") {
|
2456
|
+
maximum = schema.getAttribute("maximum");
|
2457
|
+
maximumCanEqual = schema.getAttribute("maximumCanEqual");
|
2458
|
+
if (typeof maximum === "number" && (instance.getValue() > maximum || (maximumCanEqual === false && instance.getValue() === maximum))) {
|
2459
|
+
report.addError(instance, schema, "maximum", "Number is greater then the required maximum value", maximum);
|
2460
|
+
}
|
2461
|
+
}
|
2462
|
+
}
|
2463
|
+
},
|
2464
|
+
|
2465
|
+
"minimumCanEqual" : {
|
2466
|
+
"type" : "boolean",
|
2467
|
+
"optional" : true,
|
2468
|
+
"requires" : "minimum",
|
2469
|
+
"default" : true,
|
2470
|
+
|
2471
|
+
"parser" : function (instance, self) {
|
2472
|
+
if (instance.getType() === "boolean") {
|
2473
|
+
return instance.getValue();
|
2474
|
+
}
|
2475
|
+
//else
|
2476
|
+
return true;
|
2477
|
+
}
|
2478
|
+
},
|
2479
|
+
|
2480
|
+
"maximumCanEqual" : {
|
2481
|
+
"type" : "boolean",
|
2482
|
+
"optional" : true,
|
2483
|
+
"requires" : "maximum",
|
2484
|
+
"default" : true,
|
2485
|
+
|
2486
|
+
"parser" : function (instance, self) {
|
2487
|
+
if (instance.getType() === "boolean") {
|
2488
|
+
return instance.getValue();
|
2489
|
+
}
|
2490
|
+
//else
|
2491
|
+
return true;
|
2492
|
+
}
|
2493
|
+
},
|
2494
|
+
|
2495
|
+
"minItems" : {
|
2496
|
+
"type" : "integer",
|
2497
|
+
"optional" : true,
|
2498
|
+
"minimum" : 0,
|
2499
|
+
"default" : 0,
|
2500
|
+
|
2501
|
+
"parser" : function (instance, self) {
|
2502
|
+
if (instance.getType() === "number") {
|
2503
|
+
return instance.getValue();
|
2504
|
+
}
|
2505
|
+
//else
|
2506
|
+
return 0;
|
2507
|
+
},
|
2508
|
+
|
2509
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2510
|
+
var minItems;
|
2511
|
+
if (instance.getType() === "array") {
|
2512
|
+
minItems = schema.getAttribute("minItems");
|
2513
|
+
if (typeof minItems === "number" && instance.getProperties().length < minItems) {
|
2514
|
+
report.addError(instance, schema, "minItems", "The number of items is less then the required minimum", minItems);
|
2515
|
+
}
|
2516
|
+
}
|
2517
|
+
}
|
2518
|
+
},
|
2519
|
+
|
2520
|
+
"maxItems" : {
|
2521
|
+
"type" : "integer",
|
2522
|
+
"optional" : true,
|
2523
|
+
"minimum" : 0,
|
2524
|
+
|
2525
|
+
"parser" : function (instance, self) {
|
2526
|
+
if (instance.getType() === "number") {
|
2527
|
+
return instance.getValue();
|
2528
|
+
}
|
2529
|
+
},
|
2530
|
+
|
2531
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2532
|
+
var maxItems;
|
2533
|
+
if (instance.getType() === "array") {
|
2534
|
+
maxItems = schema.getAttribute("maxItems");
|
2535
|
+
if (typeof maxItems === "number" && instance.getProperties().length > maxItems) {
|
2536
|
+
report.addError(instance, schema, "maxItems", "The number of items is greater then the required maximum", maxItems);
|
2537
|
+
}
|
2538
|
+
}
|
2539
|
+
}
|
2540
|
+
},
|
2541
|
+
|
2542
|
+
"pattern" : {
|
2543
|
+
"type" : "string",
|
2544
|
+
"optional" : true,
|
2545
|
+
"format" : "regex",
|
2546
|
+
|
2547
|
+
"parser" : function (instance, self) {
|
2548
|
+
if (instance.getType() === "string") {
|
2549
|
+
try {
|
2550
|
+
return new RegExp(instance.getValue());
|
2551
|
+
} catch (e) {
|
2552
|
+
return e;
|
2553
|
+
}
|
2554
|
+
}
|
2555
|
+
},
|
2556
|
+
|
2557
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2558
|
+
var pattern;
|
2559
|
+
try {
|
2560
|
+
pattern = schema.getAttribute("pattern");
|
2561
|
+
if (pattern instanceof Error) {
|
2562
|
+
report.addError(schema, self, "pattern", "Invalid pattern", schema.getValueOfProperty("pattern"));
|
2563
|
+
} else if (instance.getType() === "string" && pattern && !pattern.test(instance.getValue())) {
|
2564
|
+
report.addError(instance, schema, "pattern", "String does not match pattern", pattern.toString());
|
2565
|
+
}
|
2566
|
+
} catch (e) {
|
2567
|
+
report.addError(schema, self, "pattern", "Invalid pattern", schema.getValueOfProperty("pattern"));
|
2568
|
+
}
|
2569
|
+
}
|
2570
|
+
},
|
2571
|
+
|
2572
|
+
"minLength" : {
|
2573
|
+
"type" : "integer",
|
2574
|
+
"optional" : true,
|
2575
|
+
"minimum" : 0,
|
2576
|
+
"default" : 0,
|
2577
|
+
|
2578
|
+
"parser" : function (instance, self) {
|
2579
|
+
if (instance.getType() === "number") {
|
2580
|
+
return instance.getValue();
|
2581
|
+
}
|
2582
|
+
//else
|
2583
|
+
return 0;
|
2584
|
+
},
|
2585
|
+
|
2586
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2587
|
+
var minLength;
|
2588
|
+
if (instance.getType() === "string") {
|
2589
|
+
minLength = schema.getAttribute("minLength");
|
2590
|
+
if (typeof minLength === "number" && instance.getValue().length < minLength) {
|
2591
|
+
report.addError(instance, schema, "minLength", "String is less then the required minimum length", minLength);
|
2592
|
+
}
|
2593
|
+
}
|
2594
|
+
}
|
2595
|
+
},
|
2596
|
+
|
2597
|
+
"maxLength" : {
|
2598
|
+
"type" : "integer",
|
2599
|
+
"optional" : true,
|
2600
|
+
|
2601
|
+
"parser" : function (instance, self) {
|
2602
|
+
if (instance.getType() === "number") {
|
2603
|
+
return instance.getValue();
|
2604
|
+
}
|
2605
|
+
},
|
2606
|
+
|
2607
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2608
|
+
var maxLength;
|
2609
|
+
if (instance.getType() === "string") {
|
2610
|
+
maxLength = schema.getAttribute("maxLength");
|
2611
|
+
if (typeof maxLength === "number" && instance.getValue().length > maxLength) {
|
2612
|
+
report.addError(instance, schema, "maxLength", "String is greater then the required maximum length", maxLength);
|
2613
|
+
}
|
2614
|
+
}
|
2615
|
+
}
|
2616
|
+
},
|
2617
|
+
|
2618
|
+
"enum" : {
|
2619
|
+
"type" : "array",
|
2620
|
+
"optional" : true,
|
2621
|
+
"minItems" : 1,
|
2622
|
+
"uniqueItems" : true,
|
2623
|
+
|
2624
|
+
"parser" : function (instance, self) {
|
2625
|
+
if (instance.getType() === "array") {
|
2626
|
+
return instance.getValue();
|
2627
|
+
}
|
2628
|
+
},
|
2629
|
+
|
2630
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2631
|
+
var enums, x, xl;
|
2632
|
+
if (instance.getType() !== "undefined") {
|
2633
|
+
enums = schema.getAttribute("enum");
|
2634
|
+
if (enums) {
|
2635
|
+
for (x = 0, xl = enums.length; x < xl; ++x) {
|
2636
|
+
if (instance.equals(enums[x])) {
|
2637
|
+
return true;
|
2638
|
+
}
|
2639
|
+
}
|
2640
|
+
report.addError(instance, schema, "enum", "Instance is not one of the possible values", enums);
|
2641
|
+
}
|
2642
|
+
}
|
2643
|
+
}
|
2644
|
+
},
|
2645
|
+
|
2646
|
+
"title" : {
|
2647
|
+
"type" : "string",
|
2648
|
+
"optional" : true
|
2649
|
+
},
|
2650
|
+
|
2651
|
+
"description" : {
|
2652
|
+
"type" : "string",
|
2653
|
+
"optional" : true
|
2654
|
+
},
|
2655
|
+
|
2656
|
+
"format" : {
|
2657
|
+
"type" : "string",
|
2658
|
+
"optional" : true,
|
2659
|
+
|
2660
|
+
"parser" : function (instance, self) {
|
2661
|
+
if (instance.getType() === "string") {
|
2662
|
+
return instance.getValue();
|
2663
|
+
}
|
2664
|
+
},
|
2665
|
+
|
2666
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2667
|
+
var format, formatValidators;
|
2668
|
+
if (instance.getType() === "string") {
|
2669
|
+
format = schema.getAttribute("format");
|
2670
|
+
formatValidators = self.getValueOfProperty("formatValidators");
|
2671
|
+
if (typeof format === "string" && formatValidators[format] !== O[format] && typeof formatValidators[format] === "function" && !formatValidators[format].call(this, instance, report)) {
|
2672
|
+
report.addError(instance, schema, "format", "String is not in the required format", format);
|
2673
|
+
}
|
2674
|
+
}
|
2675
|
+
},
|
2676
|
+
|
2677
|
+
// JOSHFIRE: added a couple of format validators for "uri" and "email"
|
2678
|
+
"formatValidators" : {
|
2679
|
+
"uri": function (instance, report) {
|
2680
|
+
// Regular expression from @diegoperini taken from:
|
2681
|
+
// http://mathiasbynens.be/demo/url-regex
|
2682
|
+
// ... and only slightly adjusted for use in JavaScript
|
2683
|
+
var reUri = /^(?:(?:https?):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+\-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+\-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i;
|
2684
|
+
return !!reUri.test(instance._value);
|
2685
|
+
},
|
2686
|
+
"email": function (instance, report) {
|
2687
|
+
// Regular expression taken from:
|
2688
|
+
// http://www.regular-expressions.info/email.html
|
2689
|
+
var reEmail = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
|
2690
|
+
return !!reEmail.test(instance._value);
|
2691
|
+
}
|
2692
|
+
}
|
2693
|
+
// JOSHFIRE: end of custom code
|
2694
|
+
// "formatValidators": {}
|
2695
|
+
},
|
2696
|
+
|
2697
|
+
"contentEncoding" : {
|
2698
|
+
"type" : "string",
|
2699
|
+
"optional" : true
|
2700
|
+
},
|
2701
|
+
|
2702
|
+
"default" : {
|
2703
|
+
"type" : "any",
|
2704
|
+
"optional" : true
|
2705
|
+
},
|
2706
|
+
|
2707
|
+
"maxDecimal" : {
|
2708
|
+
"type" : "integer",
|
2709
|
+
"optional" : true,
|
2710
|
+
"minimum" : 0,
|
2711
|
+
|
2712
|
+
"parser" : function (instance, self) {
|
2713
|
+
if (instance.getType() === "number") {
|
2714
|
+
return instance.getValue();
|
2715
|
+
}
|
2716
|
+
},
|
2717
|
+
|
2718
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2719
|
+
var maxDecimal, decimals;
|
2720
|
+
if (instance.getType() === "number") {
|
2721
|
+
maxDecimal = schema.getAttribute("maxDecimal");
|
2722
|
+
if (typeof maxDecimal === "number") {
|
2723
|
+
decimals = instance.getValue().toString(10).split('.')[1];
|
2724
|
+
if (decimals && decimals.length > maxDecimal) {
|
2725
|
+
report.addError(instance, schema, "maxDecimal", "The number of decimal places is greater then the allowed maximum", maxDecimal);
|
2726
|
+
}
|
2727
|
+
}
|
2728
|
+
}
|
2729
|
+
}
|
2730
|
+
},
|
2731
|
+
|
2732
|
+
"disallow" : {
|
2733
|
+
"type" : ["string", "array"],
|
2734
|
+
"items" : {"type" : "string"},
|
2735
|
+
"optional" : true,
|
2736
|
+
"uniqueItems" : true,
|
2737
|
+
|
2738
|
+
"parser" : function (instance, self) {
|
2739
|
+
if (instance.getType() === "string" || instance.getType() === "array") {
|
2740
|
+
return instance.getValue();
|
2741
|
+
}
|
2742
|
+
},
|
2743
|
+
|
2744
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2745
|
+
var disallowedTypes = JSV.toArray(schema.getAttribute("disallow")),
|
2746
|
+
x, xl, key, typeValidators, subreport;
|
2747
|
+
|
2748
|
+
//for instances that are required to be a certain type
|
2749
|
+
if (instance.getType() !== "undefined" && disallowedTypes && disallowedTypes.length) {
|
2750
|
+
typeValidators = self.getValueOfProperty("typeValidators") || {};
|
2751
|
+
|
2752
|
+
//ensure that type matches for at least one of the required types
|
2753
|
+
for (x = 0, xl = disallowedTypes.length; x < xl; ++x) {
|
2754
|
+
key = disallowedTypes[x];
|
2755
|
+
if (JSV.isJSONSchema(key)) { //this is supported draft-03 and on
|
2756
|
+
subreport = JSV.createObject(report);
|
2757
|
+
subreport.errors = [];
|
2758
|
+
subreport.validated = JSV.clone(report.validated);
|
2759
|
+
if (key.validate(instance, subreport, parent, parentSchema, name).errors.length === 0) {
|
2760
|
+
//instance matches this schema
|
2761
|
+
report.addError(instance, schema, "disallow", "Instance is a disallowed type", disallowedTypes);
|
2762
|
+
return false;
|
2763
|
+
}
|
2764
|
+
} else if (typeValidators[key] !== O[key] && typeof typeValidators[key] === "function") {
|
2765
|
+
if (typeValidators[key](instance, report)) {
|
2766
|
+
report.addError(instance, schema, "disallow", "Instance is a disallowed type", disallowedTypes);
|
2767
|
+
return false;
|
2768
|
+
}
|
2769
|
+
}
|
2770
|
+
/*
|
2771
|
+
else {
|
2772
|
+
report.addError(instance, schema, "disallow", "Instance may be a disallowed type", disallowedTypes);
|
2773
|
+
return false;
|
2774
|
+
}
|
2775
|
+
*/
|
2776
|
+
}
|
2777
|
+
|
2778
|
+
//if we get to this point, type is valid
|
2779
|
+
return true;
|
2780
|
+
}
|
2781
|
+
//else, everything is allowed if no disallowed types are specified
|
2782
|
+
return true;
|
2783
|
+
},
|
2784
|
+
|
2785
|
+
"typeValidators" : TYPE_VALIDATORS
|
2786
|
+
},
|
2787
|
+
|
2788
|
+
"extends" : {
|
2789
|
+
"type" : [{"$ref" : "#"}, "array"],
|
2790
|
+
"items" : {"$ref" : "#"},
|
2791
|
+
"optional" : true,
|
2792
|
+
"default" : {},
|
2793
|
+
|
2794
|
+
"parser" : function (instance, self) {
|
2795
|
+
if (instance.getType() === "object") {
|
2796
|
+
return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
|
2797
|
+
} else if (instance.getType() === "array") {
|
2798
|
+
return JSV.mapArray(instance.getProperties(), function (instance) {
|
2799
|
+
return instance.getEnvironment().createSchema(instance, self.getEnvironment().findSchema(self.resolveURI("#")));
|
2800
|
+
});
|
2801
|
+
}
|
2802
|
+
},
|
2803
|
+
|
2804
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2805
|
+
var extensions = schema.getAttribute("extends"), x, xl;
|
2806
|
+
if (extensions) {
|
2807
|
+
if (JSV.isJSONSchema(extensions)) {
|
2808
|
+
extensions.validate(instance, report, parent, parentSchema, name);
|
2809
|
+
} else if (JSV.typeOf(extensions) === "array") {
|
2810
|
+
for (x = 0, xl = extensions.length; x < xl; ++x) {
|
2811
|
+
extensions[x].validate(instance, report, parent, parentSchema, name);
|
2812
|
+
}
|
2813
|
+
}
|
2814
|
+
}
|
2815
|
+
}
|
2816
|
+
}
|
2817
|
+
},
|
2818
|
+
|
2819
|
+
"optional" : true,
|
2820
|
+
"default" : {},
|
2821
|
+
"fragmentResolution" : "dot-delimited",
|
2822
|
+
|
2823
|
+
"parser" : function (instance, self) {
|
2824
|
+
if (instance.getType() === "object") {
|
2825
|
+
return instance.getEnvironment().createSchema(instance, self);
|
2826
|
+
}
|
2827
|
+
},
|
2828
|
+
|
2829
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2830
|
+
var propNames = schema.getPropertyNames(),
|
2831
|
+
x, xl,
|
2832
|
+
attributeSchemas = self.getAttribute("properties"),
|
2833
|
+
strict = instance.getEnvironment().getOption("strict"),
|
2834
|
+
validator;
|
2835
|
+
|
2836
|
+
for (x in attributeSchemas) {
|
2837
|
+
if (attributeSchemas[x] !== O[x]) {
|
2838
|
+
if (attributeSchemas[x].getValueOfProperty("validationRequired")) {
|
2839
|
+
JSV.pushUnique(propNames, x);
|
2840
|
+
}
|
2841
|
+
if (strict && attributeSchemas[x].getValueOfProperty("deprecated")) {
|
2842
|
+
JSV.popFirst(propNames, x);
|
2843
|
+
}
|
2844
|
+
}
|
2845
|
+
}
|
2846
|
+
|
2847
|
+
for (x = 0, xl = propNames.length; x < xl; ++x) {
|
2848
|
+
if (attributeSchemas[propNames[x]] !== O[propNames[x]]) {
|
2849
|
+
validator = attributeSchemas[propNames[x]].getValueOfProperty("validator");
|
2850
|
+
if (typeof validator === "function") {
|
2851
|
+
validator(instance, schema, attributeSchemas[propNames[x]], report, parent, parentSchema, name);
|
2852
|
+
}
|
2853
|
+
}
|
2854
|
+
}
|
2855
|
+
}
|
2856
|
+
};
|
2857
|
+
|
2858
|
+
HYPERSCHEMA_00_JSON = {
|
2859
|
+
"$schema" : "http://json-schema.org/draft-00/hyper-schema#",
|
2860
|
+
"id" : "http://json-schema.org/draft-00/hyper-schema#",
|
2861
|
+
|
2862
|
+
"properties" : {
|
2863
|
+
"links" : {
|
2864
|
+
"type" : "array",
|
2865
|
+
"items" : {"$ref" : "links#"},
|
2866
|
+
"optional" : true,
|
2867
|
+
|
2868
|
+
"parser" : function (instance, self, arg) {
|
2869
|
+
var links,
|
2870
|
+
linkSchemaURI = self.getValueOfProperty("items")["$ref"],
|
2871
|
+
linkSchema = self.getEnvironment().findSchema(linkSchemaURI),
|
2872
|
+
linkParser = linkSchema && linkSchema.getValueOfProperty("parser"),
|
2873
|
+
selfReferenceVariable;
|
2874
|
+
arg = JSV.toArray(arg);
|
2875
|
+
|
2876
|
+
if (typeof linkParser === "function") {
|
2877
|
+
links = JSV.mapArray(instance.getProperties(), function (link) {
|
2878
|
+
return linkParser(link, linkSchema);
|
2879
|
+
});
|
2880
|
+
} else {
|
2881
|
+
links = JSV.toArray(instance.getValue());
|
2882
|
+
}
|
2883
|
+
|
2884
|
+
if (arg[0]) {
|
2885
|
+
links = JSV.filterArray(links, function (link) {
|
2886
|
+
return link["rel"] === arg[0];
|
2887
|
+
});
|
2888
|
+
}
|
2889
|
+
|
2890
|
+
if (arg[1]) {
|
2891
|
+
selfReferenceVariable = self.getValueOfProperty("selfReferenceVariable");
|
2892
|
+
links = JSV.mapArray(links, function (link) {
|
2893
|
+
var instance = arg[1],
|
2894
|
+
href = link["href"];
|
2895
|
+
href = href.replace(/\{(.+)\}/g, function (str, p1, offset, s) {
|
2896
|
+
var value;
|
2897
|
+
if (p1 === selfReferenceVariable) {
|
2898
|
+
value = instance.getValue();
|
2899
|
+
} else {
|
2900
|
+
value = instance.getValueOfProperty(p1);
|
2901
|
+
}
|
2902
|
+
return value !== undefined ? String(value) : "";
|
2903
|
+
});
|
2904
|
+
return href ? JSV.formatURI(instance.resolveURI(href)) : href;
|
2905
|
+
});
|
2906
|
+
}
|
2907
|
+
|
2908
|
+
return links;
|
2909
|
+
},
|
2910
|
+
|
2911
|
+
"selfReferenceVariable" : "-this"
|
2912
|
+
},
|
2913
|
+
|
2914
|
+
"fragmentResolution" : {
|
2915
|
+
"type" : "string",
|
2916
|
+
"optional" : true,
|
2917
|
+
"default" : "dot-delimited"
|
2918
|
+
},
|
2919
|
+
|
2920
|
+
"root" : {
|
2921
|
+
"type" : "boolean",
|
2922
|
+
"optional" : true,
|
2923
|
+
"default" : false
|
2924
|
+
},
|
2925
|
+
|
2926
|
+
"readonly" : {
|
2927
|
+
"type" : "boolean",
|
2928
|
+
"optional" : true,
|
2929
|
+
"default" : false
|
2930
|
+
},
|
2931
|
+
|
2932
|
+
"pathStart" : {
|
2933
|
+
"type" : "string",
|
2934
|
+
"optional" : true,
|
2935
|
+
"format" : "uri",
|
2936
|
+
|
2937
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
2938
|
+
var pathStart;
|
2939
|
+
if (instance.getType() !== "undefined") {
|
2940
|
+
pathStart = schema.getAttribute("pathStart");
|
2941
|
+
if (typeof pathStart === "string") {
|
2942
|
+
//TODO: Find out what pathStart is relative to
|
2943
|
+
if (instance.getURI().indexOf(pathStart) !== 0) {
|
2944
|
+
report.addError(instance, schema, "pathStart", "Instance's URI does not start with " + pathStart, pathStart);
|
2945
|
+
}
|
2946
|
+
}
|
2947
|
+
}
|
2948
|
+
}
|
2949
|
+
},
|
2950
|
+
|
2951
|
+
"mediaType" : {
|
2952
|
+
"type" : "string",
|
2953
|
+
"optional" : true,
|
2954
|
+
"format" : "media-type"
|
2955
|
+
},
|
2956
|
+
|
2957
|
+
"alternate" : {
|
2958
|
+
"type" : "array",
|
2959
|
+
"items" : {"$ref" : "#"},
|
2960
|
+
"optional" : true
|
2961
|
+
}
|
2962
|
+
},
|
2963
|
+
|
2964
|
+
"links" : [
|
2965
|
+
{
|
2966
|
+
"href" : "{$ref}",
|
2967
|
+
"rel" : "full"
|
2968
|
+
},
|
2969
|
+
|
2970
|
+
{
|
2971
|
+
"href" : "{$schema}",
|
2972
|
+
"rel" : "describedby"
|
2973
|
+
},
|
2974
|
+
|
2975
|
+
{
|
2976
|
+
"href" : "{id}",
|
2977
|
+
"rel" : "self"
|
2978
|
+
}
|
2979
|
+
],
|
2980
|
+
|
2981
|
+
"initializer" : function (instance) {
|
2982
|
+
var link, extension, extended;
|
2983
|
+
|
2984
|
+
//if there is a link to a different schema, update instance
|
2985
|
+
link = instance._schema.getLink("describedby", instance);
|
2986
|
+
if (link && instance._schema._uri !== link) {
|
2987
|
+
if (instance._env._schemas[link]) {
|
2988
|
+
instance._schema = instance._env._schemas[link];
|
2989
|
+
initializer = instance._schema.getValueOfProperty("initializer");
|
2990
|
+
if (typeof initializer === "function") {
|
2991
|
+
return initializer(instance); //this function will finish initialization
|
2992
|
+
} else {
|
2993
|
+
return instance; //no further initialization
|
2994
|
+
}
|
2995
|
+
} else if (instance._env._options["validateReferences"]) {
|
2996
|
+
throw new InitializationError(instance, instance._schema, "{link:describedby}", "Unknown schema reference", link);
|
2997
|
+
}
|
2998
|
+
}
|
2999
|
+
|
3000
|
+
//if there is a link to the full representation, replace instance
|
3001
|
+
link = instance._schema.getLink("full", instance);
|
3002
|
+
if (link && instance._uri !== link) {
|
3003
|
+
if (instance._env._schemas[link]) {
|
3004
|
+
instance = instance._env._schemas[link];
|
3005
|
+
return instance; //retrieved schemas are guaranteed to be initialized
|
3006
|
+
} else if (instance._env._options["validateReferences"]) {
|
3007
|
+
throw new InitializationError(instance, instance._schema, "{link:full}", "Unknown schema reference", link);
|
3008
|
+
}
|
3009
|
+
}
|
3010
|
+
|
3011
|
+
//extend schema
|
3012
|
+
extension = instance.getAttribute("extends");
|
3013
|
+
if (JSV.isJSONSchema(extension)) {
|
3014
|
+
extended = JSV.inherits(extension, instance, true);
|
3015
|
+
instance = instance._env.createSchema(extended, instance._schema, instance._uri);
|
3016
|
+
}
|
3017
|
+
|
3018
|
+
//if instance has a URI link to itself, update it's own URI
|
3019
|
+
link = instance._schema.getLink("self", instance);
|
3020
|
+
if (JSV.typeOf(link) === "string") {
|
3021
|
+
instance._uri = JSV.formatURI(link);
|
3022
|
+
}
|
3023
|
+
|
3024
|
+
return instance;
|
3025
|
+
}
|
3026
|
+
|
3027
|
+
//not needed as JSV.inherits does the job for us
|
3028
|
+
//"extends" : {"$ref" : "http://json-schema.org/schema#"}
|
3029
|
+
};
|
3030
|
+
|
3031
|
+
LINKS_00_JSON = {
|
3032
|
+
"$schema" : "http://json-schema.org/draft-00/hyper-schema#",
|
3033
|
+
"id" : "http://json-schema.org/draft-00/links#",
|
3034
|
+
"type" : "object",
|
3035
|
+
|
3036
|
+
"properties" : {
|
3037
|
+
"href" : {
|
3038
|
+
"type" : "string"
|
3039
|
+
},
|
3040
|
+
|
3041
|
+
"rel" : {
|
3042
|
+
"type" : "string"
|
3043
|
+
},
|
3044
|
+
|
3045
|
+
"method" : {
|
3046
|
+
"type" : "string",
|
3047
|
+
"default" : "GET",
|
3048
|
+
"optional" : true
|
3049
|
+
},
|
3050
|
+
|
3051
|
+
"enctype" : {
|
3052
|
+
"type" : "string",
|
3053
|
+
"requires" : "method",
|
3054
|
+
"optional" : true
|
3055
|
+
},
|
3056
|
+
|
3057
|
+
"properties" : {
|
3058
|
+
"type" : "object",
|
3059
|
+
"additionalProperties" : {"$ref" : "hyper-schema#"},
|
3060
|
+
"optional" : true,
|
3061
|
+
|
3062
|
+
"parser" : function (instance, self, arg) {
|
3063
|
+
var env = instance.getEnvironment(),
|
3064
|
+
selfEnv = self.getEnvironment(),
|
3065
|
+
additionalPropertiesSchemaURI = self.getValueOfProperty("additionalProperties")["$ref"];
|
3066
|
+
if (instance.getType() === "object") {
|
3067
|
+
if (arg) {
|
3068
|
+
return env.createSchema(instance.getProperty(arg), selfEnv.findSchema(self.resolveURI(additionalPropertiesSchemaURI)));
|
3069
|
+
} else {
|
3070
|
+
return JSV.mapObject(instance.getProperties(), function (instance) {
|
3071
|
+
return env.createSchema(instance, selfEnv.findSchema(self.resolveURI(additionalPropertiesSchemaURI)));
|
3072
|
+
});
|
3073
|
+
}
|
3074
|
+
}
|
3075
|
+
}
|
3076
|
+
}
|
3077
|
+
},
|
3078
|
+
|
3079
|
+
"parser" : function (instance, self) {
|
3080
|
+
var selfProperties = self.getProperty("properties");
|
3081
|
+
if (instance.getType() === "object") {
|
3082
|
+
return JSV.mapObject(instance.getProperties(), function (property, key) {
|
3083
|
+
var propertySchema = selfProperties.getProperty(key),
|
3084
|
+
parser = propertySchema && propertySchema.getValueOfProperty("parser");
|
3085
|
+
if (typeof parser === "function") {
|
3086
|
+
return parser(property, propertySchema);
|
3087
|
+
}
|
3088
|
+
//else
|
3089
|
+
return property.getValue();
|
3090
|
+
});
|
3091
|
+
}
|
3092
|
+
return instance.getValue();
|
3093
|
+
}
|
3094
|
+
};
|
3095
|
+
|
3096
|
+
ENVIRONMENT.setOption("defaultFragmentDelimiter", ".");
|
3097
|
+
ENVIRONMENT.setOption("defaultSchemaURI", "http://json-schema.org/draft-00/schema#"); //updated later
|
3098
|
+
|
3099
|
+
SCHEMA_00 = ENVIRONMENT.createSchema(SCHEMA_00_JSON, true, "http://json-schema.org/draft-00/schema#");
|
3100
|
+
HYPERSCHEMA_00 = ENVIRONMENT.createSchema(JSV.inherits(SCHEMA_00, ENVIRONMENT.createSchema(HYPERSCHEMA_00_JSON, true, "http://json-schema.org/draft-00/hyper-schema#"), true), true, "http://json-schema.org/draft-00/hyper-schema#");
|
3101
|
+
|
3102
|
+
ENVIRONMENT.setOption("defaultSchemaURI", "http://json-schema.org/draft-00/hyper-schema#");
|
3103
|
+
|
3104
|
+
LINKS_00 = ENVIRONMENT.createSchema(LINKS_00_JSON, HYPERSCHEMA_00, "http://json-schema.org/draft-00/links#");
|
3105
|
+
|
3106
|
+
//We need to reinitialize these 3 schemas as they all reference each other
|
3107
|
+
SCHEMA_00 = ENVIRONMENT.createSchema(SCHEMA_00.getValue(), HYPERSCHEMA_00, "http://json-schema.org/draft-00/schema#");
|
3108
|
+
HYPERSCHEMA_00 = ENVIRONMENT.createSchema(HYPERSCHEMA_00.getValue(), HYPERSCHEMA_00, "http://json-schema.org/draft-00/hyper-schema#");
|
3109
|
+
LINKS_00 = ENVIRONMENT.createSchema(LINKS_00.getValue(), HYPERSCHEMA_00, "http://json-schema.org/draft-00/links#");
|
3110
|
+
|
3111
|
+
//
|
3112
|
+
// draft-01
|
3113
|
+
//
|
3114
|
+
|
3115
|
+
SCHEMA_01_JSON = JSV.inherits(SCHEMA_00_JSON, {
|
3116
|
+
"$schema" : "http://json-schema.org/draft-01/hyper-schema#",
|
3117
|
+
"id" : "http://json-schema.org/draft-01/schema#"
|
3118
|
+
});
|
3119
|
+
|
3120
|
+
HYPERSCHEMA_01_JSON = JSV.inherits(HYPERSCHEMA_00_JSON, {
|
3121
|
+
"$schema" : "http://json-schema.org/draft-01/hyper-schema#",
|
3122
|
+
"id" : "http://json-schema.org/draft-01/hyper-schema#"
|
3123
|
+
});
|
3124
|
+
|
3125
|
+
LINKS_01_JSON = JSV.inherits(LINKS_00_JSON, {
|
3126
|
+
"$schema" : "http://json-schema.org/draft-01/hyper-schema#",
|
3127
|
+
"id" : "http://json-schema.org/draft-01/links#"
|
3128
|
+
});
|
3129
|
+
|
3130
|
+
ENVIRONMENT.setOption("defaultSchemaURI", "http://json-schema.org/draft-01/schema#"); //update later
|
3131
|
+
|
3132
|
+
SCHEMA_01 = ENVIRONMENT.createSchema(SCHEMA_01_JSON, true, "http://json-schema.org/draft-01/schema#");
|
3133
|
+
HYPERSCHEMA_01 = ENVIRONMENT.createSchema(JSV.inherits(SCHEMA_01, ENVIRONMENT.createSchema(HYPERSCHEMA_01_JSON, true, "http://json-schema.org/draft-01/hyper-schema#"), true), true, "http://json-schema.org/draft-01/hyper-schema#");
|
3134
|
+
|
3135
|
+
ENVIRONMENT.setOption("defaultSchemaURI", "http://json-schema.org/draft-01/hyper-schema#");
|
3136
|
+
|
3137
|
+
LINKS_01 = ENVIRONMENT.createSchema(LINKS_01_JSON, HYPERSCHEMA_01, "http://json-schema.org/draft-01/links#");
|
3138
|
+
|
3139
|
+
//We need to reinitialize these 3 schemas as they all reference each other
|
3140
|
+
SCHEMA_01 = ENVIRONMENT.createSchema(SCHEMA_01.getValue(), HYPERSCHEMA_01, "http://json-schema.org/draft-01/schema#");
|
3141
|
+
HYPERSCHEMA_01 = ENVIRONMENT.createSchema(HYPERSCHEMA_01.getValue(), HYPERSCHEMA_01, "http://json-schema.org/draft-01/hyper-schema#");
|
3142
|
+
LINKS_01 = ENVIRONMENT.createSchema(LINKS_01.getValue(), HYPERSCHEMA_01, "http://json-schema.org/draft-01/links#");
|
3143
|
+
|
3144
|
+
//
|
3145
|
+
// draft-02
|
3146
|
+
//
|
3147
|
+
|
3148
|
+
SCHEMA_02_JSON = JSV.inherits(SCHEMA_01_JSON, {
|
3149
|
+
"$schema" : "http://json-schema.org/draft-02/hyper-schema#",
|
3150
|
+
"id" : "http://json-schema.org/draft-02/schema#",
|
3151
|
+
|
3152
|
+
"properties" : {
|
3153
|
+
"uniqueItems" : {
|
3154
|
+
"type" : "boolean",
|
3155
|
+
"optional" : true,
|
3156
|
+
"default" : false,
|
3157
|
+
|
3158
|
+
"parser" : function (instance, self) {
|
3159
|
+
return !!instance.getValue();
|
3160
|
+
},
|
3161
|
+
|
3162
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
3163
|
+
var value, x, xl, y, yl;
|
3164
|
+
if (instance.getType() === "array" && schema.getAttribute("uniqueItems")) {
|
3165
|
+
value = instance.getProperties();
|
3166
|
+
for (x = 0, xl = value.length - 1; x < xl; ++x) {
|
3167
|
+
for (y = x + 1, yl = value.length; y < yl; ++y) {
|
3168
|
+
if (value[x].equals(value[y])) {
|
3169
|
+
report.addError(instance, schema, "uniqueItems", "Array can only contain unique items", { x : x, y : y });
|
3170
|
+
}
|
3171
|
+
}
|
3172
|
+
}
|
3173
|
+
}
|
3174
|
+
}
|
3175
|
+
},
|
3176
|
+
|
3177
|
+
"maxDecimal" : {
|
3178
|
+
"deprecated" : true
|
3179
|
+
},
|
3180
|
+
|
3181
|
+
"divisibleBy" : {
|
3182
|
+
"type" : "number",
|
3183
|
+
"minimum" : 0,
|
3184
|
+
"minimumCanEqual" : false,
|
3185
|
+
"optional" : true,
|
3186
|
+
|
3187
|
+
"parser" : function (instance, self) {
|
3188
|
+
if (instance.getType() === "number") {
|
3189
|
+
return instance.getValue();
|
3190
|
+
}
|
3191
|
+
},
|
3192
|
+
|
3193
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
3194
|
+
var divisor;
|
3195
|
+
if (instance.getType() === "number") {
|
3196
|
+
divisor = schema.getAttribute("divisibleBy");
|
3197
|
+
if (divisor === 0) {
|
3198
|
+
report.addError(instance, schema, "divisibleBy", "Nothing is divisible by 0", divisor);
|
3199
|
+
} else if (divisor !== 1 && ((instance.getValue() / divisor) % 1) !== 0) {
|
3200
|
+
report.addError(instance, schema, "divisibleBy", "Number is not divisible by " + divisor, divisor);
|
3201
|
+
}
|
3202
|
+
}
|
3203
|
+
}
|
3204
|
+
}
|
3205
|
+
},
|
3206
|
+
|
3207
|
+
"fragmentResolution" : "slash-delimited"
|
3208
|
+
});
|
3209
|
+
|
3210
|
+
HYPERSCHEMA_02_JSON = JSV.inherits(HYPERSCHEMA_01_JSON, {
|
3211
|
+
"id" : "http://json-schema.org/draft-02/hyper-schema#",
|
3212
|
+
|
3213
|
+
"properties" : {
|
3214
|
+
"fragmentResolution" : {
|
3215
|
+
"default" : "slash-delimited"
|
3216
|
+
}
|
3217
|
+
}
|
3218
|
+
});
|
3219
|
+
|
3220
|
+
LINKS_02_JSON = JSV.inherits(LINKS_01_JSON, {
|
3221
|
+
"$schema" : "http://json-schema.org/draft-02/hyper-schema#",
|
3222
|
+
"id" : "http://json-schema.org/draft-02/links#",
|
3223
|
+
|
3224
|
+
"properties" : {
|
3225
|
+
"targetSchema" : {
|
3226
|
+
"$ref" : "hyper-schema#",
|
3227
|
+
|
3228
|
+
//need this here because parsers are run before links are resolved
|
3229
|
+
"parser" : HYPERSCHEMA_01.getAttribute("parser")
|
3230
|
+
}
|
3231
|
+
}
|
3232
|
+
});
|
3233
|
+
|
3234
|
+
ENVIRONMENT.setOption("defaultFragmentDelimiter", "/");
|
3235
|
+
ENVIRONMENT.setOption("defaultSchemaURI", "http://json-schema.org/draft-02/schema#"); //update later
|
3236
|
+
|
3237
|
+
SCHEMA_02 = ENVIRONMENT.createSchema(SCHEMA_02_JSON, true, "http://json-schema.org/draft-02/schema#");
|
3238
|
+
HYPERSCHEMA_02 = ENVIRONMENT.createSchema(JSV.inherits(SCHEMA_02, ENVIRONMENT.createSchema(HYPERSCHEMA_02_JSON, true, "http://json-schema.org/draft-02/hyper-schema#"), true), true, "http://json-schema.org/draft-02/hyper-schema#");
|
3239
|
+
|
3240
|
+
ENVIRONMENT.setOption("defaultSchemaURI", "http://json-schema.org/draft-02/hyper-schema#");
|
3241
|
+
|
3242
|
+
LINKS_02 = ENVIRONMENT.createSchema(LINKS_02_JSON, HYPERSCHEMA_02, "http://json-schema.org/draft-02/links#");
|
3243
|
+
|
3244
|
+
//We need to reinitialize these 3 schemas as they all reference each other
|
3245
|
+
SCHEMA_02 = ENVIRONMENT.createSchema(SCHEMA_02.getValue(), HYPERSCHEMA_02, "http://json-schema.org/draft-02/schema#");
|
3246
|
+
HYPERSCHEMA_02 = ENVIRONMENT.createSchema(HYPERSCHEMA_02.getValue(), HYPERSCHEMA_02, "http://json-schema.org/draft-02/hyper-schema#");
|
3247
|
+
LINKS_02 = ENVIRONMENT.createSchema(LINKS_02.getValue(), HYPERSCHEMA_02, "http://json-schema.org/draft-02/links#");
|
3248
|
+
|
3249
|
+
//
|
3250
|
+
// draft-03
|
3251
|
+
//
|
3252
|
+
|
3253
|
+
function getMatchedPatternProperties(instance, schema, report, self) {
|
3254
|
+
var matchedProperties = {}, patternProperties, pattern, regexp, properties, key;
|
3255
|
+
|
3256
|
+
if (instance.getType() === "object") {
|
3257
|
+
patternProperties = schema.getAttribute("patternProperties");
|
3258
|
+
properties = instance.getProperties();
|
3259
|
+
for (pattern in patternProperties) {
|
3260
|
+
if (patternProperties[pattern] !== O[pattern]) {
|
3261
|
+
regexp = null;
|
3262
|
+
try {
|
3263
|
+
regexp = new RegExp(pattern);
|
3264
|
+
} catch (e) {
|
3265
|
+
if (report) {
|
3266
|
+
report.addError(schema, self, "patternProperties", "Invalid pattern", pattern);
|
3267
|
+
}
|
3268
|
+
}
|
3269
|
+
|
3270
|
+
if (regexp) {
|
3271
|
+
for (key in properties) {
|
3272
|
+
if (properties[key] !== O[key] && regexp.test(key)) {
|
3273
|
+
matchedProperties[key] = matchedProperties[key] ? JSV.pushUnique(matchedProperties[key], patternProperties[pattern]) : [ patternProperties[pattern] ];
|
3274
|
+
}
|
3275
|
+
}
|
3276
|
+
}
|
3277
|
+
}
|
3278
|
+
}
|
3279
|
+
}
|
3280
|
+
|
3281
|
+
return matchedProperties;
|
3282
|
+
}
|
3283
|
+
|
3284
|
+
SCHEMA_03_JSON = JSV.inherits(SCHEMA_02_JSON, {
|
3285
|
+
"$schema" : "http://json-schema.org/draft-03/schema#",
|
3286
|
+
"id" : "http://json-schema.org/draft-03/schema#",
|
3287
|
+
|
3288
|
+
"properties" : {
|
3289
|
+
"patternProperties" : {
|
3290
|
+
"type" : "object",
|
3291
|
+
"additionalProperties" : {"$ref" : "#"},
|
3292
|
+
"default" : {},
|
3293
|
+
|
3294
|
+
"parser" : SCHEMA_02.getValueOfProperty("properties")["properties"]["parser"],
|
3295
|
+
|
3296
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
3297
|
+
var matchedProperties, key, x;
|
3298
|
+
if (instance.getType() === "object") {
|
3299
|
+
matchedProperties = getMatchedPatternProperties(instance, schema, report, self);
|
3300
|
+
for (key in matchedProperties) {
|
3301
|
+
if (matchedProperties[key] !== O[key]) {
|
3302
|
+
x = matchedProperties[key].length;
|
3303
|
+
while (x--) {
|
3304
|
+
matchedProperties[key][x].validate(instance.getProperty(key), report, instance, schema, key);
|
3305
|
+
}
|
3306
|
+
}
|
3307
|
+
}
|
3308
|
+
}
|
3309
|
+
}
|
3310
|
+
},
|
3311
|
+
|
3312
|
+
"additionalProperties" : {
|
3313
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
3314
|
+
var additionalProperties, propertySchemas, properties, matchedProperties, key;
|
3315
|
+
if (instance.getType() === "object") {
|
3316
|
+
additionalProperties = schema.getAttribute("additionalProperties");
|
3317
|
+
propertySchemas = schema.getAttribute("properties") || {};
|
3318
|
+
properties = instance.getProperties();
|
3319
|
+
matchedProperties = getMatchedPatternProperties(instance, schema);
|
3320
|
+
for (key in properties) {
|
3321
|
+
if (properties[key] !== O[key] && properties[key] && propertySchemas[key] === O[key] && matchedProperties[key] === O[key]) {
|
3322
|
+
if (JSV.isJSONSchema(additionalProperties)) {
|
3323
|
+
additionalProperties.validate(properties[key], report, instance, schema, key);
|
3324
|
+
} else if (additionalProperties === false) {
|
3325
|
+
report.addError(instance, schema, "additionalProperties", "Additional properties are not allowed", additionalProperties);
|
3326
|
+
}
|
3327
|
+
}
|
3328
|
+
}
|
3329
|
+
}
|
3330
|
+
}
|
3331
|
+
},
|
3332
|
+
|
3333
|
+
"items" : {
|
3334
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
3335
|
+
var properties, items, x, xl, itemSchema, additionalItems;
|
3336
|
+
|
3337
|
+
if (instance.getType() === "array") {
|
3338
|
+
properties = instance.getProperties();
|
3339
|
+
items = schema.getAttribute("items");
|
3340
|
+
additionalItems = schema.getAttribute("additionalItems");
|
3341
|
+
|
3342
|
+
if (JSV.typeOf(items) === "array") {
|
3343
|
+
for (x = 0, xl = properties.length; x < xl; ++x) {
|
3344
|
+
itemSchema = items[x] || additionalItems;
|
3345
|
+
if (itemSchema !== false) {
|
3346
|
+
itemSchema.validate(properties[x], report, instance, schema, x);
|
3347
|
+
} else {
|
3348
|
+
report.addError(instance, schema, "additionalItems", "Additional items are not allowed", itemSchema);
|
3349
|
+
}
|
3350
|
+
}
|
3351
|
+
} else {
|
3352
|
+
itemSchema = items || additionalItems;
|
3353
|
+
for (x = 0, xl = properties.length; x < xl; ++x) {
|
3354
|
+
itemSchema.validate(properties[x], report, instance, schema, x);
|
3355
|
+
}
|
3356
|
+
}
|
3357
|
+
}
|
3358
|
+
}
|
3359
|
+
},
|
3360
|
+
|
3361
|
+
"additionalItems" : {
|
3362
|
+
"type" : [{"$ref" : "#"}, "boolean"],
|
3363
|
+
"default" : {},
|
3364
|
+
|
3365
|
+
"parser" : SCHEMA_02.getValueOfProperty("properties")["additionalProperties"]["parser"],
|
3366
|
+
|
3367
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
3368
|
+
var additionalItems, properties, x, xl;
|
3369
|
+
//only validate if the "items" attribute is undefined
|
3370
|
+
if (instance.getType() === "array" && schema.getProperty("items").getType() === "undefined") {
|
3371
|
+
additionalItems = schema.getAttribute("additionalItems");
|
3372
|
+
properties = instance.getProperties();
|
3373
|
+
|
3374
|
+
if (additionalItems !== false) {
|
3375
|
+
for (x = 0, xl = properties.length; x < xl; ++x) {
|
3376
|
+
additionalItems.validate(properties[x], report, instance, schema, x);
|
3377
|
+
}
|
3378
|
+
} else if (properties.length) {
|
3379
|
+
report.addError(instance, schema, "additionalItems", "Additional items are not allowed", additionalItems);
|
3380
|
+
}
|
3381
|
+
}
|
3382
|
+
}
|
3383
|
+
},
|
3384
|
+
|
3385
|
+
"optional" : {
|
3386
|
+
"validationRequired" : false,
|
3387
|
+
"deprecated" : true
|
3388
|
+
},
|
3389
|
+
|
3390
|
+
"required" : {
|
3391
|
+
"type" : "boolean",
|
3392
|
+
"default" : false,
|
3393
|
+
|
3394
|
+
"parser" : function (instance, self) {
|
3395
|
+
return !!instance.getValue();
|
3396
|
+
},
|
3397
|
+
|
3398
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
3399
|
+
if (instance.getType() === "undefined" && schema.getAttribute("required")) {
|
3400
|
+
report.addError(instance, schema, "required", "Property is required", true);
|
3401
|
+
}
|
3402
|
+
}
|
3403
|
+
},
|
3404
|
+
|
3405
|
+
"requires" : {
|
3406
|
+
"deprecated" : true
|
3407
|
+
},
|
3408
|
+
|
3409
|
+
"dependencies" : {
|
3410
|
+
"type" : "object",
|
3411
|
+
"additionalProperties" : {
|
3412
|
+
"type" : ["string", "array", {"$ref" : "#"}],
|
3413
|
+
"items" : {
|
3414
|
+
"type" : "string"
|
3415
|
+
}
|
3416
|
+
},
|
3417
|
+
"default" : {},
|
3418
|
+
|
3419
|
+
"parser" : function (instance, self, arg) {
|
3420
|
+
function parseProperty(property) {
|
3421
|
+
var type = property.getType();
|
3422
|
+
if (type === "string" || type === "array") {
|
3423
|
+
return property.getValue();
|
3424
|
+
} else if (type === "object") {
|
3425
|
+
return property.getEnvironment().createSchema(property, self.getEnvironment().findSchema(self.resolveURI("#")));
|
3426
|
+
}
|
3427
|
+
}
|
3428
|
+
|
3429
|
+
if (instance.getType() === "object") {
|
3430
|
+
if (arg) {
|
3431
|
+
return parseProperty(instance.getProperty(arg));
|
3432
|
+
} else {
|
3433
|
+
return JSV.mapObject(instance.getProperties(), parseProperty);
|
3434
|
+
}
|
3435
|
+
}
|
3436
|
+
//else
|
3437
|
+
return {};
|
3438
|
+
},
|
3439
|
+
|
3440
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
3441
|
+
var dependencies, key, dependency, type, x, xl;
|
3442
|
+
if (instance.getType() === "object") {
|
3443
|
+
dependencies = schema.getAttribute("dependencies");
|
3444
|
+
for (key in dependencies) {
|
3445
|
+
if (dependencies[key] !== O[key] && instance.getProperty(key).getType() !== "undefined") {
|
3446
|
+
dependency = dependencies[key];
|
3447
|
+
type = JSV.typeOf(dependency);
|
3448
|
+
if (type === "string") {
|
3449
|
+
if (instance.getProperty(dependency).getType() === "undefined") {
|
3450
|
+
report.addError(instance, schema, "dependencies", 'Property "' + key + '" requires sibling property "' + dependency + '"', dependencies);
|
3451
|
+
}
|
3452
|
+
} else if (type === "array") {
|
3453
|
+
for (x = 0, xl = dependency.length; x < xl; ++x) {
|
3454
|
+
if (instance.getProperty(dependency[x]).getType() === "undefined") {
|
3455
|
+
report.addError(instance, schema, "dependencies", 'Property "' + key + '" requires sibling property "' + dependency[x] + '"', dependencies);
|
3456
|
+
}
|
3457
|
+
}
|
3458
|
+
} else if (JSV.isJSONSchema(dependency)) {
|
3459
|
+
dependency.validate(instance, report);
|
3460
|
+
}
|
3461
|
+
}
|
3462
|
+
}
|
3463
|
+
}
|
3464
|
+
}
|
3465
|
+
},
|
3466
|
+
|
3467
|
+
"minimumCanEqual" : {
|
3468
|
+
"deprecated" : true
|
3469
|
+
},
|
3470
|
+
|
3471
|
+
"maximumCanEqual" : {
|
3472
|
+
"deprecated" : true
|
3473
|
+
},
|
3474
|
+
|
3475
|
+
"exclusiveMinimum" : {
|
3476
|
+
"type" : "boolean",
|
3477
|
+
"default" : false,
|
3478
|
+
|
3479
|
+
"parser" : function (instance, self) {
|
3480
|
+
return !!instance.getValue();
|
3481
|
+
}
|
3482
|
+
},
|
3483
|
+
|
3484
|
+
"exclusiveMaximum" : {
|
3485
|
+
"type" : "boolean",
|
3486
|
+
"default" : false,
|
3487
|
+
|
3488
|
+
"parser" : function (instance, self) {
|
3489
|
+
return !!instance.getValue();
|
3490
|
+
}
|
3491
|
+
},
|
3492
|
+
|
3493
|
+
"minimum" : {
|
3494
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
3495
|
+
var minimum, exclusiveMinimum;
|
3496
|
+
if (instance.getType() === "number") {
|
3497
|
+
minimum = schema.getAttribute("minimum");
|
3498
|
+
exclusiveMinimum = schema.getAttribute("exclusiveMinimum") || (!instance.getEnvironment().getOption("strict") && !schema.getAttribute("minimumCanEqual"));
|
3499
|
+
if (typeof minimum === "number" && (instance.getValue() < minimum || (exclusiveMinimum === true && instance.getValue() === minimum))) {
|
3500
|
+
report.addError(instance, schema, "minimum", "Number is less then the required minimum value", minimum);
|
3501
|
+
}
|
3502
|
+
}
|
3503
|
+
}
|
3504
|
+
},
|
3505
|
+
|
3506
|
+
"maximum" : {
|
3507
|
+
"validator" : function (instance, schema, self, report, parent, parentSchema, name) {
|
3508
|
+
var maximum, exclusiveMaximum;
|
3509
|
+
if (instance.getType() === "number") {
|
3510
|
+
maximum = schema.getAttribute("maximum");
|
3511
|
+
exclusiveMaximum = schema.getAttribute("exclusiveMaximum") || (!instance.getEnvironment().getOption("strict") && !schema.getAttribute("maximumCanEqual"));
|
3512
|
+
if (typeof maximum === "number" && (instance.getValue() > maximum || (exclusiveMaximum === true && instance.getValue() === maximum))) {
|
3513
|
+
report.addError(instance, schema, "maximum", "Number is greater then the required maximum value", maximum);
|
3514
|
+
}
|
3515
|
+
}
|
3516
|
+
}
|
3517
|
+
},
|
3518
|
+
|
3519
|
+
"contentEncoding" : {
|
3520
|
+
"deprecated" : true
|
3521
|
+
},
|
3522
|
+
|
3523
|
+
"divisibleBy" : {
|
3524
|
+
"exclusiveMinimum" : true
|
3525
|
+
},
|
3526
|
+
|
3527
|
+
"disallow" : {
|
3528
|
+
"items" : {
|
3529
|
+
"type" : ["string", {"$ref" : "#"}]
|
3530
|
+
},
|
3531
|
+
|
3532
|
+
"parser" : SCHEMA_02_JSON["properties"]["type"]["parser"]
|
3533
|
+
},
|
3534
|
+
|
3535
|
+
"id" : {
|
3536
|
+
"type" : "string",
|
3537
|
+
"format" : "uri"
|
3538
|
+
},
|
3539
|
+
|
3540
|
+
"$ref" : {
|
3541
|
+
"type" : "string",
|
3542
|
+
"format" : "uri"
|
3543
|
+
},
|
3544
|
+
|
3545
|
+
"$schema" : {
|
3546
|
+
"type" : "string",
|
3547
|
+
"format" : "uri"
|
3548
|
+
}
|
3549
|
+
},
|
3550
|
+
|
3551
|
+
"dependencies" : {
|
3552
|
+
"exclusiveMinimum" : "minimum",
|
3553
|
+
"exclusiveMaximum" : "maximum"
|
3554
|
+
},
|
3555
|
+
|
3556
|
+
"initializer" : function (instance) {
|
3557
|
+
var link, extension, extended,
|
3558
|
+
schemaLink = instance.getValueOfProperty("$schema"),
|
3559
|
+
refLink = instance.getValueOfProperty("$ref"),
|
3560
|
+
idLink = instance.getValueOfProperty("id");
|
3561
|
+
|
3562
|
+
//if there is a link to a different schema, update instance
|
3563
|
+
if (schemaLink) {
|
3564
|
+
link = instance.resolveURI(schemaLink);
|
3565
|
+
if (link && instance._schema._uri !== link) {
|
3566
|
+
if (instance._env._schemas[link]) {
|
3567
|
+
instance._schema = instance._env._schemas[link];
|
3568
|
+
initializer = instance._schema.getValueOfProperty("initializer");
|
3569
|
+
if (typeof initializer === "function") {
|
3570
|
+
return initializer(instance); //this function will finish initialization
|
3571
|
+
} else {
|
3572
|
+
return instance; //no further initialization
|
3573
|
+
}
|
3574
|
+
} else if (instance._env._options["validateReferences"]) {
|
3575
|
+
throw new InitializationError(instance, instance._schema, "$schema", "Unknown schema reference", link);
|
3576
|
+
}
|
3577
|
+
}
|
3578
|
+
}
|
3579
|
+
|
3580
|
+
//if there is a link to the full representation, replace instance
|
3581
|
+
if (refLink) {
|
3582
|
+
link = instance.resolveURI(refLink);
|
3583
|
+
if (link && instance._uri !== link) {
|
3584
|
+
if (instance._env._schemas[link]) {
|
3585
|
+
instance = instance._env._schemas[link];
|
3586
|
+
return instance; //retrieved schemas are guaranteed to be initialized
|
3587
|
+
} else if (instance._env._options["validateReferences"]) {
|
3588
|
+
throw new InitializationError(instance, instance._schema, "$ref", "Unknown schema reference", link);
|
3589
|
+
}
|
3590
|
+
}
|
3591
|
+
}
|
3592
|
+
|
3593
|
+
//extend schema
|
3594
|
+
extension = instance.getAttribute("extends");
|
3595
|
+
if (JSV.isJSONSchema(extension)) {
|
3596
|
+
extended = JSV.inherits(extension, instance, true);
|
3597
|
+
instance = instance._env.createSchema(extended, instance._schema, instance._uri);
|
3598
|
+
}
|
3599
|
+
|
3600
|
+
//if instance has a URI link to itself, update it's own URI
|
3601
|
+
if (idLink) {
|
3602
|
+
link = instance.resolveURI(idLink);
|
3603
|
+
if (JSV.typeOf(link) === "string") {
|
3604
|
+
instance._uri = JSV.formatURI(link);
|
3605
|
+
}
|
3606
|
+
}
|
3607
|
+
|
3608
|
+
return instance;
|
3609
|
+
}
|
3610
|
+
});
|
3611
|
+
|
3612
|
+
HYPERSCHEMA_03_JSON = JSV.inherits(HYPERSCHEMA_02_JSON, {
|
3613
|
+
"$schema" : "http://json-schema.org/draft-03/hyper-schema#",
|
3614
|
+
"id" : "http://json-schema.org/draft-03/hyper-schema#",
|
3615
|
+
|
3616
|
+
"properties" : {
|
3617
|
+
"links" : {
|
3618
|
+
"selfReferenceVariable" : "@"
|
3619
|
+
},
|
3620
|
+
|
3621
|
+
"root" : {
|
3622
|
+
"deprecated" : true
|
3623
|
+
},
|
3624
|
+
|
3625
|
+
"contentEncoding" : {
|
3626
|
+
"deprecated" : false //moved from core to hyper
|
3627
|
+
},
|
3628
|
+
|
3629
|
+
"alternate" : {
|
3630
|
+
"deprecated" : true
|
3631
|
+
}
|
3632
|
+
}
|
3633
|
+
});
|
3634
|
+
|
3635
|
+
LINKS_03_JSON = JSV.inherits(LINKS_02_JSON, {
|
3636
|
+
"$schema" : "http://json-schema.org/draft-03/hyper-schema#",
|
3637
|
+
"id" : "http://json-schema.org/draft-03/links#",
|
3638
|
+
|
3639
|
+
"properties" : {
|
3640
|
+
"href" : {
|
3641
|
+
"required" : true,
|
3642
|
+
"format" : "link-description-object-template"
|
3643
|
+
},
|
3644
|
+
|
3645
|
+
"rel" : {
|
3646
|
+
"required" : true
|
3647
|
+
},
|
3648
|
+
|
3649
|
+
"properties" : {
|
3650
|
+
"deprecated" : true
|
3651
|
+
},
|
3652
|
+
|
3653
|
+
"schema" : {"$ref" : "http://json-schema.org/draft-03/hyper-schema#"}
|
3654
|
+
}
|
3655
|
+
});
|
3656
|
+
|
3657
|
+
ENVIRONMENT.setOption("validateReferences", true);
|
3658
|
+
ENVIRONMENT.setOption("defaultSchemaURI", "http://json-schema.org/draft-03/schema#"); //update later
|
3659
|
+
|
3660
|
+
//prevent reference errors
|
3661
|
+
ENVIRONMENT.createSchema({}, true, "http://json-schema.org/draft-03/schema#");
|
3662
|
+
ENVIRONMENT.createSchema({}, true, "http://json-schema.org/draft-03/hyper-schema#");
|
3663
|
+
ENVIRONMENT.createSchema({}, true, "http://json-schema.org/draft-03/links#");
|
3664
|
+
|
3665
|
+
SCHEMA_03 = ENVIRONMENT.createSchema(SCHEMA_03_JSON, true, "http://json-schema.org/draft-03/schema#");
|
3666
|
+
HYPERSCHEMA_03 = ENVIRONMENT.createSchema(JSV.inherits(SCHEMA_03, ENVIRONMENT.createSchema(HYPERSCHEMA_03_JSON, true, "http://json-schema.org/draft-03/hyper-schema#"), true), true, "http://json-schema.org/draft-03/hyper-schema#");
|
3667
|
+
LINKS_03 = ENVIRONMENT.createSchema(LINKS_03_JSON, true, "http://json-schema.org/draft-03/links#");
|
3668
|
+
|
3669
|
+
ENVIRONMENT.setOption("defaultSchemaURI", "http://json-schema.org/draft-03/hyper-schema#");
|
3670
|
+
|
3671
|
+
//We need to reinitialize these schemas as they reference each other
|
3672
|
+
HYPERSCHEMA_03 = ENVIRONMENT.createSchema(HYPERSCHEMA_03.getValue(), HYPERSCHEMA_03, "http://json-schema.org/draft-03/hyper-schema#");
|
3673
|
+
|
3674
|
+
ENVIRONMENT.setOption("latestJSONSchemaSchemaURI", "http://json-schema.org/draft-03/schema#");
|
3675
|
+
ENVIRONMENT.setOption("latestJSONSchemaHyperSchemaURI", "http://json-schema.org/draft-03/hyper-schema#");
|
3676
|
+
ENVIRONMENT.setOption("latestJSONSchemaLinksURI", "http://json-schema.org/draft-03/links#");
|
3677
|
+
|
3678
|
+
//
|
3679
|
+
//Latest JSON Schema
|
3680
|
+
//
|
3681
|
+
|
3682
|
+
//Hack, but WAY faster then instantiating a new schema
|
3683
|
+
ENVIRONMENT._schemas["http://json-schema.org/schema#"] = SCHEMA_03;
|
3684
|
+
ENVIRONMENT._schemas["http://json-schema.org/hyper-schema#"] = HYPERSCHEMA_03;
|
3685
|
+
ENVIRONMENT._schemas["http://json-schema.org/links#"] = LINKS_03;
|
3686
|
+
|
3687
|
+
//
|
3688
|
+
//register environment
|
3689
|
+
//
|
3690
|
+
|
3691
|
+
JSV.registerEnvironment("json-schema-draft-03", ENVIRONMENT);
|
3692
|
+
if (!JSV.getDefaultEnvironmentID() || JSV.getDefaultEnvironmentID() === "json-schema-draft-01" || JSV.getDefaultEnvironmentID() === "json-schema-draft-02") {
|
3693
|
+
JSV.setDefaultEnvironmentID("json-schema-draft-03");
|
3694
|
+
}
|
3695
|
+
|
3696
|
+
}());
|
3697
|
+
|
3698
|
+
|
3699
|
+
global.JSONFormValidator = exports.JSV;
|
3700
|
+
})(this, false);
|