Click here to Skip to main content
15,898,134 members
Articles / Web Development / HTML

Transformalizing NorthWind

Rate me:
Please Sign up or sign in to vote.
4.95/5 (29 votes)
24 Jul 2014GPL37 min read 57.9K   341   53  
Combining de-normalization, transformation, replication, and awesome-ness.
#region License
// /*
// See license included in this library folder.
// */
#endregion
#undef GENERICS
//#define GENERICS
//#if NET_2_0


using System;
using System.Collections;
using Transformalize.Libs.FileHelpers.ErrorHandling;
using Transformalize.Libs.FileHelpers.Interfaces;

#if GENERICS
using System.Collections.Generic;
#endif

namespace Transformalize.Libs.FileHelpers.Engines
{
    /// <summary>
    ///     Engine used to create diff files based on the <see cref="IComparableRecord" /> interface.
    /// </summary>
#if NET_2_0
    [DebuggerDisplay("FileDiffEngine for type: {RecordType.Name}. ErrorMode: {ErrorManager.ErrorMode.ToString()}. Encoding: {Encoding.EncodingName}")]
#endif
#if ! GENERICS
    public sealed class FileDiffEngine : EngineBase
#else
    /// <typeparam name="T">The record type.</typeparam>
    public sealed class FileDiffEngine<T>: EngineBase
		where T: IComparableRecord
#endif
    {
        /// <summary>
        ///     Creates a new <see cref="FileDiffEngine" />
        /// </summary>
        /// <param name="recordType">
        ///     The record type class that implements the <see cref="IComparableRecord" /> interface.
        /// </param>
#if ! GENERICS
        public FileDiffEngine(Type recordType) : base(recordType)
        {
            if (typeof (IComparableRecord).IsAssignableFrom(recordType) == false)
                throw new BadUsageException("The record class '" + "' need to implement the interface IComparableRecord.");
        }
#else
		public FileDiffEngine():base(typeof(T))
		{
		}
#endif


        /// <summary>Returns the records in newFile that not are in the sourceFile</summary>
        /// <param name="sourceFile">The file with the old records.</param>
        /// <param name="newFile">The file with the new records.</param>
        /// <returns>The records in newFile that not are in the sourceFile</returns>
#if ! GENERICS
        public object[] OnlyNewRecords(string sourceFile, string newFile)
        {
            var engine = CreateEngineAndClearErrors();

            var olds = (IComparableRecord[]) engine.ReadFile(sourceFile);
            ErrorManager.AddErrors(engine.ErrorManager);
            var currents = (IComparableRecord[]) engine.ReadFile(newFile);
            ErrorManager.AddErrors(engine.ErrorManager);

            var news = new ArrayList();
            ApplyDiffOnlyIn1(currents, olds, news);

            return (object[]) news.ToArray(mRecordInfo.mRecordType);
        }
#else
		public T[] OnlyNewRecords(string sourceFile, string newFile)
		{
			FileHelperEngine<T> engine = CreateEngineAndClearErrors();
			
			T[] olds = engine.ReadFile(sourceFile);
			this.ErrorManager.AddErrors(engine.ErrorManager);
			T[] currents = engine.ReadFile(newFile);
			this.ErrorManager.AddErrors(engine.ErrorManager);
            
			List<T> news = new List<T>();
			ApplyDiffOnlyIn1(currents, olds, news);

			return news.ToArray();
		} 
#endif


        /// <summary>Returns the records in newFile that not are in the sourceFile</summary>
        /// <param name="sourceFile">The file with the old records.</param>
        /// <param name="newFile">The file with the new records.</param>
        /// <returns>The records in newFile that not are in the sourceFile</returns>
#if ! GENERICS
        public object[] OnlyMissingRecords(string sourceFile, string newFile)
        {
            var engine = CreateEngineAndClearErrors();

            var olds = (IComparableRecord[]) engine.ReadFile(sourceFile);
            ErrorManager.AddErrors(engine.ErrorManager);

            var currents = (IComparableRecord[]) engine.ReadFile(newFile);
            ErrorManager.AddErrors(engine.ErrorManager);

            var news = new ArrayList();

            ApplyDiffOnlyIn1(olds, currents, news);

            return (object[]) news.ToArray(mRecordInfo.mRecordType);
        }
#else
		public T[] OnlyMissingRecords(string sourceFile, string newFile)
		{
			FileHelperEngine<T> engine = CreateEngineAndClearErrors();

			T[] olds = engine.ReadFile(sourceFile);
			this.ErrorManager.AddErrors(engine.ErrorManager);

			T[] currents = engine.ReadFile(newFile);
			this.ErrorManager.AddErrors(engine.ErrorManager);
            
			List<T> news = new List<T>();

			ApplyDiffOnlyIn1(olds, currents, news);

			return news.ToArray();
		}
#endif

#if ! GENERICS
        private FileHelperEngine CreateEngineAndClearErrors()
        {
            var engine = new FileHelperEngine(mRecordInfo);
#else
		private FileHelperEngine<T> CreateEngineAndClearErrors()
		{
			FileHelperEngine<T> engine = new FileHelperEngine<T>();
#endif
            engine.Encoding = Encoding;

            ErrorManager.ClearErrors();
            engine.ErrorManager.ErrorMode = ErrorManager.ErrorMode;

            return engine;
        }


        /// <summary>
        ///     Returns the duplicated records in both files.
        /// </summary>
        /// <param name="file1">A file with record.</param>
        /// <param name="file2">A file with record.</param>
        /// <returns>The records that appear in both files.</returns>
#if ! GENERICS
        public object[] OnlyDuplicatedRecords(string file1, string file2)
        {
            var engine = CreateEngineAndClearErrors();

            var olds = (IComparableRecord[]) engine.ReadFile(file1);
            ErrorManager.AddErrors(engine.ErrorManager);
            var currents = (IComparableRecord[]) engine.ReadFile(file2);
            ErrorManager.AddErrors(engine.ErrorManager);

            var news = new ArrayList();

            ApplyDiffInBoth(currents, olds, news);

            return (object[]) news.ToArray(mRecordInfo.mRecordType);
        }
#else
		public T[] OnlyDuplicatedRecords(string file1, string file2)
		{
			FileHelperEngine<T> engine = CreateEngineAndClearErrors();
			
			T[] olds = engine.ReadFile(file1);
			this.ErrorManager.AddErrors(engine.ErrorManager);
			T[] currents = engine.ReadFile(file2);
			this.ErrorManager.AddErrors(engine.ErrorManager);
            
			List<T> news = new List<T>();

			ApplyDiffInBoth(currents, olds, news);

			return news.ToArray();
		}
#endif

        #region "  ApplyDiff  "

#if ! GENERICS
        private static void ApplyDiffInBoth(IComparableRecord[] col1, IComparableRecord[] col2, ArrayList arr)
        {
            ApplyDiff(col1, col2, arr, true);
        }

        private static void ApplyDiffOnlyIn1(IComparableRecord[] col1, IComparableRecord[] col2, ArrayList arr)
        {
            ApplyDiff(col1, col2, arr, false);
        }

        private static void ApplyDiff(IComparableRecord[] col1, IComparableRecord[] col2, ArrayList arr, bool addIfIn1)
        {
            for (var i = 0; i < col1.Length; i++)
            {
                var isNew = false;

                //OPT: aca podemos hacer algo asi que para cada nuevo 
                //     que encuentra no empieze en j = i sino en j = i - nuevos =)
                //     Otra idea de guille es agrear un window y usar el Max de las dos

                var current = col1[i];
#else
		private static void ApplyDiffInBoth(T[] col1, T[] col2, List<T> arr)
		{
			ApplyDiff(col1, col2, arr, true);
		}

		private static void ApplyDiffOnlyIn1(T[] col1, T[] col2, List<T> arr)
		{
			ApplyDiff(col1, col2, arr, false);
		}

		private static void ApplyDiff(T[] col1, T[] col2, List<T> arr, bool addIfIn1)
		{
			for(int i = 0; i < col1.Length; i++)
			{
				bool isNew = false; 
				
				//OPT: aca podemos hacer algo asi que para cada nuevo 
				//     que encuentra no empieze en j = i sino en j = i - nuevos =)
				//     Otra idea de guille es agrear un window y usar el Max de las dos

				T current = col1[i];
#endif

                for (var j = i; j < col2.Length; j++)
                {
                    if (current.IsEqualRecord(col2[j]))
                    {
                        isNew = true;
                        break;
                    }
                }


                if (isNew == false)
                {
                    for (var j = 0; j < Math.Min(i, col2.Length); j++)
                    {
                        if (current.IsEqualRecord(col2[j]))
                        {
                            isNew = true;
                            break;
                        }
                    }
                }

                if (isNew == addIfIn1) arr.Add(current);
            }
        }

        #endregion

        /// <summary>
        ///     Returns the NON duplicated records in both files.
        /// </summary>
        /// <param name="file1">A file with record.</param>
        /// <param name="file2">A file with record.</param>
        /// <returns>The records that NOT appear in both files.</returns>
#if ! GENERICS
        public object[] OnlyNoDuplicatedRecords(string file1, string file2)
        {
            var engine = CreateEngineAndClearErrors();

            var olds = (IComparableRecord[]) engine.ReadFile(file1);
            ErrorManager.AddErrors(engine.ErrorManager);
            var currents = (IComparableRecord[]) engine.ReadFile(file2);
            ErrorManager.AddErrors(engine.ErrorManager);

            var news = new ArrayList();

            ApplyDiffOnlyIn1(currents, olds, news);

            ApplyDiffOnlyIn1(olds, currents, news);

            return (object[]) news.ToArray(mRecordInfo.mRecordType);
        }
#else
		public T[] OnlyNoDuplicatedRecords(string file1, string file2)
		{
			FileHelperEngine<T> engine = CreateEngineAndClearErrors();
			
			T[] olds = engine.ReadFile(file1);
			this.ErrorManager.AddErrors(engine.ErrorManager);
			T[] currents = engine.ReadFile(file2);
			this.ErrorManager.AddErrors(engine.ErrorManager);
            
			List<T> news = new List<T>();

			ApplyDiffOnlyIn1(currents, olds, news);

			ApplyDiffOnlyIn1(olds, currents, news);

			return news.ToArray();
    
		} 
#endif

        /// <summary>Read the source file, the new file, get the new records and write them to a destination file.</summary>
        /// <param name="sourceFile">The file with the source records.</param>
        /// <param name="newFile">The file with the new records.</param>
        /// <param name="destFile">The destination file.</param>
        /// <returns>The new records on the new file.</returns>
#if ! GENERICS
        public object[] WriteNewRecords(string sourceFile, string newFile, string destFile)
        {
            var engine = CreateEngineAndClearErrors();
            var res = OnlyNewRecords(sourceFile, newFile);
#else
		public T[] WriteNewRecords(string sourceFile, string newFile, string destFile)
		{
			FileHelperEngine<T> engine = CreateEngineAndClearErrors();
			T[] res = OnlyNewRecords(sourceFile, newFile);
#endif
            engine.WriteFile(destFile, res);
            ErrorManager.AddErrors(engine.ErrorManager);
            return res;
        }
    }
}

//#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions