ydn.db
Version:
Javascript database library for IndexedDB, WebDatabase (WebSQL) and WebStorage (localStorage) storage mechanisms supporting version migration, advanced query and transaction workflow.
251 lines (209 loc) • 5.31 kB
JavaScript
// Copyright 2012 YDN Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview A unique key for a datastore object supporting hierarchy of
* parent-child relationships for a record.
*
* The instances are immutable.
*
* @author kyawtun@yathit.com (Kyaw Tun)
*/
goog.provide('ydn.db.Key');
/**
* Builds a new Key object of known id.
*
* @param {string|!ydn.db.Key.Json} store_or_json_or_value store name of key
* object in JSON format.
* @param {!IDBKey=} opt_id key id.
* @param {ydn.db.Key=} opt_parent optional parent key.
* @constructor
*/
ydn.db.Key = function(store_or_json_or_value, opt_id, opt_parent) {
var store_name;
if (goog.isObject(store_or_json_or_value)) {
store_name = store_or_json_or_value['store'];
opt_id = store_or_json_or_value['id'];
if (goog.isDefAndNotNull(store_or_json_or_value['parent'])) {
opt_parent = new ydn.db.Key(store_or_json_or_value['parent']);
}
} else {
goog.asserts.assertString(store_or_json_or_value, 'store name of' +
' a key object must be a string');
if (!goog.isDef(opt_id)) {
// must be valueOf string
var idx = store_or_json_or_value.lastIndexOf(ydn.db.Key.SEP_PARENT);
/**
* @type {string}
*/
var store_and_id = store_or_json_or_value;
if (idx > 0) {
store_and_id = store_or_json_or_value.substr(idx);
opt_parent = new ydn.db.Key(store_or_json_or_value.substring(0, idx));
}
var parts = store_and_id.split(ydn.db.Key.SEP_STORE);
store_name = parts[0];
opt_id = parts[1];
if (!goog.isDef(opt_id)) {
throw Error('Invalid key value: ' + store_or_json_or_value);
}
} else {
store_name = store_or_json_or_value;
}
}
/**
* @final
* @type {string}
*/
this.store_name = store_name;
/**
* @final
* @type {IDBKey|undefined}
*/
this.id = opt_id;
/**
* @final
* @type {?ydn.db.Key}
*/
this.parent = opt_parent || null;
};
/**
* @typedef {number|string|!Date|!Array.<number|string|!Date>}
*/
var IDBKey;
/**
* @typedef {{
* store: string,
* id: (string|number),
* parent: (ydn.db.Key|undefined)
* }}
*/
ydn.db.Key.Json;
/**
* @private
* @type {!IDBKey}
*/
ydn.db.Key.prototype.id;
/**
* @private
* @type {string}
*/
ydn.db.Key.prototype.store_name;
/**
* @private
* @type {ydn.db.Key?}
*/
ydn.db.Key.prototype.parent;
/**
* @return {!Object} key in JSON object.
*/
ydn.db.Key.prototype.toJSON = function() {
var obj = {
'store': this.store_name,
'id': this.id
};
if (this.parent) {
obj['parent'] = this.parent.toJSON();
}
return obj;
};
/**
* Separator between child and parent.
* @const
* @type {string} seperator string.
*/
ydn.db.Key.SEP_PARENT = '^|';
/**
* Separator between table and key.
* @const {string}
*/
ydn.db.Key.SEP_STORE = '^:';
/**
* @override
* @return {string} seperator string.
*/
ydn.db.Key.prototype.valueOf = function() {
// necessary to make web-safe string ?
var parent_value = this.parent ? this.parent.valueOf() +
ydn.db.Key.SEP_PARENT : '';
return parent_value + this.store_name + ydn.db.Key.SEP_STORE + this.id;
};
/**
* @inheritDoc
*/
ydn.db.Key.prototype.toString = function() {
return this.valueOf().replace('^|', '|').replace('^:', ':');
};
/**
*
* @return {string} return store name.
*/
ydn.db.Key.prototype.getStoreName = function() {
return this.store_name;
};
/**
*
* @return {!IDBKey} key id.
*/
ydn.db.Key.prototype.getId = function() {
return this.id;
};
/**
*
* @return {string|number} normalized key.
*/
ydn.db.Key.prototype.getNormalizedId = function() {
if (goog.isArray(this.id)) {
return this.id.join(ydn.db.Key.SEP_PARENT);
} else if (this.id instanceof Date) {
return +(this.id);
} else {
return /** @type {string|number} */ (this.id);
}
};
/**
*
* @return {ydn.db.Key} return parent key if it has.
*/
ydn.db.Key.prototype.getParent = function() {
return this.parent;
};
/**
*
* @param {*} key key to test.
* @return {boolean} return true if given key is a valid key for IndexedDB.
*/
ydn.db.Key.isValidKey = function(key) {
if (!goog.isDefAndNotNull(key)) {
return false;
}
return goog.isNumber(key) || goog.isString(key) || key instanceof Date ||
(goog.isArray(key) && goog.array.every(/** @type {Array} */ (key),
ydn.db.Key.isValidKey));
};
/**
* Clone IDBKey.
* @param {IDBKey} key given key.
* @return {IDBKey} key to clone.
*/
ydn.db.Key.clone = function(key) {
if (goog.isArrayLike(key)) {
var clone = [];
for (var i = 0, n = key.length; i < n; i++) {
clone[i] = key[i];
}
return /** @type {IDBKey} */ (clone);
} else {
return key;
}
};