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    import java.util.ServiceLoader;
022    
023    import net.dpml.lang.ServiceRegistry;
024    
025    /**
026     * Simple service registry implementation that selects the first service 
027     * that is type assignable from the list of service instance supplied to 
028     * the registry constructor.
029     *
030     * @author <a href="http://www.dpml.net">Digital Product Management Laboratory</a>
031     * @version 2.0.1
032     */
033    public class SimpleServiceRegistry implements ServiceRegistry
034    {
035        private final ServiceRegistry m_parent;
036        private final Object[] m_args;
037        
038       /**
039        * Creation of a new service registry with no parent.
040        * @param args an ordered sequence of thread-safe services
041        */
042        public SimpleServiceRegistry( Object... args )
043        {
044           this( null, args );
045        }
046        
047       /**
048        * Creation of a new service registry with no parent.
049        * @param parent an optional fallback registry
050        * @param args an ordered sequence of thread-safe services
051        */
052        public SimpleServiceRegistry( ServiceRegistry parent, Object... args )
053        {
054            if( null == args )
055            {
056                throw new NullPointerException( "args" );
057            }
058            m_parent = parent;
059            m_args = args;
060        }
061        
062       /**
063        * Matches a service in the registry with the supplied type.  If no
064        * match is found and a parent registry has been delclared, the lookup
065        * request is passed onto the parent registry, otherwise null is 
066        * returned.
067        */
068        public <T>T lookup( Class<T> type )
069        {
070            for( Object object : m_args )
071            {
072                if( null != object )
073                {
074                    Class c = object.getClass();
075                    if( type.isAssignableFrom( c ) )
076                    {
077                        return type.cast( object );
078                    }
079                }
080            }
081            if( null != m_parent )
082            {
083                return m_parent.lookup( type );
084            }
085            return null;
086        }
087    }
088