001    // Copyright 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.util;
016    
017    /**
018     * A simple map-like collection, similar to (but more more limited than) JDK
019     * 1.4's IdentityHashMap. It is designed for <em>small</em> collections of
020     * objects.
021     * 
022     * @author Howard Lewis Ship
023     * @since 4.0
024     */
025    public class ObjectIdentityMap
026    {
027    
028        private int _pairCount = 0;
029    
030        // Alternates between keys and values
031    
032        private Object[] _pairs;
033    
034        /**
035         * Adds or updates a key in the bag.
036         * 
037         * @param key
038         *            the key to store a value under; an existing value with the key
039         *            is discarded
040         * @param value
041         *            the value to store
042         */
043        public void put(Object key, Object value)
044        {
045            for(int i = 0; i < _pairCount; i++)
046            {
047                int index = 2 * i;
048    
049                if (_pairs[index] == key)
050                {
051                    _pairs[index + 1] = value;
052                    return;
053                }
054            }
055    
056            expandPairsIfNeeded();
057    
058            int index = 2 * _pairCount;
059    
060            _pairs[index] = key;
061            _pairs[index + 1] = value;
062    
063            _pairCount++;
064        }
065    
066        /**
067         * Returns the object stored for the given key.
068         * 
069         * @return the value, or null if the key is not found
070         */
071    
072        public Object get(Object key)
073        {
074            for(int i = 0; i < _pairCount; i++)
075            {
076                int index = 2 * i;
077    
078                if (_pairs[index] == key) { return _pairs[index + 1]; }
079            }
080    
081            return null;
082        }
083    
084        private void expandPairsIfNeeded()
085        {
086            int currentSize = _pairs == null ? 0 : _pairs.length;
087    
088            int newLength = 2 * (_pairCount + 1);
089    
090            if (newLength >= currentSize)
091            {
092                // Expand to dobule current size. Allocate room for 5 keys and 5
093                // values
094                // initially.
095    
096                int newSize = Math.max(10, 2 * currentSize);
097    
098                Object[] newPairsArray = new Object[newSize];
099    
100                if (currentSize > 0)
101                    System.arraycopy(_pairs, 0, newPairsArray, 0, currentSize);
102    
103                _pairs = newPairsArray;
104            }
105        }
106    }