Changeset 9837

Show
Ignore:
Timestamp:
07/27/07 14:29:47 (16 months ago)
Author:
skinner
Message:

fixes #3873 -- Bug in ItemFileWriteStore? that would show up when using a file that did not specify an identifier and then calling newItem() after calling deleteItem(). Changed deleteItem() to place null values in the _arrayOfAllItems, rather than removing elements from the array. Should also improve performance of deleteItem() and revert().

Location:
dojo/trunk
Files:
3 modified

Legend:

Unmodified
Added
Removed
  • dojo/trunk/data/ItemFileReadStore.js

    r9810 r9837  
    233233                var self = this; 
    234234                var filter = function(requestArgs, arrayOfItems){ 
    235                         var items = null; 
    236  
     235                        var items = []; 
    237236                        if(requestArgs.query){ 
    238237                                var ignoreCase = requestArgs.queryOptions ? requestArgs.queryOptions.ignoreCase : false;  
    239                                 items = []; 
    240238 
    241239                                //See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the 
     
    252250                                        var match = true; 
    253251                                        var candidateItem = arrayOfItems[i]; 
    254                                         for(var key in requestArgs.query) { 
    255                                                 var value = requestArgs.query[key]; 
    256                                                 if (!self._containsValue(candidateItem, key, value, regexpList[key])){ 
    257                                                         match = false; 
     252                                        if(candidateItem === null){ 
     253                                                match = false; 
     254                                        }else{ 
     255                                                for(var key in requestArgs.query) { 
     256                                                        var value = requestArgs.query[key]; 
     257                                                        if (!self._containsValue(candidateItem, key, value, regexpList[key])){ 
     258                                                                match = false; 
     259                                                        } 
    258260                                                } 
    259261                                        } 
     
    264266                                findCallback(items, requestArgs); 
    265267                        }else{ 
    266                                 // We want a copy to pass back in case the parent wishes to sort the array.  We shouldn't allow resort  
    267                                 // of the internal list so that multiple callers can get lists and sort without affecting each other. 
    268                                 if(arrayOfItems.length> 0){ 
    269                                         items = arrayOfItems.slice(0,arrayOfItems.length);  
     268                                // We want a copy to pass back in case the parent wishes to sort the array.  
     269                                // We shouldn't allow resort of the internal list, so that multiple callers  
     270                                // can get lists and sort without affecting each other.  We also need to 
     271                                // filter out any null values that have been left as a result of deleteItem() 
     272                                // calls in ItemFileWriteStore. 
     273                                for(var i = 0; i < arrayOfItems.length; ++i){ 
     274                                        var item = arrayOfItems[i]; 
     275                                        if(item !== null){ 
     276                                                items.push(item); 
     277                                        } 
    270278                                } 
    271279                                findCallback(items, requestArgs); 
     
    454462 
    455463                var identifier = dataObject.identifier; 
     464                this._itemsByIdentity = {}; 
    456465                if(identifier){ 
    457466                        this._features['dojo.data.api.Identity'] = identifier; 
    458                         this._itemsByIdentity = {}; 
    459467                        for(i = 0; i < this._arrayOfAllItems.length; ++i){ 
    460468                                item = this._arrayOfAllItems[i]; 
  • dojo/trunk/data/ItemFileWriteStore.js

    r9810 r9837  
    176176                this._assertIsItem(item); 
    177177 
    178                 var found = this._removeArrayElement(this._arrayOfAllItems, item); 
    179                 if(found){ 
    180                         var identity = this.getIdentity(item); 
    181                         item[this._storeRefPropName] = null; 
    182                         delete this._itemsByIdentity[identity]; 
    183                         this._pending._deletedItems[identity] = item; 
    184                         this._updateItemIdIndexValues(); 
    185                         this.onDelete(item); // dojo.data.api.Notification call 
    186                          
    187                         //Remove from the toplevel items, if necessary... 
    188                         if(item[this._rootItemPropName]){ 
    189                                 this._removeArrayElement(this._arrayOfTopLevelItems, item); 
    190                         } 
    191                         return true; 
    192                 } 
    193                 return false; // boolean 
     178                // remove this item from the _arrayOfAllItems, but leave a null value in place 
     179                // of the item, so as not to change the length of the array, so that in newItem()  
     180                // we can still safely do: newIdentity = this._arrayOfAllItems.length; 
     181                var indexInArrayOfAllItems = item[this._itemNumPropName]; 
     182                this._arrayOfAllItems[indexInArrayOfAllItems] = null; 
     183                 
     184                var identity = this.getIdentity(item); 
     185                item[this._storeRefPropName] = null; 
     186                delete this._itemsByIdentity[identity]; 
     187                this._pending._deletedItems[identity] = item; 
     188                 
     189                //Remove from the toplevel items, if necessary... 
     190                if(item[this._rootItemPropName]){ 
     191                        this._removeArrayElement(this._arrayOfTopLevelItems, item); 
     192                } 
     193                this.onDelete(item); // dojo.data.api.Notification call 
     194                return true; 
    194195        }, 
    195196 
     
    351352                for(var i = 0; i < this._arrayOfAllItems.length; ++i){ 
    352353                        var item = this._arrayOfAllItems[i]; 
    353                         serializableItem = {}; 
    354                         for(var key in item){ 
    355                                 if(key !== this._storeRefPropName && key !== this._itemNumPropName){ 
    356                                         var attribute = key; 
    357                                         var valueArray = this.getValues(item, attribute); 
    358                                         if(valueArray.length == 1){ 
    359                                                 serializableItem[attribute] = this._flatten(valueArray[0]); 
    360                                         }else{ 
    361                                                 var serializableArray = []; 
    362                                                 for(var j = 0; j < valueArray.length; ++j){ 
    363                                                         serializableArray.push(this._flatten(valueArray[j])); 
    364                                                         serializableItem[attribute] = serializableArray; 
     354                        if(item !== null){ 
     355                                serializableItem = {}; 
     356                                for(var key in item){ 
     357                                        if(key !== this._storeRefPropName && key !== this._itemNumPropName){ 
     358                                                var attribute = key; 
     359                                                var valueArray = this.getValues(item, attribute); 
     360                                                if(valueArray.length == 1){ 
     361                                                        serializableItem[attribute] = this._flatten(valueArray[0]); 
     362                                                }else{ 
     363                                                        var serializableArray = []; 
     364                                                        for(var j = 0; j < valueArray.length; ++j){ 
     365                                                                serializableArray.push(this._flatten(valueArray[j])); 
     366                                                                serializableItem[attribute] = serializableArray; 
     367                                                        } 
    365368                                                } 
    366369                                        } 
    367370                                } 
    368                         } 
    369                         serializableStructure.items.push(serializableItem); 
     371                                serializableStructure.items.push(serializableItem); 
     372                        } 
    370373                } 
    371374                var prettyPrint = true; 
     
    436439                        // make the original item into a full-fledged item again 
    437440                        originalItem[this._storeRefPropName] = this; 
    438                         //originalItem[this._itemNumPropName] = identity; // WRONG! this should be a number N, the index into this._arrayOfAllItems 
    439441                        modifiedItem[this._storeRefPropName] = null; 
    440442 
    441443                        // replace the modified item with the original one 
    442                         this._removeArrayElement(this._arrayOfAllItems, modifiedItem); 
    443                         this._arrayOfAllItems.push(originalItem); 
     444                        var arrayIndex = modifiedItem[this._itemNumPropName]; 
     445                        this._arrayOfAllItems[arrayIndex] = originalItem; 
     446                         
    444447                        if(modifiedItem[this._rootItemPropName]){ 
    445                                 this._removeArrayElement(this._arrayOfTopLevelItems, modifiedItem); 
    446                                 this._arrayOfTopLevelItems.push(originalItem); 
     448                                arrayIndex = modifiedItem[this._itemNumPropName]; 
     449                                this._arrayOfTopLevelItems[arrayIndex] = originalItem; 
    447450                        } 
    448451                        this._itemsByIdentity[identity] = originalItem; 
     
    452455                        deletedItem[this._storeRefPropName] = this; 
    453456                        this._itemsByIdentity[identity] = deletedItem; 
    454                         this._arrayOfAllItems.push(deletedItem); 
     457                        var index = deletedItem[this._itemNumPropName]; 
     458                        this._arrayOfAllItems[index] = deletedItem; 
    455459                        if(deletedItem[this._rootItemPropName]){ 
    456460                                this._arrayOfTopLevelItems.push(deletedItem); 
     
    462466                        _deletedItems:{} 
    463467                }; 
    464                 this._updateItemIdIndexValues(); 
    465468                return true; // boolean 
    466         }, 
    467          
    468         _updateItemIdIndexValues: function(){ 
    469                 for(var i = 0; i < this._arrayOfAllItems.length; ++i){ 
    470                         var item = this._arrayOfAllItems[i]; 
    471                         item[this._itemNumPropName] = i; 
    472                 } 
    473469        }, 
    474470         
  • dojo/trunk/tests/data/ItemFileWriteStore.js

    r9810 r9837  
    734734                        } 
    735735                        doh.assertTrue(passed); 
     736                }, 
     737                function testIdentityAPI_noIdentifierSpecified(){ 
     738                        //      summary:  
     739                        //              Test for bug #3873. Given a datafile that does not specify an 
     740                        //              identifier, make sure ItemFileWriteStore auto-creates identities  
     741                        //              that are unique even after calls to deleteItem() and newItem() 
     742 
     743                        var args = {data: { 
     744                                label:"name", 
     745                                items:[ 
     746                                        {name:'Ecuador', capital:'Quito'}, 
     747                                        {name:'Egypt', capital:'Cairo'}, 
     748                                        {name:'El Salvador', capital:'San Salvador'}, 
     749                                        {name:'Equatorial Guinea', capital:'Malabo'}, 
     750                                        {name:'Eritrea', capital:'Asmara'}, 
     751                                        {name:'Estonia', capital:'Tallinn'}, 
     752                                        {name:'Ethiopia', capital:'Addis Ababa'} 
     753                                ] 
     754                        } };  
     755                        var store = new dojo.data.ItemFileWriteStore(args); 
     756                        var deferred = new doh.Deferred(); 
     757                         
     758                        function onError(error, request){ 
     759                                deferred.errback(error); 
     760                        } 
     761                        function onComplete(items, request){ 
     762                                doh.assertEqual(7, items.length); 
     763                                 
     764                                var lastItem = items[(items.length - 1)]; 
     765                                var idOfLastItem = store.getIdentity(lastItem); 
     766                                store.deleteItem(lastItem); 
     767                                store.newItem({name:'Canada', capital:'Ottawa'}); 
     768                                 
     769                                function onCompleteAgain(itemsAgain, requestAgain){ 
     770                                        doh.assertEqual(7, itemsAgain.length); 
     771                                        var identitiesInUse = {}; 
     772                                        for(var i = 0; i < itemsAgain.length; ++i){ 
     773                                                var item = itemsAgain[i]; 
     774                                                var id = store.getIdentity(item); 
     775                                                if(identitiesInUse.hasOwnProperty(id)){ 
     776                                                        // there should not already be an entry for this id 
     777                                                        doh.assertTrue(false); 
     778                                                }else{ 
     779                                                        // we want to add the entry now 
     780                                                        identitiesInUse[id] = item; 
     781                                                } 
     782                                        } 
     783                                        deferred.callback(true); 
     784                                } 
     785                                store.fetch({onComplete:onCompleteAgain, onError:onError}); 
     786                        } 
     787                         
     788                        store.fetch({onComplete:onComplete, onError:onError}); 
     789                        return deferred; 
    736790                } 
    737791        ]