123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828 |
- define("dojox/data/AppStore", ["dojo", "dojox", "dojo/data/util/simpleFetch", "dojo/data/util/filter", "dojox/atom/io/Connection"], function(dojo, dojox) {
- dojo.experimental("dojox.data.AppStore");
- dojo.declare("dojox.data.AppStore",
- null,{
- // url: [public] string
- // So the parser can instantiate the store via markup.
- url: "",
-
- // urlPreventCache: [public] boolean
- // Whether or not to pass the preventCache parameter to the connection
- urlPreventCache: false,
- // xmethod: [public] boolean
- // Whether to use X-Method-Override for PUT/DELETE.
- xmethod: false,
-
- _atomIO: null,
- _feed: null,
- _requests: null,
- _processing: null,
-
- _updates: null,
- _adds: null,
- _deletes: null,
-
- constructor: function(/*Object*/args){
- // summary:
- // The APP data store.
- // description:
- // The APP Store is instantiated either in markup or programmatically by supplying a
- // url of the Collection to be used.
- //
- // args:
- // An anonymous object to initialize properties. It expects the following values:
- // url: The url of the Collection to load.
- // urlPreventCache: Whether or not to append on cache prevention params (as defined by dojo.xhr*)
-
- if(args && args.url){
- this.url = args.url;
- }
- if(args && args.urlPreventCache){
- this.urlPreventCache = args.urlPreventCache;
- }
- if(!this.url){
- throw new Error("A URL is required to instantiate an APP Store object");
- }
- },
-
- _setFeed: function(feed, data){
- // summary:
- // Sets the internal feed using a dojox.atom.io.model.Feed object.
- // description:
- // Sets the internal feed using a dojox.atom.io.model.Feed object. Also adds
- // a property to the entries to track that they belong to this store. It
- // also parses stored requests (since we were waiting on a callback) and
- // executes those as well.
- //
- // feed: dojox.atom.io.model.Feed object
- // The Feed to use for this data store.
- // data: unused
- // Signature for this function is defined by AtomIO.getFeed, since this is a callback.
- this._feed = feed;
- var i;
- for(i=0; i<this._feed.entries.length; i++){
- this._feed.entries[i].store = this;
- }
- if(this._requests){
- for(i=0; i<this._requests.length; i++){
- var request = this._requests[i];
- if(request.request && request.fh && request.eh){
- this._finishFetchItems(request.request, request.fh, request.eh);
- }else if(request.clear){
- this._feed = null;
- }else if(request.add){
- this._feed.addEntry(request.add);
- }else if(request.remove){
- this._feed.removeEntry(request.remove);
- }
- }
- }
- this._requests = null;
- },
-
- _getAllItems: function(){
- // summary:
- // Function to return all entries in the Feed as an array of items.
- // description:
- // Function to return all entries in the Feed as an array of items.
- //
- // returns:
- // Array of all entries in the feed.
- var items = [];
- for(var i=0; i<this._feed.entries.length; i++){
- items.push(this._feed.entries[i]);
- }
- return items; //array
- },
-
- _assertIsItem: function(/* item */ item){
- // summary:
- // This function tests whether the item is an item.
- // description:
- // This function tests whether the item passed in is indeed an item
- // in the store.
- //
- // item:
- // The item to test for being contained by the store.
- if(!this.isItem(item)){
- throw new Error("This error message is provided when a function is called in the following form: "
- + "getAttribute(argument, attributeName). The argument variable represents the member "
- + "or owner of the object. The error is created when an item that does not belong "
- + "to this store is specified as an argument.");
- }
- },
- _assertIsAttribute: function(/* String */ attribute){
- // summary:
- // This function tests whether the item is an attribute.
- // description:
- // This function tests whether the item passed in is indeed a valid
- // 'attribute' like type for the store.
- // attribute:
- // The attribute to test for being contained by the store.
- //
- // returns:
- // Returns a boolean indicating whether this is a valid attribute.
- if(typeof attribute !== "string"){
- throw new Error("The attribute argument must be a string. The error is created "
- + "when a different type of variable is specified such as an array or object.");
- }
- for(var key in dojox.atom.io.model._actions){
- if(key == attribute){
- return true;
- }
- }
- return false;
- },
-
- _addUpdate: function(/* Object */ update){
- // summary:
- // Internal function to add an updated entry to our updates array
- // description:
- // Internal function to add an updated entry to our updates array
- //
- // update: dojox.atom.io.model.Entry object
- // The updated Entry we've changed.
- if(!this._updates){
- this._updates = [update];
- }else{
- this._updates.push(update);
- }
- },
- /***************************************
- dojo.data.api.Read API
- ***************************************/
-
- getValue: function( /* item */ item,
- /* attribute-name-string */ attribute,
- /* value? */ defaultValue){
- // summary:
- // See dojo.data.api.Read.getValue()
- var values = this.getValues(item, attribute);
- return (values.length > 0)?values[0]:defaultValue; //Object || int || Boolean
- },
- getValues: function(/* item */ item,
- /* attribute-name-string */ attribute){
- // summary:
- // See dojo.data.api.Read.getValues()
- this._assertIsItem(item);
- var flag = this._assertIsAttribute(attribute);
- if(flag){
- if((attribute === "author" || attribute === "contributor" || attribute === "link") && item[attribute+"s"]){
- return item[attribute+"s"];
- }
- if(attribute === "category" && item.categories){
- return item.categories;
- }
- if(item[attribute]){
- item = item[attribute];
- if(item.nodeType == "Content"){
- return [item.value];
- }
- return [item] ;
- }
- }
- return []; //Array
- },
- getAttributes: function(/* item */ item){
- // summary:
- // See dojo.data.api.Read.getAttributes()
- this._assertIsItem(item);
- var attributes = [];
- for(var key in dojox.atom.io.model._actions){
- if(this.hasAttribute(item, key)){
- attributes.push(key);
- }
- }
- return attributes; //Array
- },
- hasAttribute: function( /* item */ item,
- /* attribute-name-string */ attribute){
- // summary:
- // See dojo.data.api.Read.hasAttribute()
- return this.getValues(item, attribute).length > 0;
- },
- containsValue: function(/* item */ item,
- /* attribute-name-string */ attribute,
- /* anything */ value){
- // summary:
- // See dojo.data.api.Read.containsValue()
- var regexp = undefined;
- if(typeof value === "string"){
- regexp = dojo.data.util.filter.patternToRegExp(value, false);
- }
- return this._containsValue(item, attribute, value, regexp); //boolean.
- },
- _containsValue: function( /* item */ item,
- /* attribute-name-string */ attribute,
- /* anything */ value,
- /* RegExp?*/ regexp,
- /* Boolean?*/ trim){
- // summary:
- // Internal function for looking at the values contained by the item.
- // description:
- // Internal function for looking at the values contained by the item. This
- // function allows for denoting if the comparison should be case sensitive for
- // strings or not (for handling filtering cases where string case should not matter)
- //
- // item:
- // The data item to examine for attribute values.
- // attribute:
- // The attribute to inspect.
- // value:
- // The value to match.
- // regexp:
- // Optional regular expression generated off value if value was of string type to handle wildcarding.
- // If present and attribute values are string, then it can be used for comparison instead of 'value'
- var values = this.getValues(item, attribute);
- for(var i = 0; i < values.length; ++i){
- var possibleValue = values[i];
- if(typeof possibleValue === "string" && regexp){
- if(trim){
- possibleValue = possibleValue.replace(new RegExp(/^\s+/),""); // START
- possibleValue = possibleValue.replace(new RegExp(/\s+$/),""); // END
- }
- possibleValue = possibleValue.replace(/\r|\n|\r\n/g, "");
- return (possibleValue.match(regexp) !== null);
- }else{
- //Non-string matching.
- if(value === possibleValue){
- return true; // Boolean
- }
- }
- }
- return false; // Boolean
- },
- isItem: function(/* anything */ something){
- // summary:
- // See dojo.data.api.Read.isItem()
- return something && something.store && something.store === this; //boolean
- },
- isItemLoaded: function(/* anything */ something){
- // summary:
- // See dojo.data.api.Read.isItemLoaded()
- return this.isItem(something);
- },
- loadItem: function(/* Object */ keywordArgs){
- // summary:
- // See dojo.data.api.Read.loadItem()
- this._assertIsItem(keywordArgs.item);
- },
-
- _fetchItems: function(request, fetchHandler, errorHandler){
- // summary:
- // Fetch items (Atom entries) that match to a query
- // description:
- // Fetch items (Atom entries) that match to a query
- // request:
- // A request object
- // fetchHandler:
- // A function to call for fetched items
- // errorHandler:
- // A function to call on error
- if(this._feed){
- this._finishFetchItems(request, fetchHandler, errorHandler);
- }else{
- var flag = false;
- if(!this._requests){
- this._requests = [];
- flag = true;
- }
- this._requests.push({request: request, fh: fetchHandler, eh: errorHandler});
- if(flag){
- this._atomIO = new dojox.atom.io.Connection(false, this.urlPreventCache);
- this._atomIO.getFeed(this.url,this._setFeed, null, this);
- }
- }
- },
-
- _finishFetchItems: function(request, fetchHandler, errorHandler){
- // summary:
- // Internal function for finishing a fetch request.
- // description:
- // Internal function for finishing a fetch request. Needed since the feed
- // might not have been loaded, so we finish the fetch in a callback.
- //
- // request:
- // A request object
- // fetchHandler:
- // A function to call for fetched items
- // errorHandler:
- // A function to call on error
- var items = null;
- var arrayOfAllItems = this._getAllItems();
- if(request.query){
- var ignoreCase = request.queryOptions ? request.queryOptions.ignoreCase : false;
- items = [];
- //See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the
- //same value for each item examined. Much more efficient.
- var regexpList = {};
- var key;
- var value;
- for(key in request.query){
- value = request.query[key]+'';
- if(typeof value === "string"){
- regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
- }
- }
- for(var i = 0; i < arrayOfAllItems.length; ++i){
- var match = true;
- var candidateItem = arrayOfAllItems[i];
- for(key in request.query){
- value = request.query[key]+'';
- if(!this._containsValue(candidateItem, key, value, regexpList[key], request.trim)){
- match = false;
- }
- }
- if(match){
- items.push(candidateItem);
- }
- }
- }else{
- // We want a copy to pass back in case the parent wishes to sort the array. We shouldn't allow resort
- // of the internal list so that multiple callers can get listsand sort without affecting each other.
- if(arrayOfAllItems.length> 0){
- items = arrayOfAllItems.slice(0,arrayOfAllItems.length);
- }
- }
- try{
- fetchHandler(items, request);
- }catch(e){
- errorHandler(e, request);
- }
- },
- getFeatures: function(){
- // summary:
- // See dojo.data.api.Read.getFeatures()
- return {
- 'dojo.data.api.Read': true,
- 'dojo.data.api.Write': true,
- 'dojo.data.api.Identity': true
- };
- },
-
- close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
- // summary:
- // See dojo.data.api.Read.close()
- // nothing to do here!
- this._feed = null;
- },
- getLabel: function(/* item */ item){
- // summary:
- // See dojo.data.api.Read.getLabel()
- if(this.isItem(item)){
- return this.getValue(item, "title", "No Title");
- }
- return undefined;
- },
- getLabelAttributes: function(/* item */ item){
- // summary:
- // See dojo.data.api.Read.getLabelAttributes()
- return ["title"];
- },
- /***************************************
- dojo.data.api.Identity API
- ***************************************/
- getIdentity: function(/* item */ item){
- // summary:
- // See dojo.data.api.Identity.getIdentity()
- this._assertIsItem(item);
- return this.getValue(item, "id");
- },
- getIdentityAttributes: function(/* item */ item){
- // summary:
- // See dojo.data.api.Identity.getIdentityAttributes()
- return ["id"];
- },
- fetchItemByIdentity: function(keywordArgs){
- // summary:
- // See dojo.data.api.Identity.fetchItemByIdentity()
- this._fetchItems({query:{id:keywordArgs.identity}, onItem: keywordArgs.onItem, scope: keywordArgs.scope},
- function(items, request){
- var scope = request.scope;
- if(!scope){
- scope = dojo.global;
- }
- if(items.length < 1){
- request.onItem.call(scope, null);
- }else{
- request.onItem.call(scope, items[0]);
- }
- }, keywordArgs.onError);
- },
- /***************************************
- dojo.data.api.Identity API
- ***************************************/
- newItem: function(/* Object? */ keywordArgs){
- // summary:
- // See dojo.data.api.Write.newItem()
- var entry = new dojox.atom.io.model.Entry();
- var value = null;
- var temp = null;
- var i;
- for(var key in keywordArgs){
- if(this._assertIsAttribute(key)){
- value = keywordArgs[key];
- switch(key){
- case "link":
- for(i in value){
- temp = value[i];
- entry.addLink(temp.href,temp.rel,temp.hrefLang,temp.title,temp.type);
- }
- break;
- case "author":
- for(i in value){
- temp = value[i];
- entry.addAuthor(temp.name, temp.email, temp.uri);
- }
- break;
- case "contributor":
- for(i in value){
- temp = value[i];
- entry.addContributor(temp.name, temp.email, temp.uri);
- }
- break;
- case "category":
- for(i in value){
- temp = value[i];
- entry.addCategory(temp.scheme, temp.term, temp.label);
- }
- break;
- case "icon":
- case "id":
- case "logo":
- case "xmlBase":
- case "rights":
- entry[key] = value;
- break;
- case "updated":
- case "published":
- case "issued":
- case "modified":
- entry[key] = dojox.atom.io.model.util.createDate(value);
- break;
- case "content":
- case "summary":
- case "title":
- case "subtitle":
- entry[key] = new dojox.atom.io.model.Content(key);
- entry[key].value = value;
- break;
- default:
- entry[key] = value;
- break;
- }
- }
- }
- entry.store = this;
- entry.isDirty = true;
- if(!this._adds){
- this._adds = [entry];
- }else{
- this._adds.push(entry);
- }
- if(this._feed){
- this._feed.addEntry(entry);
- }else{
- if(this._requests){
- this._requests.push({add:entry});
- }else{
- this._requests = [{add:entry}];
- this._atomIO = new dojox.atom.io.Connection(false, this.urlPreventCache);
- this._atomIO.getFeed(this.url,dojo.hitch(this,this._setFeed));
- }
- }
- return true;
- },
- deleteItem: function(/* item */ item){
- // summary:
- // See dojo.data.api.Write.deleteItem()
- this._assertIsItem(item);
- if(!this._deletes){
- this._deletes = [item];
- }else{
- this._deletes.push(item);
- }
- if(this._feed){
- this._feed.removeEntry(item);
- }else{
- if(this._requests){
- this._requests.push({remove:item});
- }else{
- this._requests = [{remove:item}];
- this._atomIO = new dojox.atom.io.Connection(false, this.urlPreventCache);
- this._atomIO.getFeed(this.url,dojo.hitch(this,this._setFeed));
- }
- }
- item = null;
- return true;
- },
- setValue: function( /* item */ item,
- /* string */ attribute,
- /* almost anything */ value){
- // summary:
- // See dojo.data.api.Write.setValue()
- this._assertIsItem(item);
-
- var update = {item: item};
- if(this._assertIsAttribute(attribute)){
- switch(attribute){
- case "link":
- update.links = item.links;
- this._addUpdate(update);
- item.links = null;
- item.addLink(value.href,value.rel,value.hrefLang,value.title,value.type);
- item.isDirty = true;
- return true;
- case "author":
- update.authors = item.authors;
- this._addUpdate(update);
- item.authors = null;
- item.addAuthor(value.name, value.email, value.uri);
- item.isDirty = true;
- return true;
- case "contributor":
- update.contributors = item.contributors;
- this._addUpdate(update);
- item.contributors = null;
- item.addContributor(value.name, value.email, value.uri);
- item.isDirty = true;
- return true;
- case "category":
- update.categories = item.categories;
- this._addUpdate(update);
- item.categories = null;
- item.addCategory(value.scheme, value.term, value.label);
- item.isDirty = true;
- return true;
- case "icon":
- case "id":
- case "logo":
- case "xmlBase":
- case "rights":
- update[attribute] = item[attribute];
- this._addUpdate(update);
- item[attribute] = value;
- item.isDirty = true;
- return true;
- case "updated":
- case "published":
- case "issued":
- case "modified":
- update[attribute] = item[attribute];
- this._addUpdate(update);
- item[attribute] = dojox.atom.io.model.util.createDate(value);
- item.isDirty = true;
- return true;
- case "content":
- case "summary":
- case "title":
- case "subtitle":
- update[attribute] = item[attribute];
- this._addUpdate(update);
- item[attribute] = new dojox.atom.io.model.Content(attribute);
- item[attribute].value = value;
- item.isDirty = true;
- return true;
- default:
- update[attribute] = item[attribute];
- this._addUpdate(update);
- item[attribute] = value;
- item.isDirty = true;
- return true;
- }
- }
- return false;
- },
- setValues: function(/* item */ item,
- /* string */ attribute,
- /* array */ values){
- // summary:
- // See dojo.data.api.Write.setValues()
- if(values.length === 0){
- return this.unsetAttribute(item, attribute);
- }
- this._assertIsItem(item);
-
- var update = {item: item};
- var value;
- var i;
- if(this._assertIsAttribute(attribute)){
- switch(attribute){
- case "link":
- update.links = item.links;
- item.links = null;
- for(i in values){
- value = values[i];
- item.addLink(value.href,value.rel,value.hrefLang,value.title,value.type);
- }
- item.isDirty = true;
- return true;
- case "author":
- update.authors = item.authors;
- item.authors = null;
- for(i in values){
- value = values[i];
- item.addAuthor(value.name, value.email, value.uri);
- }
- item.isDirty = true;
- return true;
- case "contributor":
- update.contributors = item.contributors;
- item.contributors = null;
- for(i in values){
- value = values[i];
- item.addContributor(value.name, value.email, value.uri);
- }
- item.isDirty = true;
- return true;
- case "categories":
- update.categories = item.categories;
- item.categories = null;
- for(i in values){
- value = values[i];
- item.addCategory(value.scheme, value.term, value.label);
- }
- item.isDirty = true;
- return true;
- case "icon":
- case "id":
- case "logo":
- case "xmlBase":
- case "rights":
- update[attribute] = item[attribute];
- item[attribute] = values[0];
- item.isDirty = true;
- return true;
- case "updated":
- case "published":
- case "issued":
- case "modified":
- update[attribute] = item[attribute];
- item[attribute] = dojox.atom.io.model.util.createDate(values[0]);
- item.isDirty = true;
- return true;
- case "content":
- case "summary":
- case "title":
- case "subtitle":
- update[attribute] = item[attribute];
- item[attribute] = new dojox.atom.io.model.Content(attribute);
- item[attribute].values[0] = values[0];
- item.isDirty = true;
- return true;
- default:
- update[attribute] = item[attribute];
- item[attribute] = values[0];
- item.isDirty = true;
- return true;
- }
- }
- this._addUpdate(update);
- return false;
- },
- unsetAttribute: function( /* item */ item,
- /* string */ attribute){
- // summary:
- // See dojo.data.api.Write.unsetAttribute()
- this._assertIsItem(item);
- if(this._assertIsAttribute(attribute)){
- if(item[attribute] !== null){
- var update = {item: item};
- switch(attribute){
- case "author":
- case "contributor":
- case "link":
- update[attribute+"s"] = item[attribute+"s"];
- break;
- case "category":
- update.categories = item.categories;
- break;
- default:
- update[attribute] = item[attribute];
- break;
- }
- item.isDirty = true;
- item[attribute] = null;
- this._addUpdate(update);
- return true;
- }
- }
- return false; // boolean
- },
- save: function(/* object */ keywordArgs){
- // summary:
- // See dojo.data.api.Write.save()
- // keywordArgs:
- // {
- // onComplete: function
- // onError: function
- // scope: object
- // }
- var i;
- for(i in this._adds){
- this._atomIO.addEntry(this._adds[i], null, function(){}, keywordArgs.onError, false, keywordArgs.scope);
- }
-
- this._adds = null;
-
- for(i in this._updates){
- this._atomIO.updateEntry(this._updates[i].item, function(){}, keywordArgs.onError, false, this.xmethod, keywordArgs.scope);
- }
-
- this._updates = null;
-
- for(i in this._deletes){
- this._atomIO.removeEntry(this._deletes[i], function(){}, keywordArgs.onError, this.xmethod, keywordArgs.scope);
- }
-
- this._deletes = null;
-
- this._atomIO.getFeed(this.url,dojo.hitch(this,this._setFeed));
-
- if(keywordArgs.onComplete){
- var scope = keywordArgs.scope || dojo.global;
- keywordArgs.onComplete.call(scope);
- }
- },
- revert: function(){
- // summary:
- // See dojo.data.api.Write.revert()
- var i;
- for(i in this._adds){
- this._feed.removeEntry(this._adds[i]);
- }
-
- this._adds = null;
-
- var update, item, key;
- for(i in this._updates){
- update = this._updates[i];
- item = update.item;
- for(key in update){
- if(key !== "item"){
- item[key] = update[key];
- }
- }
- }
- this._updates = null;
-
- for(i in this._deletes){
- this._feed.addEntry(this._deletes[i]);
- }
- this._deletes = null;
- return true;
- },
- isDirty: function(/* item? */ item){
- // summary:
- // See dojo.data.api.Write.isDirty()
- if(item){
- this._assertIsItem(item);
- return item.isDirty?true:false; //boolean
- }
- return (this._adds !== null || this._updates !== null); //boolean
- }
- });
- dojo.extend(dojox.data.AppStore,dojo.data.util.simpleFetch);
- return dojox.data.AppStore;
- });
|