001    // Copyright 2006 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.tapestry5.internal.util;
016    
017    import java.util.Arrays;
018    
019    /**
020     * Combines multiple values to form a single composite key. MultiKey can often be used as an alternative to nested
021     * maps.
022     */
023    public final class MultiKey
024    {
025        private static final int PRIME = 31;
026    
027        private final Object[] values;
028    
029        private final int hashCode;
030    
031        /**
032         * Creates a new instance from the provided values. It is assumed that the values provided are good map keys
033         * themselves -- immutable, with proper implementations of equals() and hashCode().
034         *
035         * @param values
036         */
037        public MultiKey(Object... values)
038        {
039            this.values = values;
040    
041            hashCode = PRIME * Arrays.hashCode(this.values);
042        }
043    
044        @Override
045        public int hashCode()
046        {
047            return hashCode;
048        }
049    
050        @Override
051        public boolean equals(Object obj)
052        {
053            if (this == obj)
054                return true;
055            if (obj == null)
056                return false;
057            if (getClass() != obj.getClass())
058                return false;
059            final MultiKey other = (MultiKey) obj;
060    
061            return Arrays.equals(values, other.values);
062        }
063    
064        @Override
065        public String toString()
066        {
067            StringBuilder builder = new StringBuilder("MultiKey[");
068    
069            boolean first = true;
070    
071            for (Object o : values)
072            {
073                if (!first)
074                    builder.append(", ");
075    
076                builder.append(o);
077    
078                first = false;
079            }
080    
081            builder.append("]");
082    
083            return builder.toString();
084        }
085    
086    }