<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Folke.Orm
{
    public static class ManyToOneHelpers
    {
        /// <summary>
        /// Updates a collection of items from a collection of item views. Existing items are updated or deleted. New items are added.
        /// </summary>
        /// <typeparam name="TChild">The database item</typeparam>
        /// <typeparam name="TChildView">A view of this database item. Matching items have same Id</typeparam>
        /// <param name="connection">The database connection</param>
        /// <param name="currentValues">The current value from the database</param>
        /// <param name="newValues">The new values</param>
        /// <param name="factory">A factory that create a new item</param>
        /// <param name="updater">A delegate that updates an existing item</param>
        public static void UpdateCollectionFromViews<TChild, TChildView>(this IFolkeConnection connection, IEnumerable<TChild> currentValues, IEnumerable<TChildView> newValues,
            Func<TChildView, TChild> factory, Func<TChildView, TChild, bool> updater)
            where TChild: class, IFolkeTable, new()
            where TChildView: class, IFolkeTable, new()
        {
            var newValueToAdd = newValues.Where(x => currentValues.All(y => y.Id != x.Id));
            foreach (var currentValue in currentValues)
            {
                var newValue = newValues.FirstOrDefault(x => x.Id == currentValue.Id);
                if (newValue == null)
                {
                    connection.Delete(currentValue);
                }
                else
                {
                    if (updater(newValue, currentValue))
                        connection.Update(currentValue);
                }
            }

            foreach (var childDto in newValueToAdd)
            {
                var child = factory(childDto);
                connection.Save(child);
            }
        }

        /// <summary>
        /// Update a collection of items using a collection of values. These values don't have an id to identity them, so a areEqual delegate
        /// must be given as a parameter. Existing items that is not in newValues are deleted. 
        /// </summary>
        /// <typeparam name="TChild">The database item type</typeparam>
        /// <typeparam name="TChildView">The view type</typeparam>
        /// <param name="connection">The database connection</param>
        /// <param name="currentValues">The current value from the database</param>
        /// <param name="newValues">The new values</param>
        /// <param name="areEqual">Must return true if the two values are equal</param>
        /// <param name="factory">Create a new item</param>
        public static void UpdateCollectionFromValues<TChild, TChildView>(this IFolkeConnection connection, IEnumerable<TChild> currentValues, IEnumerable<TChildView> newValues,
            Func<TChildView, TChild> factory, Func<TChildView, TChild, bool> areEqual)
            where TChild : class, IFolkeTable, new()
        {
            var newValueToAdd = newValues.Where(x => currentValues.All(y => !areEqual(x, y)));
            foreach (var currentValue in currentValues)
            {
                var newValue = newValues.FirstOrDefault(x => areEqual(x, currentValue));
                if (newValue == null)
                {
                    connection.Delete(currentValue);
                }
            }
<commit_msg>Fix a bug in UpdateCollectionFromValues<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Folke.Orm
{
    public static class ManyToOneHelpers
    {
        /// <summary>
        /// Updates a collection of items from a collection of item views. Existing items are updated or deleted. New items are added.
        /// </summary>
        /// <typeparam name="TChild">The database item</typeparam>
        /// <typeparam name="TChildView">A view of this database item. Matching items have same Id</typeparam>
        /// <param name="connection">The database connection</param>
        /// <param name="currentValues">The current value from the database</param>
        /// <param name="newValues">The new values</param>
        /// <param name="factory">A factory that create a new item</param>
        /// <param name="updater">A delegate that updates an existing item</param>
        public static void UpdateCollectionFromViews<TChild, TChildView>(this IFolkeConnection connection, IEnumerable<TChild> currentValues, IEnumerable<TChildView> newValues,
            Func<TChildView, TChild> factory, Func<TChildView, TChild, bool> updater)
            where TChild: class, IFolkeTable, new()
            where TChildView: class, IFolkeTable, new()
        {
            var newValueToAdd = newValues.Where(x => currentValues.All(y => y.Id != x.Id));
            foreach (var currentValue in currentValues)
            {
                var newValue = newValues.FirstOrDefault(x => x.Id == currentValue.Id);
                if (newValue == null)
                {
                    connection.Delete(currentValue);
                }
                else
                {
                    if (updater(newValue, currentValue))
                        connection.Update(currentValue);
                }
            }

            foreach (var childDto in newValueToAdd)
            {
                var child = factory(childDto);
                connection.Save(child);
            }
        }

        /// <summary>
        /// Update a collection of items using a collection of values. These values don't have an id to identity them, so a areEqual delegate
        /// must be given as a parameter. Existing items that is not in newValues are deleted. 
        /// </summary>
        /// <typeparam name="TChild">The database item type</typeparam>
        /// <typeparam name="TChildView">The view type</typeparam>
        /// <param name="connection">The database connection</param>
        /// <param name="currentValues">The current value from the database</param>
        /// <param name="newValues">The new values</param>
        /// <param name="areEqual">Must return true if the two values are equal</param>
        /// <param name="factory">Create a new item</param>
        public static void UpdateCollectionFromValues<TChild, TChildView>(this IFolkeConnection connection, IEnumerable<TChild> currentValues, IEnumerable<TChildView> newValues,
            Func<TChildView, TChild> factory, Func<TChildView, TChild, bool> areEqual)
            where TChild : class, IFolkeTable, new()
        {
            var newValueToAdd = newValues.Where(x => currentValues.All(y => !areEqual(x, y)));
            foreach (var currentValue in currentValues)
            {
                if (!newValues.Any(x => areEqual(x, currentValue)))
                {
                    connection.Delete(currentValue);
                }
            }

{'fraction_non_alphanumeric': 0.10492505353319058, 'fraction_numerical': 0.0, 'mean_word_length': 2.129075480125056, 'pattern_counts': {'":': 0, '<': 87, '<?xml version=': 0, '>': 99, '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': '2948115', 'n_tokens_mistral': 1780, 'n_tokens_neox': 1746, 'n_words': 532}