| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599 | 
							- define("dojox/data/CdfStore", ["dojo", "dojox", "dojo/data/util/sorter"], function(dojo, dojox) {
 
- dojox.data.ASYNC_MODE = 0;
 
- dojox.data.SYNC_MODE = 1;
 
- dojo.declare("dojox.data.CdfStore", null, {
 
- 	//	summary:
 
- 	//		IMPORTANT: The CDF Store is designed to work with Tibco GI, and references Tibco's
 
- 	//		JSX3 JavaScript library and will not work without it.
 
- 	//
 
- 	//		The CDF Store implements dojo.data.Read, Write, and Identity api's.  It is a local
 
- 	//		(in memory) store that handles XML documents formatted according to the
 
- 	//		Common Data Format (CDF) spec:
 
- 	//		http://www.tibco.com/devnet/resources/gi/3_1/tips_and_techniques/CommonDataFormatCDF.pdf
 
- 	//
 
- 	//		The purpose of this store is to provide a glue between a jsx3 CDF file and a Dijit.
 
- 	//
 
- 	//		While a CDF document is an XML file, other than the initial input, all data returned
 
- 	//		from and written to this store should be in object format.
 
- 	//
 
- 	// identity: [const] String
 
- 	//		The unique identifier for each item. Defaults to "jsxid" which is standard for a CDF
 
- 	//		document. Should not be changed.
 
- 	identity: "jsxid",
 
- 	//
 
- 	//	url : String
 
- 	//		The location from which to fetch the XML (CDF) document.
 
- 	url: "",
 
- 	//
 
- 	//	xmlStr: String
 
- 	//		A string that can be parsed into an XML document and should be formatted according
 
- 	//		to the CDF spec.
 
- 	//	example:
 
- 	//		|	'<data jsxid="jsxroot"><record jsxtext="A"/><record jsxtext="B" jsxid="2" jsxid="2"/></data>'
 
- 	xmlStr:"",
 
- 	//
 
- 	//	data:	Object
 
- 	//		A object that will be converted into the xmlStr property, and then parsed into a CDF.
 
- 	data:null,
 
- 	//
 
- 	//	label:	String
 
- 	//		The property within each item used to define the item.
 
- 	label: "",
 
- 	//
 
- 	//	mode [const]: dojox.data.ASYNC_MODE | dojox.data.SYNC_MODE
 
- 	//		This store supports syncronous fetches if this property is set to dojox.data.SYNC_MODE.
 
- 	mode:dojox.data.ASYNC_MODE,
 
- 	
 
- 	constructor: function(/* Object */ args){
 
- 		// summary:
 
- 		//	Constructor for the CDF store. Instantiate a new CdfStore.
 
- 		//
 
- 		if(args){
 
- 			this.url = args.url;
 
- 			this.xmlStr = args.xmlStr || args.str;
 
- 			if(args.data){
 
- 				this.xmlStr = this._makeXmlString(args.data);
 
- 			}
 
- 			this.identity = args.identity || this.identity;
 
- 			this.label = args.label || this.label;
 
- 			this.mode = args.mode !== undefined ? args.mode : this.mode;
 
- 		}
 
- 		this._modifiedItems = {};
 
- 		
 
- 		this.byId = this.fetchItemByIdentity;
 
- 	},
 
- 	
 
- 	/* dojo.data.api.Read */
 
- 	getValue: function(/* jsx3.xml.Entity */ item, /* String */ property, /* value? */ defaultValue){
 
- 		//	summary:
 
- 		//		Return an property value of an item
 
- 		//
 
- 		return item.getAttribute(property) || defaultValue; // anything
 
- 	},
 
- 	getValues: function(/* jsx3.xml.Entity */ item, /* String */ property){
 
- 		//	summary:
 
- 		//		Return an array of values
 
- 		//
 
- 		//	TODO!!! Can't find an example of an array in any CDF files
 
- 		//
 
- 		var v = this.getValue(item, property, []);
 
- 		return dojo.isArray(v) ? v : [v];
 
- 	},
 
- 	getAttributes: function(/* jsx3.xml.Entity */ item){
 
- 		//	summary:
 
- 		//		Return an array of property names
 
- 		//
 
- 		return item.getAttributeNames(); // Array
 
- 	},
 
- 	hasAttribute: function(/* jsx3.xml.Entity */ item, /* String */ property){
 
- 		//	summary:
 
- 		//		Check whether an item has a property
 
- 		//
 
- 		return (this.getValue(item, property) !== undefined); // Boolean
 
- 	},
 
- 	
 
- 	hasProperty: function(/* jsx3.xml.Entity */ item, /* String */ property){
 
- 		// summary:
 
- 		//	Alias for hasAttribute
 
- 		return this.hasAttribute(item, property);
 
- 	},
 
- 	
 
- 	containsValue: function(/* jsx3.xml.Entity */ item, /* String */ property, /* anything */ value){
 
- 		//	summary:
 
- 		//		Check whether an item contains a value
 
- 		//
 
- 		var values = this.getValues(item, property);
 
- 		for(var i = 0; i < values.length; i++){
 
- 			if(values[i] === null){ continue; }
 
- 			if((typeof value === "string")){
 
- 				if(values[i].toString && values[i].toString() === value){
 
- 					return true;
 
- 				}
 
- 			}else if(values[i] === value){
 
- 				return true; //boolean
 
- 			}
 
- 		}
 
- 		return false;//boolean
 
- 	},
 
- 	isItem: function(/* anything */ something){
 
- 		//	summary:
 
- 		//		Check whether the object is an item (jsx3.xml.Entity)
 
- 		//
 
- 		if(something.getClass && something.getClass().equals(jsx3.xml.Entity.jsxclass)){
 
- 			return true; //boolean
 
- 		}
 
- 		return false; //boolran
 
- 	},
 
- 	isItemLoaded: function(/* anything */ something){
 
- 		//	summary:
 
- 		//		Check whether the object is a jsx3.xml.Entity object and loaded
 
- 		//
 
- 		return this.isItem(something); // Boolean
 
- 	},
 
- 	loadItem: function(/* object */ keywordArgs){
 
- 		//	summary:
 
- 		//		Load an item
 
- 		//	description:
 
- 		//		The store always loads all items, so if it's an item, then it's loaded.
 
- 	},
 
- 	getFeatures: function(){
 
- 		//	summary:
 
- 		//		Return supported data APIs
 
- 		//
 
- 		return {
 
- 			"dojo.data.api.Read": true,
 
- 			"dojo.data.api.Write": true,
 
- 			"dojo.data.api.Identity":true
 
- 		}; // Object
 
- 	},
 
- 	getLabel: function(/* jsx3.xml.Entity */ item){
 
- 		//	summary:
 
- 		//		See dojo.data.api.Read.getLabel()
 
- 		//
 
- 		if((this.label !== "") && this.isItem(item)){
 
- 			var label = this.getValue(item,this.label);
 
- 			if(label){
 
- 				return label.toString();
 
- 			}
 
- 		}
 
- 		return undefined; //undefined
 
- 	},
 
- 	getLabelAttributes: function(/* jsx3.xml.Entity */ item){
 
- 		//	summary:
 
- 		//		returns an array of what properties of the item that were used
 
- 		//      to generate its label
 
- 		//		See dojo.data.api.Read.getLabelAttributes()
 
- 		//
 
- 		if(this.label !== ""){
 
- 			return [this.label]; //array
 
- 		}
 
- 		return null; //null
 
- 	},
 
- 	
 
- 	fetch: function(/* Object? */ request){
 
- 		// summary:
 
- 		//		Returns an Array of items based on the request arguments.
 
- 		// description:
 
- 		//		Returns an Array of items based on the request arguments.
 
- 		//		If the store is in ASYNC mode, the items should be expected in an onComplete
 
- 		//		method passed in the request object. If store is in SYNC mode, the items will
 
- 		//		be return directly as well as within the onComplete method.
 
- 		//	note:
 
- 		//		The mode can be set on store initialization or during a fetch as one of the
 
- 		//		parameters.
 
- 		//
 
- 		//	query: String
 
- 		//		The items in the store are treated as objects, but this is reading an XML
 
- 		//		document. Further, the actual querying of the items takes place in Tibco GI's
 
- 		//		jsx3.xml.Entity. Therefore, we are using their syntax which is xpath.
 
- 		//	Note:
 
- 		//		As conforming to a CDF document, most, if not all nodes are considered "records"
 
- 		//		and their tagNames are as such. The root node is named "data".
 
- 		//
 
- 		//	examples:
 
- 		//		All items:
 
- 		//		|	store.fetch({query:"*"});
 
- 		//		Item with a jsxid attribute equal to "1" (note you could use byId for this)
 
- 		//		|	store.fetch({query:"//record[@jsxid='1']"});
 
- 		//		All items with any jsxid attribute:
 
- 		//		|	"//record[@jsxid='*']"
 
- 		//		The items with a jsxid of '1' or '4':
 
- 		//		|	"//record[@jsxid='4' or @jsxid='1']"
 
- 		//		All children within a "group" node (could be multiple group nodes):
 
- 		//		"//group/record"
 
- 		//		All children within a specific group node:
 
- 		//		"//group[@name='mySecondGroup']/record"
 
- 		//		Any record, anywhere in the document:
 
- 		//		|	"//record"
 
- 		//		Only the records beneath the root (data) node:
 
- 		//		|	"//data/record"
 
- 		//
 
- 		//	See:
 
- 		//	http://www.tibco.com/devnet/resources/gi/3_7/api/html/jsx3/xml/Entity.html#method:selectNodes
 
- 		//	http://www.w3.org/TR/xpath
 
- 		//	http://msdn.microsoft.com/en-us/library/ms256086.aspx
 
- 		//
 
- 		//	See dojo.data.Read.fetch():
 
- 		//	onBegin
 
- 		//	onComplete
 
- 		//	onItem
 
- 		//	onError
 
- 		//	scope
 
- 		//	start
 
- 		//	count
 
- 		//	sort
 
- 		//
 
- 		request = request || {};
 
- 		if(!request.store){
 
- 			request.store = this;
 
- 		}
 
- 		if(request.mode !== undefined){
 
- 			this.mode = request.mode;
 
- 		}
 
- 		var self = this;
 
- 	
 
- 		var errorHandler = function(errorData){
 
- 			if(request.onError){
 
- 				var scope = request.scope || dojo.global;
 
- 				request.onError.call(scope, errorData, request);
 
- 			}else{
 
- 				console.error("cdfStore Error:", errorData);
 
- 			}
 
- 		};
 
- 	
 
- 		var fetchHandler = function(items, requestObject){
 
- 			requestObject = requestObject || request;
 
- 			var oldAbortFunction = requestObject.abort || null;
 
- 			var aborted = false;
 
- 	
 
- 			var startIndex = requestObject.start?requestObject.start:0;
 
- 			var endIndex = (requestObject.count && (requestObject.count !== Infinity))?(startIndex + requestObject.count):items.length;
 
- 	
 
- 			requestObject.abort = function(){
 
- 				aborted = true;
 
- 				if(oldAbortFunction){
 
- 					oldAbortFunction.call(requestObject);
 
- 				}
 
- 			};
 
- 	
 
- 			var scope = requestObject.scope || dojo.global;
 
- 			if(!requestObject.store){
 
- 				requestObject.store = self;
 
- 			}
 
- 			if(requestObject.onBegin){
 
- 				requestObject.onBegin.call(scope, items.length, requestObject);
 
- 			}
 
- 			if(requestObject.sort){
 
- 				items.sort(dojo.data.util.sorter.createSortFunction(requestObject.sort, self));
 
- 			}
 
- 			
 
- 			if(requestObject.onItem){
 
- 				for(var i = startIndex; (i < items.length) && (i < endIndex); ++i){
 
- 					var item = items[i];
 
- 					if(!aborted){
 
- 						requestObject.onItem.call(scope, item, requestObject);
 
- 					}
 
- 				}
 
- 			}
 
- 			if(requestObject.onComplete && !aborted){
 
- 				if(!requestObject.onItem){
 
- 					items = items.slice(startIndex, endIndex);
 
- 					if(requestObject.byId){
 
- 						items = items[0];
 
- 					}
 
- 				}
 
- 				requestObject.onComplete.call(scope, items, requestObject);
 
- 			}else{
 
- 				items = items.slice(startIndex, endIndex);
 
- 				if(requestObject.byId){
 
- 					items = items[0];
 
- 				}
 
- 			}
 
- 			return items;
 
- 		};
 
- 		
 
- 		if(!this.url && !this.data && !this.xmlStr){
 
- 			errorHandler(new Error("No URL or data specified."));
 
- 			return false;
 
- 		}
 
- 		var localRequest = request || "*"; // use request for _getItems()
 
- 		
 
- 		if(this.mode == dojox.data.SYNC_MODE){
 
- 			// sync mode. items returned directly
 
- 			var res = this._loadCDF();
 
- 			if(res instanceof Error){
 
- 				if(request.onError){
 
- 					request.onError.call(request.scope || dojo.global, res, request);
 
- 				}else{
 
- 					console.error("CdfStore Error:", res);
 
- 				}
 
- 				return res;
 
- 			}
 
- 			this.cdfDoc = res;
 
- 			
 
- 			var items = this._getItems(this.cdfDoc, localRequest);
 
- 			if(items && items.length > 0){
 
- 				items = fetchHandler(items, request);
 
- 			}else{
 
- 				items = fetchHandler([], request);
 
- 			}
 
- 			return items;
 
- 		
 
- 		}else{
 
- 			
 
- 			// async mode. Return a Deferred.
 
- 			var dfd = this._loadCDF();
 
- 			dfd.addCallbacks(dojo.hitch(this, function(cdfDoc){
 
- 				var items = this._getItems(this.cdfDoc, localRequest);
 
- 				if(items && items.length > 0){
 
- 					fetchHandler(items, request);
 
- 				}else{
 
- 					fetchHandler([], request);
 
- 				}
 
- 			}),
 
- 			dojo.hitch(this, function(err){
 
- 				errorHandler(err, request);
 
- 			}));
 
- 			
 
- 			return dfd;	// Object
 
- 		}
 
- 	},
 
- 	
 
- 	_loadCDF: function(){
 
- 		//	summary:
 
- 		//		Internal method.
 
- 		//		If a cdfDoc exists, return it. Otherwise, get one from JSX3,
 
- 		//		load the data or url, and return the doc or a deferred.
 
- 		var dfd = new dojo.Deferred();
 
- 		if(this.cdfDoc){
 
- 			if(this.mode == dojox.data.SYNC_MODE){
 
- 				return this.cdfDoc; // jsx3.xml.CDF
 
- 			}else{
 
- 				setTimeout(dojo.hitch(this, function(){
 
- 					dfd.callback(this.cdfDoc);
 
- 				}), 0);
 
- 				return dfd; // dojo.Deferred
 
- 			}
 
- 		}
 
- 		
 
- 		this.cdfDoc = jsx3.xml.CDF.Document.newDocument();
 
- 		this.cdfDoc.subscribe("response", this, function(evt){
 
- 			dfd.callback(this.cdfDoc);
 
- 		});
 
- 		this.cdfDoc.subscribe("error", this, function(err){
 
- 			dfd.errback(err);
 
- 		});
 
- 		
 
- 		this.cdfDoc.setAsync(!this.mode);
 
- 		if(this.url){
 
- 			this.cdfDoc.load(this.url);
 
- 		}else if(this.xmlStr){
 
- 			this.cdfDoc.loadXML(this.xmlStr);
 
- 			if(this.cdfDoc.getError().code){
 
- 				return new Error(this.cdfDoc.getError().description); // Error
 
- 			}
 
- 		}
 
- 		
 
- 		if(this.mode == dojox.data.SYNC_MODE){
 
- 			return this.cdfDoc; // jsx3.xml.CDF
 
- 		}else{
 
- 			return dfd;			// dojo.Deferred
 
- 		}
 
- 	},
 
- 	
 
- 	_getItems: function(/* jsx3.xml.Entity */cdfDoc, /* Object */request){
 
- 		// summary:
 
- 		//		Internal method.
 
- 		//		Requests the items from jsx3.xml.Entity with an xpath query.
 
- 		//
 
- 		var itr = cdfDoc.selectNodes(request.query, false, 1);
 
- 		var items = [];
 
- 		while(itr.hasNext()){
 
- 			items.push(itr.next());
 
- 		}
 
- 		return items;
 
- 	},
 
- 	close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
 
- 		 //	summary:
 
- 		 //		See dojo.data.api.Read.close()
 
- 	},
 
- /* dojo.data.api.Write */
 
- 	newItem: function(/* object? */ keywordArgs, /* object? || String? */parentInfo){
 
- 		//	summary:
 
- 		//		Creates a jsx3.xml.Entity item and inserts it either inside the
 
- 		//		parent or appends it to the root
 
- 		//
 
- 		keywordArgs = (keywordArgs || {});
 
- 		if(keywordArgs.tagName){
 
- 			// record tagName is automatic and this would add it
 
- 			// as a property
 
- 			if(keywordArgs.tagName!="record"){
 
- 				// TODO: How about some sort of group?
 
- 				console.warn("Only record inserts are supported at this time");
 
- 			}
 
- 			delete keywordArgs.tagName;
 
- 		}
 
- 		keywordArgs.jsxid = keywordArgs.jsxid || this.cdfDoc.getKey();
 
- 		if(this.isItem(parentInfo)){
 
- 			parentInfo = this.getIdentity(parentInfo);
 
- 		}
 
- 		var item = this.cdfDoc.insertRecord(keywordArgs, parentInfo);
 
- 		this._makeDirty(item);
 
- 		
 
- 		return item; // jsx3.xml.Entity
 
- 	},
 
- 	
 
- 	deleteItem: function(/* jsx3.xml.Entity */ item){
 
- 		//	summary:
 
- 		//		Delete an jsx3.xml.Entity (wrapper to a XML element).
 
- 		//
 
- 		this.cdfDoc.deleteRecord(this.getIdentity(item));
 
- 		this._makeDirty(item);
 
- 		return true; //boolean
 
- 	},
 
- 	
 
- 	setValue: function(/* jsx3.xml.Entity */ item, /* String */ property, /* almost anything */ value){
 
- 		//	summary:
 
- 		//		Set an property value
 
- 		//
 
- 		this._makeDirty(item);
 
- 		item.setAttribute(property, value);
 
- 		return true; // Boolean
 
- 	},
 
- 		
 
- 	setValues: function(/* jsx3.xml.Entity */ item, /* String */ property, /*array*/ values){
 
- 		//	summary:
 
- 		//		Set property values
 
- 		//		TODO: Needs to be fully implemented.
 
- 		//
 
- 		this._makeDirty(item);
 
- 		console.warn("cdfStore.setValues only partially implemented.");
 
- 		return item.setAttribute(property, values);
 
- 		
 
- 	},
 
- 	
 
- 	unsetAttribute: function(/* jsx3.xml.Entity */ item, /* String */ property){
 
- 		//	summary:
 
- 		//		Remove an property
 
- 		//
 
- 		this._makeDirty(item);
 
- 		item.removeAttribute(property);
 
- 		return true; // Boolean
 
- 	},
 
- 	
 
- 	revert: function(){
 
- 		// summary:
 
- 		//		Invalidate changes (new and/or modified elements)
 
- 		//		Resets data by simply deleting the reference to the cdfDoc.
 
- 		//		Subsequent fetches will load the new data.
 
- 		// Note:
 
- 		//		Any items outside the store will no longer be valid and may cause errors.
 
- 		//
 
- 		delete this.cdfDoc;
 
- 		this._modifiedItems = {};
 
- 		return true; //boolean
 
- 	},
 
- 	
 
- 	isDirty: function(/* jsx3.xml.Entity ? */ item){
 
- 		//	summary:
 
- 		//		Check whether an item is new, modified or deleted.
 
- 		//		If no item is passed, checks if anything in the store has changed.
 
- 		//
 
- 		if(item){
 
- 			return !!this._modifiedItems[this.getIdentity(item)]; // Boolean
 
- 		}else{
 
- 			var _dirty = false;
 
- 			for(var nm in this._modifiedItems){ _dirty = true; break; }
 
- 			return _dirty; // Boolean
 
- 		}
 
- 	},
 
- 	
 
- /* internal API */
 
- 	_makeDirty: function(item){
 
- 		// summary:
 
- 		//		Internal method.
 
- 		//		Marks items as modified, deleted or new.
 
- 		var id = this.getIdentity(item);
 
- 		this._modifiedItems[id] = item;
 
- 	},
 
- 	
 
- 	
 
- 	_makeXmlString: function(obj){
 
- 		// summary:
 
- 		//		Internal method.
 
- 		//		Converts an object into an XML string.
 
- 		//
 
- 		var parseObj = function(obj, name){
 
- 			var xmlStr = "";
 
- 			var nm;
 
- 			if(dojo.isArray(obj)){
 
- 				for(var i=0;i<obj.length;i++){
 
- 					xmlStr += parseObj(obj[i], name);
 
- 				}
 
- 			}else if(dojo.isObject(obj)){
 
- 				xmlStr += '<'+name+' ';
 
- 				for(nm in obj){
 
- 					if(!dojo.isObject(obj[nm])){
 
- 						xmlStr += nm+'="'+obj[nm]+'" ';
 
- 					}
 
- 				}
 
- 				xmlStr +='>';
 
- 				for(nm in obj){
 
- 					if(dojo.isObject(obj[nm])){
 
- 						xmlStr += parseObj(obj[nm], nm);
 
- 					}
 
- 				}
 
- 				xmlStr += '</'+name+'>';
 
- 			}
 
- 			return xmlStr;
 
- 		};
 
- 		return parseObj(obj, "data");
 
- 	},
 
- 	/*************************************
 
- 	 * Dojo.data Identity implementation *
 
- 	 *************************************/
 
- 	getIdentity: function(/* jsx3.xml.Entity */ item){
 
- 		//	summary:
 
- 		//		Returns the identifier for an item.
 
- 		//
 
- 		return this.getValue(item, this.identity); // String
 
- 	},
 
- 	getIdentityAttributes: function(/* jsx3.xml.Entity */ item){
 
- 		//	summary:
 
- 		//		Returns the property used for the identity.
 
- 		//
 
- 		return [this.identity]; // Array
 
- 	},
 
- 	fetchItemByIdentity: function(/* Object || String */ args){
 
- 		//	summary:
 
- 		//		See dojo.data.api.Identity.fetchItemByIdentity(keywordArgs)
 
- 		//
 
- 		//	Note:
 
- 		//		This method can be synchronous if mode is set.
 
- 		//		Also, there is a more finger friendly alias of this method, byId();
 
- 		if(dojo.isString(args)){
 
- 			var id = args;
 
- 			args = {query:"//record[@jsxid='"+id+"']", mode: dojox.data.SYNC_MODE};
 
- 		}else{
 
- 			if(args){
 
- 				args.query = "//record[@jsxid='"+args.identity+"']";
 
- 			}
 
- 			if(!args.mode){args.mode = this.mode;}
 
- 		}
 
- 		args.byId = true;
 
- 		return this.fetch(args); // dojo.Deferred || Array
 
- 	},
 
- 	byId: function(/* Object || String */ args){
 
- 		// stub. See fetchItemByIdentity
 
- 	}
 
- 	
 
- });
 
- return dojox.data.CdfStore;
 
- });
 
 
  |