diff --git a/entity/Organisation_entity/recordcontainers/index/affectedIds.js b/entity/Organisation_entity/recordcontainers/index/affectedIds.js index a8b02566f9728cbe5a6c53033c884d780b6a71b8..ee11b9a9e9cf1d5ef4297d4b25d2da7fd27210a7 100644 --- a/entity/Organisation_entity/recordcontainers/index/affectedIds.js +++ b/entity/Organisation_entity/recordcontainers/index/affectedIds.js @@ -4,11 +4,13 @@ import("system.vars"); import("IndexSearch_lib"); import("Sql_lib"); -var infoContainer, onUpdFn, tableName, res; +var infoContainer, onUpdFn, tableName, res, action; tableName = vars.get("$local.table"); idValue = vars.get("$local.idvalue"); -infoContainer = IndexsearchUtils.createAffectedInfoContainer(idValue, null, vars.get("$local.action") +action = vars.get("$local.action"); + +infoContainer = IndexsearchUtils.createAffectedInfoContainer(idValue, null, action ,function (){return vars.get("$local.columns")} ,function (){return vars.get("$local.oldvalues")} ,function (){return vars.get("$local.values")}); @@ -19,13 +21,21 @@ switch (tableName) res = [idValue]; break; case "ORGANISATION": - res = newSelect("CONTACT.CONTACTID") + //if an organisation is created or deleted there is no need to do this for the ORGANISATION and CONTACT-table twice, since everytime a + //entry in ORGANISATION is done´, it is also done in CONTACT which is handled in the switch case above => skip then the ORGANISATION-part + //(also on delete the record does not exist anymore) + if (action == "U") + { + res = newSelect("CONTACT.CONTACTID") .from("CONTACT") .where("CONTACT.PERSON_ID is null") .and("CONTACT.ORGANISATION_ID", idValue) .arrayColumn(); + } break; case "ADDRESS": + //do not skip here if it's a delete action since it could be that only an address is removed and not a whole record-set of + //organisation, address, communication, etc. res = IndexsearchUtils.getAffectedIdValues("CONTACT_ID", infoContainer, function (id){ return newSelect("ADDRESS.CONTACT_ID") .from("ADDRESS") @@ -34,6 +44,8 @@ switch (tableName) }); break; case "COMMUNICATION": + //do not skip here if it's a delete action since it could be that only a communication-entry is removed and not a whole record-set of + //organisation, address, communication, etc. res = IndexsearchUtils.getAffectedIdValues("CONTACT_ID", infoContainer, function (id){ return newSelect("COMMUNICATION.CONTACT_ID") .from("COMMUNICATION") @@ -41,10 +53,10 @@ switch (tableName) .arrayColumn(); }); break; - default: - res = []; //needed, because the Index is being rebuilt if nothing gets returned } +//needed, because the complete index (fullIndexer) is being rebuilt if nothing gets returned here +if (res) result.object(res); - - +else + result.object([]); diff --git a/entity/Person_entity/recordcontainers/index/affectedIds.js b/entity/Person_entity/recordcontainers/index/affectedIds.js index 1cbcfeeb6850a41a4d13165adc198e5e10eb94c8..6a5716e6cc8f003f680f186b5bc46a13033e808b 100644 --- a/entity/Person_entity/recordcontainers/index/affectedIds.js +++ b/entity/Person_entity/recordcontainers/index/affectedIds.js @@ -4,11 +4,13 @@ import("system.vars"); import("IndexSearch_lib"); import("Sql_lib"); -var infoContainer, onUpdFn, tableName, res; +var infoContainer, onUpdFn, tableName, res, action; tableName = vars.get("$local.table"); idValue = vars.get("$local.idvalue"); -infoContainer = IndexsearchUtils.createAffectedInfoContainer(idValue, null, vars.get("$local.action") +action = vars.get("$local.action"); + +infoContainer = IndexsearchUtils.createAffectedInfoContainer(idValue, null, action ,function (){return vars.get("$local.columns")} ,function (){return vars.get("$local.oldvalues")} ,function (){return vars.get("$local.values")}); @@ -19,19 +21,32 @@ switch (tableName) res = [idValue]; break; case "PERSON": - res = newSelect("CONTACT.CONTACTID") - .from("CONTACT") - .where("CONTACT.PERSON_ID", idValue) - .arrayColumn(); + //if a contact person is created or deleted there is no need to determine the index-uid for the PERSON and CONTACT-table, since everytime a + //entry in PERSON is done, there is also one mande in the CONTACT table which is handled in the switch case above + //=> skip then the PERSON-part (also on delete the record does not exist anymore) + if (action == "U") + { + res = newSelect("CONTACT.CONTACTID") + .from("CONTACT") + .where("CONTACT.PERSON_ID", idValue) + .arrayColumn(); + } break; case "ORGANISATION": - res = newSelect("CONTACT.CONTACTID") - .from("CONTACT") - .where("CONTACT.ORGANISATION_ID", idValue) - .and("CONTACT.PERSON_ID is not null") - .arrayColumn(); + //an organisation can only be deleted if there are no persons left and if an organisation is created there is no entry for person that has + //to be indexed => only in the update-case necessary + if (action == "U") + { + res = newSelect("CONTACT.CONTACTID") + .from("CONTACT") + .where("CONTACT.ORGANISATION_ID", idValue) + .and("CONTACT.PERSON_ID is not null") + .arrayColumn(); + } break; case "ADDRESS": + //do not skip here if it's a delete action since it could be that only an address is removed and not a whole record-set of organisation, + //person, address, communication, etc. res = IndexsearchUtils.getAffectedIdValues("CONTACT_ID", infoContainer, function (id){ return newSelect("ADDRESS.CONTACT_ID") .from("ADDRESS") @@ -40,6 +55,8 @@ switch (tableName) }); break; case "COMMUNICATION": + //do not skip here if it's a delete action since it could be that only a communication-entry is removed and not a whole record-set of + //organisation, person, address, communication, etc. res = IndexsearchUtils.getAffectedIdValues("CONTACT_ID", infoContainer, function (id){ return newSelect("COMMUNICATION.CONTACT_ID") .from("COMMUNICATION") @@ -47,9 +64,10 @@ switch (tableName) .arrayColumn(); }); break; - default: - res = []; //needed, because the Index is being rebuilt if nothing gets returned - break; } - result.object(res); \ No newline at end of file +//needed, because the complete index (fullIndexer) is being rebuilt if nothing gets returned here +if (res) + result.object(res); +else + result.object([]); diff --git a/process/IndexSearch_lib/process.js b/process/IndexSearch_lib/process.js index 532ec972fe333d7fb1e89cf731d3127c8bd20a1b..be35ad2cc8c0a24fabe76bd57ba2a64d9ce9b310 100644 --- a/process/IndexSearch_lib/process.js +++ b/process/IndexSearch_lib/process.js @@ -5,20 +5,66 @@ import("system.text"); * provides static methods for special handling of entities in JDito-Processes * do not create an instance of this * - * TODO: lib has to be updated with new Indexsearch when it is available - * * @class */ function IndexsearchUtils() {} /** - * TODO: Comment everything! + * Searches within an affectedInfoContainer for an id value <br/> + * This id value can be used in the affectedIds-process of an index-recordContainer for example <br/> + * + * Depending on the provided action the given ID-field is searched in: <br/> + * <ul> + * <li>the newValues (action: I), no other values are yet present</li> + * <li>the oldValues (action: D), other values are not anymore present</li> + * <li>another source by calling a function (action: U), in the update case only values are provided that acutally changed so + * another source (usually the dattabase) is needed to perform the lookup</li> + * <li>Otherwise an empty array is given (action X for example)</li> + * </ul> + * + * @param {String} fieldname <p> Name of the field that shall be searched within the infocontainer + * @param {Object} affectedInfoContainer <p> affectedInfoContainer like it is provided by the IndexsearchUtils.createAffectedInfoContainer-function + * + * @param {Function} updateFn <p> a callback function that is called when an update-action is provided in the affectedInfoContianer + * (which means there are no [useful] newvalues/oldvalues) + * + * @return {Array} <p> 1D-array of Strings with all affectedIds that where found depeding on the information in the + * affectedInfoContainer + * @example + * //example for an affectedIds-procces for a indexer that is built on top of the database table OFFER + * //explanations of the example are written as code-comments + * ...imports, variables and more code here... + * //this is always the uid of the record that has been changed, so if an OFFER-entry has been changed the OFFERID is returned, if an OFFERITEM-entry + * //has been changed the OFFERITEMID is returned and so on + * var idValue = vars.get("$local.idvalue"); + * var infoContainer = ...code for creating a infoContainer... * - * @param {} fieldname - * @param {} affectedInfoContainer - * @param {} updateFn + * switch (tableName)//the tableName is always the name of the DB table that has been changed (changed = inserted, updated or deleted) + * { + * //if the OFFER itself has been changed it's very easy because it's possible to return the OFFERID directly + * case "OFFER": + * res = [idValue]; + * break; + * //for other items (like the OFFERITEM in this exmaple) however it is not that easy, because the index-UID is needed as result in the + * //affectedIdsProcess, so we have find the correct OFFERID for the OFFERITEM that has been changed + * // therefore we have to define the columnname of the index-UID we are searching within our table (here: OFFER_ID) and we have to define a + * //callback function that returns the index-UID with for the given ID of the record that has been changed [to see why we need a function see the + * //descriptiontext of this function] + * case "OFFERITEM": + * res = IndexsearchUtils.getAffectedIdValues("OFFER_ID", infoContainer, function (offerItemId){ + * return newSelect("OFFERITEM.OFFER_ID") + * .from("OFFERITEM") + * .where("OFFERITEM.OFFERITEMID", offerItemId) + * .arrayColumn(); + * }); + * break; + * } * - * @return {} + * //this needed as a savegate, because the Index is being rebuilt by the indexer if nothing gets returned => do a final check here! + * if (res) + * result.object(res); + * else + * result.object([]); */ IndexsearchUtils.getAffectedIdValues = function(fieldname, affectedInfoContainer, updateFn) { var affectedIds; @@ -26,30 +72,51 @@ IndexsearchUtils.getAffectedIdValues = function(fieldname, affectedInfoContainer { case "I": affectedIds = affectedInfoContainer.newValues[affectedInfoContainer.columns.indexOf(fieldname)]; - affectedIds = affectedIds ? [affectedIds] : [] + affectedIds = affectedIds ? [affectedIds] : [];//check if affectedIds are present because otherwise we may would return [null] break; case "U": affectedIds = updateFn.call(null, affectedInfoContainer.id); break; case "D": affectedIds = affectedInfoContainer.oldValues[affectedInfoContainer.columns.indexOf(fieldname)]; - affectedIds = affectedIds ? [affectedIds] : [] + affectedIds = affectedIds ? [affectedIds] : [];//check if affectedIds are present because otherwise we may would return [null] break; } - return affectedIds || []; + if(affectedIds) + return affectedIds; + else + return []; } /** - * TODO: Comment everything! + * Builds an object with various properties and returns the newly created object. + * The object that is retruned is so called affectedInfoContainer, but the type and prototype is still object.<br/> + * <br/> + * Each object represents one audited change in a db table with a sepcific type (insert, update, delete, etc.) for one row. + * The object is basically a unified blueprint for such a change.<br/> + * <br/> + * Main purpose of the object is to make the handling of given values within a affectedIdProcess in an entity-indexRecordContainer easier. + * However it could be used in other cases too, for example in the auditProcess. * - * @param {} changedIdValue - * @param {} changedTable - * @param {} action - * @param {} columnsFn - * @param {} oldValueFn - * @param {} newValueFn + * @param {String} changedIdValue <p> UID of the row where the change has been audited + * @param {String} changedTable <p> name of the db table where the change has been audited + * @param {String} action <p> action type of the audited change in short form, for exmaple: I, U, D, ... + * @param {Function} columnsFn <p> callbackFunction that has to return an array with the column names of the audited table + * @param {Function} oldValueFn <p> callbackFunction that has to return an array with the new values that exist after the audited change + * @param {Function} newValueFn <p> callbackFunction that has to return an array with the old values that have existed before the audited change * - * @return {} + * @return {Object} object with the following properties (values depend on the parameters): + * <ul> + * <li>id: uid of the changed record</li> + * <li>table: name of the database table of the changed record</li> + * <li>action: type of the change, this is usually "I" for insert, "U" for update, "D" for delete and "X" for unknown</li> + * <li>columns: array of column names of the table that have been audited (if present)</li> + * <li>oldValues: detemined values before the change (if present)</li> + * <li>newValues: detemined values after the change (if present)</li> + * </ul> + * <br/> + * Note that this only what the object SHOULD contain, the actual values depend on the input parameters. + * */ IndexsearchUtils.createAffectedInfoContainer = function(changedIdValue, changedTable, action, columnsFn, oldValueFn, newValueFn) { var res, internalStorage;