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
015package org.apache.tapestry5.commons.util;
016
017import 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 */
023public 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    /**
087     * Returns a copy of the values array.
088     * @since 5.8.3
089     */
090    public Object[] getValues() {
091        return values.clone();
092    }
093    
094}