Subversion Repositories SoapBoxCore

Rev

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

Rev Author Line No. Line
8 scott 1
#region "SoapBox.Core License"
2
/// <header module="SoapBox.Core"> 
3
/// Copyright (C) 2009 SoapBox Automation Inc., All Rights Reserved.
4
/// Contact: SoapBox Automation Licencing (license@soapboxautomation.com)
5
/// 
6
/// This file is part of SoapBox Core.
7
/// 
8
/// Commercial Usage
9
/// Licensees holding valid SoapBox Automation Commercial licenses may use  
10
/// this file in accordance with the SoapBox Automation Commercial License
11
/// Agreement provided with the Software or, alternatively, in accordance 
12
/// with the terms contained in a written agreement between you and
13
/// SoapBox Automation Inc.
14
/// 
15
/// GNU Lesser General Public License Usage
16
/// SoapBox Core is free software: you can redistribute it and/or modify 
17
/// it under the terms of the GNU Lesser General Public License
18
/// as published by the Free Software Foundation, either version 3 of the
19
/// License, or (at your option) any later version.
20
/// 
21
/// SoapBox Core is distributed in the hope that it will be useful, 
22
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
23
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
/// GNU Lesser General Public License for more details.
25
/// 
26
/// You should have received a copy of the GNU Lesser General Public License 
27
/// along with SoapBox Core. If not, see <http://www.gnu.org/licenses/>.
28
/// </header>
29
#endregion
30
 
31
using System;
32
using System.Collections.Generic;
33
using System.Collections.ObjectModel;
34
using System.ComponentModel.Composition;
35
 
36
namespace SoapBox.Core
37
{
38
 
39
    /// <summary>
40
    /// Utility methods and functions to work with IExtension objects.
41
    /// </summary>
12 scott 42
    [Export((Services.Host.ExtensionService), typeof(IExtensionService))]
8 scott 43
    public class ExtensionService : IExtensionService
44
    {
12 scott 45
        [Import(Services.Logging.LoggingService, typeof(ILoggingService))]
8 scott 46
        private ILoggingService logger { get; set; }
47
 
48
        /// <summary>
49
        /// Takes a collection of extensions and returns a sorted list
50
        /// of those extensions based on the InsertBeforeID  
51
        /// property of each extension.
52
        /// </summary>
53
        /// <typeparam name="T"></typeparam>
54
        /// <param name="extensions"></param>
55
        /// <returns></returns>
56
        public IList<T> Sort<T>(IEnumerable<T> extensionCollection) where T : IExtension
57
        {
58
            List<T> extensions = new List<T>(extensionCollection);
59
            List<T> sortedExtensions = new List<T>();
60
            List<T> unsortedExtensions = new List<T>();
61
            foreach (T newExtension in extensions)
62
            {
63
                if (newExtension.InsertRelativeToID == null)
64
                {
65
                    sortedExtensions.Add(newExtension);
66
                }
67
                else if(FindByID(newExtension.InsertRelativeToID, extensions) == -1)
68
                {
69
                    // found a configuration error
70
                    logger.ErrorWithFormat("Configuration error with extension ID {0}, InsertBeforeID of {1} doesn't exist.",
71
                        newExtension.ID, newExtension.InsertRelativeToID);
72
                    sortedExtensions.Add(newExtension);
73
                }
74
                else
75
                {
76
                    unsortedExtensions.Add(newExtension);
77
                }
78
            }
79
            while (unsortedExtensions.Count > 0)
80
            {
81
                List<T> stillUnsortedExtensions = new List<T>();
82
                int startingCount = unsortedExtensions.Count;
83
                foreach (T newExtension in unsortedExtensions)
84
                {
85
                    int index = FindByID(newExtension.InsertRelativeToID, sortedExtensions);
86
                    if (index > -1)
87
                    {
88
                        if (newExtension.BeforeOrAfter == RelativeDirection.Before)
89
                        {
90
                            sortedExtensions.Insert(index, newExtension);
91
                        }
92
                        else
93
                        {
94
                            if (index == sortedExtensions.Count - 1)
95
                            {
96
                                //it's to be inserted after the last item in the list
97
                                sortedExtensions.Add(newExtension);
98
                            }
99
                            else
100
                            {
101
                                sortedExtensions.Insert(index + 1, newExtension);
102
                            }
103
                        }
104
                    }
105
                    else
106
                    {
107
                        stillUnsortedExtensions.Add(newExtension);
108
                    }
109
                }
110
                if (startingCount == stillUnsortedExtensions.Count)
111
                {
112
                    // We didn't make any progress
113
                    logger.Error("Configuration error with one of these extensions:");
114
                    foreach(IExtension ext in stillUnsortedExtensions)
115
                    {
116
                        logger.ErrorWithFormat("ID = {0}, InsertBeforeID = {1}", ext.ID, ext.InsertRelativeToID);
117
                    }
118
                    // Pick one and add it at the end.
119
                    sortedExtensions.Add(stillUnsortedExtensions[0]);
120
                    stillUnsortedExtensions.RemoveAt(0);
121
                }
122
                unsortedExtensions = stillUnsortedExtensions;
123
            }
124
            return sortedExtensions;
125
        }
126
 
127
        /// <summary>
128
        /// Returns the index of the extension with the given ID,
129
        /// or -1 if not found.
130
        /// </summary>
131
        /// <param name="ID"></param>
132
        /// <param name="extensions"></param>
133
        /// <returns></returns>
134
        private int FindByID<T>(string ID, IList<T> extensions) where T : IExtension
135
        {
136
            for (int i = 0; i < extensions.Count; i++)
137
            {
138
                if (extensions[i].ID == ID)
139
                {
140
                    return i;
141
                }
142
            }
143
            return -1;
144
        }
145
 
146
    }
147
}