001    /*
002     * Copyright 2006 Stephen J. McConnell.
003     *
004     * Licensed  under the  Apache License,  Version 2.0  (the "License");
005     * you may not use  this file  except in  compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *   http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed  under the  License is distributed on an "AS IS" BASIS,
012     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
013     * implied.
014     *
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package net.dpml.lang;
020    
021    /**
022     * Simple service registry implementation that selects the first service 
023     * that is type assignable from the list of service instance supplied to 
024     * the registry constructor.
025     *
026     * @author <a href="http://www.dpml.net">Digital Product Management Laboratory</a>
027     * @version 2.0.2
028     */
029    public class SimpleServiceRegistry implements ServiceRegistry
030    {
031        private final ServiceRegistry m_parent;
032        private final Object[] m_args;
033        
034       /**
035        * Creation of a new service registry with no parent.
036        * @param args an ordered sequence of thread-safe services
037        */
038        public SimpleServiceRegistry( Object... args )
039        {
040           this( null, args );
041        }
042        
043       /**
044        * Creation of a new service registry with no parent.
045        * @param parent an optional fallback registry
046        * @param args an ordered sequence of thread-safe services
047        */
048        public SimpleServiceRegistry( ServiceRegistry parent, Object... args )
049        {
050            if( null == args )
051            {
052                throw new NullPointerException( "args" );
053            }
054            m_parent = parent;
055            m_args = args;
056        }
057        
058       /**
059        * Matches a service in the registry with the supplied type.  If no
060        * match is found and a parent registry has been delclared, the lookup
061        * request is passed onto the parent registry, otherwise null is 
062        * returned.
063        * @param type the service type
064        * @return an instance of the type or null if the type could not be resolved
065        */
066        public <T>T lookup( Class<T> type )
067        {
068            for( Object object : m_args )
069            {
070                if( null != object )
071                {
072                    Class c = object.getClass();
073                    if( type.isAssignableFrom( c ) )
074                    {
075                        return type.cast( object );
076                    }
077                }
078            }
079            if( null != m_parent )
080            {
081                return m_parent.lookup( type );
082            }
083            return null;
084        }
085    }
086