/*
* 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/>.
*/
/** Postprocess Files. Merge file chunk documents into file documents.
*
* @memberof PKM
* @instance
* @param {string} dbName - Database name
* @param {Array.<Object>} file_chunk_documents - File chunk documents
* @param {Object} [options] - options
*
* @return {Promise<Array.<Object>>} a promise
*/
function postprocess_files(file_chunk_documents, options = {})
{
return new Promise(function(resolve, reject)
{
let file_documents = [];
// the file chunk document may be out-of-order, so we first need to reorder the chunks for each filename
let chunks_per_filename = new Map();
file_chunk_documents.forEach((file_chunk_document) =>
{
if(chunks_per_filename.has(file_chunk_document.filename))
{
let chunks = chunks_per_filename.get(file_chunk_document.filename);
if(!file_chunk_document.hasOwnProperty('chunkId'))
{
throw Error('File database object named ' + file_chunk_document.filename + ' has no chunk field');
}
if(file_chunk_document.chunkId > chunks.length)
{
while(file_chunk_document.chunkId > chunks.length) chunks.push(undefined); // expand chunks array with holes (holes shall vanish before the end of the process)
chunks.push(file_chunk_document);
}
else
{
chunks[file_chunk_document.chunkId] = file_chunk_document;
}
}
else
{
let chunks = [];
if(file_chunk_document.hasOwnProperty('chunkId'))
{
while(file_chunk_document.chunkId > chunks.length) chunks.push(undefined); // expand chunks array with holes (holes shall vanish before the end of the process)
}
chunks.push(file_chunk_document);
chunks_per_filename.set(file_chunk_document.filename, chunks);
}
});
// for each filename
Array.from(chunks_per_filename.keys()).forEach((filename) =>
{
let chunks = chunks_per_filename.get(filename);
let fileFormat;
let has_filecontent;
// check that the integrity of chunks, in particular that there are no holes, that file format and content presence are coherent among the chunks
chunks.forEach((chunk) =>
{
if(chunk === undefined)
{
throw Error('File chunks for ' + filename + ' have holes');
}
if(fileFormat === undefined)
{
fileFormat = chunk.fileFormat;
}
if(has_filecontent === undefined)
{
has_filecontent = (chunk.filecontent !== undefined);
}
if(chunk.fileFormat !== fileFormat)
{
throw Error('File chunks for ' + filename + ' have different formats');
}
if(has_filecontent ^ (chunk.filecontent !== undefined))
{
throw Error('some File chunks for ' + filename + ' have contents, some others have not');
}
});
// merge content of the chunks
let file_chunk_document = chunks[0];
let file_document =
{
filecontent : ((file_chunk_document.filecontent !== undefined) ? chunks.map((chunk) => chunk.filecontent).join('') : undefined),
};
[ 'filename', 'fileType', 'fileMimeType', 'fileFormat', 'fileEncoding', 'gitWorkingTree', 'gitDirty', 'gitUnmerged' ].forEach((key) =>
{
if(file_chunk_document[key] !== undefined)
{
file_document[key] = file_chunk_document[key];
}
});
file_documents.push(file_document);
});
// serve the file documents
resolve(file_documents);
}.bind(this));
}
module.exports.postprocess_files = postprocess_files;