blob: 3afa2637cc4e2b860ded218e62b88e9078a26155 [file]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace Lucene.Net.Util
{
/*
* 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.
*/
/// <summary> Base class for Attributes that can be added to a
/// <see cref="Lucene.Net.Util.AttributeSource" />.
/// <p/>
/// Attributes are used to add data in a dynamic, yet type-safe way to a source
/// of usually streamed objects, e. g. a <see cref="Lucene.Net.Analysis.TokenStream" />.
/// </summary>
#if FEATURE_SERIALIZABLE
[Serializable]
#endif
public abstract class Attribute : IAttribute
#if FEATURE_CLONEABLE
, ICloneable
#endif
{
/// <summary> Clears the values in this Attribute and resets it to its
/// default value. If this implementation implements more than one Attribute interface
/// it clears all.
/// </summary>
public abstract void Clear();
/// <summary>
/// This is equivalent to the anonymous class in the java version of ReflectAsString
/// </summary>
private class StringBuilderAttributeReflector : IAttributeReflector
{
private readonly StringBuilder buffer;
private readonly bool prependAttClass;
public StringBuilderAttributeReflector(StringBuilder buffer, bool prependAttClass)
{
this.buffer = buffer;
this.prependAttClass = prependAttClass;
}
public void Reflect<T>(string key, object value)
where T : IAttribute
{
Reflect(typeof(T), key, value);
}
public void Reflect(Type type, string key, object value)
{
if (buffer.Length > 0)
{
buffer.Append(',');
}
if (prependAttClass)
{
buffer.Append(type.Name).Append('#');
}
buffer.Append(key).Append('=').Append(object.ReferenceEquals(value, null) ? (object)"null" : value);
}
}
public string ReflectAsString(bool prependAttClass)
{
StringBuilder buffer = new StringBuilder();
ReflectWith(new StringBuilderAttributeReflector(buffer, prependAttClass));
return buffer.ToString();
}
public virtual void ReflectWith(IAttributeReflector reflector) // LUCENENET NOTE: This method was abstract in Lucene
{
Type clazz = this.GetType();
LinkedList<WeakReference> interfaces = AttributeSource.GetAttributeInterfaces(clazz);
if (interfaces.Count != 1)
{
throw new NotSupportedException(clazz.Name + " implements more than one Attribute interface, the default ReflectWith() implementation cannot handle this.");
}
Type interf = (System.Type)interfaces.First().Target;
/*object target = interfaces.First.Value;
if (target == null)
return;
Type interf = target.GetType();// as Type;*/
//problem: the interfaces list has weak references that could have expired already
FieldInfo[] fields = clazz.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
try
{
for (int i = 0; i < fields.Length; i++)
{
FieldInfo f = fields[i];
if (f.IsStatic) continue;
reflector.Reflect(interf, f.Name, f.GetValue(this));
}
}
catch (MemberAccessException e)
{
throw new Exception(e.ToString(), e);
}
}
/// <summary> The default implementation of this method accesses all declared
/// fields of this object and prints the values in the following syntax:
///
/// <code>
/// public String toString() {
/// return "start=" + startOffset + ",end=" + endOffset;
/// }
/// </code>
///
/// This method may be overridden by subclasses.
/// </summary>
public override string ToString() // LUCENENET NOTE: This method didn't exist in Lucene
{
StringBuilder buffer = new StringBuilder();
Type clazz = this.GetType();
FieldInfo[] fields = clazz.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Static);
for (int i = 0; i < fields.Length; i++)
{
FieldInfo f = fields[i];
if (f.IsStatic)
continue;
//f.setAccessible(true); // {{Aroush-2.9}} java.lang.reflect.AccessibleObject.setAccessible
object value_Renamed = f.GetValue(this);
if (buffer.Length > 0)
{
buffer.Append(',');
}
if (value_Renamed == null)
{
buffer.Append(f.Name + "=null");
}
else
{
buffer.Append(f.Name + "=" + value_Renamed);
}
}
return buffer.ToString();
}
/// <summary> Copies the values from this Attribute into the passed-in
/// target attribute. The target implementation must support all the
/// Attributes this implementation supports.
/// </summary>
public abstract void CopyTo(IAttribute target);
/// <summary> Shallow clone. Subclasses must override this if they
/// need to clone any members deeply,
/// </summary>
public virtual object Clone()
{
return base.MemberwiseClone();
}
}
}