commit 1434b8aa7ac9685753e288e246d52153064a44c3
parent 5f0aa6aa9fd12224d8fc25102c9776cc1c4bf38b
Author: Dan Stillman <dstillman@zotero.org>
Date: Fri, 10 Oct 2008 01:48:19 +0000
Reworked and standarized data object caching -- this should fix problems of long-term references containing stale, orphaned versions of data objects
Diffstat:
10 files changed, 311 insertions(+), 250 deletions(-)
diff --git a/chrome/content/zotero/xpcom/data/collection.js b/chrome/content/zotero/xpcom/data/collection.js
@@ -310,7 +310,6 @@ Zotero.Collection.prototype.save = function () {
Zotero.DB.query("DELETE FROM collections WHERE collectionID=?", oldID);
Zotero.DB.query("UPDATE collections SET key=? WHERE collectionID=?", [row.key, this.id]);
- Zotero.Collections.unload(oldID);
Zotero.Notifier.trigger('id-change', 'collection', oldID + '-' + this.id);
// Update child collections that have cached the previous id
diff --git a/chrome/content/zotero/xpcom/data/collections.js b/chrome/content/zotero/xpcom/data/collections.js
@@ -28,26 +28,20 @@ Zotero.Collections = new function() {
Zotero.DataObjects.apply(this, ['collection']);
this.constructor.prototype = new Zotero.DataObjects();
- var _collections = {};
- var _collectionsLoaded = false;
-
this.get = get;
this.add = add;
this.getUpdated = getUpdated;
this.getCollectionsContainingItems = getCollectionsContainingItems;
- this.reload = reload;
- this.reloadAll = reloadAll;
this.erase = erase;
- this.unload = unload;
/*
* Returns a Zotero.Collection object for a collectionID
*/
function get(id) {
- if (!_collectionsLoaded) {
+ if (this._reloadCache) {
this.reloadAll();
}
- return (typeof _collections[id]!='undefined') ? _collections[id] : false;
+ return this._objectCache[id] ? this._objectCache[id] : false;
}
@@ -107,8 +101,8 @@ Zotero.Collections = new function() {
ids = Zotero.flattenArguments(ids);
for each(var id in ids) {
- if (_collections[id]) {
- _collections[id]._refreshParent();
+ if (this._objectCache[id]) {
+ this._objectCache[id]._refreshParent();
}
}
}
@@ -124,65 +118,10 @@ Zotero.Collections = new function() {
ids = Zotero.flattenArguments(ids);
for each(var id in ids) {
- if (_collections[id]) {
- _collections[id]._refreshChildCollections();
- }
- }
- }
-
-
- function reload(id) {
- if (!_collectionsLoaded) {
- this.reloadAll();
- return;
- }
-
- if (!_collections[id]) {
- _collections[id] = new Zotero.Collection(id);
- }
- _collections[id].load();
- }
-
-
- /**
- * Loads collection data from DB and adds to internal cache
- **/
- function reloadAll() {
- Zotero.debug('Loading all collections');
-
- // This should be the same as the query in Zotero.Collection.load(),
- // just without a specific collectionID
- var sql = "SELECT C.*, "
- + "(SELECT COUNT(*) FROM collections WHERE "
- + "parentCollectionID=C.collectionID)!=0 AS hasChildCollections, "
- + "(SELECT COUNT(*) FROM collectionItems WHERE "
- + "collectionID=C.collectionID)!=0 AS hasChildItems "
- + "FROM collections C";
- var result = Zotero.DB.query(sql);
-
- var collectionIDs = [];
-
- if (result) {
- for (var i=0; i<result.length; i++) {
- var collectionID = result[i].collectionID;
- collectionIDs.push(collectionID);
-
- // If collection doesn't exist, create new object and stuff in array
- if (!_collections[collectionID]) {
- _collections[collectionID] = new Zotero.Collection;
- }
- _collections[collectionID].loadFromRow(result[i]);
- }
- }
-
- // Remove old collections that no longer exist
- for each(var c in _collections) {
- if (collectionIDs.indexOf(c.id) == -1) {
- this.unload(c.id);
+ if (this._objectCache[id]) {
+ this._objectCache[id]._refreshChildCollections();
}
}
-
- _collectionsLoaded = true;
}
@@ -204,18 +143,50 @@ Zotero.Collections = new function() {
}
- /**
- * Clear collection from internal cache (used by Zotero.Collection.erase())
- *
- * Can be passed ids as individual parameters or as an array of ids, or both
- **/
- function unload() {
- var ids = Zotero.flattenArguments(arguments);
+ this._load = function () {
+ if (!arguments[0] && !this._reloadCache) {
+ return;
+ }
+
+ this._reloadCache = false;
+
+ // This should be the same as the query in Zotero.Collection.load(),
+ // just without a specific collectionID
+ var sql = "SELECT C.*, "
+ + "(SELECT COUNT(*) FROM collections WHERE "
+ + "parentCollectionID=C.collectionID)!=0 AS hasChildCollections, "
+ + "(SELECT COUNT(*) FROM collectionItems WHERE "
+ + "collectionID=C.collectionID)!=0 AS hasChildItems "
+ + "FROM collections C WHERE 1";
+ if (arguments[0]) {
+ sql += " AND collectionID IN (" + Zotero.join(arguments[0], ",") + ")";
+ }
+ var rows = Zotero.DB.query(sql);
+ var ids = [];
+ for each(var row in rows) {
+ var id = row.collectionID;
+ ids.push(id);
+
+ // Creator doesn't exist -- create new object and stuff in array
+ if (!this._objectCache[id]) {
+ //this.get(id);
+ this._objectCache[id] = new Zotero.Collection;
+ this._objectCache[id].loadFromRow(row);
+ }
+ // Existing creator -- reload in place
+ else {
+ this._objectCache[id].loadFromRow(row);
+ }
+ }
- for(var i=0; i<ids.length; i++) {
- delete _collections[ids[i]];
+ // If loading all creators, remove old creators that no longer exist
+ if (!arguments[0]) {
+ for each(var c in this._objectCache) {
+ if (ids.indexOf(c.id) == -1) {
+ this.unload(c.id);
+ }
+ }
}
}
-
}
diff --git a/chrome/content/zotero/xpcom/data/creator.js b/chrome/content/zotero/xpcom/data/creator.js
@@ -166,9 +166,11 @@ Zotero.Creator.prototype.save = function () {
Zotero.DB.query("DELETE FROM creators WHERE creatorID=?", oldID);
Zotero.DB.query("UPDATE creators SET key=? WHERE creatorID=?", [row.key, this.id]);
- Zotero.Creators.unload(oldID);
Zotero.Notifier.trigger('id-change', 'creator', oldID + '-' + this.id);
+ // Do this here because otherwise updateLinkedItems() below would
+ // load a duplicate copy in the new position
+ Zotero.Creators.reload(this.id);
// update caches
}
@@ -230,6 +232,7 @@ Zotero.Creator.prototype.save = function () {
}
if (this.id) {
+ Zotero.debug("Updating linked items");
this.updateLinkedItems();
}
@@ -390,31 +393,43 @@ Zotero.Creator.prototype.erase = function () {
}
-// Also called from Zotero.Creators.reload()
-Zotero.Creator.prototype.load = function () {
+Zotero.Creator.prototype.load = function (allowFail) {
Zotero.debug("Loading data for creator " + this.id + " in Zotero.Creator.load()");
if (!this.id) {
throw ("creatorID not set in Zotero.Creator.load()");
}
- var sql = "SELECT key, dateModified, creatorDataID, CD.* "
- + "FROM creators C NATURAL JOIN creatorData CD WHERE creatorID=?";
- var data = Zotero.DB.rowQuery(sql, this.id);
+ var sql = "SELECT C.*, CD.* FROM creators C NATURAL JOIN creatorData CD "
+ + "WHERE creatorID=?";
+ var row = Zotero.DB.rowQuery(sql, this.id);
+ if (!row) {
+ if (allowFail) {
+ this._loaded = true;
+ return false;
+ }
+ throw ("Creator " + this.id + " not found in Zotero.Item.load()");
+ }
+
+ this.loadFromRow(row);
+ return true;
+}
+
+
+Zotero.Creator.prototype.loadFromRow = function (row) {
this._init();
- this._loaded = true;
- if (!data) {
- return;
+ for (var col in row) {
+ //Zotero.debug("Setting field '" + col + "' to '" + row[col] + "' for creator " + this.id);
+ this['_' + col] = row[col] ? row[col] : '';
}
- for (var key in data) {
- this['_' + key] = data[key];
- }
+ this._loaded = true;
}
+
Zotero.Creator.prototype._checkValue = function (field, value) {
if (this['_' + field] === undefined) {
throw ("Invalid property " + field + " in Zotero.Creator._checkValue()");
diff --git a/chrome/content/zotero/xpcom/data/creators.js b/chrome/content/zotero/xpcom/data/creators.js
@@ -25,9 +25,6 @@ Zotero.Creators = new function() {
Zotero.DataObjects.apply(this, ['creator']);
this.constructor.prototype = new Zotero.DataObjects();
- var _creatorsByID = {}; // Zotero.Creator objects indexed by creatorID
- var _creatorDataHash = {}; // creatorDataIDs indexed by md5 hash of data
-
this.get = get;
this.getUpdated = getUpdated;
this.getDataID = getDataID;
@@ -35,21 +32,19 @@ Zotero.Creators = new function() {
this.countCreatorsWithData = countCreatorsWithData;
this.updateData = updateData;
this.deleteData = deleteData;
- this.reload = reload;
this.erase = erase;
this.purge = purge;
- this.unload = unload;
this.fields = ['firstName', 'lastName', 'fieldMode', 'birthYear'];
- var self = this;
+ var _creatorDataHash = {}; // creatorDataIDs indexed by md5 hash of data
/*
* Returns a Zotero.Creator object for a given creatorID
*/
function get(creatorID) {
- if (_creatorsByID[creatorID]) {
- return _creatorsByID[creatorID];
+ if (this._objectCache[creatorID]) {
+ return this._objectCache[creatorID];
}
var sql = 'SELECT COUNT(*) FROM creators WHERE creatorID=?';
@@ -59,8 +54,8 @@ Zotero.Creators = new function() {
return false;
}
- _creatorsByID[creatorID] = new Zotero.Creator(creatorID);
- return _creatorsByID[creatorID];
+ this._objectCache[creatorID] = new Zotero.Creator(creatorID);
+ return this._objectCache[creatorID];
}
@@ -173,32 +168,6 @@ Zotero.Creators = new function() {
}
- /*
- * Reloads data for specified creators into internal array
- *
- * Can be passed ids as individual parameters or as an array of ids, or both
- */
- function reload() {
- if (!arguments[0]) {
- return false;
- }
-
- var ids = Zotero.flattenArguments(arguments);
- Zotero.debug('Reloading creators ' + ids);
-
- for each(var id in ids) {
- if (!_creatorsByID[id]) {
- this.get(id);
- }
- else {
- _creatorsByID[id].load();
- }
- }
-
- return true;
- }
-
-
/**
* Remove creator(s) from all linked items and call this.purge()
* to delete creator rows
@@ -249,7 +218,7 @@ Zotero.Creators = new function() {
if (toDelete) {
// Clear creator entries in internal array
for each(var creatorID in toDelete) {
- delete _creatorsByID[creatorID];
+ delete this._objectCache[creatorID];
}
var sql = "DELETE FROM creators WHERE creatorID NOT IN "
@@ -275,20 +244,47 @@ Zotero.Creators = new function() {
}
- /**
- * Clear creator from internal array
- *
- * @param int id creatorID
- */
- function unload(id) {
- delete _creatorsByID[id];
- }
-
-
- this.unloadAll = function () {
- Zotero.debug("Unloading all creators");
- _creatorsByID = {};
- _creatorDataHash = {};
+ this._load = function () {
+ if (!arguments[0] && !this._reloadCache) {
+ return;
+ }
+
+ if (this._reloadCache) {
+ Zotero.debug("Clearing creator data hash");
+ _creatorDataHash = {};
+ }
+
+ var sql = "SELECT C.*, CD.* FROM creators C NATURAL JOIN creatorData CD "
+ + "WHERE 1";
+ if (arguments[0]) {
+ sql += " AND creatorID IN (" + Zotero.join(arguments[0], ",") + ")";
+ }
+ var rows = Zotero.DB.query(sql);
+ var ids = [];
+ for each(var row in rows) {
+ var id = row.creatorID;
+ ids.push(id);
+
+ // Creator doesn't exist -- create new object and stuff in array
+ if (!this._objectCache[id]) {
+ this.get(id);
+ }
+ // Existing creator -- reload in place
+ else {
+ this._objectCache[id].loadFromRow(row);
+ }
+ }
+
+ // If loading all creators, remove old creators that no longer exist
+ if (!arguments[0]) {
+ for each(var c in this._objectCache) {
+ if (ids.indexOf(c.id) == -1) {
+ this.unload(c.id);
+ }
+ }
+
+ this._reloadCache = false;
+ }
}
@@ -349,8 +345,8 @@ Zotero.Creators = new function() {
var creators = getCreatorsWithData(creatorDataID);
for each(var creatorID in creators) {
- if (_creatorsByID[creatorID]) {
- _creatorsByID[creatorID].load();
+ if (this._objectCache[creatorID]) {
+ this._objectCache[creatorID].load();
}
}
}
diff --git a/chrome/content/zotero/xpcom/data/dataObjects.js b/chrome/content/zotero/xpcom/data/dataObjects.js
@@ -14,6 +14,9 @@ Zotero.DataObjects = function (object, objectPlural, id, table) {
this._ZDO_id = (id ? id : object) + 'ID';
this._ZDO_table = table ? table : this._ZDO_objects;
+ this._objectCache = {};
+ this._reloadCache = true;
+
/**
* Retrieves an object by its secondary lookup key
@@ -30,5 +33,92 @@ Zotero.DataObjects = function (object, objectPlural, id, table) {
}
return Zotero[this._ZDO_Objects].get(id);
}
+
+
+ /*
+ * Reloads data for specified items into internal array
+ *
+ * Can be passed ids as individual parameters or as an array of ids, or both
+ */
+ this.reload = function () {
+ if (!arguments[0]) {
+ return false;
+ }
+
+ var ids = Zotero.flattenArguments(arguments);
+ Zotero.debug('Reloading ' + this._ZDO_objects + ' ' + ids);
+
+ // Reset cache keys to itemIDs stored in database using object keys
+ var sql = "SELECT " + this._ZDO_id + " AS id, key FROM " + this._ZDO_table
+ + " WHERE " + this._ZDO_id + " IN ("
+ + ids.map(function () '?').join() + ")";
+ var rows = Zotero.DB.query(sql, ids);
+
+ var keyIDs = {};
+ for each(var row in rows) {
+ keyIDs[row.key] = row.id
+ }
+ var store = {};
+
+ for (var id in this._objectCache) {
+ var obj = this._objectCache[id];
+ var dbID = keyIDs[obj.key];
+ if (!dbID || id == dbID) {
+ continue;
+ }
+ store[dbID] = obj;
+ delete this._objectCache[id];
+ }
+ for (var id in store) {
+ if (this._objectCache[id]) {
+ throw("Existing " + this._ZDO_object + " " + id
+ + " exists in cache in Zotero.DataObjects.reload()");
+ }
+ this._objectCache[id] = store[id];
+ }
+
+ // Reload data
+ this._load(ids);
+
+ return true;
+ }
+
+
+ this.reloadAll = function () {
+ Zotero.debug("Reloading all " + this._ZDO_objects);
+
+ // Reset cache keys to itemIDs stored in database using object keys
+ var sql = "SELECT " + this._ZDO_id + " AS id, key FROM " + this._ZDO_table;
+ var rows = Zotero.DB.query(sql);
+
+ var keyIDs = {};
+ for each(var row in rows) {
+ keyIDs[row.key] = row.id;
+ }
+
+ var store = {};
+ for each(var obj in this._objectCache) {
+ store[keyIDs[obj.key]] = obj;
+ }
+
+ this._objectCache = store;
+
+ // Reload data
+ this._reloadCache = true;
+ this._load();
+ }
+
+
+ /**
+ * Clear object from internal array
+ *
+ * @param int[] ids objectIDs
+ */
+ this.unload = function () {
+ var ids = Zotero.flattenArguments(arguments);
+ for (var i=0; i<ids.length; i++) {
+ delete _objectCache[ids[i]];
+ }
+ }
}
diff --git a/chrome/content/zotero/xpcom/data/item.js b/chrome/content/zotero/xpcom/data/item.js
@@ -302,7 +302,6 @@ Zotero.Item.prototype.loadPrimaryData = function(allowFail) {
}
this.loadFromRow(row);
-
return true;
}
@@ -1038,7 +1037,6 @@ Zotero.Item.prototype.save = function() {
Zotero.DB.query("DELETE FROM items WHERE itemID=?", oldID);
Zotero.DB.query("UPDATE items SET key=? WHERE itemID=?", [row.key, this.id]);
- Zotero.Items.unload(oldID);
Zotero.Notifier.trigger('id-change', 'item', oldID + '-' + this.id);
// update caches
@@ -2792,7 +2790,7 @@ Zotero.Item.prototype.getTags = function() {
var tagObjs = [];
for (var i=0; i<tags.length; i++) {
- var tag = Zotero.Tags.get(tags[i].tagID, true);
+ var tag = Zotero.Tags.get(tags[i].tagID);
tagObjs.push(tag);
}
return tagObjs;
diff --git a/chrome/content/zotero/xpcom/data/items.js b/chrome/content/zotero/xpcom/data/items.js
@@ -34,18 +34,13 @@ Zotero.Items = new function() {
this.getAll = getAll;
this.getUpdated = getUpdated;
this.add = add;
- this.reload = reload;
- this.reloadAll = reloadAll;
this.cacheFields = cacheFields;
this.erase = erase;
this.purge = purge;
- this.unload = unload;
this.getFirstCreatorSQL = getFirstCreatorSQL;
this.getSortTitle = getSortTitle;
// Private members
- var _items = [];
- var _itemsLoaded = false;
var _cachedFields = [];
var _firstCreatorSQL = '';
@@ -71,33 +66,33 @@ Zotero.Items = new function() {
for (var i=0; i<ids.length; i++) {
// Check if already loaded
- if (!_items[ids[i]]) {
+ if (!this._objectCache[ids[i]]) {
toLoad.push(ids[i]);
}
}
// New items to load
if (toLoad.length) {
- _load(toLoad);
+ this._load(toLoad);
}
// If single id, return the object directly
if (arguments[0] && typeof arguments[0]!='object'
&& typeof arguments[1]=='undefined') {
- if (!_items[arguments[0]]) {
+ if (!this._objectCache[arguments[0]]) {
Zotero.debug("Item " + arguments[0] + " doesn't exist", 2);
return false;
}
- return _items[arguments[0]];
+ return this._objectCache[arguments[0]];
}
// Otherwise, build return array
for (i=0; i<ids.length; i++) {
- if (!_items[ids[i]]) {
+ if (!this._objectCache[ids[i]]) {
Zotero.debug("Item " + ids[i] + " doesn't exist", 2);
continue;
}
- loaded.push(_items[ids[i]]);
+ loaded.push(this._objectCache[ids[i]]);
}
return loaded;
@@ -210,36 +205,19 @@ Zotero.Items = new function() {
}
- /*
- * Reloads data for specified items into internal array
- *
- * Can be passed ids as individual parameters or as an array of ids, or both
- */
- function reload() {
- if (!arguments[0]) {
- return false;
+ function cacheFields(fields, items) {
+ if (items && items.length == 0) {
+ return;
}
- var ids = Zotero.flattenArguments(arguments);
- Zotero.debug('Reloading ' + ids);
- _load(ids);
-
- return true;
- }
-
-
- function reloadAll() {
- Zotero.debug("Loading all items");
- _items = [];
- _itemsLoaded = false;
- _load();
- }
-
-
- function cacheFields(fields, items) {
Zotero.debug("Caching fields [" + fields.join() + "]"
- + (items ? " for " + items + " items" : ''));
- _load(items);
+ + (items ? " for " + items.length + " items" : ''));
+ if (items && items.length > 0) {
+ this._load(items);
+ }
+ else {
+ this._load();
+ }
var primaryFields = [];
var fieldIDs = [];
@@ -270,7 +248,7 @@ Zotero.Items = new function() {
var rows = Zotero.DB.query(sql);
for each(var row in rows) {
//Zotero.debug('Calling loadFromRow for item ' + row.itemID);
- _items[row.itemID].loadFromRow(row);
+ this._objectCache[row.itemID].loadFromRow(row);
}
}
@@ -292,8 +270,8 @@ Zotero.Items = new function() {
var itemDataRows = Zotero.DB.query(sql);
for each(var row in itemDataRows) {
//Zotero.debug('Setting field ' + row.fieldID + ' for item ' + row.itemID);
- if (_items[row.itemID]) {
- _items[row.itemID].setField(row.fieldID, row.value, true);
+ if (this._objectCache[row.itemID]) {
+ this._objectCache[row.itemID].setField(row.fieldID, row.value, true);
}
else {
if (!missingItems) {
@@ -323,8 +301,8 @@ Zotero.Items = new function() {
for each(var row in rows) {
//Zotero.debug('Setting title for note ' + row.itemID);
- if (_items[row.itemID]) {
- _items[row.itemID].setField(titleFieldID, row['title'], true);
+ if (this._objectCache[row.itemID]) {
+ this._objectCache[row.itemID].setField(titleFieldID, row.title, true);
}
else {
if (!missingItems) {
@@ -341,10 +319,10 @@ Zotero.Items = new function() {
// Set nonexistent fields in the cache list to false (instead of null)
for each(var itemID in allItemIDs) {
for each(var fieldID in fieldIDs) {
- if (Zotero.ItemFields.isValidForType(fieldID, _items[itemID].itemTypeID)) {
+ if (Zotero.ItemFields.isValidForType(fieldID, this._objectCache[itemID].itemTypeID)) {
if (!itemFieldsCached[itemID] || !itemFieldsCached[itemID][fieldID]) {
//Zotero.debug('Setting field ' + fieldID + ' to false for item ' + itemID);
- _items[itemID].setField(fieldID, false, true);
+ this._objectCache[itemID].setField(fieldID, false, true);
}
}
}
@@ -409,14 +387,6 @@ Zotero.Items = new function() {
}
- /**
- * Clear item from internal array (used by Zotero.Item.erase())
- **/
- function unload(id) {
- delete _items[id];
- }
-
-
/*
* Generate SQL to retrieve firstCreator field
*
@@ -541,8 +511,8 @@ Zotero.Items = new function() {
}
- function _load() {
- if (!arguments[0] && _itemsLoaded) {
+ this._load = function () {
+ if (!arguments[0] && !this._reloadCache) {
return;
}
@@ -552,9 +522,8 @@ Zotero.Items = new function() {
+ "(SELECT COUNT(*) FROM itemNotes WHERE sourceItemID=I.itemID) AS numNotes, "
+ "(SELECT COUNT(*) FROM itemAttachments WHERE sourceItemID=I.itemID) AS numAttachments "
+ 'FROM items I WHERE 1';
-
if (arguments[0]) {
- sql += ' AND I.itemID IN (' + Zotero.join(arguments,',') + ')';
+ sql += ' AND I.itemID IN (' + Zotero.join(arguments[0], ',') + ')';
}
var itemsRows = Zotero.DB.query(sql);
var itemIDs = [];
@@ -564,30 +533,28 @@ Zotero.Items = new function() {
itemIDs.push(itemID);
// Item doesn't exist -- create new object and stuff in array
- if (!_items[row.itemID]) {
+ if (!this._objectCache[row.itemID]) {
var item = new Zotero.Item();
item.loadFromRow(row, true);
- _items[row.itemID] = item;
+ this._objectCache[row.itemID] = item;
}
// Existing item -- reload in place
else {
- _items[row.itemID].loadFromRow(row, true);
+ this._objectCache[row.itemID].loadFromRow(row, true);
}
}
// If loading all items, remove old items that no longer exist
if (!arguments[0]) {
- for each(var c in _items) {
+ for each(var c in this._objectCache) {
if (itemIDs.indexOf(c.id) == -1) {
this.unload(c.id);
}
}
- }
-
- if (!arguments[0]) {
- _itemsLoaded = true;
+
_cachedFields = ['itemID', 'itemTypeID', 'dateAdded', 'dateModified',
'firstCreator', 'numNotes', 'numAttachments', 'numChildren'];
+ this._reloadCache = false;
}
}
}
diff --git a/chrome/content/zotero/xpcom/data/tag.js b/chrome/content/zotero/xpcom/data/tag.js
@@ -118,21 +118,26 @@ Zotero.Tag.prototype.load = function() {
}
var sql = "SELECT name, type, dateModified, key FROM tags WHERE tagID=?";
- var data = Zotero.DB.rowQuery(sql, this.id);
+ var row = Zotero.DB.rowQuery(sql, this.id);
+ this.loadFromRow(row);
+ return true;
+}
+
+
+Zotero.Tag.prototype.loadFromRow = function (row) {
this._init();
- this._loaded = true;
- if (!data) {
- return;
+ for (var col in row) {
+ //Zotero.debug("Setting field '" + col + "' to '" + row[col] + "' for tag " + this.id);
+ this['_' + col] = row[col] ? row[col] : '';
}
- for (var key in data) {
- this['_' + key] = data[key];
- }
+ this._loaded = true;
}
+
/**
* Returns items linked to this tag
*
@@ -249,7 +254,6 @@ Zotero.Tag.prototype.save = function () {
Zotero.DB.query("UPDATE tags SET key=? WHERE tagID=?", [row.key, this.id]);
- Zotero.Tags.unload(oldID);
Zotero.Notifier.trigger('id-change', 'tag', oldID + '-' + this.id);
// update caches
diff --git a/chrome/content/zotero/xpcom/data/tags.js b/chrome/content/zotero/xpcom/data/tags.js
@@ -29,7 +29,6 @@ Zotero.Tags = new function() {
this.constructor.prototype = new Zotero.DataObjects();
var _tags = {}; // indexed by tag text
- var _tagsByID = {}; // indexed by tagID
this.get = get;
this.getName = getName;
@@ -42,31 +41,18 @@ Zotero.Tags = new function() {
this.getTagItems = getTagItems;
this.search = search;
this.rename = rename;
- this.reload = reload;
this.erase = erase;
this.purge = purge;
- this.unload = unload;
/*
* Returns a tag and type for a given tagID
*/
- function get(tagID, skipCheck) {
- if (_tagsByID[tagID]) {
- return _tagsByID[tagID];
+ function get(id, skipCheck) {
+ if (this._reloadCache) {
+ this.reloadAll();
}
-
- if (!skipCheck) {
- var sql = 'SELECT COUNT(*) FROM tags WHERE tagID=?';
- var result = Zotero.DB.valueQuery(sql, tagID);
-
- if (!result) {
- return false;
- }
- }
-
- _tagsByID[tagID] = new Zotero.Tag(tagID);
- return _tagsByID[tagID];
+ return this._objectCache[id] ? this._objectCache[id] : false;
}
@@ -326,11 +312,6 @@ Zotero.Tags = new function() {
}
- function reload(ids) {
- this.unload(ids);
- }
-
-
function erase(ids) {
ids = Zotero.flattenArguments(ids);
@@ -415,12 +396,12 @@ Zotero.Tags = new function() {
*
* @param int|array ids One or more tagIDs
*/
- function unload() {
+ this.unload = function () {
var ids = Zotero.flattenArguments(arguments);
for each(var id in ids) {
- var tag = _tagsByID[id];
- delete _tagsByID[id];
+ var tag = this._objectCache[id];
+ delete this._objectCache[id];
if (tag && _tags[tag.type]) {
delete _tags[tag.type]['_' + tag.name];
}
@@ -428,9 +409,49 @@ Zotero.Tags = new function() {
}
- this.unloadAll = function (ids) {
- _tags = {};
- _tagsByID = {};
+ this._load = function () {
+ if (!arguments[0] && !this._reloadCache) {
+ return;
+ }
+
+ if (this._reloadCache) {
+ _tags = {};
+ }
+
+ this._reloadCache = false;
+
+ // This should be the same as the query in Zotero.Tag.load(),
+ // just without a specific tagID
+ var sql = "SELECT * FROM tags WHERE 1";
+ if (arguments[0]) {
+ sql += " AND tagID IN (" + Zotero.join(arguments[0], ",") + ")";
+ }
+ var rows = Zotero.DB.query(sql);
+ var ids = [];
+ for each(var row in rows) {
+ var id = row.tagID;
+ ids.push(id);
+
+ // Tag doesn't exist -- create new object and stuff in array
+ if (!this._objectCache[id]) {
+ //this.get(id);
+ this._objectCache[id] = new Zotero.Tag;
+ this._objectCache[id].loadFromRow(row);
+ }
+ // Existing tag -- reload in place
+ else {
+ this._objectCache[id].loadFromRow(row);
+ }
+ }
+
+ if (!arguments[0]) {
+ // If loading all tags, remove old tags that no longer exist
+ for each(var c in this._objectCache) {
+ if (ids.indexOf(c.id) == -1) {
+ this.unload(c.id);
+ }
+ }
+ }
}
}
diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js
@@ -934,9 +934,9 @@ var Zotero = new function(){
function reloadDataObjects() {
- Zotero.Tags.unloadAll();
+ Zotero.Tags.reloadAll();
Zotero.Collections.reloadAll();
- Zotero.Creators.unloadAll();
+ Zotero.Creators.reloadAll();
Zotero.Items.reloadAll();
}
};