context: /* Copyright (C) 2004 - 2009  Versant Inc.  http://www.db4o.com */
  
  using System;
  using System.Collections;
  using Db4objects.Db4o;
  using Db4objects.Db4o.Config;
  using Db4objects.Db4o.Ext;
  using Db4objects.Db4o.Foundation;
  using Db4objects.Db4o.Internal;
  using Db4objects.Db4o.Internal.Activation;
  using Db4objects.Db4o.Internal.Classindex;
  using Db4objects.Db4o.Internal.Delete;
  using Db4objects.Db4o.Internal.Diagnostic;
  using Db4objects.Db4o.Internal.Encoding;
  using Db4objects.Db4o.Internal.Handlers;
  using Db4objects.Db4o.Internal.Handlers.Array;
  using Db4objects.Db4o.Internal.Marshall;
  using Db4objects.Db4o.Internal.Metadata;
  using Db4objects.Db4o.Internal.Query.Processor;
  using Db4objects.Db4o.Internal.Reflect;
  using Db4objects.Db4o.Marshall;
  using Db4objects.Db4o.Query;
  using Db4objects.Db4o.Reflect;
  using Db4objects.Db4o.Reflect.Core;
  using Db4objects.Db4o.Reflect.Generic;
  using Db4objects.Db4o.Typehandlers;
  
  namespace Db4objects.Db4o.Internal
  {
  	/// <exclude></exclude>
  	public class ClassMetadata : PersistentBase, IStoredClass
  	{
  		/// <summary>
  		/// For reference types, _typeHandler always holds a StandardReferenceTypeHandler
  		/// that will use the _aspects of this class to take care of its business.
  		/// </summary>
  		/// <remarks>
  		/// For reference types, _typeHandler always holds a StandardReferenceTypeHandler
  		/// that will use the _aspects of this class to take care of its business. A custom
  		/// type handler would appear as a TypeHandlerAspect in that case.
  		/// For value types, _typeHandler always holds the actual value type handler be it
  		/// a custom type handler or a builtin one.
  		/// </remarks>
  		protected ITypeHandler4 _typeHandler;
  
  		public Db4objects.Db4o.Internal.ClassMetadata _ancestor;
  
  		private Config4Class _config;
  
  		public ClassAspect[] _aspects;
  
  		private IClassIndexStrategy _index;
  
  		private string i_name;
  
  		private readonly ObjectContainerBase _container;
  
  		internal byte[] i_nameBytes;
  
  		private ByteArrayBuffer i_reader;
  
  		private bool _classIndexed;
  
  		private IReflectClass _classReflector;
  
  		private IEventDispatcher _eventDispatcher;
  
  		private bool _internal;
  
  		private bool _unversioned;
  
  		private TernaryBool _canUpdateFast = TernaryBool.Unspecified;
  
  		private TranslatedAspect _translator;
  
  		private IModificationAware _modificationChecker = ClassMetadata.AlwaysModified.Instance;
  
  		private IFieldAccessor _fieldAccessor;
  
  		private IFunction4 _constructor;
  
  		private TypeHandlerAspect _customTypeHandlerAspect;
  
  		private IAspectTraversalStrategy _aspectTraversalStrategy;
  
  		internal bool CanUpdateFast()
  		{
  			if (_canUpdateFast == TernaryBool.Unspecified)
  			{
  				_canUpdateFast = TernaryBool.ForBoolean(CheckCanUpdateFast());
  			}
  			return _canUpdateFast.BooleanValue(false);
  		}
  
  		private bool CheckCanUpdateFast()
  		{
  			if (_ancestor != null && !_ancestor.CanUpdateFast())
  			{
  				return false;
  			}
  			if (_config != null && _config.CascadeOnDelete() == TernaryBool.Yes)
  			{
  				return false;
  			}
  			BooleanByRef hasIndex = new BooleanByRef(false);
  			TraverseDeclaredFields(new _IProcedure4_101(hasIndex));
  			return !hasIndex.value;
  		}
  
  		private sealed class _IProcedure4_101 : IProcedure4
  		{
  			public _IProcedure4_101(BooleanByRef hasIndex)
  			{
  				this.hasIndex = hasIndex;
  			}
  
  			public void Apply(object arg)
  			{
  				if (((FieldMetadata)arg).HasIndex())
  				{
  					hasIndex.value = true;
  				}
  			}
  
  			private readonly BooleanByRef hasIndex;
  		}
  
  		public virtual bool IsInternal()
  		{
  			return _internal;
  		}
  
  		private IClassIndexStrategy CreateIndexStrategy()
  		{
  			return new BTreeClassIndexStrategy(this);
  		}
  
  		protected ClassMetadata(ObjectContainerBase container)
  		{
  			if (null == container)
  			{
  				throw new ArgumentNullException();
  			}
  			_container = container;
  			_index = CreateIndexStrategy();
  			_classIndexed = true;
  			_fieldAccessor = new StrictFieldAccessor();
  		}
  
  		public ClassMetadata(ObjectContainerBase container, IReflectClass classReflector)
  		{
  			if (null == container)
  			{
  				throw new ArgumentNullException();
  			}
  			_container = container;
  			ClassReflector(classReflector);
  			_index = CreateIndexStrategy();
  			_classIndexed = true;
  			if (_container.Config().ExceptionsOnNotStorable())
  			{
  				_fieldAccessor = new StrictFieldAccessor();
  			}
  			else
  			{
  				_fieldAccessor = new LenientFieldAccessor();
  			}
  		}
  
  		internal virtual IFieldAccessor FieldAccessor()
  		{
  			return _fieldAccessor;
  		}
  
  		private ITypeHandler4 CreateDefaultTypeHandler()
  		{
  			// TODO: make sure initializeAspects has been executed
  			// before the actual type handler is required
  			// and remove this method
  			return new StandardReferenceTypeHandler(this);
  		}
  
  		public virtual void CascadeActivation(IActivationContext context)
  		{
  			if (!ObjectCanActivate(context.Transaction(), context.TargetObject()))
  			{
  				return;
  			}
  			TraverseAllAspects(new _ITraverseAspectCommand_160(context));
  		}
  
  		private sealed class _ITraverseAspectCommand_160 : ITraverseAspectCommand
  		{
  			public _ITraverseAspectCommand_160(IActivationContext context)
  			{
  				this.context = context;
  			}
  
  			public void ProcessAspectOnMissingClass(ClassAspect aspect, int currentSlot)
  			{
  			}
  
  			// do nothing
  			public void ProcessAspect(ClassAspect aspect, int currentSlot)
  			{
  				aspect.CascadeActivation(context);
  			}
  
  			public int DeclaredAspectCount(Db4objects.Db4o.Internal.ClassMetadata classMetadata
  				)
  			{
  				return classMetadata.DeclaredAspectCount();
  			}
  
  			public bool Cancelled()
  			{
  				return false;
  			}
  
  			private readonly IActivationContext context;
  		}
  
  		public void AddFieldIndices(StatefulBuffer buffer)
  		{
  			if (!StandardReferenceTypeHandlerIsUsed())
  			{
  				return;
  			}
  			if (HasClassIndex() || HasVirtualAttributes())
  			{
  				ObjectHeader oh = new ObjectHeader(this, buffer);
  				ObjectIdContextImpl context = new ObjectIdContextImpl(buffer.Transaction(), buffer
  					, oh, buffer.GetID());
  				Handlers4.FieldAwareTypeHandler(CorrectHandlerVersion(context)).AddFieldIndices(context
  					);
  			}
  		}
  
  		// FIXME: This method wants to be removed.
  		private bool StandardReferenceTypeHandlerIsUsed()
  		{
  			return _typeHandler is StandardReferenceTypeHandler;
  		}
  
  		internal virtual void InitializeAspects()
  		{
  			BitTrue(Const4.CheckedChanges);
  			Collection4 aspects = new Collection4();
  			if (null != _aspects)
  			{
  				aspects.AddAll(_aspects);
  			}
  			ITypeHandler4 customTypeHandler = Container().Handlers.ConfiguredTypeHandler(ClassReflector
  				());
  			bool dirty = IsDirty();
  			if (InstallTranslator(aspects, customTypeHandler))
  			{
  				dirty = true;
  			}
  			if (Container().DetectSchemaChanges())
  			{
  				if (GenerateCommitTimestamps())
  				{
  					if (!HasCommitTimestampField())
  					{
  						aspects.Add(Container().CommitTimestampIndex());
  						dirty = true;
  					}
  				}
  				if (GenerateUUIDs())
  				{
  					if (!HasUUIDField())
  					{
  						aspects.Add(Container().UUIDIndex());
  						dirty = true;
  					}
  				}
  			}
  			if (InstallCustomTypehandler(aspects, customTypeHandler))
  			{
  				dirty = true;
  			}
  			bool defaultFieldBehaviour = _translator == null && customTypeHandler == null;
  			if (Container().DetectSchemaChanges())
  			{
  				if (defaultFieldBehaviour)
  				{
  					if (CollectReflectFields(aspects))
  					{
  						dirty = true;
  					}
  				}
  				if (dirty)
  				{
  					_container.SetDirtyInSystemTransaction(this);
  				}
  			}
  			if (dirty || !defaultFieldBehaviour)
  			{
  				_aspects = ToClassAspectArray(aspects);
  			}
  			DiagnosticProcessor dp = _container._handlers.DiagnosticProcessor();
  			if (dp.Enabled())
  			{
  				dp.CheckClassHasFields(this);
  			}
  			if (_aspects == null)
  			{
  				_aspects = new FieldMetadata[0];
  			}
  			InitializeConstructor(customTypeHandler);
  			if (StateDead())
  			{
  				return;
  			}
  			_container.Callbacks().ClassOnRegistered(this);
  			SetStateOK();
  		}
  
  		private ClassAspect[] ToClassAspectArray(Collection4 aspects)
  		{
  			ClassAspect[] array = new ClassAspect[aspects.Size()];
  			aspects.ToArray(array);
  			for (int i = 0; i < array.Length; i++)
  			{
  				array[i].SetHandle(i);
  			}
  			return array;
  		}
  
  		private bool InstallCustomTypehandler(Collection4 aspects, ITypeHandler4 customTypeHandler
  			)
  		{
  			if (customTypeHandler == null)
  			{
  				return false;
  			}
  			if (customTypeHandler is IModificationAware)
  			{
  				_modificationChecker = (IModificationAware)customTypeHandler;
  			}
  			if (Handlers4.IsStandaloneTypeHandler(customTypeHandler))
  			{
  				_typeHandler = customTypeHandler;
  				return false;
  			}
  			bool dirty = false;
  			TypeHandlerAspect typeHandlerAspect = new TypeHandlerAspect(this, customTypeHandler
  				);
  			if (!ReplaceAspectByName(aspects, typeHandlerAspect))
  			{
  				aspects.Add(typeHandlerAspect);
  				dirty = true;
  			}
  			DisableAspectsBefore(aspects, typeHandlerAspect);
  			_customTypeHandlerAspect = typeHandlerAspect;
  			return dirty;
  		}
  
  		private void DisableAspectsBefore(Collection4 aspects, TypeHandlerAspect typeHandlerAspect
  			)
  		{
  			int disableFromVersion = aspects.IndexOf(typeHandlerAspect) + 1;
  			IEnumerator i = aspects.GetEnumerator();
  			while (i.MoveNext())
  			{
  				ClassAspect aspect = (ClassAspect)i.Current;
  				if (aspect == typeHandlerAspect)
  				{
  					break;
  				}
  				aspect.DisableFromAspectCountVersion(disableFromVersion);
  			}
  		}
  
  		private bool InstallTranslator(Collection4 aspects, ITypeHandler4 customTypeHandler
  			)
  		{
  
gt: 			if (_config == null)