/*
 Copyright (c) 2007 Eric J. Feminella <eric@ericfeminella.com>
 All rights reserved.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy 
 of this software and associated documentation files (the "Software"), to deal 
 in the Software without restriction, including without limitation the rights 
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is furnished 
 to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in all 
 copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
 PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 @internal
 */

package com.ericfeminella.ns
{    
    import com.ericfeminella.utils.SingletonManager;
    
    /**
     *  
     * <code>ContextNamespace</code> is a Singleton class which 
     * can be utilized by classes within an application to retrieve 
     * a contextual namespace in which methods and properties of 
     * an object are to be referenced under
     * 
     * <p>
     * <code>ContextNamespace</code>  contains a reference to the 
     * current contextual namespace which represents the context 
     * from which the application is executing.
     * </p>
     * 
     * <p>
     * For instance, let's say we have an application which requires 
     * slightly different behaviors depending on the type of user. 
     * If the user is a guest, the application only needs to display 
     * a fairly simple view, however if the user is an administrator 
     * the application must display a more complex view to the user. 
     * Based on the type of user we can deduce context, and from this 
     * context we can provide contextual namespaces from which methods
     * can be invoked on an object without the need to directly refer
     * to the specific namespace.
     * </p>
     * 
     * @example An example which demonstrates this behavior is as
     * follows
     * 
     * <listing version="3.0">
     * 
     * package
     * {
     *    import com.domain.namespaces.admin;
     *    import com.domain.namespaces.guest;
     * 
     *    public class UserViewHelper
     *    {
     *        admin static function renderView()
     *        {
     *           // admin implementation code...
     *        }
     * 
     *        guest static function renderView()
     *        {
     *           // guest implementation code...
     *        }
     *    }
     * }
     * 
     * </listing>
     * 
     * @example We can utilize <code>ContextualNamespace</code> to 
     * reference the current contextual namespace and invoke methods
     * on a class or instance of a class based on the local reference
     * 
     * <listing version="3.0">
     * 
     * var ns:Namespace = ContextualNamespace.instance.getNamespace();
     * UserViewHelper.ns::renderView();
     * 
     * </listing>
     * 
     * @see http://livedocs.adobe.com/labs/flex/3/langref/Namespace.html
     *  
     */    
    public final class ContextNamespace implements INamespaceManager
    {        
        /**
         * 
         * Defines the Singleton instance of <code>ContextNamespace</code>
         * which is utilized by an application to determine and retrieve
         * the current context <code>Namespace</code> of the application
         * 
         * @example 
         * 
         * <listing version="3.0">
         * 
         * import com.ericfeminella.core.ns.ContextNamespace;
         * 
         * var ns:INamespaceManager = ContextNamespace.instance;
         * 
         * </listing>
         * 
         * @see INamespaceManager
         * 
         */
        public static var instance:INamespaceManager = new ContextNamespace();
        
        /**
         * 
         * Defines the custom namespace which will be used throughout
         * the application based on the context in which the application
         * is executing
         * 
         */
        private var ns:Namespace;
            
        /**
         * 
         * Performs initialization of the <code>ContextNamespace</code>
         * Singleton instance
         * 
         * @see com.ericfeminella.utils.SingletonManager
         * 
         */        
        public function ContextNamespace()
        {
            SingletonManager.validateInstance( this );
        }
                
        /**
         * 
         * Retrieves the qualified namespace object which is based on
         * the current context in which the application is executing
         * 
         * <p>
         * The namespace referenced by <code>getNamespace</code> is to 
         * be utilized to determine the context from which methods are 
         * to be invoked on an object
         * </p>
         * 
         * @example The following demonstrates a typical use-case which 
         * utilizes <code>ContextNamespace</code> to reference the 
         * appropriate contextual namespace 
         * 
         * <listing version="3.0">
         * 
         * var ns:Namespace = ContextNamespace.instance.getNamespace();
         * someObject.ns::someMethod();
         * 
         * </listing>
         * 
         * @return the current contextual <code>Namespace</code> 
         * 
         */        
        public function getNamespace() : Namespace
        {
            return ns;
        }

        /**
         * 
         * Sets the qualified namespace object based on the current 
         * context of the application
         * 
         * <p>
         * The namespace referenced by <code>getNamespace</code> is to 
         * be utilized to determine the context from which methods are 
         * called. This namespace is set by <code>setNamespace</code>
         * </p>
         * 
         * @example The following demonstrates a typical use-case which 
         * sets the <code>ContextNamespace</code> namespace based on the 
         * current context of the application
         * 
         * <listing version="3.0">
         * 
         * import com.ericfeminella.core.ns.ContextNamespace;
         * 
         * var us:Namespace = new Namespace("http://domain.com/ns/locale/us");
         * ContextNamespace.instance.setNamespace( us );
         * 
         * </listing>
         *  
         * @param the contextual Namespace of the application
         * 
         */        
        public function setNamespace(ns:Namespace) : void
        {
            this.ns = ns;
        }
            
        /**
         * 
         * Retrieves the qualified namespace URI of the current
         * namespace
         * 
         * @example The following example demonstrates retrieving
         * the URI of the current contextual namespace
         * 
         * <listing version="3.0">
         * 
         * var us:Namespace = new Namespace("http://domain.com/ns/locale/us");
         * ContextNamespace.instance.setNamespace( us );
         * 
         * var uri:String = ContextNamespace.instance.namespaceURI;
         * 
         * trace( uri );
         * // http://domain.com/ns/locale/us
         * 
         * </listing>
         * 
         * @return URI of the current <code>Namespace</code>
         * 
         */        
        public function get namespaceURI() : String
        {
            return ns.uri;
        }
        
        /**
         * 
         * Retrieves the qualified namespace prefix from the current
         * namespace
         * 
         * @example The following example demonstrates retrieving
         * the prefix of the current contextual namespace
         * 
         * <listing version="3.0">
         * 
         * var us:Namespace = new Namespace("http://domain.com/ns/locale/us");
         * ContextNamespace.instance.setNamespace( us );
         * 
         * var prefix:String = ContextNamespace.instance.namespacePrefix;
         * trace( prefix );
         * 
         * </listing>
         * 
         * @return namespace prefix for the current namespace
         * 
         */        
        public function get namespacePrefix() : String
        {
            return ns.prefix;
        }
        
        /**
         *
         * Determines if the current contextual <code>Namespace</code> 
         * is that of the specified <code>Namespace</code>
         * 
         * @example The following example demonstrates how to determine
         * if the current contextual namespace is equal to the specified 
         * <code>Namespace</code> 
         * 
         * <listing version="3.0">
         * 
         * var us:Namespace = new Namespace("http://domain.com/ns/locale/us");
         * var it:Namespace = new Namespace("http://domain.com/ns/locale/it");
         * 
         * ContextNamespace.instance.setNamespace( us );
         * 
         * trace( ContextNamespace.instance.isCurrentContext( us ) );
         * // true
         * 
         * trace( ContextNamespace.instance.isCurrentContext( it ) );
         * // false
         * 
         * </listing>
         * 
         * @param   the namespace to determine a contextual match
         * @return  true of the current namespaces are equal, otherwise false
         * 
         */        
        public function isCurrentContext(ns:Namespace) : Boolean
        {
            var result:Boolean = this.ns === ns;
            return result;
        }
        
        /**
         *
         * Determines if the current contextual <code>Namespace</code> 
         * URI is equal to that of the specified <code>Namespace</code>
         * 
         * @example The following example demonstrates how to determine
         * if the current contextual namespace URI is equal to the 
         * specified URI
         * 
         * <listing version="3.0">
         * 
         * var us:Namespace = new Namespace("http://domain.com/ns/locale/us");
         * var it:String = "http://domain.com/ns/locale/it";
         * 
         * ContextNamespace.instance.setNamespace( us );
         * 
         * trace( ContextNamespace.instance.isCurrentURI( us.uri ) );
         * // true
         * 
         * trace( ContextNamespace.instance.isCurrentURI( it.uri ) );
         * // false
         * 
         * </listing>
         * 
         * @param   the namespace URI in which to determine a contextual match
         * @return  true of the current namespaces are equal, otherwise false
         * 
         */        
        public function isCurrentURI(uri:String) : Boolean
        {
            var result:Boolean = ns.uri == uri;
            return result;
        }
    }
}