001    package org.apache.commons.betwixt.registry;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one or more
005     * contributor license agreements.  See the NOTICE file distributed with
006     * this work for additional information regarding copyright ownership.
007     * The ASF licenses this file to You under the Apache License, Version 2.0
008     * (the "License"); you may not use this file except in compliance with
009     * the License.  You may obtain a copy of the License at
010     * 
011     *      http://www.apache.org/licenses/LICENSE-2.0
012     * 
013     * Unless required by applicable law or agreed to in writing, software
014     * distributed under the License is distributed on an "AS IS" BASIS,
015     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016     * See the License for the specific language governing permissions and
017     * limitations under the License.
018     */ 
019    
020    import java.util.Collection;
021    import java.util.HashMap;
022    import java.util.Iterator;
023    import java.util.Map;
024    
025    import org.apache.commons.betwixt.ElementDescriptor;
026    import org.apache.commons.betwixt.XMLBeanInfo;
027    import org.apache.commons.betwixt.io.read.ElementMapping;
028    import org.apache.commons.betwixt.io.read.ReadContext;
029    
030    /** The default caching implementation.
031      * A hashmap is used.
032      *
033      * @author <a href="mailto:rdonkin@apache.org">Robert Burrell Donkin</a>
034      * @version $Id: DefaultXMLBeanInfoRegistry.java 438373 2006-08-30 05:17:21Z bayard $
035      */
036    public class DefaultXMLBeanInfoRegistry implements XMLBeanInfoRegistry, PolymorphicReferenceResolver {
037    
038        /** Used to associated <code>XMLBeanInfo</code>'s to classes */
039        private Map xmlBeanInfos = new HashMap();
040        
041        /**
042          * Get <code>XMLBeanInfo</code> from cache. 
043          *
044          * @param forThisClass the class for which to find a <code>XMLBeanInfo</code>
045          * @return cached <code>XMLBeanInfo</code> associated with given class
046          * or <code>null</code> if no <code>XMLBeanInfo</code> has been associated
047          */
048        public XMLBeanInfo get(Class forThisClass) {
049            return (XMLBeanInfo) xmlBeanInfos.get(forThisClass);
050        }
051        
052        /**
053          * Put into cache
054          *
055          * @param forThisClass the class to cache the <code>XMLBeanInfo</code> for
056          * @param beanInfo the <code>XMLBeanInfo</code> to cache
057          */
058        public void put(Class forThisClass, XMLBeanInfo beanInfo) {
059            xmlBeanInfos.put(forThisClass, beanInfo);
060        }
061        
062        /**
063          * Flush existing cached <code>XMLBeanInfo</code>'s.
064          */
065        public void flush() {
066            xmlBeanInfos.clear();
067        }
068    
069        /**
070         * Checks all registered <code>XMLBeanInfo</code>'s for the
071         * first suitable match. 
072         * If a suitable one is found, then the class of that info is used. 
073         * @see org.apache.commons.betwixt.registry.PolymorphicReferenceResolver#resolveType(org.apache.commons.betwixt.io.read.ElementMapping, org.apache.commons.betwixt.io.read.ReadContext)
074         * @since 0.7
075         */
076        public Class resolveType(ElementMapping mapping, ReadContext context) {
077            Class result = null;
078            Collection cachedClasses = getCachedClasses();
079            ElementDescriptor mappedDescriptor = mapping.getDescriptor();
080            Class mappedType = mappedDescriptor.getSingularPropertyType();
081            if (mappedType == null) {
082                mappedType = mappedDescriptor.getPropertyType();
083            }
084            for (Iterator it = cachedClasses.iterator(); it.hasNext();) {
085                XMLBeanInfo  beanInfo  = get((Class)it.next());
086                ElementDescriptor typeDescriptor = beanInfo.getElementDescriptor();
087                boolean sameName = mapping.getName().equals(typeDescriptor.getQualifiedName());
088                if (sameName)
089                {
090                    
091                    boolean compatibleClass = mappedType.isAssignableFrom(beanInfo.getBeanClass());
092                    if (compatibleClass ) {
093                        result = beanInfo.getBeanClass();
094                        break;
095                    }
096                }
097            }
098            return result;
099        }
100        
101        /**
102         * Gets all classes that are cached in this registry.
103         * 
104         * @return The classes
105         */
106        private Collection getCachedClasses()
107        {
108            return xmlBeanInfos.keySet();
109        }
110    }