// Copyright 2003-2004 The Apache Software Foundation // // Licensed 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. namespace Apache.Avalon.Framework { using System; using System.Collections; using System.Runtime.Serialization; /// /// Default implementation of IContext. /// public class DefaultContext : IContext { [Serializable] private sealed class Hidden { } private static Hidden HIDDEN_MAKER = new Hidden(); private IDictionary m_contextData; private IContext m_parent; private bool m_readOnly; /// /// Create a Context with specified data and parent. /// /// the context data /// the parent Context (may be null) public DefaultContext( IDictionary contextData, IContext parent ) { m_parent = parent; m_contextData = contextData; } /// /// Create a Context with specified data. /// /// the context data public DefaultContext( IDictionary contextData ) : this( contextData, null ) { } /// /// Create a Context with specified parent. /// /// the parent Context (may be null) public DefaultContext( IContext parent ) : this( Hashtable.Synchronized( new Hashtable() ), parent ) { } /// /// Create a Context with no parent. /// public DefaultContext() : this( (IContext) null ) { } #region IContext Members /// /// Retrieve an item from the Context. /// /// the key of item /// the item stored in context /// if item not present public object this[ object key ] { get { object data = m_contextData[key]; if( null != data ) { if( data is Hidden ) { // Always fail. string message = String.Format("Unable to locate {0}", key); throw new ContextException( message ); } if( data is IResolvable ) { return ( (IResolvable)data ).Resolve( this ); } return data; } // If data was null, check the parent if( null == m_parent ) { // There was no parent, and no data string message = String.Format("Unable to resolve context key {0}", key); throw new ContextException( message ); } return m_parent[ key ]; } } #endregion /// /// Helper method fo adding items to Context. /// /// the items key /// the item /// if context is read only public void Put( object key, object value ) { CheckWriteable(); if( null == value ) { m_contextData.Remove( key ); } else { m_contextData[ key ] = value; } } /// /// Hides the item in the context. /// After Hide(key) has been called, a Get(key) /// will always fail, even if the parent context /// has such a mapping. /// /// the items key /// if context is read only public void Hide( object key ) { CheckWriteable(); m_contextData[ key ] = HIDDEN_MAKER; } /// /// Utility method to retrieve context data. /// /// the context data protected IDictionary GetContextData() { return m_contextData; } /// /// Get parent context if any. /// /// the parent Context (may be null) protected IContext Parent { get { return m_parent; } } /// /// Make the context read-only. /// Any attempt to write to the context via Add() /// will result in an IllegalStateException. /// public void MakeReadOnly() { m_readOnly = true; } /// /// Utility method to check if context is writeable and if not throw exception. /// /// if context is read only protected void CheckWriteable() { if( m_readOnly ) { string message = "Context is read only and can not be modified"; throw new ContextException( message ); } } } }