summaryrefslogtreecommitdiff
path: root/js/dojo-1.7.2/dojox/json
diff options
context:
space:
mode:
Diffstat (limited to 'js/dojo-1.7.2/dojox/json')
-rw-r--r--js/dojo-1.7.2/dojox/json/README42
-rw-r--r--js/dojo-1.7.2/dojox/json/query.js262
-rw-r--r--js/dojo-1.7.2/dojox/json/ref.js360
-rw-r--r--js/dojo-1.7.2/dojox/json/schema.js223
4 files changed, 887 insertions, 0 deletions
diff --git a/js/dojo-1.7.2/dojox/json/README b/js/dojo-1.7.2/dojox/json/README
new file mode 100644
index 0000000..b80d139
--- /dev/null
+++ b/js/dojo-1.7.2/dojox/json/README
@@ -0,0 +1,42 @@
+-------------------------------------------------------------------------------
+DojoX JSON Modules
+-------------------------------------------------------------------------------
+Version 0.1
+Release date: 07/06/2008
+-------------------------------------------------------------------------------
+Project state:
+beta
+-------------------------------------------------------------------------------
+Credits
+ Kris Zyp (kris@sitepen.com)
+-------------------------------------------------------------------------------
+Project description
+JSONQuery (dojox.json.query) - A comprehensive object data query tool
+JSON Schema (dojox.json.schema) - An object validation tool based on JSON Schema
+JSON Referencing (dojox.json.ref) - JSON Referencing capable serializer and
+deserializer.
+
+-------------------------------------------------------------------------------
+Dependencies:
+
+dojox.json.ref uses dojo.date.stamp
+-------------------------------------------------------------------------------
+Documentation
+See the Dojo API tool (http://dojotoolkit.org/api)
+-------------------------------------------------------------------------------
+Installation instructions
+
+Grab the following from the Dojo SVN Repository:
+http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/json/*
+
+Install into the following directory structure:
+/dojox/json/
+
+...which should be at the same level as your Dojo checkout.
+
+/dojox/json/*
+
+Require in the dojox.data stores you wish to use.
+-------------------------------------------------------------------------------
+Additional Notes
+
diff --git a/js/dojo-1.7.2/dojox/json/query.js b/js/dojo-1.7.2/dojox/json/query.js
new file mode 100644
index 0000000..0f4c914
--- /dev/null
+++ b/js/dojo-1.7.2/dojox/json/query.js
@@ -0,0 +1,262 @@
+//>>built
+define("dojox/json/query", ["dojo/_base/kernel", "dojox", "dojo/_base/array"], function(dojo, dojox){
+
+ dojo.getObject("json", true, dojox);
+
+ dojox.json._slice = function(obj,start,end,step){
+ // handles slice operations: [3:6:2]
+ var len=obj.length,results = [];
+ end = end || len;
+ start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
+ end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end);
+ for(var i=start; i<end; i+=step){
+ results.push(obj[i]);
+ }
+ return results;
+ }
+ dojox.json._find = function e(obj,name){
+ // handles ..name, .*, [*], [val1,val2], [val]
+ // name can be a property to search for, undefined for full recursive, or an array for picking by index
+ var results = [];
+ function walk(obj){
+ if(name){
+ if(name===true && !(obj instanceof Array)){
+ //recursive object search
+ results.push(obj);
+ }else if(obj[name]){
+ // found the name, add to our results
+ results.push(obj[name]);
+ }
+ }
+ for(var i in obj){
+ var val = obj[i];
+ if(!name){
+ // if we don't have a name we are just getting all the properties values (.* or [*])
+ results.push(val);
+ }else if(val && typeof val == 'object'){
+
+ walk(val);
+ }
+ }
+ }
+ if(name instanceof Array){
+ // this is called when multiple items are in the brackets: [3,4,5]
+ if(name.length==1){
+ // this can happen as a result of the parser becoming confused about commas
+ // in the brackets like [@.func(4,2)]. Fixing the parser would require recursive
+ // analsys, very expensive, but this fixes the problem nicely.
+ return obj[name[0]];
+ }
+ for(var i = 0; i < name.length; i++){
+ results.push(obj[name[i]]);
+ }
+ }else{
+ // otherwise we expanding
+ walk(obj);
+ }
+ return results;
+ }
+
+ dojox.json._distinctFilter = function(array, callback){
+ // does the filter with removal of duplicates in O(n)
+ var outArr = [];
+ var primitives = {};
+ for(var i=0,l=array.length; i<l; ++i){
+ var value = array[i];
+ if(callback(value, i, array)){
+ if((typeof value == 'object') && value){
+ // with objects we prevent duplicates with a marker property
+ if(!value.__included){
+ value.__included = true;
+ outArr.push(value);
+ }
+ }else if(!primitives[value + typeof value]){
+ // with primitives we prevent duplicates by putting it in a map
+ primitives[value + typeof value] = true;
+ outArr.push(value);
+ }
+ }
+ }
+ for(i=0,l=outArr.length; i<l; ++i){
+ // cleanup the marker properties
+ if(outArr[i]){
+ delete outArr[i].__included;
+ }
+ }
+ return outArr;
+ }
+ return dojox.json.query = function(/*String*/query,/*Object?*/obj){
+ // summary:
+ // Performs a JSONQuery on the provided object and returns the results.
+ // If no object is provided (just a query), it returns a "compiled" function that evaluates objects
+ // according to the provided query.
+ // query:
+ // Query string
+ // obj:
+ // Target of the JSONQuery
+ //
+ // description:
+ // JSONQuery provides a comprehensive set of data querying tools including filtering,
+ // recursive search, sorting, mapping, range selection, and powerful expressions with
+ // wildcard string comparisons and various operators. JSONQuery generally supersets
+ // JSONPath and provides syntax that matches and behaves like JavaScript where
+ // possible.
+ //
+ // JSONQuery evaluations begin with the provided object, which can referenced with
+ // $. From
+ // the starting object, various operators can be successively applied, each operating
+ // on the result of the last operation.
+ //
+ // Supported Operators:
+ // --------------------
+ // * .property - This will return the provided property of the object, behaving exactly
+ // like JavaScript.
+ // * [expression] - This returns the property name/index defined by the evaluation of
+ // the provided expression, behaving exactly like JavaScript.
+ // * [?expression] - This will perform a filter operation on an array, returning all the
+ // items in an array that match the provided expression. This operator does not
+ // need to be in brackets, you can simply use ?expression, but since it does not
+ // have any containment, no operators can be used afterwards when used
+ // without brackets.
+ // * [^?expression] - This will perform a distinct filter operation on an array. This behaves
+ // as [?expression] except that it will remove any duplicate values/objects from the
+ // result set.
+ // * [/expression], [\expression], [/expression, /expression] - This performs a sort
+ // operation on an array, with sort based on the provide expression. Multiple comma delimited sort
+ // expressions can be provided for multiple sort orders (first being highest priority). /
+ // indicates ascending order and \ indicates descending order
+ // * [=expression] - This performs a map operation on an array, creating a new array
+ // with each item being the evaluation of the expression for each item in the source array.
+ // * [start:end:step] - This performs an array slice/range operation, returning the elements
+ // from the optional start index to the optional end index, stepping by the optional step number.
+ // * [expr,expr] - This a union operator, returning an array of all the property/index values from
+ // the evaluation of the comma delimited expressions.
+ // * .* or [*] - This returns the values of all the properties of the current object.
+ // * $ - This is the root object, If a JSONQuery expression does not being with a $,
+ // it will be auto-inserted at the beginning.
+ // * @ - This is the current object in filter, sort, and map expressions. This is generally
+ // not necessary, names are auto-converted to property references of the current object
+ // in expressions.
+ // * ..property - Performs a recursive search for the given property name, returning
+ // an array of all values with such a property name in the current object and any subobjects
+ // * expr = expr - Performs a comparison (like JS's ==). When comparing to
+ // a string, the comparison string may contain wildcards * (matches any number of
+ // characters) and ? (matches any single character).
+ // * expr ~ expr - Performs a string comparison with case insensitivity.
+ // * ..[?expression] - This will perform a deep search filter operation on all the objects and
+ // subobjects of the current data. Rather than only searching an array, this will search
+ // property values, arrays, and their children.
+ // * $1,$2,$3, etc. - These are references to extra parameters passed to the query
+ // function or the evaluator function.
+ // * +, -, /, *, &, |, %, (, ), <, >, <=, >=, != - These operators behave just as they do
+ // in JavaScript.
+ //
+ //
+ //
+ // | dojox.json.query(queryString,object)
+ // and
+ // | dojox.json.query(queryString)(object)
+ // always return identical results. The first one immediately evaluates, the second one returns a
+ // function that then evaluates the object.
+ //
+ // example:
+ // | dojox.json.query("foo",{foo:"bar"})
+ // This will return "bar".
+ //
+ // example:
+ // | evaluator = dojox.json.query("?foo='bar'&rating>3");
+ // This creates a function that finds all the objects in an array with a property
+ // foo that is equals to "bar" and with a rating property with a value greater
+ // than 3.
+ // | evaluator([{foo:"bar",rating:4},{foo:"baz",rating:2}])
+ // This returns:
+ // | {foo:"bar",rating:4}
+ //
+ // example:
+ // | evaluator = dojox.json.query("$[?price<15.00][\rating][0:10]");
+ // This finds objects in array with a price less than 15.00 and sorts then
+ // by rating, highest rated first, and returns the first ten items in from this
+ // filtered and sorted list.
+ var depth = 0;
+ var str = [];
+ query = query.replace(/"(\\.|[^"\\])*"|'(\\.|[^'\\])*'|[\[\]]/g,function(t){
+ depth += t == '[' ? 1 : t == ']' ? -1 : 0; // keep track of bracket depth
+ return (t == ']' && depth > 0) ? '`]' : // we mark all the inner brackets as skippable
+ (t.charAt(0) == '"' || t.charAt(0) == "'") ? "`" + (str.push(t) - 1) :// and replace all the strings
+ t;
+ });
+ var prefix = '';
+ function call(name){
+ // creates a function call and puts the expression so far in a parameter for a call
+ prefix = name + "(" + prefix;
+ }
+ function makeRegex(t,a,b,c,d,e,f,g){
+ // creates a regular expression matcher for when wildcards and ignore case is used
+ return str[g].match(/[\*\?]/) || f == '~' ?
+ "/^" + str[g].substring(1,str[g].length-1).replace(/\\([btnfr\\"'])|([^\w\*\?])/g,"\\$1$2").replace(/([\*\?])/g,"[\\w\\W]$1") + (f == '~' ? '$/i' : '$/') + ".test(" + a + ")" :
+ t;
+ }
+ query.replace(/(\]|\)|push|pop|shift|splice|sort|reverse)\s*\(/,function(){
+ throw new Error("Unsafe function call");
+ });
+
+ query = query.replace(/([^<>=]=)([^=])/g,"$1=$2"). // change the equals to comparisons except operators ==, <=, >=
+ replace(/@|(\.\s*)?[a-zA-Z\$_]+(\s*:)?/g,function(t){
+ return t.charAt(0) == '.' ? t : // leave .prop alone
+ t == '@' ? "$obj" :// the reference to the current object
+ (t.match(/:|^(\$|Math|true|false|null)$/) ? "" : "$obj.") + t; // plain names should be properties of root... unless they are a label in object initializer
+ }).
+ replace(/\.?\.?\[(`\]|[^\]])*\]|\?.*|\.\.([\w\$_]+)|\.\*/g,function(t,a,b){
+ var oper = t.match(/^\.?\.?(\[\s*\^?\?|\^?\?|\[\s*==)(.*?)\]?$/); // [?expr] and ?expr and [=expr and =expr
+ if(oper){
+ var prefix = '';
+ if(t.match(/^\./)){
+ // recursive object search
+ call("dojox.json._find");
+ prefix = ",true)";
+ }
+ call(oper[1].match(/\=/) ? "dojo.map" : oper[1].match(/\^/) ? "dojox.json._distinctFilter" : "dojo.filter");
+ return prefix + ",function($obj){return " + oper[2] + "})";
+ }
+ oper = t.match(/^\[\s*([\/\\].*)\]/); // [/sortexpr,\sortexpr]
+ if(oper){
+ // make a copy of the array and then sort it using the sorting expression
+ return ".concat().sort(function(a,b){" + oper[1].replace(/\s*,?\s*([\/\\])\s*([^,\\\/]+)/g,function(t,a,b){
+ return "var av= " + b.replace(/\$obj/,"a") + ",bv= " + b.replace(/\$obj/,"b") + // FIXME: Should check to make sure the $obj token isn't followed by characters
+ ";if(av>bv||bv==null){return " + (a== "/" ? 1 : -1) +";}\n" +
+ "if(bv>av||av==null){return " + (a== "/" ? -1 : 1) +";}\n";
+ }) + "return 0;})";
+ }
+ oper = t.match(/^\[(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)\]/); // slice [0:3]
+ if(oper){
+ call("dojox.json._slice");
+ return "," + (oper[1] || 0) + "," + (oper[2] || 0) + "," + (oper[3] || 1) + ")";
+ }
+ if(t.match(/^\.\.|\.\*|\[\s*\*\s*\]|,/)){ // ..prop and [*]
+ call("dojox.json._find");
+ return (t.charAt(1) == '.' ?
+ ",'" + b + "'" : // ..prop
+ t.match(/,/) ?
+ "," + t : // [prop1,prop2]
+ "") + ")"; // [*]
+ }
+ return t;
+ }).
+ replace(/(\$obj\s*((\.\s*[\w_$]+\s*)|(\[\s*`([0-9]+)\s*`\]))*)(==|~)\s*`([0-9]+)/g,makeRegex). // create regex matching
+ replace(/`([0-9]+)\s*(==|~)\s*(\$obj\s*((\.\s*[\w_$]+)|(\[\s*`([0-9]+)\s*`\]))*)/g,function(t,a,b,c,d,e,f,g){ // and do it for reverse =
+ return makeRegex(t,c,d,e,f,g,b,a);
+ });
+ query = prefix + (query.charAt(0) == '$' ? "" : "$") + query.replace(/`([0-9]+|\])/g,function(t,a){
+ //restore the strings
+ return a == ']' ? ']' : str[a];
+ });
+ // create a function within this scope (so it can use expand and slice)
+
+ var executor = eval("1&&function($,$1,$2,$3,$4,$5,$6,$7,$8,$9){var $obj=$;return " + query + "}");
+ for(var i = 0;i<arguments.length-1;i++){
+ arguments[i] = arguments[i+1];
+ }
+ return obj ? executor.apply(this,arguments) : executor;
+ };
+
+}); \ No newline at end of file
diff --git a/js/dojo-1.7.2/dojox/json/ref.js b/js/dojo-1.7.2/dojox/json/ref.js
new file mode 100644
index 0000000..4da8d80
--- /dev/null
+++ b/js/dojo-1.7.2/dojox/json/ref.js
@@ -0,0 +1,360 @@
+//>>built
+define("dojox/json/ref", ["dojo/_base/kernel", "dojox", "dojo/date/stamp", "dojo/_base/array", "dojo/_base/json"], function(dojo, dojox){
+
+dojo.getObject("json", true, dojox);
+
+return dojox.json.ref = {
+ // summary:
+ // Adds advanced JSON {de}serialization capabilities to the base json library.
+ // This enhances the capabilities of dojo.toJson and dojo.fromJson,
+ // adding referencing support, date handling, and other extra format handling.
+ // On parsing, references are resolved. When references are made to
+ // ids/objects that have been loaded yet, the loader function will be set to
+ // _loadObject to denote a lazy loading (not loaded yet) object.
+
+
+ resolveJson: function(/*Object*/ root,/*Object?*/ args){
+ // summary:
+ // Indexes and resolves references in the JSON object.
+ // description:
+ // A JSON Schema object that can be used to advise the handling of the JSON (defining ids, date properties, urls, etc)
+ //
+ // root:
+ // The root object of the object graph to be processed
+ // args:
+ // Object with additional arguments:
+ //
+ // The *index* parameter.
+ // This is the index object (map) to use to store an index of all the objects.
+ // If you are using inter-message referencing, you must provide the same object for each call.
+ // The *defaultId* parameter.
+ // This is the default id to use for the root object (if it doesn't define it's own id)
+ // The *idPrefix* parameter.
+ // This the prefix to use for the ids as they enter the index. This allows multiple tables
+ // to use ids (that might otherwise collide) that enter the same global index.
+ // idPrefix should be in the form "/Service/". For example,
+ // if the idPrefix is "/Table/", and object is encountered {id:"4",...}, this would go in the
+ // index as "/Table/4".
+ // The *idAttribute* parameter.
+ // This indicates what property is the identity property. This defaults to "id"
+ // The *assignAbsoluteIds* parameter.
+ // This indicates that the resolveJson should assign absolute ids (__id) as the objects are being parsed.
+ //
+ // The *schemas* parameter
+ // This provides a map of schemas, from which prototypes can be retrieved
+ // The *loader* parameter
+ // This is a function that is called added to the reference objects that can't be resolved (lazy objects)
+ // return:
+ // An object, the result of the processing
+ args = args || {};
+ var idAttribute = args.idAttribute || 'id';
+ var refAttribute = this.refAttribute;
+ var idAsRef = args.idAsRef;
+ var prefix = args.idPrefix || '';
+ var assignAbsoluteIds = args.assignAbsoluteIds;
+ var index = args.index || {}; // create an index if one doesn't exist
+ var timeStamps = args.timeStamps;
+ var ref,reWalk=[];
+ var pathResolveRegex = /^(.*\/)?(\w+:\/\/)|[^\/\.]+\/\.\.\/|^.*\/(\/)/;
+ var addProp = this._addProp;
+ var F = function(){};
+ function walk(it, stop, defaultId, needsPrefix, schema, defaultObject){
+ // this walks the new graph, resolving references and making other changes
+ var i, update, val, id = idAttribute in it ? it[idAttribute] : defaultId;
+ if(idAttribute in it || ((id !== undefined) && needsPrefix)){
+ id = (prefix + id).replace(pathResolveRegex,'$2$3');
+ }
+ var target = defaultObject || it;
+ if(id !== undefined){ // if there is an id available...
+ if(assignAbsoluteIds){
+ it.__id = id;
+ }
+ if(args.schemas && (!(it instanceof Array)) && // won't try on arrays to do prototypes, plus it messes with queries
+ (val = id.match(/^(.+\/)[^\.\[]*$/))){ // if it has a direct table id (no paths)
+ schema = args.schemas[val[1]];
+ }
+ // if the id already exists in the system, we should use the existing object, and just
+ // update it... as long as the object is compatible
+ if(index[id] && ((it instanceof Array) == (index[id] instanceof Array))){
+ target = index[id];
+ delete target.$ref; // remove this artifact
+ delete target._loadObject;
+ update = true;
+ }else{
+ var proto = schema && schema.prototype; // and if has a prototype
+ if(proto){
+ // if the schema defines a prototype, that needs to be the prototype of the object
+ F.prototype = proto;
+ target = new F();
+ }
+ }
+ index[id] = target; // add the prefix, set _id, and index it
+ if(timeStamps){
+ timeStamps[id] = args.time;
+ }
+ }
+ while(schema){
+ var properties = schema.properties;
+ if(properties){
+ for(i in it){
+ var propertyDefinition = properties[i];
+ if(propertyDefinition && propertyDefinition.format == 'date-time' && typeof it[i] == 'string'){
+ it[i] = dojo.date.stamp.fromISOString(it[i]);
+ }
+ }
+ }
+ schema = schema["extends"];
+ }
+ var length = it.length;
+ for(i in it){
+ if(i==length){
+ break;
+ }
+ if(it.hasOwnProperty(i)){
+ val=it[i];
+ if((typeof val =='object') && val && !(val instanceof Date) && i != '__parent'){
+ ref=val[refAttribute] || (idAsRef && val[idAttribute]);
+ if(!ref || !val.__parent){
+ if(it != reWalk){
+ val.__parent = target;
+ }
+ }
+ if(ref){ // a reference was found
+ // make sure it is a safe reference
+ delete it[i];// remove the property so it doesn't resolve to itself in the case of id.propertyName lazy values
+ var path = ref.toString().replace(/(#)([^\.\[])/,'$1.$2').match(/(^([^\[]*\/)?[^#\.\[]*)#?([\.\[].*)?/); // divide along the path
+ if(index[(prefix + ref).replace(pathResolveRegex,'$2$3')]){
+ ref = index[(prefix + ref).replace(pathResolveRegex,'$2$3')];
+ }else if((ref = (path[1]=='$' || path[1]=='this' || path[1]=='') ? root : index[(prefix + path[1]).replace(pathResolveRegex,'$2$3')])){ // a $ indicates to start with the root, otherwise start with an id
+ // if there is a path, we will iterate through the path references
+ if(path[3]){
+ path[3].replace(/(\[([^\]]+)\])|(\.?([^\.\[]+))/g,function(t,a,b,c,d){
+ ref = ref && ref[b ? b.replace(/[\"\'\\]/,'') : d];
+ });
+ }
+ }
+ if(ref){
+ val = ref;
+ }else{
+ // otherwise, no starting point was found (id not found), if stop is set, it does not exist, we have
+ // unloaded reference, if stop is not set, it may be in a part of the graph not walked yet,
+ // we will wait for the second loop
+ if(!stop){
+ var rewalking;
+ if(!rewalking){
+ reWalk.push(target); // we need to rewalk it to resolve references
+ }
+ rewalking = true; // we only want to add it once
+ val = walk(val, false, val[refAttribute], true, propertyDefinition);
+ // create a lazy loaded object
+ val._loadObject = args.loader;
+ }
+ }
+ }else{
+ if(!stop){ // if we are in stop, that means we are in the second loop, and we only need to check this current one,
+ // further walking may lead down circular loops
+ val = walk(
+ val,
+ reWalk==it,
+ id === undefined ? undefined : addProp(id, i), // the default id to use
+ false,
+ propertyDefinition,
+ // if we have an existing object child, we want to
+ // maintain it's identity, so we pass it as the default object
+ target != it && typeof target[i] == 'object' && target[i]
+ );
+ }
+ }
+ }
+ it[i] = val;
+ if(target!=it && !target.__isDirty){// do updates if we are updating an existing object and it's not dirty
+ var old = target[i];
+ target[i] = val; // only update if it changed
+ if(update && val !== old && // see if it is different
+ !target._loadObject && // no updates if we are just lazy loading
+ !(i.charAt(0) == '_' && i.charAt(1) == '_') && i != "$ref" &&
+ !(val instanceof Date && old instanceof Date && val.getTime() == old.getTime()) && // make sure it isn't an identical date
+ !(typeof val == 'function' && typeof old == 'function' && val.toString() == old.toString()) && // make sure it isn't an indentical function
+ index.onUpdate){
+ index.onUpdate(target,i,old,val); // call the listener for each update
+ }
+ }
+ }
+ }
+
+ if(update && (idAttribute in it || target instanceof Array)){
+ // this means we are updating with a full representation of the object, we need to remove deleted
+ for(i in target){
+ if(!target.__isDirty && target.hasOwnProperty(i) && !it.hasOwnProperty(i) && !(i.charAt(0) == '_' && i.charAt(1) == '_') && !(target instanceof Array && isNaN(i))){
+ if(index.onUpdate && i != "_loadObject" && i != "_idAttr"){
+ index.onUpdate(target,i,target[i],undefined); // call the listener for each update
+ }
+ delete target[i];
+ while(target instanceof Array && target.length && target[target.length-1] === undefined){
+ // shorten the target if necessary
+ target.length--;
+ }
+ }
+ }
+ }else{
+ if(index.onLoad){
+ index.onLoad(target);
+ }
+ }
+ return target;
+ }
+ if(root && typeof root == 'object'){
+ root = walk(root,false,args.defaultId, true); // do the main walk through
+ walk(reWalk,false); // re walk any parts that were not able to resolve references on the first round
+ }
+ return root;
+ },
+
+
+ fromJson: function(/*String*/ str,/*Object?*/ args){
+ // summary:
+ // evaluates the passed string-form of a JSON object.
+ //
+ // str:
+ // a string literal of a JSON item, for instance:
+ // '{ "foo": [ "bar", 1, { "baz": "thud" } ] }'
+ // args: See resolveJson
+ //
+ // return:
+ // An object, the result of the evaluation
+ function ref(target){ // support call styles references as well
+ var refObject = {};
+ refObject[this.refAttribute] = target;
+ return refObject;
+ }
+ try{
+ var root = eval('(' + str + ')'); // do the eval
+ }catch(e){
+ throw new SyntaxError("Invalid JSON string: " + e.message + " parsing: "+ str);
+ }
+ if(root){
+ return this.resolveJson(root, args);
+ }
+ return root;
+ },
+
+ toJson: function(/*Object*/ it, /*Boolean?*/ prettyPrint, /*Object?*/ idPrefix, /*Object?*/ indexSubObjects){
+ // summary:
+ // Create a JSON serialization of an object.
+ // This has support for referencing, including circular references, duplicate references, and out-of-message references
+ // id and path-based referencing is supported as well and is based on http://www.json.com/2007/10/19/json-referencing-proposal-and-library/.
+ //
+ // it:
+ // an object to be serialized.
+ //
+ // prettyPrint:
+ // if true, we indent objects and arrays to make the output prettier.
+ // The variable dojo.toJsonIndentStr is used as the indent string
+ // -- to use something other than the default (tab),
+ // change that variable before calling dojo.toJson().
+ //
+ // idPrefix: The prefix that has been used for the absolute ids
+ //
+ // return:
+ // a String representing the serialized version of the passed object.
+ var useRefs = this._useRefs;
+ var addProp = this._addProp;
+ var refAttribute = this.refAttribute;
+ idPrefix = idPrefix || ''; // the id prefix for this context
+ var paths={};
+ var generated = {};
+ function serialize(it,path,_indentStr){
+ if(typeof it == 'object' && it){
+ var value;
+ if(it instanceof Date){ // properly serialize dates
+ return '"' + dojo.date.stamp.toISOString(it,{zulu:true}) + '"';
+ }
+ var id = it.__id;
+ if(id){ // we found an identifiable object, we will just serialize a reference to it... unless it is the root
+ if(path != '#' && ((useRefs && !id.match(/#/)) || paths[id])){
+ var ref = id;
+ if(id.charAt(0)!='#'){
+ if(it.__clientId == id){
+ ref = "cid:" + id;
+ }else if(id.substring(0, idPrefix.length) == idPrefix){ // see if the reference is in the current context
+ // a reference with a prefix matching the current context, the prefix should be removed
+ ref = id.substring(idPrefix.length);
+ }else{
+ // a reference to a different context, assume relative url based referencing
+ ref = id;
+ }
+ }
+ var refObject = {};
+ refObject[refAttribute] = ref;
+ return serialize(refObject,'#');
+ }
+ path = id;
+ }else{
+ it.__id = path; // we will create path ids for other objects in case they are circular
+ generated[path] = it;
+ }
+ paths[path] = it;// save it here so they can be deleted at the end
+ _indentStr = _indentStr || "";
+ var nextIndent = prettyPrint ? _indentStr + dojo.toJsonIndentStr : "";
+ var newLine = prettyPrint ? "\n" : "";
+ var sep = prettyPrint ? " " : "";
+
+ if(it instanceof Array){
+ var res = dojo.map(it, function(obj,i){
+ var val = serialize(obj, addProp(path, i), nextIndent);
+ if(typeof val != "string"){
+ val = "undefined";
+ }
+ return newLine + nextIndent + val;
+ });
+ return "[" + res.join("," + sep) + newLine + _indentStr + "]";
+ }
+
+ var output = [];
+ for(var i in it){
+ if(it.hasOwnProperty(i)){
+ var keyStr;
+ if(typeof i == "number"){
+ keyStr = '"' + i + '"';
+ }else if(typeof i == "string" && (i.charAt(0) != '_' || i.charAt(1) != '_')){
+ // we don't serialize our internal properties __id and __clientId
+ keyStr = dojo._escapeString(i);
+ }else{
+ // skip non-string or number keys
+ continue;
+ }
+ var val = serialize(it[i],addProp(path, i),nextIndent);
+ if(typeof val != "string"){
+ // skip non-serializable values
+ continue;
+ }
+ output.push(newLine + nextIndent + keyStr + ":" + sep + val);
+ }
+ }
+ return "{" + output.join("," + sep) + newLine + _indentStr + "}";
+ }else if(typeof it == "function" && dojox.json.ref.serializeFunctions){
+ return it.toString();
+ }
+
+ return dojo.toJson(it); // use the default serializer for primitives
+ }
+ var json = serialize(it,'#','');
+ if(!indexSubObjects){
+ for(var i in generated) {// cleanup the temporary path-generated ids
+ delete generated[i].__id;
+ }
+ }
+ return json;
+ },
+ _addProp: function(id, prop){
+ return id + (id.match(/#/) ? id.length == 1 ? '' : '.' : '#') + prop;
+ },
+ // refAttribute: String
+ // This indicates what property is the reference property. This acts like the idAttribute
+ // except that this is used to indicate the current object is a reference or only partially
+ // loaded. This defaults to "$ref".
+ refAttribute: "$ref",
+ _useRefs: false,
+ serializeFunctions: false
+};
+});
diff --git a/js/dojo-1.7.2/dojox/json/schema.js b/js/dojo-1.7.2/dojox/json/schema.js
new file mode 100644
index 0000000..6659956
--- /dev/null
+++ b/js/dojo-1.7.2/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;
+});