You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by mh...@apache.org on 2011/08/12 03:46:37 UTC
[Lucene.Net] svn commit: r1156935 - in /incubator/lucene.net/branches/Lucene.Net_4e:
src/Lucene.Net/ src/Lucene.Net/Analysis/
src/Lucene.Net/Analysis/TokenAttributes/ src/Lucene.Net/Support/
src/Lucene.Net/Util/ test/Lucene.Net.Test/Support/
Author: mherndon
Date: Fri Aug 12 01:46:36 2011
New Revision: 1156935
URL: http://svn.apache.org/viewvc?rev=1156935&view=rev
Log:
Porting Lucene 4's AttributeSource and AttributeFactory and default attribute factory without tests at the moment. This is in order to work towards finishing up with the analysis folder.
Added:
incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Support/ICloneableOfT.cs
- copied, changed from r1156492, incubator/lucene.net/branches/Lucene.Net_4e/test/Lucene.Net.Test/Support/ICloneable.cs
incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeFactory.cs
Modified:
incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/CharTermAttribute.cs
incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/FlagsAttribute.cs
incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/PayloadAttribute.cs
incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/TypeAttribute.cs
incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenStream.cs
incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Lucene.Net.csproj
incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeBase.cs
incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeSource.cs
incubator/lucene.net/branches/Lucene.Net_4e/test/Lucene.Net.Test/Support/ICloneable.cs
Modified: incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/CharTermAttribute.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/CharTermAttribute.cs?rev=1156935&r1=1156934&r2=1156935&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/CharTermAttribute.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/CharTermAttribute.cs Fri Aug 12 01:46:36 2011
@@ -220,7 +220,7 @@ namespace Lucene.Net.Analysis.TokenAttri
/// Creates a clone of the object, generally shallow.
/// </summary>
/// <returns>an the clone of the current instance.</returns>
- public override object Clone()
+ public override AttributeBase Clone()
{
CharTermAttribute clone = (CharTermAttribute)this.MemberwiseClone();
Modified: incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/FlagsAttribute.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/FlagsAttribute.cs?rev=1156935&r1=1156934&r2=1156935&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/FlagsAttribute.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/FlagsAttribute.cs Fri Aug 12 01:46:36 2011
@@ -85,7 +85,7 @@ namespace Lucene.Net.Analysis.TokenAttri
/// Creates a clone of the object, generally shallow.
/// </summary>
/// <returns>an the clone of the current instance.</returns>
- public override object Clone()
+ public override AttributeBase Clone()
{
return new FlagsAttribute { Flags = this.Flags };
}
Modified: incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/PayloadAttribute.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/PayloadAttribute.cs?rev=1156935&r1=1156934&r2=1156935&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/PayloadAttribute.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/PayloadAttribute.cs Fri Aug 12 01:46:36 2011
@@ -66,7 +66,7 @@ namespace Lucene.Net.Analysis.TokenAttri
/// Creates a clone of the object, generally shallow.
/// </summary>
/// <returns>an the clone of the current instance.</returns>
- public override object Clone()
+ public override AttributeBase Clone()
{
PayloadAttribute clone = (PayloadAttribute)this.MemberwiseClone();
Modified: incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/TypeAttribute.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/TypeAttribute.cs?rev=1156935&r1=1156934&r2=1156935&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/TypeAttribute.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenAttributes/TypeAttribute.cs Fri Aug 12 01:46:36 2011
@@ -72,7 +72,7 @@ namespace Lucene.Net.Analysis.TokenAttri
/// Creates a clone of the object, generally shallow.
/// </summary>
/// <returns>an the clone of the current instance.</returns>
- public override object Clone()
+ public override AttributeBase Clone()
{
return new TypeAttribute() { Type = this.Type };
}
Modified: incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenStream.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenStream.cs?rev=1156935&r1=1156934&r2=1156935&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenStream.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Analysis/TokenStream.cs Fri Aug 12 01:46:36 2011
@@ -25,11 +25,12 @@ namespace Lucene.Net.Analysis
using System.Collections.Generic;
using System.Linq;
using System.Text;
+ using Lucene.Net.Util;
/// <summary>
/// TODO: port
/// </summary>
- public class TokenStream
+ public class TokenStream : AttributeSource
{
}
}
\ No newline at end of file
Modified: incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Lucene.Net.csproj
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Lucene.Net.csproj?rev=1156935&r1=1156934&r2=1156935&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Lucene.Net.csproj (original)
+++ incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Lucene.Net.csproj Fri Aug 12 01:46:36 2011
@@ -18,7 +18,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\build\bin\core\Debug\</OutputPath>
- <DefineConstants>TRACE;DEBUG;SILVERLIGHT;WMP;</DefineConstants>
+ <DefineConstants>TRACE;DEBUG;SILVERLIGHT;WMP;SILVERLIGHT_4;WMP_4</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>..\..\build\bin\core\Debug\Lucene.Net.XML</DocumentationFile>
@@ -70,6 +70,7 @@
<Compile Include="Support\BaseDictionaryOfTKeyTValue.cs" />
<Compile Include="Support\ICloneable.cs" />
<Compile Include="Support\DictionaryExtensions.cs" />
+ <Compile Include="Support\ICloneableOfT.cs" />
<Compile Include="Support\ICloseable.cs" />
<Compile Include="Support\Threading\LocalDataStoreSlot.cs" />
<Compile Include="Support\Threading\ThreadData.cs" />
@@ -81,6 +82,7 @@
<Compile Include="Support\WeakReferenceOfT.cs" />
<Compile Include="Util\ArrayUtil.cs" />
<Compile Include="Util\AttributeBase.cs" />
+ <Compile Include="Util\AttributeFactory.cs" />
<Compile Include="Util\AttributeSource.cs" />
<Compile Include="Util\BytesRef.cs" />
<Compile Include="Util\IAttribute.cs" />
Copied: incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Support/ICloneableOfT.cs (from r1156492, incubator/lucene.net/branches/Lucene.Net_4e/test/Lucene.Net.Test/Support/ICloneable.cs)
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Support/ICloneableOfT.cs?p2=incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Support/ICloneableOfT.cs&p1=incubator/lucene.net/branches/Lucene.Net_4e/test/Lucene.Net.Test/Support/ICloneable.cs&r1=1156492&r2=1156935&rev=1156935&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_4e/test/Lucene.Net.Test/Support/ICloneable.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Support/ICloneableOfT.cs Fri Aug 12 01:46:36 2011
@@ -1,5 +1,5 @@
// -----------------------------------------------------------------------
-// <copyright company="Apache" file="ICloneable.cs">
+// <copyright company="Apache" file="ICloneableOfT.cs">
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
@@ -27,11 +27,15 @@ namespace Lucene.Net.Support
using System.Text;
/// <summary>
- ///
+ /// Contract for clone an object
/// </summary>
- /// <typeparam name="T"></typeparam>
+ /// <typeparam name="T">The clone type</typeparam>
public interface ICloneable<out T> : ICloneable
{
+ /// <summary>
+ /// Clones this instance.
+ /// </summary>
+ /// <returns>returns a cloned instance of the specified type.</returns>
new T Clone();
}
-}
+}
\ No newline at end of file
Modified: incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeBase.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeBase.cs?rev=1156935&r1=1156934&r2=1156935&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeBase.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeBase.cs Fri Aug 12 01:46:36 2011
@@ -49,7 +49,7 @@ namespace Lucene.Net.Util
/// </para>
/// </note>
/// </remarks>
- public abstract class AttributeBase : IAttribute, ICloneable
+ public abstract class AttributeBase : IAttribute, ICloneable, ICloneable<AttributeBase>
{
/// <summary>
/// Clears the instance.
@@ -130,9 +130,18 @@ namespace Lucene.Net.Util
/// Creates a clone of the object, generally shallow.
/// </summary>
/// <returns>an the clone of the current instance.</returns>
- public virtual object Clone()
+ object ICloneable.Clone()
{
- var obj = this.MemberwiseClone();
+ return this.Clone();
+ }
+
+ /// <summary>
+ /// Creates a shallow clone of this instance by default.
+ /// </summary>
+ /// <returns>an instance of <see cref="AttributeBase"/></returns>
+ public virtual AttributeBase Clone()
+ {
+ var obj = (AttributeBase)this.MemberwiseClone();
return obj;
}
}
Added: incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeFactory.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeFactory.cs?rev=1156935&view=auto
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeFactory.cs (added)
+++ incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeFactory.cs Fri Aug 12 01:46:36 2011
@@ -0,0 +1,136 @@
+// -----------------------------------------------------------------------
+// <copyright company="Apache" file="AttributeFactory.cs">
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// </copyright>
+// -----------------------------------------------------------------------
+
+namespace Lucene.Net.Util
+{
+ using System;
+ using Support;
+
+
+ /// <summary>
+ /// A contract for factories that create instances of <see cref="AttributeBase" />
+ /// that are map to interfaces that extend <see cref="IAttribute" />
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The factory is abstract so the behavior of how interfaces that derive from
+ /// <see cref="IAttribute"/> are mapped to concrete types that implement that
+ /// interface. The factory also can change how the concrete types are created.
+ /// </para>
+ /// <para>
+ /// You could easily create your own factory that replaces the default
+ /// behavior with Dependency Injection.
+ /// </para>
+ /// </remarks>
+ /// <seealso cref="DefaultFactory"/>
+ public abstract class AttributeFactory
+ {
+ /// <summary>
+ /// Returns the default implementation for <see cref="AttributeFactory"/>, an instance of
+ /// <see cref="DefaultAttributeFactory"/>.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The default factory uses a name convention to retrieve and create instances
+ /// of <see cref="AttributeBase" />. The convention is based on the name of
+ /// the interface types that are subclasses of <see cref="IAttribute"/>.
+ /// </para>
+ /// <para>
+ /// The Java version appends "Impl" to each interface name. The .NET version
+ /// removes the "I" from the interface name by using <c>type.Name.Substring(0)</c>.
+ /// </para>
+ /// </remarks>
+ public static readonly AttributeFactory DefaultFactory = new DefaultAttributeFactory();
+
+ /// <summary>
+ /// Creates the <see cref="AttributeBase"/> instance based on the <typeparamref name="T"/> parameter
+ /// that must derive from both <see cref="AttributeBase"/> and <see cref="IAttribute"/>.
+ /// </summary>
+ /// <typeparam name="T">The type of interface</typeparam>
+ /// <returns>An instance of <see cref="AttributeBase"/>.</returns>
+ public abstract AttributeBase CreateAttributeInstance<T>() where T : IAttribute;
+
+ /// <summary>
+ /// Creates the <see cref="AttributeBase"/> instance based on the interface <paramref name="type"/>
+ /// that derives from <see cref="IAttribute"/>.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ /// <returns>
+ /// An instance of <see cref="AttributeBase"/>.
+ /// </returns>
+ public abstract AttributeBase CreateAttributeInstance(Type type);
+
+
+ /// <summary>
+ /// The default attribute factory implementation.
+ /// </summary>
+ private sealed class DefaultAttributeFactory : AttributeFactory
+ {
+ private static readonly WeakDictionary<Type, Type> map =
+ new WeakDictionary<Type, Type>();
+
+
+ public override AttributeBase CreateAttributeInstance<T>()
+ {
+ var implementationType = FetchClassForInterface(typeof(T));
+ return CreateAttributeInstance(typeof(T));
+ }
+
+ public override AttributeBase CreateAttributeInstance(Type type)
+ {
+ var implementationType = FetchClassForInterface(type);
+ return (AttributeBase)Activator.CreateInstance(implementationType);
+ }
+
+
+ private static Type FetchClassForInterface(Type type)
+ {
+ Type value;
+ lock (map)
+ {
+ if (!map.TryGetValue(type, out value))
+ {
+ var interfaceName = type.Name;
+ var typeName = interfaceName.Substring(1);
+
+ try
+ {
+ value = Type.GetType(string.Format("{0}.{1}", type.Namespace, typeName));
+ }
+ catch (Exception ex)
+ {
+ throw new ArgumentException(
+ string.Format(
+ "The implementation '{0}' could not be found for attribute interface '{1}'",
+ typeName,
+ type.FullName),
+ ex);
+ }
+
+ map.Add(type, value);
+ }
+ }
+
+ return value;
+ }
+ }
+ }
+}
Modified: incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeSource.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeSource.cs?rev=1156935&r1=1156934&r2=1156935&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeSource.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_4e/src/Lucene.Net/Util/AttributeSource.cs Fri Aug 12 01:46:36 2011
@@ -19,10 +19,15 @@
// </copyright>
// -----------------------------------------------------------------------
+
+
+
namespace Lucene.Net.Util
{
using System;
using System.Collections.Generic;
+ using Lucene.Net.Analysis;
+ using Lucene.Net.Analysis.TokenAttributes;
using Support;
@@ -54,13 +59,75 @@ namespace Lucene.Net.Util
/// </para>
/// </note>
/// </remarks>
- public class AttributeSource
+ public partial class AttributeSource
{
private static readonly object instanceLock = new object();
-
private static readonly WeakDictionary<Type, LinkedList<WeakReference<Type>>> knownAttributeClasses =
new WeakDictionary<Type, LinkedList<WeakReference<Type>>>();
+ private readonly Dictionary<Type, AttributeBase> interfaceMap = new Dictionary<Type, AttributeBase>();
+ private readonly Dictionary<Type, AttributeBase> attributeMap = new Dictionary<Type, AttributeBase>();
+
+ private State[] currentState;
+
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AttributeSource"/> class.
+ /// This constructor uses the <see cref="AttributeFactory.DefaultFactory"/>
+ /// </summary>
+ public AttributeSource()
+ : this(AttributeFactory.DefaultFactory)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AttributeSource"/> class.
+ /// This uses another attribute source to create a new one based on the internally
+ /// store maps of <see cref="Type"/> to instances of <see cref="AttributeBase"/>
+ /// </summary>
+ /// <param name="source">The source.</param>
+ public AttributeSource(AttributeSource source)
+ {
+ this.attributeMap = source.attributeMap;
+ this.interfaceMap = source.interfaceMap;
+ this.currentState = source.currentState;
+ this.Factory = source.Factory;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AttributeSource"/> class. Creates
+ /// a new attribute source with the specified factory.
+ /// </summary>
+ /// <param name="factory">The factory.</param>
+ public AttributeSource(AttributeFactory factory)
+ {
+ this.attributeMap = new Dictionary<Type, AttributeBase>();
+ this.interfaceMap = new Dictionary<Type, AttributeBase>();
+ this.currentState = new State[1];
+
+ this.Factory = factory;
+ }
+
+
+ /// <summary>
+ /// Gets the attribute factory.
+ /// </summary>
+ /// <value>The factory.</value>
+ public AttributeFactory Factory { get; private set; }
+
+ /// <summary>
+ /// Gets a value indicating whether this instance has attributes.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if this instance has attributes; otherwise, <c>false</c>.
+ /// </value>
+ public bool HasAttributes
+ {
+ get { return this.attributeMap.Count > 0; }
+ }
+
+
+
/// <summary>
/// Gets the attribute interfaces.
/// </summary>
@@ -92,7 +159,7 @@ namespace Lucene.Net.Util
foundInterfaces.AddLast(new WeakReference<Type>(currentInterface));
}
}
-
+
activeType = activeType.BaseType;
} while (activeType != null);
}
@@ -101,13 +168,540 @@ namespace Lucene.Net.Util
}
}
+
+ /// <summary>
+ /// Adds the attribute.
+ /// </summary>
+ /// <param name="attribute">The attribute.</param>
+ public void AddAttribute(AttributeBase attribute)
+ {
+ if (attribute == null)
+ throw new ArgumentNullException("attribute");
+
+ Type type = attribute.GetType();
+ if (this.attributeMap.ContainsKey(type))
+ return;
+
+ var foundInterfaces = GetAttributeInterfaces(type);
+ foreach (var interfaceTypeRef in foundInterfaces)
+ {
+ var interfaceType = interfaceTypeRef.Target;
+
+#if DEBUG
+ System.Diagnostics.Debug.Assert(interfaceType != null, "We have a strong reference on the class holding the interfaces, so they should never get evicted");
+#endif
+
+ if (!this.interfaceMap.ContainsKey(interfaceType))
+ {
+ this.currentState[0] = null;
+ this.attributeMap.Add(type, attribute);
+ this.interfaceMap.Add(interfaceType, attribute);
+ }
+ }
+ }
+
/// <summary>
/// Adds an attribute.
/// </summary>
/// <param name="attributeType">The type of attribute that is to be added.</param>
- public void AddAttribute(Type attributeType)
+ /// <exception cref="ArgumentNullException">
+ /// Thrown when <paramref name="attributeType"/> is null.
+ /// </exception>
+ /// <exception cref="ArgumentException">
+ /// Thrown when <paramref name="attributeType"/> is not a type of interface
+ /// that inherits from <see cref="IAttribute"/>.
+ /// </exception>
+ /// <returns>
+ /// The instance of <see cref="AttributeBase"/> that was created.
+ /// </returns>
+ public AttributeBase AddAttribute(Type attributeType)
{
- throw new NotImplementedException();
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+
+ AttributeBase instance;
+
+ if (this.attributeMap.TryGetValue(attributeType, out instance))
+ {
+ if (!attributeType.IsInterface)
+ throw new ArgumentException("The type must be an interface.");
+
+ if (!attributeType.IsSubclassOf(typeof(IAttribute)))
+ throw new ArgumentException(
+ string.Format(
+ "The interface type '{0}' is not a subclass of IAttribute.",
+ attributeType.FullName));
+
+ this.AddAttribute(instance = this.Factory.CreateAttributeInstance(attributeType));
+ }
+
+ return instance;
+ }
+
+ /// <summary>
+ /// Adds the attribute.
+ /// </summary>
+ /// <typeparam name="T">The type of AttributeBase that is to be added.</typeparam>
+ /// <returns>An instance of <typeparamref name="T"/>.</returns>
+ public T AddAttribute<T>() where T : AttributeBase, IAttribute
+ {
+ return (T)this.AddAttribute(typeof(T));
+ }
+
+ /// <summary>
+ /// Captures the state.
+ /// </summary>
+ /// <returns>An instance of <see cref="State"/>.</returns>
+ public State CaptureState()
+ {
+ State state = this.GetCurrentState();
+ return state == null ? null : state.Clone();
+ }
+
+
+
+ /// <summary>
+ /// Clears the attributes.
+ /// </summary>
+ public void ClearAttributes()
+ {
+ for (var state = this.GetCurrentState(); state != null; state = state.Next)
+ state.Attribute.Clear();
+ }
+
+ /// <summary>
+ /// Clones the current <see cref="AttributeSource"/> and injects clones of all of
+ /// the stored <see cref="AttributeBase"/> instances into the <see cref="AttributeSource"/> clone.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// This method can be use to create another <see cref="Lucene.Net.Analysis.TokenStream"/>
+ /// with exactly the same attributes. You can also use this method as a non-performant
+ /// replacement for <see cref="CaptureState"/> for times you wish to modify or peek at
+ /// the captured state.
+ /// </para>
+ /// </remarks>
+ /// <returns>
+ /// A new instance of <see cref="AttributeSource"/> with cloned attributes.
+ /// </returns>
+ public AttributeSource CloneAttributes()
+ {
+ var clone = new AttributeSource(this.Factory);
+
+ if (this.HasAttributes)
+ {
+ this.ForEachState((state) => {
+ clone.attributeMap.Add(state.Attribute.GetType(), state.Attribute.Clone());
+ });
+
+ foreach (var pair in this.interfaceMap)
+ clone.interfaceMap.Add(pair.Key, pair.Value.Clone());
+ }
+
+ return clone;
+ }
+
+ /// <summary>
+ /// Determines whether the specified type contains attribute.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ /// <returns>
+ /// <c>true</c> if the specified type contains attribute; otherwise, <c>false</c>.
+ /// </returns>
+ public bool ContainsAttribute(Type type)
+ {
+ if (type.IsInterface)
+ return this.interfaceMap.ContainsKey(type);
+ else
+ return this.attributeMap.ContainsKey(type);
+ }
+
+ /// <summary>
+ /// Copies the contents of this <see cref="AttributeSource"/> to the specified
+ /// <see cref="AttributeSource"/> <paramref name="source"/>.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <paramref name="source"/> has to provide all <see cref="IAttribute"/>s this instance contains.
+ /// The actual attribute implementations must be identical in both <see cref="AttributeSource"/> instances;
+ /// ideally both <see cref="AttributeSource"/> instances should use the same <see cref="AttributeFactory"/>.
+ /// You can use this method as a replacement for <see cref="RestoreState"/>, if you use
+ /// <see cref="CloneAttributes"/> instead of <see cref="CaptureState"/>.
+ /// </para>
+ /// </remarks>
+ /// <param name="source">The source.</param>
+ /// <exception cref="ArgumentException">
+ /// Thrown when the <paramref name="source"/> contains an instance
+ /// of <see cref="IAttribute"/> that current <see cref="AttributeSource"/>
+ /// object does not contain.
+ /// </exception>
+ public void CopyTo(AttributeSource source)
+ {
+ this.ForEachState((state) => {
+ var attribute = this.attributeMap[state.Attribute.GetType()];
+ if (attribute == null)
+ throw new ArgumentException(this.CreateStateExceptionMessage(state));
+
+ state.Attribute.CopyTo(attribute);
+ });
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
+ /// </summary>
+ /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
+ /// <returns>
+ /// <c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
+ /// </returns>
+ public override bool Equals(object obj)
+ {
+ if (obj == this)
+ return true;
+
+ AttributeSource compare = (AttributeSource)obj;
+
+ if (compare == null)
+ return false;
+
+ if (!this.HasAttributes)
+ return !compare.HasAttributes;
+
+ if (!compare.HasAttributes ||
+ (compare.attributeMap.Count != this.attributeMap.Count))
+ return false;
+
+ var localState = this.GetCurrentState();
+ var compareState = compare.GetCurrentState();
+
+ while (localState != null && compareState != null)
+ {
+ // this differs from java-lucene-core:
+ // .NET's attributes will return false if the types mismatch.
+ if (!localState.Attribute.Equals(compareState.Attribute))
+ return false;
+
+ localState = localState.Next;
+ compareState = compareState.Next;
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Finds the specified attribute based on the <typeparamref name="T"/> which must
+ /// a type that implements <see cref="AttributeBase"/> and <see cref="IAttribute"/>.
+ /// </summary>
+ /// <typeparam name="T">The type that </typeparam>
+ /// <returns>An instance of <typeparamref name="T"/>.</returns>
+ /// <exception cref="ArgumentException">
+ /// Thrown when the type of <typeparamref name="T"/> could not be found in this instance.
+ /// </exception>
+ public T FindAttribute<T>() where T : IAttribute
+ {
+ AttributeBase value;
+ if (!this.interfaceMap.TryGetValue(typeof(T), out value))
+ throw new ArgumentException(
+ string.Format(
+ "The specified type '{0}' could not be found, try using " +
+ "ContainsAttribute(Type) first.",
+ typeof(T).FullName));
+
+ object unbox = value;
+ return (T)unbox;
+ }
+
+ /// <summary>
+ /// Finds the specified attribute based on the <paramref name="type"/> which must
+ /// be a <see cref="Type"/> that implements <see cref="AttributeBase"/>
+ /// and <see cref="IAttribute"/>.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ /// <returns>
+ /// An instance of <see cref="AttributeBase"/>.
+ /// </returns>
+ public AttributeBase FindAttribute(Type type)
+ {
+ AttributeBase value;
+
+ if (type.IsInterface)
+ {
+ if (!this.interfaceMap.TryGetValue(type, out value))
+ throw new ArgumentException(
+ string.Format(
+ "The specified type '{0}' could not be found, try using " +
+ "ContainsAttribute(Type) first.",
+ type.FullName));
+ }
+ else
+ {
+ if (!this.attributeMap.TryGetValue(type, out value))
+ throw new ArgumentException(
+ string.Format(
+ "The specified type '{0}' could not be found, try using " +
+ "ContainsAttribute(Type) first.",
+ type.FullName));
+ }
+
+
+ return value;
+ }
+
+ /// <summary>
+ /// Returns the enumerator for stored interface types in the same order
+ /// they were stored int.
+ /// </summary>
+ /// <returns>
+ /// An instance of <see cref="IEnumerator{Type}"/>.
+ /// </returns>
+ public IEnumerator<Type> GetAttributeTypesEnumerator()
+ {
+ return this.interfaceMap.Keys.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Creates and returns an <see cref="AttributeEnumerator"/> that will enumerate
+ /// throw all available instances of <see cref="AttributeBase"/>. The enumerator
+ /// may contain less instances than <see cref="GetAttributeTypesEnumerator"/>.
+ /// </summary>
+ /// <returns>
+ /// An instance of <see cref="IEnumerator{AttributeBase}"/>.
+ /// </returns>
+ public IEnumerator<AttributeBase> GetAttributeEnumerator()
+ {
+ return new AttributeEnumerator(this);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this instance.
+ /// </summary>
+ /// <returns>
+ /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
+ /// </returns>
+ public override int GetHashCode()
+ {
+ int code = 0;
+ for (var state = this.GetCurrentState(); state != null; state = state.Next)
+ code = (code * 31) + state.Attribute.GetHashCode();
+
+ return code;
+ }
+
+ /// <summary>
+ /// Restores the attribute source state by copying the values of all
+ /// attribute instances that the state contains into the target stream.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The target stream must contain a corresponding instance for
+ /// each argument contained in this state. It is not possible
+ /// to restore the state of an <see cref="AttributeSource"/>
+ /// containing a <c>TermAttribute</c> into an <see cref="AttributeSource"/>
+ /// using a <see cref="Token"/> instance.
+ /// </para>
+ /// <note>
+ /// This method does not affect attributes of the target stream
+ /// that are not contained in this state. If the target stream
+ /// contains an <see cref="OffsetAttribute"/>, but this <paramref name="state"/>
+ /// does not, then the value of the <see cref="OffsetAttribute"/>
+ /// remains unchanged.
+ /// </note>
+ /// <para>
+ /// It might be desirable to reset its value to the default.
+ /// The caller should first call <see cref="ClearAttributes"/> on
+ /// the target stream in order to reset its value.
+ /// </para>
+ /// </remarks>
+ /// <param name="state">The state.</param>
+ /// <exception cref="ArgumentException">
+ /// Thrown when a state contains ain attribute that is not found
+ /// within the current instance of <see cref="AttributeSource"/>
+ /// </exception>
+ public void RestoreState(State state)
+ {
+ if (state == null)
+ return;
+ do
+ {
+ var attribute = this.attributeMap[state.Attribute.GetType()];
+
+ if (attribute == null)
+ throw new ArgumentException(this.CreateStateExceptionMessage(state));
+
+ state.Attribute.CopyTo(attribute);
+ state = state.Next;
+ }
+ while (state != null);
+ }
+
+ /// <summary>
+ /// Enumerates over the stored states in the <see cref="AttributeSource"/>
+ /// </summary>
+ /// <param name="invoke">The action to invoke on each state.</param>
+ protected void ForEachState(Action<State> invoke)
+ {
+ for (var state = this.GetCurrentState(); state != null; state = state.Next)
+ invoke(state);
+ }
+
+ private State GetCurrentState()
+ {
+ State state = this.currentState[0];
+
+ if (state != null || !this.HasAttributes)
+ return state;
+
+ State current = state = this.currentState[0] = new State();
+
+ var enumerator = this.attributeMap.Values.GetEnumerator();
+ enumerator.MoveNext();
+ current.Attribute = enumerator.Current;
+
+ while (enumerator.MoveNext())
+ {
+ current = current.Next = new State();
+ current.Attribute = enumerator.Current;
+ }
+
+ return state;
+ }
+
+ private string CreateStateExceptionMessage(State state)
+ {
+ return string.Format(
+ "The state contains an attribute of type '{0}' " +
+ "that is currently not found within this instance of '{1}#{2}'. ",
+ state.Attribute.GetType(),
+ this.GetType().Name,
+ this.GetHashCode());
+ }
+
+ /// <summary>
+ /// The enumerator for <see cref="AttributeBase"/> instances stored inside
+ /// of an <see cref="AttributeSource"/> instance.
+ /// </summary>
+ public sealed class AttributeEnumerator : IEnumerator<AttributeBase>
+ {
+ private State state;
+ private AttributeSource source;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AttributeEnumerator"/> class.
+ /// </summary>
+ /// <param name="source">The source.</param>
+ internal AttributeEnumerator(AttributeSource source)
+ {
+ this.source = source;
+ this.state = source.GetCurrentState();
+ }
+
+ /// <summary>
+ /// Gets the current <see cref="AttributeBase"/> at this position.
+ /// </summary>
+ /// <value>The current.</value>
+ /// <exception cref="ObjectDisposedException">
+ /// Thrown when <see cref="Dispose"/> has already been called on the object.
+ /// </exception>
+ public AttributeBase Current
+ {
+ get
+ {
+ if (this.source == null)
+ throw new ObjectDisposedException(this.GetType().Name);
+
+ return this.state.Attribute;
+ }
+ }
+
+ object System.Collections.IEnumerator.Current
+ {
+ get { return this.Current; }
+ }
+
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ this.state = null;
+ this.source = null;
+ }
+
+
+
+
+
+ /// <summary>
+ /// Advances the enumerator to the next element of the collection.
+ /// </summary>
+ /// <returns>
+ /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
+ /// </returns>
+ /// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception>
+ /// <exception cref="ObjectDisposedException">
+ /// Thrown when <see cref="Dispose"/> has already been called on the object.
+ /// </exception>
+ public bool MoveNext()
+ {
+ if (this.source == null)
+ throw new ObjectDisposedException(this.GetType().Name);
+
+ this.state = this.state.Next;
+ return this.state != null;
+ }
+
+ /// <summary>
+ /// Sets the enumerator to its initial position, which is before the first element in the collection.
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception>
+ /// <exception cref="ObjectDisposedException">
+ /// Thrown when <see cref="Dispose"/> has already been called on the object.
+ /// </exception>
+ public void Reset()
+ {
+ if (this.source == null)
+ throw new ObjectDisposedException(this.GetType().Name);
+
+ this.state = this.source.GetCurrentState();
+ }
+ }
+
+
+ /// <summary>
+ /// The state of an attribute source.
+ /// </summary>
+ public sealed class State : ICloneable, ICloneable<State>
+ {
+ /// <summary>
+ /// Gets or sets the attribute.
+ /// </summary>
+ /// <value>The attribute.</value>
+ public AttributeBase Attribute { get; set; }
+
+ /// <summary>
+ /// Gets or sets the next state.
+ /// </summary>
+ /// <value>The next.</value>
+ public State Next { get; set; }
+
+ /// <summary>
+ /// Fully clones this instance.
+ /// </summary>
+ /// <returns>an instance of the cloned <see cref="State"/>.</returns>
+ public State Clone()
+ {
+ State state = new State { Attribute = this.Attribute.Clone() };
+
+ if (this.Next != null)
+ state.Next = this.Next.Clone();
+
+ return state;
+ }
+
+ object ICloneable.Clone()
+ {
+ return this.Clone();
+ }
}
}
}
Modified: incubator/lucene.net/branches/Lucene.Net_4e/test/Lucene.Net.Test/Support/ICloneable.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/branches/Lucene.Net_4e/test/Lucene.Net.Test/Support/ICloneable.cs?rev=1156935&r1=1156934&r2=1156935&view=diff
==============================================================================
--- incubator/lucene.net/branches/Lucene.Net_4e/test/Lucene.Net.Test/Support/ICloneable.cs (original)
+++ incubator/lucene.net/branches/Lucene.Net_4e/test/Lucene.Net.Test/Support/ICloneable.cs Fri Aug 12 01:46:36 2011
@@ -25,6 +25,7 @@ namespace Lucene.Net.Support
using System.Collections.Generic;
using System.Linq;
using System.Text;
+ using System.Collections.Concurrent;
/// <summary>
///