2006-02-27 Gabor Kelemen <kelemeng@gnome.hu>
[beagle.git] / bludgeon / Toolbox.cs
blobb24a0ef3bd32cd013898441334fd474672da5b4e
1 using System;
2 using System.Collections;
3 using System.Reflection;
5 using Beagle.Util;
7 namespace Bludgeon {
9 public class Toolbox {
11 private class Pair {
12 public HammerAttribute Attribute;
13 public Type Type;
15 public IHammer CreateInstance () {
16 return Activator.CreateInstance (Type) as IHammer;
20 static ArrayList all_pairs = new ArrayList ();
21 static Hashtable pairs_by_name = new Hashtable ();
23 /////////////////////////////////////////////////////
25 private Toolbox () { } // This is a static class
27 static Toolbox ()
29 LoadAllPairs (Assembly.GetExecutingAssembly ());
32 // These are strings
33 static public ICollection HammerNames {
34 get { return pairs_by_name.Keys; }
37 /////////////////////////////////////////////////////
39 private class MixedHammer : IHammer {
40 Random random = new Random ();
41 ArrayList hammers = new ArrayList ();
43 public void Add (IHammer hammer)
45 hammers.Add (hammer);
48 public int Count {
49 get { return hammers.Count; }
52 public bool HammerOnce (DirectoryObject dir, EventTracker tracker)
54 // We randomly pick an IHammer, and call HammerOnce on it.
55 // If it returns false, we try the next IHammer until we
56 // find one that returns true or until we've exhausted
57 // all possibilities.
58 int i;
59 i = random.Next (hammers.Count);
61 for (int j = 0; j < hammers.Count; ++j) {
62 int k = (i + j) % hammers.Count;
63 IHammer hammer;
64 hammer = hammers [k] as IHammer;
65 if (hammer.HammerOnce (dir, tracker))
66 return true;
69 return false;
73 static private IHammer GetMixedHammer (string name)
75 string [] parts;
76 parts = name.Split (',');
78 MixedHammer mixed;
79 mixed = new MixedHammer ();
80 foreach (string part in parts) {
81 IHammer hammer;
83 if (part.IndexOf ('*') != -1) {
84 foreach (IHammer match in GetMatchingHammers (part))
85 mixed.Add (match);
86 continue;
89 hammer = GetHammer (part);
90 if (hammer != null)
91 mixed.Add (hammer);
94 return mixed.Count > 0 ? mixed : null;
97 static public IHammer GetHammer (string name)
99 if (name.IndexOf (',') != -1 || name.IndexOf ('*') != -1)
100 return GetMixedHammer (name);
102 Pair pair;
103 pair = pairs_by_name [name] as Pair;
104 if (pair == null)
105 return null; // should probably throw exception
107 return pair.CreateInstance ();
110 static public ICollection GetMatchingHammers (string pattern)
112 ArrayList matches;
113 matches = new ArrayList ();
115 foreach (Pair pair in all_pairs)
116 if (StringFu.GlobMatch (pattern, pair.Attribute.Name))
117 matches.Add (pair.CreateInstance ());
119 return matches;
122 /////////////////////////////////////////////////////
124 // Yuck.
126 static bool ThisApiSoVeryIsBroken (Type m, object criteria)
128 return m == (Type) criteria;
131 static bool TypeImplementsInterface (Type t, Type iface)
133 Type[] impls = t.FindInterfaces (new TypeFilter (ThisApiSoVeryIsBroken),
134 iface);
135 return impls.Length > 0;
138 static private void LoadAllPairs (Assembly assembly)
140 foreach (Type type in assembly.GetTypes ()) {
142 if (TypeImplementsInterface (type, typeof (IHammer))) {
144 object [] attributes;
145 attributes = Attribute.GetCustomAttributes (type);
147 foreach (object obj in attributes) {
148 HammerAttribute attr;
149 attr = obj as HammerAttribute;
150 if (attr != null) {
152 Pair pair;
153 pair = new Pair ();
154 pair.Attribute = attr;
155 pair.Type = type;
157 all_pairs.Add (pair);
158 pairs_by_name [pair.Attribute.Name] = pair;
160 break;