/*
* This file is part of PKM (Persistent Knowledge Monitor).
* Copyright (c) 2020 Capgemini Group, Commissariat à l'énergie atomique et aux énergies alternatives,
* OW2, Sysgo AG, Technikon, Tree Technology, Universitat Politècnica de València.
*
* PKM is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation.
*
* PKM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with PKM. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Get Traceability Matrix Documents
*
* @memberof PKM
* @instance
* @param {string} dbName - database name
* @param {string} [query] - query
* @param {Object} [options] - options
*
* @return {Promise.<Array<Object> >} a promise
*/
function get_traceability_matrix(dbName, query = {}, options = {})
{
return new Promise(async function(resolve, reject)
{
const debug = this.debug;
const collection_name = 'TraceabilityMatrix';
this.get_collection(dbName, collection_name).then(async (documents_collection) =>
{
let find_options = Object.assign({}, options);
delete delete find_options.rowRole;
if(options.skip !== undefined) delete find_options.skip;
if(options.limit !== undefined) delete find_options.limit;
let transposed_matrix;
switch(options.rowRole)
{
case 'target':
transposed_matrix = true;
break;
case 'source':
transposed_matrix = false;
break;
default:
reject(this.BadRequest('rowRole shall be target or source'));
}
// ask MongoDB to sort cells in ascending order
find_options.sort = transposed_matrix ? { tgt_path : 1, tgt_access : 1, src_path : 1, src_access : 1 }
: { src_path : 1, src_access : 1, tgt_path : 1, tgt_access : 1 };
let document_cursor = documents_collection.find(query, find_options);
let documents = [];
let row = 0;
let col = 0;
let last_document;
let error;
// scan cells
while(await document_cursor.hasNext().catch((err) => { error = err }))
{
// get cell
const document = await document_cursor.next().catch((err) => { error = err });
if(error !== undefined) break;
// detect row change, and compute row and column numbers
if(last_document !== undefined)
{
if((transposed_matrix && ((document.tgt_path != last_document.tgt_path) || (document.tgt_access != last_document.tgt_access))) ||
(!transposed_matrix && ((document.src_path != last_document.src_path) || (document.src_access != last_document.src_access))))
{
++row;
col = 0;
}
else
{
++col;
}
}
// stop scanning cells as soon as enough cells have been collected
if((options.toRow !== undefined) && ((row > options.toRow) || ((options.toColumn !== undefined) && (row == options.toRow) && (col > options.toColumn))))
{
break;
}
// filter cells
if(((options.fromRow === undefined) || (row >= options.fromRow)) &&
((options.fromColumn === undefined) || (col >= options.fromColumn)) &&
((options.toColumn === undefined) || (col <= options.toColumn)))
{
// add cell
// For debugging, uncomment lines below
// document.row = row;
// document.col = col;
// document.transposed_matrix = transposed_matrix;
documents.push(this.fix_document(document, collection_name));
}
last_document = document;
}
if(error !== undefined)
{
reject(this.Error(error));
}
else
{
resolve(documents);
}
}).catch((err) =>
{
reject(this.Error(err));
});
}.bind(this));
}
exports.get_traceability_matrix = get_traceability_matrix;