| /** | 
|  * JSONSchema Validator - Validates JavaScript objects using JSON Schemas | 
|  *    (http://www.json.com/json-schema-proposal/) | 
|  * Licensed under AFL-2.1 OR BSD-3-Clause | 
| To use the validator call the validate function with an instance object and an optional schema object. | 
| If a schema is provided, it will be used to validate. If the instance object refers to a schema (self-validating), | 
| that schema will be used to validate and the schema parameter is not necessary (if both exist, | 
| both validations will occur). | 
| The validate method will return an array of validation errors. If there are no errors, then an | 
| empty list will be returned. A validation error will have two properties: | 
| "property" which indicates which property had the error | 
| "message" which indicates what the error was | 
|  */ | 
| (function (root, factory) { | 
|     if (typeof define === 'function' && define.amd) { | 
|         // AMD. Register as an anonymous module. | 
|         define([], function () { | 
|             return factory(); | 
|         }); | 
|     } else if (typeof module === 'object' && module.exports) { | 
|         // Node. Does not work with strict CommonJS, but | 
|         // only CommonJS-like environments that support module.exports, | 
|         // like Node. | 
|         module.exports = factory(); | 
|     } else { | 
|         // Browser globals | 
|         root.jsonSchema = factory(); | 
|     } | 
| }(this, function () {// setup primitive classes to be JSON Schema types | 
| var exports = validate | 
| exports.Integer = {type:"integer"}; | 
| var primitiveConstructors = { | 
|     String: String, | 
|     Boolean: Boolean, | 
|     Number: Number, | 
|     Object: Object, | 
|     Array: Array, | 
|     Date: Date | 
| } | 
| exports.validate = validate; | 
| function validate(/*Any*/instance,/*Object*/schema) { | 
|         // Summary: | 
|         //      To use the validator call JSONSchema.validate with an instance object and an optional schema object. | 
|         //         If a schema is provided, it will be used to validate. If the instance object refers to a schema (self-validating), | 
|         //         that schema will be used to validate and the schema parameter is not necessary (if both exist, | 
|         //         both validations will occur). | 
|         //         The validate method will return an object with two properties: | 
|         //             valid: A boolean indicating if the instance is valid by the schema | 
|         //             errors: An array of validation errors. If there are no errors, then an | 
|         //                     empty list will be returned. A validation error will have two properties: | 
|         //                         property: which indicates which property had the error | 
|         //                         message: which indicates what the error was | 
|         // | 
|         return validate(instance, schema, {changing: false});//, coerce: false, existingOnly: false}); | 
|     }; | 
| exports.checkPropertyChange = function(/*Any*/value,/*Object*/schema, /*String*/property) { | 
|         // Summary: | 
|         //         The checkPropertyChange method will check to see if an value can legally be in property with the given schema | 
|         //         This is slightly different than the validate method in that it will fail if the schema is readonly and it will | 
|         //         not check for self-validation, it is assumed that the passed in value is already internally valid. | 
|         //         The checkPropertyChange method will return the same object type as validate, see JSONSchema.validate for | 
|         //         information. | 
|         // | 
|         return validate(value, schema, {changing: property || "property"}); | 
|     }; | 
| var validate = exports._validate = function(/*Any*/instance,/*Object*/schema,/*Object*/options) { | 
|   | 
|     if (!options) options = {}; | 
|     var _changing = options.changing; | 
|   | 
|     function getType(schema){ | 
|         return schema.type || (primitiveConstructors[schema.name] == schema && schema.name.toLowerCase()); | 
|     } | 
|     var errors = []; | 
|     // validate a value against a property definition | 
|     function checkProp(value, schema, path,i){ | 
|   | 
|         var l; | 
|         path += path ? typeof i == 'number' ? '[' + i + ']' : typeof i == 'undefined' ? '' : '.' + i : i; | 
|         function addError(message){ | 
|             errors.push({property:path,message:message}); | 
|         } | 
|   | 
|         if((typeof schema != 'object' || schema instanceof Array) && (path || typeof schema != 'function') && !(schema && getType(schema))){ | 
|             if(typeof schema == 'function'){ | 
|                 if(!(value instanceof schema)){ | 
|                     addError("is not an instance of the class/constructor " + schema.name); | 
|                 } | 
|             }else if(schema){ | 
|                 addError("Invalid schema/property definition " + schema); | 
|             } | 
|             return null; | 
|         } | 
|         if(_changing && schema.readonly){ | 
|             addError("is a readonly field, it can not be changed"); | 
|         } | 
|         if(schema['extends']){ // if it extends another schema, it must pass that schema as well | 
|             checkProp(value,schema['extends'],path,i); | 
|         } | 
|         // validate a value against a type definition | 
|         function checkType(type,value){ | 
|             if(type){ | 
|                 if(typeof type == 'string' && type != 'any' && | 
|                         (type == 'null' ? value !== null : typeof value != type) && | 
|                         !(value instanceof Array && type == 'array') && | 
|                         !(value instanceof Date && type == 'date') && | 
|                         !(type == 'integer' && value%1===0)){ | 
|                     return [{property:path,message:value + " - " + (typeof value) + " value found, but a " + type + " is required"}]; | 
|                 } | 
|                 if(type instanceof Array){ | 
|                     var unionErrors=[]; | 
|                     for(var j = 0; j < type.length; j++){ // a union type | 
|                         if(!(unionErrors=checkType(type[j],value)).length){ | 
|                             break; | 
|                         } | 
|                     } | 
|                     if(unionErrors.length){ | 
|                         return unionErrors; | 
|                     } | 
|                 }else if(typeof type == 'object'){ | 
|                     var priorErrors = errors; | 
|                     errors = []; | 
|                     checkProp(value,type,path); | 
|                     var theseErrors = errors; | 
|                     errors = priorErrors; | 
|                     return theseErrors; | 
|                 } | 
|             } | 
|             return []; | 
|         } | 
|         if(value === undefined){ | 
|             if(schema.required){ | 
|                 addError("is missing and it is required"); | 
|             } | 
|         }else{ | 
|             errors = errors.concat(checkType(getType(schema),value)); | 
|             if(schema.disallow && !checkType(schema.disallow,value).length){ | 
|                 addError(" disallowed value was matched"); | 
|             } | 
|             if(value !== null){ | 
|                 if(value instanceof Array){ | 
|                     if(schema.items){ | 
|                         var itemsIsArray = schema.items instanceof Array; | 
|                         var propDef = schema.items; | 
|                         for (i = 0, l = value.length; i < l; i += 1) { | 
|                             if (itemsIsArray) | 
|                                 propDef = schema.items[i]; | 
|                             if (options.coerce) | 
|                                 value[i] = options.coerce(value[i], propDef); | 
|                             errors.concat(checkProp(value[i],propDef,path,i)); | 
|                         } | 
|                     } | 
|                     if(schema.minItems && value.length < schema.minItems){ | 
|                         addError("There must be a minimum of " + schema.minItems + " in the array"); | 
|                     } | 
|                     if(schema.maxItems && value.length > schema.maxItems){ | 
|                         addError("There must be a maximum of " + schema.maxItems + " in the array"); | 
|                     } | 
|                 }else if(schema.properties || schema.additionalProperties){ | 
|                     errors.concat(checkObj(value, schema.properties, path, schema.additionalProperties)); | 
|                 } | 
|                 if(schema.pattern && typeof value == 'string' && !value.match(schema.pattern)){ | 
|                     addError("does not match the regex pattern " + schema.pattern); | 
|                 } | 
|                 if(schema.maxLength && typeof value == 'string' && value.length > schema.maxLength){ | 
|                     addError("may only be " + schema.maxLength + " characters long"); | 
|                 } | 
|                 if(schema.minLength && typeof value == 'string' && value.length < schema.minLength){ | 
|                     addError("must be at least " + schema.minLength + " characters long"); | 
|                 } | 
|                 if(typeof schema.minimum !== 'undefined' && typeof value == typeof schema.minimum && | 
|                         schema.minimum > value){ | 
|                     addError("must have a minimum value of " + schema.minimum); | 
|                 } | 
|                 if(typeof schema.maximum !== 'undefined' && typeof value == typeof schema.maximum && | 
|                         schema.maximum < value){ | 
|                     addError("must have a maximum value of " + schema.maximum); | 
|                 } | 
|                 if(schema['enum']){ | 
|                     var enumer = schema['enum']; | 
|                     l = enumer.length; | 
|                     var found; | 
|                     for(var j = 0; j < l; j++){ | 
|                         if(enumer[j]===value){ | 
|                             found=1; | 
|                             break; | 
|                         } | 
|                     } | 
|                     if(!found){ | 
|                         addError("does not have a value in the enumeration " + enumer.join(", ")); | 
|                     } | 
|                 } | 
|                 if(typeof schema.maxDecimal == 'number' && | 
|                     (value.toString().match(new RegExp("\\.[0-9]{" + (schema.maxDecimal + 1) + ",}")))){ | 
|                     addError("may only have " + schema.maxDecimal + " digits of decimal places"); | 
|                 } | 
|             } | 
|         } | 
|         return null; | 
|     } | 
|     // validate an object against a schema | 
|     function checkObj(instance,objTypeDef,path,additionalProp){ | 
|   | 
|         if(typeof objTypeDef =='object'){ | 
|             if(typeof instance != 'object' || instance instanceof Array){ | 
|                 errors.push({property:path,message:"an object is required"}); | 
|             } | 
|              | 
|             for(var i in objTypeDef){  | 
|                 if(objTypeDef.hasOwnProperty(i) && i != '__proto__' && i != 'constructor'){ | 
|                     var value = instance.hasOwnProperty(i) ? instance[i] : undefined; | 
|                     // skip _not_ specified properties | 
|                     if (value === undefined && options.existingOnly) continue; | 
|                     var propDef = objTypeDef[i]; | 
|                     // set default | 
|                     if(value === undefined && propDef["default"]){ | 
|                         value = instance[i] = propDef["default"]; | 
|                     } | 
|                     if(options.coerce && i in instance){ | 
|                         value = instance[i] = options.coerce(value, propDef); | 
|                     } | 
|                     checkProp(value,propDef,path,i); | 
|                 } | 
|             } | 
|         } | 
|         for(i in instance){ | 
|             if(instance.hasOwnProperty(i) && !(i.charAt(0) == '_' && i.charAt(1) == '_') && objTypeDef && !objTypeDef[i] && additionalProp===false){ | 
|                 if (options.filter) { | 
|                     delete instance[i]; | 
|                     continue; | 
|                 } else { | 
|                     errors.push({property:path,message:"The property " + i + | 
|                         " is not defined in the schema and the schema does not allow additional properties"}); | 
|                 } | 
|             } | 
|             var requires = objTypeDef && objTypeDef[i] && objTypeDef[i].requires; | 
|             if(requires && !(requires in instance)){ | 
|                 errors.push({property:path,message:"the presence of the property " + i + " requires that " + requires + " also be present"}); | 
|             } | 
|             value = instance[i]; | 
|             if(additionalProp && (!(objTypeDef && typeof objTypeDef == 'object') || !(i in objTypeDef))){ | 
|                 if(options.coerce){ | 
|                     value = instance[i] = options.coerce(value, additionalProp); | 
|                 } | 
|                 checkProp(value,additionalProp,path,i); | 
|             } | 
|             if(!_changing && value && value.$schema){ | 
|                 errors = errors.concat(checkProp(value,value.$schema,path,i)); | 
|             } | 
|         } | 
|         return errors; | 
|     } | 
|     if(schema){ | 
|         checkProp(instance,schema,'',_changing || ''); | 
|     } | 
|     if(!_changing && instance && instance.$schema){ | 
|         checkProp(instance,instance.$schema,'',''); | 
|     } | 
|     return {valid:!errors.length,errors:errors}; | 
| }; | 
| exports.mustBeValid = function(result){ | 
|     //    summary: | 
|     //        This checks to ensure that the result is valid and will throw an appropriate error message if it is not | 
|     // result: the result returned from checkPropertyChange or validate | 
|     if(!result.valid){ | 
|         throw new TypeError(result.errors.map(function(error){return "for property " + error.property + ': ' + error.message;}).join(", \n")); | 
|     } | 
| } | 
|   | 
| return exports; | 
| })); |