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
015package org.apache.tapestry.util;
016
017/**
018 * A simple map-like collection, similar to (but more more limited than) JDK 1.4's IdentityHashMap.
019 * It is designed for <em>small</em> collections of objects.
020 * 
021 * @author Howard Lewis Ship
022 * @since 4.0
023 */
024public class ObjectIdentityMap
025{
026    private int _pairCount = 0;
027
028    // Alternates between keys and values
029
030    private Object[] _pairs;
031
032    /**
033     * Adds or updates a key in the bag.
034     * 
035     * @param key
036     *            the key to store a value under; an existing value with the key is discarded
037     * @param value
038     *            the value to store
039     */
040    public void put(Object key, Object value)
041    {
042        for (int i = 0; i < _pairCount; i++)
043        {
044            int index = 2 * i;
045
046            if (_pairs[index] == key)
047            {
048                _pairs[index + 1] = value;
049                return;
050            }
051        }
052
053        expandPairsIfNeeded();
054
055        int index = 2 * _pairCount;
056
057        _pairs[index] = key;
058        _pairs[index + 1] = value;
059
060        _pairCount++;
061    }
062
063    /**
064     * Returns the object stored for the given key.
065     * 
066     * @return the value, or null if the key is not found
067     */
068
069    public Object get(Object key)
070    {
071        for (int i = 0; i < _pairCount; i++)
072        {
073            int index = 2 * i;
074
075            if (_pairs[index] == key)
076            {
077                return _pairs[index + 1];
078            }
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 values
093            // initially.
094
095            int newSize = Math.max(10, 2 * currentSize);
096
097            Object[] newPairsArray = new Object[newSize];
098
099            if (currentSize > 0)
100                System.arraycopy(_pairs, 0, newPairsArray, 0, currentSize);
101
102            _pairs = newPairsArray;
103        }
104    }
105}