blob: ee1ab2c6d11468d0c0be619e7e2a3cd70b4e3daa [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.qpid.server.util;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
public class FixedKeyMapCreator
{
private final String[] _keys;
private final int[] _keyHashCodes;
private final Set<String> _keySet = new AbstractSet<String>()
{
@Override
public Iterator<String> iterator()
{
return new KeysIterator();
}
@Override
public int size()
{
return _keys.length;
}
};
public FixedKeyMapCreator(final String... keys)
{
_keys = keys;
_keyHashCodes = new int[keys.length];
Set<String> uniqueKeys = new HashSet<>(Arrays.asList(keys));
if(uniqueKeys.size() != keys.length)
{
List<String> duplicateKeys = new ArrayList<>(Arrays.asList(keys));
duplicateKeys.removeAll(uniqueKeys);
throw new IllegalArgumentException("The supplied keys must be unique, but the following keys are duplicated: " + duplicateKeys);
}
for(int i = 0; i < keys.length; i++)
{
_keyHashCodes[i] = keys[i].hashCode();
}
}
public Map<String,Object> createMap(Object... values)
{
if(values.length != _keys.length)
{
throw new IllegalArgumentException("There are " + _keys.length + " keys, so that many values must be supplied");
}
return new FixedKeyMap(values);
}
private final class FixedKeyMap extends AbstractMap<String,Object>
{
private final Object[] _values;
private FixedKeyMap(final Object[] values)
{
_values = values;
}
@Override
public Object get(final Object key)
{
int keyHashCode = key.hashCode();
for(int i = 0; i < _keys.length; i++)
{
if(_keyHashCodes[i] == keyHashCode && _keys[i].equals(key))
{
return _values[i];
}
}
return null;
}
@Override
public boolean isEmpty()
{
return false;
}
@Override
public boolean containsValue(final Object value)
{
if(value == null)
{
for(Object o : _values)
{
if(o == null)
{
return true;
}
}
}
else
{
for (Object o : _values)
{
if (value.equals(o))
{
return true;
}
}
}
return false;
}
@Override
public boolean containsKey(final Object key)
{
int keyHashCode = key.hashCode();
for(int i = 0; i < _keys.length; i++)
{
if(_keyHashCodes[i] == keyHashCode && _keys[i].equals(key))
{
return true;
}
}
return false;
}
@Override
public Object put(final String key, final Object value)
{
throw new UnsupportedOperationException();
}
@Override
public Object remove(final Object key)
{
throw new UnsupportedOperationException();
}
@Override
public void putAll(final Map<? extends String, ?> m)
{
throw new UnsupportedOperationException();
}
@Override
public void clear()
{
throw new UnsupportedOperationException();
}
@Override
public Set<String> keySet()
{
return _keySet;
}
@Override
public Collection<Object> values()
{
return Collections.unmodifiableCollection(Arrays.asList(_values));
}
@Override
public int size()
{
return _values.length;
}
@Override
public Set<Entry<String, Object>> entrySet()
{
return new EntrySet();
}
private class EntrySet extends AbstractSet<Entry<String,Object>>
{
@Override
public Iterator<Entry<String, Object>> iterator()
{
return new EntrySetIterator();
}
@Override
public int size()
{
return _keys.length;
}
}
private class EntrySetIterator implements Iterator<Entry<String, Object>>
{
private int _position = 0;
@Override
public boolean hasNext()
{
return _position < _keys.length;
}
@Override
public Entry<String, Object> next()
{
try
{
final String key = _keys[_position];
final Object value = _values[_position++];
return new FixedKeyEntry(key, value);
}
catch (ArrayIndexOutOfBoundsException e)
{
throw new NoSuchElementException();
}
}
@Override
public void remove()
{
throw new UnsupportedOperationException();
}
}
}
private static class FixedKeyEntry implements Map.Entry<String, Object>
{
private final String _key;
private final Object _value;
private FixedKeyEntry(final String key, final Object value)
{
_key = key;
_value = value;
}
@Override
public String getKey()
{
return _key;
}
@Override
public Object getValue()
{
return _value;
}
@Override
public Object setValue(final Object value)
{
throw new UnsupportedOperationException();
}
@Override
public boolean equals(final Object o)
{
if(this == o)
{
return true;
}
else if(o instanceof Map.Entry)
{
Map.Entry e2 = (Map.Entry) o;
return _key.equals(e2.getKey())
&& (_value == null ? e2.getValue() == null
: _value.equals(e2.getValue()));
}
return false;
}
@Override
public int hashCode()
{
return _key.hashCode() ^ (_value == null ? 0 : _value.hashCode());
}
}
private class KeysIterator implements Iterator<String>
{
private int _position = 0;
@Override
public boolean hasNext()
{
return _position < _keys.length;
}
@Override
public String next()
{
try
{
return _keys[_position++];
}
catch (ArrayIndexOutOfBoundsException e)
{
throw new NoSuchElementException();
}
}
@Override
public void remove()
{
throw new UnsupportedOperationException();
}
}
}