adding more "owned" attribute methods to Note entity

This commit is contained in:
zadam 2019-12-01 10:57:28 +01:00
parent 29eb5a8435
commit ba8a8dca7b

View File

@ -196,26 +196,36 @@ class Note extends Entity {
return null; return null;
} }
async loadOwnedAttributesToCache() {
this.__ownedAttributeCache = await repository.getEntities(`SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ?`, [this.noteId]);
return this.__ownedAttributeCache;
}
/** /**
* @returns {Promise<Attribute[]>} 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<Attribute[]>} note's "owned" attributes - excluding inherited ones
*/ */
async getOwnedAttributes(type, name) { async getOwnedAttributes(type, name) {
let query = `SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ?`; if (!this.__ownedAttributeCache) {
const params = [this.noteId]; await this.loadOwnedAttributesToCache();
if (type) {
query += ` AND type = ?`;
params.push(type);
} }
if (name) { if (type && name) {
query += ` AND name = ?`; return this.__ownedAttributeCache.filter(attr => attr.type === type && attr.name === name);
params.push(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<Attribute[]>} all note's attributes, including inherited ones * @returns {Promise<Attribute[]>} all note's attributes, including inherited ones
*/ */
async getAttributes(name) { async getAttributes(type, name) {
if (!this.__attributeCache) { if (!this.__attributeCache) {
await this.loadAttributesToCache(); 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); return this.__attributeCache.filter(attr => attr.name === name);
} }
else { else {
return this.__attributeCache; return this.__attributeCache.slice();
} }
} }
@ -258,7 +275,7 @@ class Note extends Entity {
* @returns {Promise<Attribute[]>} all note's labels (attributes with type label), including inherited ones * @returns {Promise<Attribute[]>} all note's labels (attributes with type label), including inherited ones
*/ */
async getLabels(name) { 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<Attribute[]>} all note's label definitions, including inherited ones * @returns {Promise<Attribute[]>} all note's label definitions, including inherited ones
*/ */
async getLabelDefinitions(name) { 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<Attribute[]>} all note's relations (attributes with type relation), including inherited ones * @returns {Promise<Attribute[]>} all note's relations (attributes with type relation), including inherited ones
*/ */
async getRelations(name) { 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<Attribute[]>} all note's relation definitions including inherited ones * @returns {Promise<Attribute[]>} all note's relation definitions including inherited ones
*/ */
async getRelationDefinitions(name) { 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() { invalidateAttributeCache() {
this.__attributeCache = null; this.__attributeCache = null;
this.__ownedAttributeCache = null;
} }
/** @returns {Promise<void>} */ /** @returns {Promise<void>} */
@ -381,6 +399,15 @@ class Note extends Entity {
return !!await this.getAttribute(type, name); return !!await this.getAttribute(type, name);
} }
/**
* @param {string} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name
* @returns {Promise<boolean>} 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} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name * @param {string} name - attribute name
@ -395,7 +422,7 @@ class Note extends Entity {
/** /**
* @param {string} type - attribute type (label, relation, etc.) * @param {string} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name * @param {string} name - attribute name
* @returns {Promise<string>} attribute value of given type and name or null if no such attribute exists. * @returns {Promise<string|null>} attribute value of given type and name or null if no such attribute exists.
*/ */
async getAttributeValue(type, name) { async getAttributeValue(type, name) {
const attr = await this.getAttribute(type, name); const attr = await this.getAttribute(type, name);
@ -403,6 +430,17 @@ class Note extends Entity {
return attr ? attr.value : null; return attr ? attr.value : null;
} }
/**
* @param {string} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name
* @returns {Promise<string|null>} 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. * Based on enabled, attribute is either set or removed.
* *
@ -430,7 +468,7 @@ class Note extends Entity {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async setAttribute(type, name, value) { 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); let attr = attributes.find(attr => attr.type === type && attr.name === name);
if (attr) { if (attr) {
@ -464,7 +502,7 @@ class Note extends Entity {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async removeAttribute(type, name, value) { async removeAttribute(type, name, value) {
const attributes = await this.getOwnedAttributes(); const attributes = await this.loadOwnedAttributesToCache();
for (const attribute of attributes) { for (const attribute of attributes) {
if (attribute.type === type && (value === undefined || value === attribute.value)) { 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); } async hasLabel(name) { return await this.hasAttribute(LABEL, name); }
/**
* @param {string} name - label name
* @returns {Promise<boolean>} true if label exists (excluding inherited)
*/
async hasOwnedLabel(name) { return await this.hasOwnedAttribute(LABEL, name); }
/** /**
* @param {string} name - relation name * @param {string} name - relation name
* @returns {Promise<boolean>} true if relation exists (including inherited) * @returns {Promise<boolean>} true if relation exists (including inherited)
*/ */
async hasRelation(name) { return await this.hasAttribute(RELATION, name); } async hasRelation(name) { return await this.hasAttribute(RELATION, name); }
/**
* @param {string} name - relation name
* @returns {Promise<boolean>} true if relation exists (excluding inherited)
*/
async hasOwnedRelation(name) { return await this.hasOwnedAttribute(RELATION, name); }
/** /**
* @param {string} name - label name * @param {string} name - label name
* @returns {Promise<Attribute>} label if it exists, null otherwise * @returns {Promise<Attribute|null>} label if it exists, null otherwise
*/ */
async getLabel(name) { return await this.getAttribute(LABEL, name); } async getLabel(name) { return await this.getAttribute(LABEL, name); }
/**
* @param {string} name - label name
* @returns {Promise<Attribute|null>} label if it exists, null otherwise
*/
async getOwnedLabel(name) { return await this.getOwnedAttribute(LABEL, name); }
/** /**
* @param {string} name - relation name * @param {string} name - relation name
* @returns {Promise<Attribute>} relation if it exists, null otherwise * @returns {Promise<Attribute|null>} relation if it exists, null otherwise
*/ */
async getRelation(name) { return await this.getAttribute(RELATION, name); } async getRelation(name) { return await this.getAttribute(RELATION, name); }
/**
* @param {string} name - relation name
* @returns {Promise<Attribute|null>} relation if it exists, null otherwise
*/
async getOwnedRelation(name) { return await this.getOwnedAttribute(RELATION, name); }
/** /**
* @param {string} name - label name * @param {string} name - label name
* @returns {Promise<string>} label value if label exists, null otherwise * @returns {Promise<string|null>} label value if label exists, null otherwise
*/ */
async getLabelValue(name) { return await this.getAttributeValue(LABEL, name); } async getLabelValue(name) { return await this.getAttributeValue(LABEL, name); }
/**
* @param {string} name - label name
* @returns {Promise<string|null>} label value if label exists, null otherwise
*/
async getOwnedLabelValue(name) { return await this.getOwnedAttributeValue(LABEL, name); }
/** /**
* @param {string} name - relation name * @param {string} name - relation name
* @returns {Promise<string>} relation value if relation exists, null otherwise * @returns {Promise<string|null>} relation value if relation exists, null otherwise
*/ */
async getRelationValue(name) { return await this.getAttributeValue(RELATION, name); } async getRelationValue(name) { return await this.getAttributeValue(RELATION, name); }
/**
* @param {string} name - relation name
* @returns {Promise<string|null>} relation value if relation exists, null otherwise
*/
async getOwnedRelationValue(name) { return await this.getOwnedAttributeValue(RELATION, name); }
/** /**
* @param {string} name * @param {string} name
* @returns {Promise<Note>|null} target note of the relation or null (if target is empty or note was not found) * @returns {Promise<Note>|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; return relation ? await repository.getNote(relation.value) : null;
} }
/**
* @param {string} name
* @returns {Promise<Note>|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. * Based on enabled, label is either set or removed.
* *