<commit_before>import _ from 'lodash';
import createError from 'create-error';

/** Thrown when mapOne does not find an object in the resultSet and "isRequired" is passed in as true */
let NotFoundError = createError('NotFoundError');

/**
 * Maps a resultSet to an array of objects.
 *
 * @param {Array} resultSet - an array of database results
 * @param {Array} maps - an array of result maps
 * @param {String} mapId - mapId of the top-level objects in the resultSet
 * @param {String} [columnPrefix] - prefix that should be applied to the column names of the top-level objects
 * @returns {Array} array of mapped objects
 */
function map(resultSet, maps, mapId, columnPrefix) {

    let mappedCollection = [];

    _.each(resultSet, function(result) {
        injectResultInCollection(result, mappedCollection, maps, mapId, columnPrefix);
    });

    return mappedCollection;
}

/**
 * Maps a resultSet to a single object.
 *
 * Although the result is a single object, resultSet may have multiple results (e.g. when the
 * top-level object has many children in a one-to-many relationship). So mapOne() must still
 * call map(), only difference is that it will return only the first result.
 *
 * @param {Array} resultSet - an array of database results
 * @param {Array} maps - an array of result maps
 * @param {String} mapId - mapId of the top-level object in the resultSet
 * @param {String} [columnPrefix] - prefix that should be applied to the column names of the top-level object
 * @param {boolean} [isRequired] - is it required to have a mapped object as a return value? Default is true.
 * @returns {Object} one mapped object or null
 * @throws {NotFoundError} if object is not found and isRequired is true
 */
function mapOne(resultSet, maps, mapId, columnPrefix, isRequired) {

    // Set up a default value for isRequired
    if (isRequired === undefined) {
        isRequired = true;
    }

    var mappedCollection = map(resultSet, maps, mapId, columnPrefix);

    if (mappedCollection.length > 0) {
        return mappedCollection[0];
    }
    else if (isRequired) {
        throw new NotFoundError('EmptyResponse');
    }
    else {
        return null;
    }
}

/**
 * Maps a single database result to a single object using mapId and injects it into mappedCollection.
 *
 * @param {Object} result - a single database result (one row)
 * @param {Array} mappedCollection - the collection in which the mapped object should be injected.
 * @param {Array} maps - an array of result maps
 * @param {String} mapId - mapId of the top-level objects in the resultSet
 * @param {String} [columnPrefix] - prefix that should be applied to the column names of the top-level objects
 */
function injectResultInCollection(result, mappedCollection, maps, mapId, columnPrefix) {

    // Set up a default value for columnPrefix
    if (columnPrefix === undefined) {
        columnPrefix = '';
    }

    // Check if the object is already in mappedCollection
    let resultMap = _.find(maps, 'mapId', mapId);
    let idProperty = getIdProperty(resultMap);
    let mappedObject = _.find(mappedCollection, idProperty.name, result[columnPrefix + idProperty.column]);

    // Create mappedObject if it does not exist in mappedCollection
    if (!mappedObject) {
        mappedObject = createMappedObject(resultMap);
        mappedCollection.push(mappedObject);
    }

    // Inject result in object
    injectResultInObject(result, mappedObject, maps, mapId, columnPrefix);
}

/**
 * Injects id, properties, associations and collections to the supplied mapped object.
 *
 * @param {Object} result - a single database result (one row)
 * @param {Object} mappedObject - the object in which result needs to be injected<commit_msg>gracefully not adding objects whose id field is null<commit_after>import _ from 'lodash';
import createError from 'create-error';

/** Thrown when mapOne does not find an object in the resultSet and "isRequired" is passed in as true */
let NotFoundError = createError('NotFoundError');

/**
 * Maps a resultSet to an array of objects.
 *
 * @param {Array} resultSet - an array of database results
 * @param {Array} maps - an array of result maps
 * @param {String} mapId - mapId of the top-level objects in the resultSet
 * @param {String} [columnPrefix] - prefix that should be applied to the column names of the top-level objects
 * @returns {Array} array of mapped objects
 */
function map(resultSet, maps, mapId, columnPrefix) {

    let mappedCollection = [];

    _.each(resultSet, function(result) {
        injectResultInCollection(result, mappedCollection, maps, mapId, columnPrefix);
    });

    return mappedCollection;
}

/**
 * Maps a resultSet to a single object.
 *
 * Although the result is a single object, resultSet may have multiple results (e.g. when the
 * top-level object has many children in a one-to-many relationship). So mapOne() must still
 * call map(), only difference is that it will return only the first result.
 *
 * @param {Array} resultSet - an array of database results
 * @param {Array} maps - an array of result maps
 * @param {String} mapId - mapId of the top-level object in the resultSet
 * @param {String} [columnPrefix] - prefix that should be applied to the column names of the top-level object
 * @param {boolean} [isRequired] - is it required to have a mapped object as a return value? Default is true.
 * @returns {Object} one mapped object or null
 * @throws {NotFoundError} if object is not found and isRequired is true
 */
function mapOne(resultSet, maps, mapId, columnPrefix, isRequired) {

    // Set up a default value for isRequired
    if (isRequired === undefined) {
        isRequired = true;
    }

    var mappedCollection = map(resultSet, maps, mapId, columnPrefix);

    if (mappedCollection.length > 0) {
        return mappedCollection[0];
    }
    else if (isRequired) {
        throw new NotFoundError('EmptyResponse');
    }
    else {
        return null;
    }
}

/**
 * Maps a single database result to a single object using mapId and injects it into mappedCollection.
 *
 * @param {Object} result - a single database result (one row)
 * @param {Array} mappedCollection - the collection in which the mapped object should be injected.
 * @param {Array} maps - an array of result maps
 * @param {String} mapId - mapId of the top-level objects in the resultSet
 * @param {String} [columnPrefix] - prefix that should be applied to the column names of the top-level objects
 */
function injectResultInCollection(result, mappedCollection, maps, mapId, columnPrefix) {

    // Set up a default value for columnPrefix
    if (columnPrefix === undefined) {
        columnPrefix = '';
    }

    // Check if the object is already in mappedCollection
    let resultMap = _.find(maps, 'mapId', mapId);
    let idProperty = getIdProperty(resultMap);
    let mappedObject = _.find(mappedCollection, idProperty.name, result[columnPrefix + idProperty.column]);

    // ignore null keys
    if ( result[columnPrefix + idProperty.column]) {
        // Create mappedObject if it does not exist in mappedCollection
        if (!mappedObject) {
            mappedObject = createMappedObject(resultMap);
            mappedCollection.push(mappedObject);
        }

        // Inject result in object
        injectResultInObject(result, mappedObject, maps, mapId, columnPrefix);
    }
}

/**
 * Injects id, properties, associations and collections to the supplied mapped object.
 *
 * @param {Object} result - a single database result (one row)
 * @param {Object} mappedObject - the object in which result needs to be injected
{'fraction_non_alphanumeric': 0.08921052631578948, 'fraction_numerical': 0.0005263157894736842, 'mean_word_length': 3.5270994639666466, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2792080', 'n_tokens_mistral': 2035, 'n_tokens_neox': 2004, 'n_words': 879}