/*
* 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/>.
*/
/**
* Find in Documentation
*
* @memberof PKM
* @instance
* @param {string} dbName - database name
* @param {Object} [query] - query
* @param {Object} [options] - options
*
* @return {Promise<Array.<Object>>} a promise
*/
function find_in_doc(dbName, query = {}, options = {})
{
return new Promise(function(resolve, reject)
{
const member_keys = [ 'invariant', 'field', 'method', 'type', 'macro', 'constant' ];
let get_doc_query = {};
let get_doc_options;
let search_query = {};
let querying_member = false;
const query_is_empty = Object.keys(query).length == 0;
if(query.id !== undefined)
{
search_query.id = query.id;
}
if((query.id === undefined) &&
((query.doc !== undefined) ||
(query.filename !== undefined) ||
(query.unit !== undefined) ||
(query.class !== undefined) ||
(query.invariant !== undefined) ||
(query.field !== undefined) ||
(query.method !== undefined) ||
(query.type !== undefined) ||
(query.macro !== undefined) ||
(query.member !== undefined)))
{
get_doc_options = Object.assign({}, options);
if(get_doc_options.skip !== undefined) delete get_doc_options.skip;
if(get_doc_options.limit !== undefined) delete get_doc_options.limit;
get_doc_query.$and = [];
if((query.doc !== undefined) || (query.filename !== undefined))
{
let get_doc_id_query = [];
if((query.doc !== undefined) && query.doc.startsWith('/') && query.doc.endsWith('/'))
{
get_doc_id_query.push({ name : { $regex : query.doc.slice(1, query.doc.length - 1) } });
}
else
{
get_doc_id_query.push({ name : query.doc });
}
if((query.filename !== undefined) && query.filename.startsWith('/') && query.filename.endsWith('/'))
{
get_doc_id_query.push({ sourceFile : { $regex : query.filename.slice(1, query.filename.length - 1) } });
}
else
{
get_doc_id_query.push({ sourceFile : query.filename });
}
get_doc_query.$and.push(get_doc_id_query);
}
if(query.unit !== undefined)
{
if(query.unit.startsWith('/') && query.unit.endsWith('/'))
{
get_doc_query.$and.push({ 'units.name' : { $regex : query.unit.slice(1, query.unit.length - 1) } });
search_query.unit = new RegExp(query.unit.slice(1, query.unit.length - 1));
}
else
{
get_doc_query.$and.push({ 'units.name' : query.unit });
search_query.unit = query.unit;
}
}
if(query.class !== undefined)
{
if(query.class.startsWith('/') && query.class.endsWith('/'))
{
get_doc_query.$and.push({ 'units.classes.name' : { $regex : query.class.slice(1, query.class.length - 1) } });
search_query.class = new RegExp(query.class.slice(1, query.class.length - 1));
}
else
{
get_doc_query.$and.push({ 'units.classes.name' : query.class });
search_query.class = query.class;
}
}
if((query.invariant !== undefined) ||
(query.field !== undefined) ||
(query.method !== undefined) ||
(query.type !== undefined) ||
(query.macro !== undefined) ||
(query.member !== undefined))
{
querying_member = true;
get_doc_member_query = [];
member_keys.forEach((key) =>
{
if((query[key] !== undefined) || (query.member !== undefined))
{
let q = {};
if(query.member !== undefined)
{
if(query.member.startsWith('/') && query.member.endsWith('/'))
{
q['units.classes.' + key + 's.name'] = { $regex : query.member.slice(1, query.member.length - 1) };
search_query[key] = new RegExp(query.member.slice(1, query.member.length - 1));
}
else
{
q['units.classes.' + key + 's.name'] = query.member;
search_query[key] = query.member;
}
}
else if(query[key].startsWith('/') && query[key].endsWith('/'))
{
q['units.classes.' + key + 's.name'] = { $regex : query[key].slice(1, query[key].length - 1) };
search_query[key] = new RegExp(query[key].slice(1, query[key].length - 1));
}
else
{
q['units.classes.' + key + 's.name'] = query[key];
search_query[key] = query[key];
}
get_doc_member_query.push(q);
}
});
get_doc_query.$and.push({ $or : get_doc_member_query });
}
}
else
{
get_doc_options = options;
}
this.get_documents(dbName, 'Documentation', get_doc_query, get_doc_options).then((doc_documents) =>
{
if((search_query.id !== undefined) ||
(search_query.unit !== undefined) ||
(search_query.class !== undefined) ||
querying_member)
{
let result = [];
doc_documents.forEach((doc_document) =>
{
if(Array.isArray(doc_document.units))
{
doc_document.units.forEach((unit) =>
{
if((search_query.id !== undefined) ||
(search_query.unit === undefined) || // match all
((typeof search_query.unit === 'string') && (search_query.unit === unit.name)) || // match bare string
((search_query.unit instanceof RegExp) && search_query.unit.test(unit.name))) // match regular expression
{
if((search_query.id !== undefined) || (search_query.class !== undefined) || querying_member)
{
if(Array.isArray(unit.classes))
{
unit.classes.forEach((cls) =>
{
if((search_query.id !== undefined) ||
(search_query.class === undefined) ||
((typeof search_query.class === 'string') && (search_query.class === cls.name)) || // match all
((search_query.class instanceof RegExp) && search_query.class.test(cls.name))) // match bare string
{ // match regular expression
if(querying_member)
{
member_keys.forEach((key) =>
{
if(search_query[key] !== undefined)
{
const members = cls[key + 's'];
if(Array.isArray(members))
{
members.forEach((member) =>
{
if(((search_query.id === undefined) || (search_query.id === member.id)) && // match id
(((typeof search_query[key] === 'string') && (search_query[key] === member.name)) || // match bare string
((search_query[key] instanceof RegExp) && search_query[key].test(member.name)))) // match regular expression
{
member.type = 'DocClass' + key.substring(0,1).toUpperCase() + key.substring(1);
result.push(member);
}
});
}
}
});
}
else if((search_query.id === undefined) || (search_query.id === cls.id))
{
cls.type = 'DocClass';
result.push(cls);
}
}
});
}
}
else if((search_query.id === undefined) || (search_query.id === unit.id))
{
unit.type = 'DocUnit';
result.push(unit);
}
}
});
}
});
if(result.length || query_is_empty)
{
if((options.skip !== undefined) || (options.limit !== undefined))
{
let start = options.skip || 0;
let end = start + (options.limit ? options.limit : result.length);
resolve(result.slice(start, end));
}
else
{
resolve(result);
}
}
else
{
reject(this.NotFound());
}
}
else if(search_query.id === undefined)
{
resolve(doc_documents);
}
}).catch((err) =>
{
reject(this.Error(err));
});
}.bind(this));
}
exports.find_in_doc = find_in_doc;