/*
* 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 methods or fields in C++ class
*
* @memberof PKM
* @instance
* @param {string} dbName - database name
* @param {string} className - class name
* @param {string} kind - either 'field' or 'method'
*
* @return {Promise<Array.<Object>>} a promise that passes the result (an array) to resolve callback
*/
function find_in_cpp_class(dbName, className, kind)
{
return new Promise(function(resolve, reject)
{
const debug = this.debug;
function search_element(document, id)
{
if(document.hasOwnProperty('id') && (document.id === id))
{
return document;
}
if(document.hasOwnProperty('inner'))
{
for(let i = 0; i < document.inner.length; ++i)
{
const inner_element = document.inner[i];
const found = search_element(inner_element, id)
if(found) return found;
}
}
return undefined;
}
function search(document, query)
{
let result = [];
if(document.hasOwnProperty('manifest'))
{
document.manifest.forEach((manifest_item) =>
{
if(((query.id === undefined) || (query.id === manifest_item.id)) &&
((query.kind === undefined) || ((typeof query.kind === 'string') && (query.kind === manifest_item.kind)) || ((query.kind instanceof RegExp) && query.kind.test(manifest_item.kind))) &&
((query.path === undefined) || ((typeof query.path === 'string') && (query.path === manifest_item.path)) || ((query.path instanceof RegExp) && query.path.test(manifest_item.path))))
{
document.inner.forEach((inner_element) =>
{
const found = search_element(inner_element, manifest_item.id);
if(found !== undefined)
{
result.push(found);
}
});
}
});
}
return result;
}
if((kind === 'field') || (kind === 'method'))
{
let get_doc_query =
{
$and :
[
{
'manifest.path' : className
},
{
$or :
[
{ 'manifest.kind' : 'class' },
{ 'manifest.kind' : 'struct' },
{ 'manifest.kind' : 'union' }
]
}
]
};
this.get_documents(dbName, 'sourcecodeCPP', get_doc_query).then((documents) =>
{
let search_promises = documents.map((document) => new Promise((resolve, reject) =>
{
let result = [];
let class_documents = search(document, { kind : new RegExp('^class$|^struct$|^union$'), path : className });
const CppClass = require('../util/cpp_class');
class_documents.map(class_document => new CppClass(class_document)).forEach((cpp_class) =>
{
if(cpp_class.hasOwnProperty(kind + 's'))
{
cpp_class[kind + 's'].forEach(({ id }) =>
{
let class_member = search_element(cpp_class, id);
if(class_member !== undefined)
{
result.push(class_member);
}
});
}
});
resolve(result);
}));
Promise.all(search_promises).then((results) =>
{
let result = results.reduce((acc, val) => acc.concat(val), []);
resolve(result);
});
}).catch((err) =>
{
reject(this.Error(err));
});
}
else
{
reject(this.BadRequest('bad kind'));
}
}.bind(this));
}
exports.find_in_cpp_class = find_in_cpp_class;