<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Signum.Utilities;
using System.Data.SqlClient;
using Signum.Entities;
using Signum.Utilities.DataStructures;
using Signum.Engine;
using System.Data;
using Signum.Entities.Reflection;
using Signum.Engine.Maps;
using Signum.Engine.Properties;

namespace Signum.Engine
{
    internal static class Saver
    {
        public static void SaveAll(IdentifiableEntity[] idents)
        {
            Save(() => GraphExplorer.FromRoots(idents));
        }

        public static void Save(IdentifiableEntity ident)
        {
            Save(() => GraphExplorer.FromRoot(ident));
        }

        static readonly IdentifiableEntity[] None = new IdentifiableEntity[0];

        static void Save(Func<DirectedGraph<Modifiable>> createGraph)
        {
            DirectedGraph<Modifiable> modifiables = GraphExplorer.PreSaving(createGraph);

            Schema schema = Schema.Current;
            modifiables = GraphExplorer.ModifyGraph(modifiables, (Modifiable m, ref bool graphModified) =>
                {
                    IdentifiableEntity ident = m as IdentifiableEntity;

                    if (ident != null)
                        schema.OnPreSaving(ident, ref graphModified);
                }, createGraph);

            string error = GraphExplorer.Integrity(modifiables);
            if (error.HasText())
                throw new ApplicationException(error);

            GraphExplorer.PropagateModifications(modifiables.Inverse());

            //colapsa modifiables (collections and embeddeds) keeping indentifiables only
            DirectedGraph<IdentifiableEntity> identifiables = GraphExplorer.ColapseIdentifiables(modifiables);

            foreach (var node in identifiables)
                schema.OnSaving(node);

            //Remove all the edges that doesn't mean a dependency
            identifiables.RemoveAll(identifiables.Edges.Where(e => !e.To.IsNew).ToList());

            //Remove all the nodes that are not modified
            List<IdentifiableEntity> notModified = identifiables.Where(node => node.Modified == false).ToList();

            notModified.ForEach(node => identifiables.RemoveFullNode(node, None));

            //separa las conexiones 'prohibidas' de las buenas
            DirectedGraph<IdentifiableEntity> backEdges = identifiables.FeedbackEdgeSet();

            if (backEdges.IsEmpty())
                backEdges = null;
            else
                identifiables.RemoveAll(backEdges.Edges);

            IEnumerable<HashSet<IdentifiableEntity>> groups = identifiables.CompilationOrderGroups();

            foreach (var group in groups)
            {
                SaveGroup(schema, group, backEdges);
            }

            if (backEdges != null)
            {
                var postSavings = backEdges.Edges.Select(e => e.From).ToHashSet();

                SaveGroup(schema, postSavings, null);
            }

            EntityCache.Add(identifiables);
            EntityCache.Add(notModified);
        }

        private static void SaveGroup(Schema schema, HashSet<IdentifiableEntity> group, DirectedGraph<IdentifiableEntity> backEdges)
        {
            foreach (var gr in group.GroupBy(a => new { Type = a.GetType(), a.IsNew }).ToList())
            {
                var table = schema.Table(gr.Key.Type);
                if (gr.Key.IsNew)<commit_msg>fix spelling<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Signum.Utilities;
using System.Data.SqlClient;
using Signum.Entities;
using Signum.Utilities.DataStructures;
using Signum.Engine;
using System.Data;
using Signum.Entities.Reflection;
using Signum.Engine.Maps;
using Signum.Engine.Properties;

namespace Signum.Engine
{
    internal static class Saver
    {
        public static void SaveAll(IdentifiableEntity[] idents)
        {
            Save(() => GraphExplorer.FromRoots(idents));
        }

        public static void Save(IdentifiableEntity ident)
        {
            Save(() => GraphExplorer.FromRoot(ident));
        }

        static readonly IdentifiableEntity[] None = new IdentifiableEntity[0];

        static void Save(Func<DirectedGraph<Modifiable>> createGraph)
        {
            DirectedGraph<Modifiable> modifiables = GraphExplorer.PreSaving(createGraph);

            Schema schema = Schema.Current;
            modifiables = GraphExplorer.ModifyGraph(modifiables, (Modifiable m, ref bool graphModified) =>
                {
                    IdentifiableEntity ident = m as IdentifiableEntity;

                    if (ident != null)
                        schema.OnPreSaving(ident, ref graphModified);
                }, createGraph);

            string error = GraphExplorer.Integrity(modifiables);
            if (error.HasText())
                throw new ApplicationException(error);

            GraphExplorer.PropagateModifications(modifiables.Inverse());

            //colapsa modifiables (collections and embeddeds) keeping indentifiables only
            DirectedGraph<IdentifiableEntity> identifiables = GraphExplorer.ColapseIdentifiables(modifiables);

            foreach (var node in identifiables)
                schema.OnSaving(node);

            //Remove all the edges that doesn't mean a dependency
            identifiables.RemoveAll(identifiables.Edges.Where(e => !e.To.IsNew).ToList());

            //Remove all the nodes that are not modified
            List<IdentifiableEntity> notModified = identifiables.Where(node => node.Modified == false).ToList();

            notModified.ForEach(node => identifiables.RemoveFullNode(node, None));

            //takes apart the 'forbidden' connections from the good ones
            DirectedGraph<IdentifiableEntity> backEdges = identifiables.FeedbackEdgeSet();

            if (backEdges.IsEmpty())
                backEdges = null;
            else
                identifiables.RemoveAll(backEdges.Edges);

            IEnumerable<HashSet<IdentifiableEntity>> groups = identifiables.CompilationOrderGroups();

            foreach (var group in groups)
            {
                SaveGroup(schema, group, backEdges);
            }

            if (backEdges != null)
            {
                var postSavings = backEdges.Edges.Select(e => e.From).ToHashSet();

                SaveGroup(schema, postSavings, null);
            }

            EntityCache.Add(identifiables);
            EntityCache.Add(notModified);
        }

        private static void SaveGroup(Schema schema, HashSet<IdentifiableEntity> group, DirectedGraph<IdentifiableEntity> backEdges)
        {
            foreach (var gr in group.GroupBy(a => new { Type = a.GetType(), a.IsNew }).ToList())
            {
                var table = schema.Table(gr.Key.Type);
                if (gr.Key.IsNew)
{'fraction_non_alphanumeric': 0.0903150863946566, 'fraction_numerical': 0.0002904022070567736, 'mean_word_length': 2.2893982808022924, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 39, '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': '6317762', 'n_tokens_mistral': 1831, 'n_tokens_neox': 1751, 'n_words': 396}