text: /*
  	JSON parsing and stringifying with support for id and path based referencing.
  	Uses the "old" JSON JS API that does not break enumerability.
  	Modified version of the Douglas Crockford's JSON library from http://www.json.org/js.html
      Public Domain? How are you supposed to license something when you modify public domain code?
      Usage: 
      JSON.stringify(value) turns a JS value into JSON string. When an object is encountered more
      than one (through circular or multiple referencing), a reference is made to it.
      JSON.parse(string) turns a JSON string into a JS object. When a reference is encountered it is resolved.
       References are in the form of:
      {"$ref":"$|id.path"}     
  */
  (function() {
    var ids={};
    JSON= {
    	resolveRef: function(ref) {
  		throw new Error("Reference to " + ref + " could not be resolved");  		
    	},
       stringify: function (v) {
  	   var a = [];
  	   var paths={};
  	   var m = {
  	       '\b': '\\b',
  	       '\t': '\\t',
  	       '\n': '\\n',
  	       '\f': '\\f',
  	       '\r': '\\r',
  	       '"' : '\\"',
  	       '\\': '\\\\'
  	   };
  	   function e(s) {
  	       a[a.length] = s;
  	   }
  	   function s(x) {
              if (/["\\\x00-\x1f]/.test(x)) {
                 return '"' + x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
                     var c = m[b];
                     if (c) {
                         return c;
                     }
                     c = b.charCodeAt();
                     return '\\u00' +
                         Math.floor(c / 16).toString(16) +
                         (c % 16).toString(16);
                 }) + '"';
             }
             return '"' + x + '"';
  	   }
  	   function g(x,p) {
  	       var c, i, l, v;
  	       switch (typeof x) {
  	       case 'object':
  	           if (x) {
  	               if (x instanceof Date) {
  				        function f(n) {
  				            return n < 10 ? '0' + n : n;
  				        }
  
  				        return e('"' + this.getUTCFullYear() + '-' +
  				                f(this.getUTCMonth() + 1) + '-' +
  				                f(this.getUTCDate()) + 'T' +
  				                f(this.getUTCHours()) + ':' +
  				                f(this.getUTCMinutes()) + ':' +
  				                f(this.getUTCSeconds()) + 'Z"');
                      }
                      // ref ->
                     if (x.id) {
                      	if (ids[x.id] || paths[x.id]) 
                      		return g({$ref:x.id});
                      	else
                      		ids[p = x.id] = x;
                     	}
                     	else {
                     		x.id = p;
                     		paths[p] = x;
                    	}
                     // <- ref
  	               if (x instanceof Array) {
  	                   e('[');
  	                   l = a.length;
  	                   for (i = 0; i < x.length; i += 1) {
  	                       v = x[i];
  	                       if (typeof v != 'undefined' &&
  	                               typeof v != 'function') {
  	                           if (l < a.length) {
  	                               e(',');
  	                           }
  	                           g(v,p +'['+i+']');
  	                       }
  	                   }
  	                   e(']');
  	                   return;
  	               } 
  	                    else if (typeof x.valueOf == 'function') {
  	                        e('{');
  	                        l = a.length;
  	                        for (i in x) {
  	                            v = x[i];
  	                            if (typeof v != 'undefined' && !(i == 'id' && paths[v]) &&
  	                                    typeof v != 'function' &&
  	                                    (!v || typeof v != 'object' ||
  	                                        typeof v.valueOf == 'function')) {
  	                                if (l < a.length) {
  	                                    e(',');
  	                                }
  	                                e(s(i));
  	                                e(':');
  	                                // -> ref
  	                                g(v,p+(i.match(/^[a-zA-Z]\w*$/) ? ('.' + i) : ('[' + s(i) + ']')));
  	                                // <- ref
  	                            }
  	                        }
  	                        return e('}');
  	                    }
  	                }
  	                e('null');
  	                return;
  	            case 'number':
  	                e(isFinite(x) ? +x : 'null');
  	                return;
  	            case 'string':
  	            	e(s(x));
  	                return;
  	            case 'boolean':
  	                e(String(x));
  	                return;
  	            default:
  	                e('null');
  	                return;
  	            }
  	        }
  	        g(v,'$');
  	        for (i in paths) 
  	        	delete paths[i].id;   
  	        return a.join('');
  	    },
  	parse : function(str,stop) { 
  			var j,ref,rw=[];
              function walk(v,stop) {
             	    // ref ->
              	if (v.id)
  					ids[v.id] = v;
              	for (var i in v) {
  					if (v.hasOwnProperty(i) && (typeof (val=v[i]) =='object') && val) {
  						if (ref=val.$ref) {
  							var stripped = ref.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
  							if(/[\w\[\]\.\$ \/\r\n\t]/.test(stripped) && !/=|((^|\W)new\W)/.test(stripped)) {
  								var path = ref.match(/(^[\$\w]+)(\W.*)?/);
  								(ref=path[1]=='$'?j:ids[path[1]]) ?
  									(v[i] = path[2] ? eval('ref' + path[2]) : ref) : (stop ? JSON.resolveRef(val.$ref) : rw.push(v)); 
  							}
  						}
  						if (!stop) // <- ref
  							walk(val,rw==v);
  					}
  				}
              }
              if (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/.test(str.
                      replace(/\\./g, '@').
                      replace(/"[^"\\\n\r]*"/g, ''))) {
                  j = eval('(' + str + ')');
                  walk(j);
                  walk(rw);
                  return j;
              }
              throw new SyntaxError('parseJSON');
          }
  	}
  })();