Subversion Repositories SoapBoxCore

Rev

Rev 8 | Rev 18 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#region "SoapBox.Core License"
/// <header module="SoapBox.Core">
/// Copyright (C) 2009 SoapBox Automation Inc., All Rights Reserved.
/// Contact: SoapBox Automation Licencing (license@soapboxautomation.com)
///
/// This file is part of SoapBox Core.
///
/// Commercial Usage
/// Licensees holding valid SoapBox Automation Commercial licenses may use  
/// this file in accordance with the SoapBox Automation Commercial License
/// Agreement provided with the Software or, alternatively, in accordance
/// with the terms contained in a written agreement between you and
/// SoapBox Automation Inc.
///
/// GNU Lesser General Public License Usage
/// SoapBox Core is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Lesser General Public License
/// as published by the Free Software Foundation, either version 3 of the
/// License, or (at your option) any later version.
///
/// SoapBox Core 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 Lesser General Public License for more details.
///
/// You should have received a copy of the GNU Lesser General Public License
/// along with SoapBox Core. If not, see <http://www.gnu.org/licenses/>.
/// </header>
#endregion
       
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;

namespace SoapBox.Core
{

    /// <summary>
    /// Utility methods and functions to work with IExtension objects.
    /// </summary>
    [Export((Services.Host.ExtensionService), typeof(IExtensionService))]
    public class ExtensionService : IExtensionService
    {
        [Import(Services.Logging.LoggingService, typeof(ILoggingService))]
        private ILoggingService logger { get; set; }

        /// <summary>
        /// Takes a collection of extensions and returns a sorted list
        /// of those extensions based on the InsertBeforeID  
        /// property of each extension.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="extensions"></param>
        /// <returns></returns>
        public IList<T> Sort<T>(IEnumerable<T> extensionCollection) where T : IExtension
        {
            List<T> extensions = new List<T>(extensionCollection);
            List<T> sortedExtensions = new List<T>();
            List<T> unsortedExtensions = new List<T>();
            foreach (T newExtension in extensions)
            {
                if (newExtension.InsertRelativeToID == null)
                {
                    sortedExtensions.Add(newExtension);
                }
                else if(FindByID(newExtension.InsertRelativeToID, extensions) == -1)
                {
                    // found a configuration error
                    logger.ErrorWithFormat("Configuration error with extension ID {0}, InsertBeforeID of {1} doesn't exist.",
                        newExtension.ID, newExtension.InsertRelativeToID);
                    sortedExtensions.Add(newExtension);
                }
                else
                {
                    unsortedExtensions.Add(newExtension);
                }
            }
            while (unsortedExtensions.Count > 0)
            {
                List<T> stillUnsortedExtensions = new List<T>();
                int startingCount = unsortedExtensions.Count;
                foreach (T newExtension in unsortedExtensions)
                {
                    int index = FindByID(newExtension.InsertRelativeToID, sortedExtensions);
                    if (index > -1)
                    {
                        if (newExtension.BeforeOrAfter == RelativeDirection.Before)
                        {
                            sortedExtensions.Insert(index, newExtension);
                        }
                        else
                        {
                            if (index == sortedExtensions.Count - 1)
                            {
                                //it's to be inserted after the last item in the list
                                sortedExtensions.Add(newExtension);
                            }
                            else
                            {
                                sortedExtensions.Insert(index + 1, newExtension);
                            }
                        }
                    }
                    else
                    {
                        stillUnsortedExtensions.Add(newExtension);
                    }
                }
                if (startingCount == stillUnsortedExtensions.Count)
                {
                    // We didn't make any progress
                    logger.Error("Configuration error with one of these extensions:");
                    foreach(IExtension ext in stillUnsortedExtensions)
                    {
                        logger.ErrorWithFormat("ID = {0}, InsertBeforeID = {1}", ext.ID, ext.InsertRelativeToID);
                    }
                    // Pick one and add it at the end.
                    sortedExtensions.Add(stillUnsortedExtensions[0]);
                    stillUnsortedExtensions.RemoveAt(0);
                }
                unsortedExtensions = stillUnsortedExtensions;
            }
            return sortedExtensions;
        }

        /// <summary>
        /// Returns the index of the extension with the given ID,
        /// or -1 if not found.
        /// </summary>
        /// <param name="ID"></param>
        /// <param name="extensions"></param>
        /// <returns></returns>
        private int FindByID<T>(string ID, IList<T> extensions) where T : IExtension
        {
            for (int i = 0; i < extensions.Count; i++)
            {
                if (extensions[i].ID == ID)
                {
                    return i;
                }
            }
            return -1;
        }

    }
}