diff options
Diffstat (limited to 'js/dojo/dojox/json/schema.js')
| -rw-r--r-- | js/dojo/dojox/json/schema.js | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/js/dojo/dojox/json/schema.js b/js/dojo/dojox/json/schema.js new file mode 100644 index 0000000..6659956 --- /dev/null +++ b/js/dojo/dojox/json/schema.js @@ -0,0 +1,223 @@ +//>>built +define("dojox/json/schema", ["dojo/_base/kernel", "dojox", "dojo/_base/array"], function(dojo, dojox){ + +dojo.getObject("json.schema", true, dojox); + + +dojox.json.schema.validate = function(/*Any*/instance,/*Object*/schema){ + // summary: + // To use the validator call this 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). + // instance: + // The instance value/object to validate + // schema: + // The schema to use to validate + // description: + // 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 this._validate(instance,schema,false); +}; +dojox.json.schema.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. + // value: + // The new instance value/object to check + // schema: + // The schema to use to validate + // return: + // see dojox.validate.jsonSchema.validate + // + return this._validate(value,schema, property || "property"); +}; +dojox.json.schema.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(dojo.map(result.errors,function(error){return "for property " + error.property + ': ' + error.message;}).join(", ")); + } +} +dojox.json.schema._validate = function(/*Any*/instance,/*Object*/schema,/*Boolean*/ _changing){ + + 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')){ + if(typeof schema == 'function'){ + if(!(Object(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') && + !(type == 'integer' && value%1===0)){ + return [{property:path,message:(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.optional){ + addError("is missing and it is not optional"); + } + }else{ + errors = errors.concat(checkType(schema.type,value)); + if(schema.disallow && !checkType(schema.disallow,value).length){ + addError(" disallowed value was matched"); + } + if(value !== null){ + if(value instanceof Array){ + if(schema.items){ + if(schema.items instanceof Array){ + for(i=0,l=value.length; i<l; i++){ + errors.concat(checkProp(value[i],schema.items[i],path,i)); + } + }else{ + for(i=0,l=value.length; i<l; i++){ + errors.concat(checkProp(value[i],schema.items,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){ + 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.charAt(0) == '_' && i.charAt(1) == '_')){ + var value = instance[i]; + var propDef = objTypeDef[i]; + checkProp(value,propDef,path,i); + } + } + } + for(i in instance){ + if(instance.hasOwnProperty(i) && !(i.charAt(0) == '_' && i.charAt(1) == '_') && objTypeDef && !objTypeDef[i] && additionalProp===false){ + errors.push({property:path,message:(typeof value) + "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(objTypeDef && typeof objTypeDef == 'object' && !(i in objTypeDef)){ + 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}; +}; + +return dojox.json.schema; +}); |
