pywebexec 2.1.15__py3-none-any.whl → 2.1.17__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.
@@ -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);