19 using System.Collections.Generic;
21 using System.Reflection;
22 using Lucene.Net.Support;
25 namespace Lucene.Net.Util
47 public static readonly
AttributeFactory DEFAULT_ATTRIBUTE_FACTORY =
new DefaultAttributeFactory();
52 private static readonly WeakDictionary<Type, WeakReference> attClassImplMap =
53 new WeakDictionary<Type, WeakReference>();
55 internal DefaultAttributeFactory()
59 public override Attribute CreateAttributeInstance<TAttImpl>()
63 return (
Attribute)System.Activator.CreateInstance(GetClassForInterface<TAttImpl>());
65 catch (System.UnauthorizedAccessException)
67 throw new System.ArgumentException(
"Could not instantiate implementing class for " + typeof(TAttImpl).FullName);
75 private static System.Type GetClassForInterface<T>() where T : IAttribute
77 lock (attClassImplMap)
79 var attClass = typeof (T);
80 WeakReference refz = attClassImplMap[attClass];
81 System.Type clazz = (refz == null) ? null : ((System.Type) refz.Target);
86 string name = attClass.FullName.Replace(attClass.Name, attClass.Name.Substring(1)) +
", " + attClass.Assembly.FullName;
87 attClassImplMap.Add(attClass,
new WeakReference( clazz = System.Type.GetType(name,
true)));
89 catch (System.TypeLoadException)
91 throw new System.ArgumentException(
"Could not find implementing class for " + attClass.FullName);
102 private GeneralKeyedCollection<Type, AttributeImplItem> attributes;
103 private GeneralKeyedCollection<Type, AttributeImplItem> attributeImpls;
105 private State[] currentState = null;
106 private AttributeFactory factory;
118 throw new System.ArgumentException(
"input AttributeSource must not be null");
120 this.attributes = input.attributes;
121 this.attributeImpls = input.attributeImpls;
122 this.currentState = input.currentState;
123 this.factory = input.factory;
129 this.attributes =
new GeneralKeyedCollection<Type, AttributeImplItem>(att => att.Key);
130 this.attributeImpls =
new GeneralKeyedCollection<Type, AttributeImplItem>(att => att.Key);
131 this.currentState =
new State[1];
132 this.factory = factory;
136 public virtual AttributeFactory Factory
138 get {
return factory; }
148 [System.Diagnostics.CodeAnalysis.SuppressMessage(
"Microsoft.Design",
"CA1024:UsePropertiesWhereAppropriate")]
149 public virtual IEnumerable<Type> GetAttributeTypesIterator()
151 return this.attributes.Select(item => item.Key);
159 [System.Diagnostics.CodeAnalysis.SuppressMessage(
"Microsoft.Design",
"CA1024:UsePropertiesWhereAppropriate")]
160 public virtual IEnumerable<Attribute> GetAttributeImplsIterator()
162 var initState = GetCurrentState();
163 while (initState != null)
165 var att = initState.attribute;
166 initState = initState.next;
172 private static readonly WeakDictionary<Type, System.Collections.Generic.LinkedList<WeakReference>>
173 knownImplClasses =
new WeakDictionary<Type, System.Collections.Generic.LinkedList<WeakReference>>();
186 System.Type clazz = att.GetType();
187 if (attributeImpls.Contains(clazz))
189 System.Collections.Generic.LinkedList<WeakReference> foundInterfaces;
190 lock (knownImplClasses)
192 foundInterfaces = knownImplClasses[clazz];
193 if (foundInterfaces == null)
197 knownImplClasses.Add(clazz, foundInterfaces =
new LinkedList<WeakReference>());
200 System.Type actClazz = clazz;
203 System.Type[] interfaces = actClazz.GetInterfaces();
204 for (
int i = 0; i < interfaces.Length; i++)
206 System.Type curInterface = interfaces[i];
209 foundInterfaces.AddLast(
new WeakReference(curInterface));
212 actClazz = actClazz.BaseType;
214 while (actClazz != null);
219 foreach(var curInterfaceRef
in foundInterfaces)
221 System.Type curInterface = (System.Type) curInterfaceRef.Target;
222 System.Diagnostics.Debug.Assert(curInterface != null,
223 "We have a strong reference on the class holding the interfaces, so they should never get evicted");
225 if (!attributes.ContainsKey(curInterface))
228 this.currentState[0] = null;
229 attributes.Add(
new AttributeImplItem(curInterface, att));
230 if (!attributeImpls.ContainsKey(clazz))
232 attributeImpls.Add(
new AttributeImplItem(clazz, att));
246 var attClass = typeof (T);
247 if (!attributes.ContainsKey(attClass))
249 if (!(attClass.IsInterface && typeof(
IAttribute).IsAssignableFrom(attClass)))
251 throw new ArgumentException(
252 "AddAttribute() only accepts an interface that extends Attribute, but " +
253 attClass.FullName +
" does not fulfil this contract."
257 AddAttributeImpl(this.factory.CreateAttributeInstance<T>());
260 return (T)(
IAttribute)attributes[attClass].Value;
264 public virtual bool HasAttributes
266 get {
return this.attributes.Count != 0; }
274 return this.attributes.Contains(typeof(T));
292 var attClass = typeof (T);
293 if (!this.attributes.ContainsKey(attClass))
295 throw new System.ArgumentException(
"This AttributeSource does not have the attribute '" + attClass.FullName +
"'.");
299 return (T)(
IAttribute)this.attributes[attClass].Value;
308 public sealed
class State : System.ICloneable
313 public System.Object Clone()
327 private State GetCurrentState()
329 var s = currentState[0];
330 if (s != null || !HasAttributes)
335 var c = s = currentState[0] =
new State();
336 var it = attributeImpls.Values().GetEnumerator();
338 c.attribute = it.Current.Value;
340 while (it.MoveNext())
342 c.next =
new State();
344 c.attribute = it.Current.Value;
353 public virtual void ClearAttributes()
355 for (var state = GetCurrentState(); state != null; state = state.next)
357 state.attribute.Clear();
366 var state = this.GetCurrentState();
367 return (state == null) ? null : (
State) state.Clone();
384 public virtual void RestoreState(
State state)
391 if (!attributeImpls.ContainsKey(state.attribute.GetType()))
393 throw new System.ArgumentException(
"State contains an AttributeImpl that is not in this AttributeSource");
395 state.attribute.
CopyTo(attributeImpls[state.attribute.GetType()].Value);
398 while (state != null);
401 public override int GetHashCode()
405 for (var state = GetCurrentState(); state != null; state = state.next)
413 public override bool Equals(System.Object obj)
431 if (this.attributeImpls.Count != other.attributeImpls.Count)
437 var thisState = this.GetCurrentState();
438 var otherState = other.GetCurrentState();
439 while (thisState != null && otherState != null)
441 if (otherState.attribute.GetType() != thisState.attribute.GetType() || !otherState.attribute.Equals(thisState.attribute))
445 thisState = thisState.next;
446 otherState = otherState.next;
459 public override System.String ToString()
461 System.Text.StringBuilder sb =
new System.Text.StringBuilder().Append(
'(');
465 if (currentState[0] == null)
467 currentState[0] = GetCurrentState();
469 for (var state = currentState[0]; state != null; state = state.next)
471 if (state != currentState[0])
473 sb.Append(state.attribute.ToString());
476 return sb.Append(
')').ToString();
490 for (var state = GetCurrentState(); state != null; state = state.next)
492 var impl = (
Attribute) state.attribute.Clone();
494 if (!clone.attributeImpls.ContainsKey(impl.GetType()))
496 clone.attributeImpls.Add(
new AttributeImplItem(impl.GetType(), impl));
502 foreach (var att
in this.attributes)
504 clone.attributes.Add(
new AttributeImplItem(att.Key, clone.attributeImpls[att.Value.GetType()].Value));