001    /*
002     * Copyright 2002-2004 The Apache Software Foundation
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 implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.apache.commons.clazz.common;
017    
018    import java.util.ArrayList;
019    import java.util.Collections;
020    import java.util.List;
021    
022    import org.apache.commons.clazz.Clazz;
023    import org.apache.commons.clazz.ClazzLoader;
024    import org.apache.commons.clazz.ModelClazzLoader;
025    
026    /**
027     * Aggregates multiple ClazzLoaders, which are invoked one after another
028     * according to the ChainOfResponsibility pattern.  Note that member clazz
029     * loaders are invoked in the order reverse to the order they were added. 
030     * 
031     * @author <a href="mailto:dmitri@apache.org">Dmitri Plotnikov</a>
032     * @version $Id: GroupClazzLoader.java 155436 2005-02-26 13:17:48Z dirkv $
033     */
034    public class GroupClazzLoader extends ClazzLoader {
035        /**
036         * List of member loaders. Note that the list is always iterated in the
037         * reverse direction, so the loaded add last is the one invoked first.
038         */
039        protected ArrayList loaders = new ArrayList();
040    
041        public GroupClazzLoader(ModelClazzLoader modelClazzLoader) {
042            super(modelClazzLoader);
043        }
044    
045        /**
046         * Returns true if the supplied loader "belongs" in the group and can be
047         * added to it.  The default implementation returns true.
048         */
049        public boolean canAddClazzLoader(ClazzLoader loader) {
050            return true;
051        }
052    
053        /**
054         * Adds a ClazzLoader to the group. ClazzLoaders added last are invoked
055         * first.  Before the group adds the loader to itself, it checks if any
056         * of its members are groups themselves and, if so, tries to add the new
057         * loader to those subgroups.  
058         */
059        public void addClazzLoader(ClazzLoader loader) {
060            for (int i = loaders.size(); --i >= 0;) {
061                ClazzLoader member = (ClazzLoader) loaders.get(i);
062                if (member instanceof GroupClazzLoader) {
063                    GroupClazzLoader group = (GroupClazzLoader) member;
064                    if (group.canAddClazzLoader(loader)) {
065                        group.addClazzLoader(loader);
066                        return;
067                    }
068                }
069            }
070            loaders.add(loader);
071        }
072    
073        /**
074         * Returns true iff this group has a member loader that has or can construct
075         * a Clazz for the supplied instance.
076         */
077        public boolean isMember(Object instance) {
078            // Note the reverse order
079            for (int i = loaders.size(); --i >= 0;) {
080                ClazzLoader loader = (ClazzLoader) loaders.get(i);
081                if (loader.isMember(instance)) {
082                    return true;
083                }
084            }
085            return false;
086        }
087    
088        public String getClazzName(Object instance) {
089            // Note the reverse order
090            for (int i = loaders.size(); --i >= 0;) {
091                ClazzLoader loader = (ClazzLoader) loaders.get(i);
092                String name = loader.getClazzName(instance);
093                if (name != null) {
094                    return name;
095                }
096            }
097            return null;
098        }
099    
100        /**
101         * Given a Clazz name, produces the corresponding Clazz by invoking member
102         * loaders one by one until the clazz is found.
103         */
104        public Clazz getClazzForName(String name) {
105            Clazz clazz = null;
106            // Note the reverse order
107            for (int i = loaders.size(); --i >= 0;) {
108                ClazzLoader loader = (ClazzLoader) loaders.get(i);
109                clazz = loader.getClazzForName(name);
110                if (clazz != null) {
111                    break;
112                }
113            }
114            return clazz;
115        }
116    
117        /**
118         * @see ClazzLoader#defineClazz(String, Class, Class)
119         */
120        public Clazz defineClazz(
121            String name,
122            Class clazzClass,
123            Class instanceClass) 
124        {
125            Clazz clazz = null;
126            // Note the reverse order
127            for (int i = loaders.size(); --i >= 0;) {
128                ClazzLoader loader = (ClazzLoader) loaders.get(i);
129                clazz = loader.defineClazz(name, clazzClass, instanceClass);
130                if (clazz != null) {
131                    break;
132                }
133            }
134            return clazz;
135        }
136    
137        /**
138         * Returns all clazz loaders registered with this group,
139         * in the order of priority
140         */
141        public List getClazzLoaders() {
142            return Collections.unmodifiableList(loaders);
143        }
144    
145        /**
146         * Returns clazzloaders matching the supplied Predicate
147         */
148    //    public List getClazzLoaders(Predicate predicate) {
149    //    }
150    }