235 lines
6.7 KiB
Java
235 lines
6.7 KiB
Java
/*
|
|
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
|
* Copyright (C) 2012 Kristian S. Stangeland
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
|
* GNU General Public License as published by the Free Software Foundation; either version 2 of
|
|
* the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with this program;
|
|
* if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|
* 02111-1307 USA
|
|
*/
|
|
|
|
package com.comphenix.protocol.wrappers.collection;
|
|
|
|
import com.google.common.collect.Collections2;
|
|
|
|
import java.util.Collection;
|
|
import java.util.Iterator;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* Represents a map that wraps another map by transforming the entries going in and out.
|
|
*
|
|
* @author Kristian
|
|
*
|
|
* @param <VInner> - type of the value in the entries in the inner invisible map.
|
|
* @param <VOuter> - type of the value in the entries publically accessible in the outer map.
|
|
*/
|
|
public abstract class ConvertedMap<Key, VInner, VOuter> extends AbstractConverted<VInner, VOuter> implements Map<Key, VOuter> {
|
|
// Inner map
|
|
private Map<Key, VInner> inner;
|
|
|
|
// Inner conversion
|
|
private final BiFunction<Key, VOuter, VInner> innerConverter = this::toInner;
|
|
|
|
// Outer conversion
|
|
private final BiFunction<Key, VInner, VOuter> outerConverter = this::toOuter;
|
|
|
|
public ConvertedMap(Map<Key, VInner> inner) {
|
|
if (inner == null)
|
|
throw new IllegalArgumentException("Inner map cannot be NULL.");
|
|
this.inner = inner;
|
|
}
|
|
|
|
@Override
|
|
public void clear() {
|
|
inner.clear();
|
|
}
|
|
|
|
@Override
|
|
public boolean containsKey(Object key) {
|
|
return inner.containsKey(key);
|
|
}
|
|
|
|
@Override
|
|
@SuppressWarnings("unchecked")
|
|
public boolean containsValue(Object value) {
|
|
return inner.containsValue(toInner((VOuter) value));
|
|
}
|
|
|
|
@Override
|
|
public Set<Entry<Key, VOuter>> entrySet() {
|
|
return convertedEntrySet(inner.entrySet(), innerConverter, outerConverter);
|
|
}
|
|
|
|
/**
|
|
* Convert a value from the inner map to the outer visible map.
|
|
* @param key - unused value.
|
|
* @param inner - the inner value.
|
|
* @return The outer value.
|
|
*/
|
|
protected VOuter toOuter(Key key, VInner inner) {
|
|
return toOuter(inner);
|
|
}
|
|
|
|
/**
|
|
* Convert a value from the outer map to the internal inner map.
|
|
* @param key - unused value.
|
|
* @param outer - the outer value.
|
|
* @return The inner value.
|
|
*/
|
|
protected VInner toInner(Key key, VOuter outer) {
|
|
return toInner(outer);
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
@Override
|
|
public VOuter get(Object key) {
|
|
return toOuter((Key) key, inner.get(key));
|
|
}
|
|
|
|
@Override
|
|
public boolean isEmpty() {
|
|
return inner.isEmpty();
|
|
}
|
|
|
|
@Override
|
|
public Set<Key> keySet() {
|
|
return inner.keySet();
|
|
}
|
|
|
|
@Override
|
|
public VOuter put(Key key, VOuter value) {
|
|
return toOuter(key, inner.put(key, toInner(key, value)));
|
|
}
|
|
|
|
@Override
|
|
public void putAll(Map<? extends Key, ? extends VOuter> m) {
|
|
for (Entry<? extends Key, ? extends VOuter> entry : m.entrySet()) {
|
|
put(entry.getKey(), entry.getValue());
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
@Override
|
|
public VOuter remove(Object key) {
|
|
return toOuter((Key) key, inner.remove(key));
|
|
}
|
|
|
|
@Override
|
|
public int size() {
|
|
return inner.size();
|
|
}
|
|
|
|
@Override
|
|
public Collection<VOuter> values() {
|
|
return Collections2.transform(entrySet(), Entry::getValue);
|
|
}
|
|
|
|
/**
|
|
* Returns a string representation of this map. The string representation
|
|
* consists of a list of key-value mappings in the order returned by the
|
|
* map's <code>entrySet</code> view's iterator, enclosed in braces
|
|
* (<code>"{}"</code>). Adjacent mappings are separated by the characters
|
|
* <code>", "</code> (comma and space). Each key-value mapping is rendered as
|
|
* the key followed by an equals sign (<code>"="</code>) followed by the
|
|
* associated value. Keys and values are converted to strings as by
|
|
* {@link String#valueOf(Object)}.
|
|
*
|
|
* @return a string representation of this map
|
|
*/
|
|
@Override
|
|
public String toString() {
|
|
Iterator<Entry<Key, VOuter>> i = entrySet().iterator();
|
|
if (!i.hasNext())
|
|
return "{}";
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.append('{');
|
|
for (;;) {
|
|
Entry<Key, VOuter> e = i.next();
|
|
Key key = e.getKey();
|
|
VOuter value = e.getValue();
|
|
sb.append(key == this ? "(this Map)" : key);
|
|
sb.append('=');
|
|
sb.append(value == this ? "(this Map)" : value);
|
|
if (! i.hasNext())
|
|
return sb.append('}').toString();
|
|
sb.append(", ");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convert a collection of entries.
|
|
* @param entries - the collection of entries.
|
|
* @param innerFunction - the inner entry converter.
|
|
* @param outerFunction - the outer entry converter.
|
|
* @return The converted set of entries.
|
|
*/
|
|
static <Key, VInner, VOuter> Set<Entry<Key, VOuter>> convertedEntrySet(
|
|
final Collection<Entry<Key, VInner>> entries,
|
|
final BiFunction<Key, VOuter, VInner> innerFunction,
|
|
final BiFunction<Key, VInner, VOuter> outerFunction) {
|
|
|
|
return new ConvertedSet<Entry<Key,VInner>, Entry<Key,VOuter>>(entries) {
|
|
@Override
|
|
protected Entry<Key, VInner> toInner(final Entry<Key, VOuter> outer) {
|
|
return new Entry<Key, VInner>() {
|
|
@Override
|
|
public Key getKey() {
|
|
return outer.getKey();
|
|
}
|
|
|
|
@Override
|
|
public VInner getValue() {
|
|
return innerFunction.apply(getKey(), outer.getValue());
|
|
}
|
|
|
|
@Override
|
|
public VInner setValue(VInner value) {
|
|
return innerFunction.apply(getKey(), outer.setValue(outerFunction.apply(getKey(), value)));
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return String.format("\"%s\": %s", getKey(), getValue());
|
|
}
|
|
};
|
|
}
|
|
|
|
@Override
|
|
protected Entry<Key, VOuter> toOuter(final Entry<Key, VInner> inner) {
|
|
return new Entry<Key, VOuter>() {
|
|
@Override
|
|
public Key getKey() {
|
|
return inner.getKey();
|
|
}
|
|
|
|
@Override
|
|
public VOuter getValue() {
|
|
return outerFunction.apply(getKey(), inner.getValue());
|
|
}
|
|
|
|
@Override
|
|
public VOuter setValue(VOuter value) {
|
|
final VInner converted = innerFunction.apply(getKey(), value);
|
|
return outerFunction.apply(getKey(), inner.setValue(converted));
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return String.format("\"%s\": %s", getKey(), getValue());
|
|
}
|
|
};
|
|
}
|
|
};
|
|
}
|
|
}
|