From ba8a8dca7b56b12e5d7da594fa19768789bcfb24 Mon Sep 17 00:00:00 2001 From: zadam Date: Sun, 1 Dec 2019 10:57:28 +0100 Subject: [PATCH] adding more "owned" attribute methods to Note entity --- src/entities/note.js | 140 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 112 insertions(+), 28 deletions(-) diff --git a/src/entities/note.js b/src/entities/note.js index e9d4e1aba..567300804 100644 --- a/src/entities/note.js +++ b/src/entities/note.js @@ -196,26 +196,36 @@ class Note extends Entity { return null; } + async loadOwnedAttributesToCache() { + this.__ownedAttributeCache = await repository.getEntities(`SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ?`, [this.noteId]); + return this.__ownedAttributeCache; + } + /** - * @returns {Promise} attributes belonging to this specific note (excludes inherited attributes) + * This method is a faster variant of getAttributes() which looks for only owned attributes. + * Use when inheritance is not needed and/or in batch/performance sensitive operations. * - * This method can be significantly faster than the getAttributes() + * @param {string} [type] - (optional) attribute type to filter + * @param {string} [name] - (optional) attribute name to filter + * @returns {Promise} note's "owned" attributes - excluding inherited ones */ async getOwnedAttributes(type, name) { - let query = `SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ?`; - const params = [this.noteId]; - - if (type) { - query += ` AND type = ?`; - params.push(type); + if (!this.__ownedAttributeCache) { + await this.loadOwnedAttributesToCache(); } - if (name) { - query += ` AND name = ?`; - params.push(name); + if (type && name) { + return this.__ownedAttributeCache.filter(attr => attr.type === type && attr.name === name); + } + else if (type) { + return this.__ownedAttributeCache.filter(attr => attr.type === type); + } + else if (name) { + return this.__ownedAttributeCache.filter(attr => attr.name === name); + } + else { + return this.__ownedAttributeCache.slice(); } - - return await repository.getEntities(query, params); } /** @@ -237,19 +247,26 @@ class Note extends Entity { } /** - * @param {string} [name] - attribute name to filter + * @param {string} [type] - (optional) attribute type to filter + * @param {string} [name] - (optional) attribute name to filter * @returns {Promise} all note's attributes, including inherited ones */ - async getAttributes(name) { + async getAttributes(type, name) { if (!this.__attributeCache) { await this.loadAttributesToCache(); } - if (name) { + if (type && name) { + return this.__attributeCache.filter(attr => attr.type === type && attr.name === name); + } + else if (type) { + return this.__attributeCache.filter(attr => attr.type === type); + } + else if (name) { return this.__attributeCache.filter(attr => attr.name === name); } else { - return this.__attributeCache; + return this.__attributeCache.slice(); } } @@ -258,7 +275,7 @@ class Note extends Entity { * @returns {Promise} all note's labels (attributes with type label), including inherited ones */ async getLabels(name) { - return (await this.getAttributes(name)).filter(attr => attr.type === LABEL); + return await this.getAttributes(LABEL, name); } /** @@ -266,7 +283,7 @@ class Note extends Entity { * @returns {Promise} all note's label definitions, including inherited ones */ async getLabelDefinitions(name) { - return (await this.getAttributes(name)).filter(attr => attr.type === LABEL_DEFINITION); + return await this.getAttributes(LABEL_DEFINITION, name); } /** @@ -274,7 +291,7 @@ class Note extends Entity { * @returns {Promise} all note's relations (attributes with type relation), including inherited ones */ async getRelations(name) { - return (await this.getAttributes(name)).filter(attr => attr.type === RELATION); + return await this.getAttributes(RELATION, name); } /** @@ -297,7 +314,7 @@ class Note extends Entity { * @returns {Promise} all note's relation definitions including inherited ones */ async getRelationDefinitions(name) { - return (await this.getAttributes(name)).filter(attr => attr.type === RELATION_DEFINITION); + return await this.getAttributes(RELATION_DEFINITION, name); } /** @@ -306,6 +323,7 @@ class Note extends Entity { */ invalidateAttributeCache() { this.__attributeCache = null; + this.__ownedAttributeCache = null; } /** @returns {Promise} */ @@ -381,6 +399,15 @@ class Note extends Entity { return !!await this.getAttribute(type, name); } + /** + * @param {string} type - attribute type (label, relation, etc.) + * @param {string} name - attribute name + * @returns {Promise} true if note has an attribute with given type and name (excluding inherited) + */ + async hasOwnedAttribute(type, name) { + return !!await this.getOwnedAttribute(type, name); + } + /** * @param {string} type - attribute type (label, relation, etc.) * @param {string} name - attribute name @@ -395,7 +422,7 @@ class Note extends Entity { /** * @param {string} type - attribute type (label, relation, etc.) * @param {string} name - attribute name - * @returns {Promise} attribute value of given type and name or null if no such attribute exists. + * @returns {Promise} attribute value of given type and name or null if no such attribute exists. */ async getAttributeValue(type, name) { const attr = await this.getAttribute(type, name); @@ -403,6 +430,17 @@ class Note extends Entity { return attr ? attr.value : null; } + /** + * @param {string} type - attribute type (label, relation, etc.) + * @param {string} name - attribute name + * @returns {Promise} attribute value of given type and name or null if no such attribute exists. + */ + async getOwnedAttributeValue(type, name) { + const attr = await this.getOwnedAttribute(type, name); + + return attr ? attr.value : null; + } + /** * Based on enabled, attribute is either set or removed. * @@ -430,7 +468,7 @@ class Note extends Entity { * @returns {Promise} */ async setAttribute(type, name, value) { - const attributes = await this.getOwnedAttributes(); + const attributes = await this.loadOwnedAttributesToCache(); let attr = attributes.find(attr => attr.type === type && attr.name === name); if (attr) { @@ -464,7 +502,7 @@ class Note extends Entity { * @returns {Promise} */ async removeAttribute(type, name, value) { - const attributes = await this.getOwnedAttributes(); + const attributes = await this.loadOwnedAttributesToCache(); for (const attribute of attributes) { if (attribute.type === type && (value === undefined || value === attribute.value)) { @@ -508,36 +546,72 @@ class Note extends Entity { */ async hasLabel(name) { return await this.hasAttribute(LABEL, name); } + /** + * @param {string} name - label name + * @returns {Promise} true if label exists (excluding inherited) + */ + async hasOwnedLabel(name) { return await this.hasOwnedAttribute(LABEL, name); } + /** * @param {string} name - relation name * @returns {Promise} true if relation exists (including inherited) */ async hasRelation(name) { return await this.hasAttribute(RELATION, name); } + /** + * @param {string} name - relation name + * @returns {Promise} true if relation exists (excluding inherited) + */ + async hasOwnedRelation(name) { return await this.hasOwnedAttribute(RELATION, name); } + /** * @param {string} name - label name - * @returns {Promise} label if it exists, null otherwise + * @returns {Promise} label if it exists, null otherwise */ async getLabel(name) { return await this.getAttribute(LABEL, name); } + /** + * @param {string} name - label name + * @returns {Promise} label if it exists, null otherwise + */ + async getOwnedLabel(name) { return await this.getOwnedAttribute(LABEL, name); } + /** * @param {string} name - relation name - * @returns {Promise} relation if it exists, null otherwise + * @returns {Promise} relation if it exists, null otherwise */ async getRelation(name) { return await this.getAttribute(RELATION, name); } + /** + * @param {string} name - relation name + * @returns {Promise} relation if it exists, null otherwise + */ + async getOwnedRelation(name) { return await this.getOwnedAttribute(RELATION, name); } + /** * @param {string} name - label name - * @returns {Promise} label value if label exists, null otherwise + * @returns {Promise} label value if label exists, null otherwise */ async getLabelValue(name) { return await this.getAttributeValue(LABEL, name); } + /** + * @param {string} name - label name + * @returns {Promise} label value if label exists, null otherwise + */ + async getOwnedLabelValue(name) { return await this.getOwnedAttributeValue(LABEL, name); } + /** * @param {string} name - relation name - * @returns {Promise} relation value if relation exists, null otherwise + * @returns {Promise} relation value if relation exists, null otherwise */ async getRelationValue(name) { return await this.getAttributeValue(RELATION, name); } + /** + * @param {string} name - relation name + * @returns {Promise} relation value if relation exists, null otherwise + */ + async getOwnedRelationValue(name) { return await this.getOwnedAttributeValue(RELATION, name); } + /** * @param {string} name * @returns {Promise|null} target note of the relation or null (if target is empty or note was not found) @@ -548,6 +622,16 @@ class Note extends Entity { return relation ? await repository.getNote(relation.value) : null; } + /** + * @param {string} name + * @returns {Promise|null} target note of the relation or null (if target is empty or note was not found) + */ + async getOwnedRelationTarget(name) { + const relation = await this.getOwnedRelation(name); + + return relation ? await repository.getNote(relation.value) : null; + } + /** * Based on enabled, label is either set or removed. *