All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.rinde.rinsim.util.LinkedHashBiMap Maven / Gradle / Ivy

There is a newer version: 4.4.6
Show newest version
/*
 * Copyright (C) 2011-2016 Rinde van Lon, iMinds-DistriNet, KU Leuven
 *
 * Licensed 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 com.github.rinde.rinsim.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nullable;

import com.google.common.collect.AbstractIterator;
import com.google.common.collect.BiMap;
import com.google.common.collect.ForwardingSet;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;

/**
 * {@link BiMap} with key based insertion ordering. Note that all its collection
 * views are unmodifiable.
 *
 * @author Rinde van Lon
 * @param  Key type.
 * @param  Value type.
 */
public class LinkedHashBiMap extends ForwardingBiMap {

  final BiMap delegateBiMap;
  final Set set;
  @Nullable
  private BiMap inverse;

  LinkedHashBiMap() {
    delegateBiMap = HashBiMap.create();
    set = new LinkedHashSet<>();
  }

  // views are unmodifiable

  @Override
  public Set values() {
    return new OrderedValuesSet<>(set, delegateBiMap);
  }

  @Override
  public Set keySet() {
    return Collections.unmodifiableSet(set);
  }

  @Override
  public Set> entrySet() {
    return new EntrySet<>(set, delegateBiMap);
  }

  // modifications

  @Override
  public V put(@Nullable K key, @Nullable V value) {
    final V v = delegate().put(key, value);
    set.add(key);
    return v;
  }

  @Override
  public V forcePut(@Nullable K key, @Nullable V value) {
    final V v = delegate().forcePut(key, value);
    set.add(key);
    return v;
  }

  @Override
  public void putAll(@Nullable Map map) {
    if (map == null) {
      return;
    }
    for (final Entry entry : map.entrySet()) {
      put(entry.getKey(), entry.getValue());
    }
  }

  @Override
  public V remove(@Nullable Object key) {
    final V val = delegate().remove(key);
    set.remove(key);
    return val;
  }

  @Override
  public void clear() {
    delegate().clear();
    set.clear();
  }

  @Override
  public BiMap inverse() {
    final BiMap inv = inverse;
    return inv == null ? inverse = new Inverse() : inv;
  }

  @Override
  protected BiMap delegate() {
    return delegateBiMap;
  }

  public static  LinkedHashBiMap create() {
    return new LinkedHashBiMap<>();
  }

  private final class Inverse extends ForwardingBiMap {

    Inverse() {}

    BiMap forward() {
      return LinkedHashBiMap.this;
    }

    @Override
    public BiMap inverse() {
      return forward();
    }

    // views are unmodifiable

    @Override
    public Set values() {
      return forward().keySet();
    }

    @Override
    public Set keySet() {
      return forward().values();
    }

    @Override
    @Deprecated
    public Set> entrySet() {
      throw new UnsupportedOperationException(
        "Use inverse().entrySet() instead.");
    }

    // modifications

    @Override
    public K put(@Nullable V key, @Nullable K value) {
      final K val = get(key);
      forward().put(value, key);
      return val;
    }

    @Override
    public K forcePut(@Nullable V key, @Nullable K value) {
      final K val = get(key);
      forward().forcePut(value, key);
      return val;
    }

    @Override
    public void putAll(@Nullable Map map) {
      if (map == null) {
        return;
      }
      for (final Entry entry : map.entrySet()) {
        put(entry.getKey(), entry.getValue());
      }
    }

    @Override
    protected BiMap delegate() {
      return delegateBiMap.inverse();
    }
  }

  private static final class OrderedValuesSet extends UnmodifiableSet {
    final Set ordering;
    final BiMap delegateMap;

    OrderedValuesSet(Set order, BiMap delegate) {
      ordering = order;
      delegateMap = delegate;
    }

    @Override
    public Iterator iterator() {
      final Iterator it = ordering.iterator();
      return new AbstractIterator() {
        @Override
        protected V computeNext() {
          if (it.hasNext()) {
            return delegateMap.get(it.next());
          }
          return super.endOfData();
        }
      };
    }

    @Override
    public Object[] toArray() {
      return Iterators.toArray(iterator(), Object.class);
    }

    @Override
    public  T[] toArray(@Nullable T[] a) {
      final List list = new ArrayList<>(size());
      Iterators.addAll(list, iterator());
      return list.toArray(a);
    }

    @Override
    protected Set delegate() {
      return delegateMap.values();
    }

  }

  private static final class EntrySet extends
      UnmodifiableSet> {

    final Map delegateSet;
    private final Set ordering;

    EntrySet(Set order, Map map) {
      ordering = order;
      delegateSet = map;
    }

    @Override
    protected Set> delegate() {
      return delegateSet.entrySet();
    }

    @Override
    public Iterator> iterator() {
      final Iterator it = ordering.iterator();

      return new AbstractIterator>() {

        @Override
        protected Map.Entry computeNext() {
          if (it.hasNext()) {
            final A key = it.next();
            return Maps.immutableEntry(key, delegateSet.get(key));
          }
          return super.endOfData();
        }
      };

    }

    @Override
    public Object[] toArray() {
      return Iterators.toArray(iterator(), Entry.class);
    }

    @Override
    public  T[] toArray(@Nullable T[] a) {
      final List> list = new ArrayList<>(size());
      Iterators.addAll(list, iterator());
      return list.toArray(a);
    }
  }

  private abstract static class UnmodifiableSet extends ForwardingSet {

    UnmodifiableSet() {}

    @Override
    @Deprecated
    public boolean add(@Nullable T e) {
      throw new UnsupportedOperationException();
    }

    @Override
    @Deprecated
    public boolean remove(@Nullable Object o) {
      throw new UnsupportedOperationException();
    }

    @Override
    @Deprecated
    public boolean addAll(@Nullable Collection c) {
      throw new UnsupportedOperationException();
    }

    @Override
    @Deprecated
    public boolean retainAll(@Nullable Collection c) {
      throw new UnsupportedOperationException();
    }

    @Override
    @Deprecated
    public boolean removeAll(@Nullable Collection c) {
      throw new UnsupportedOperationException();
    }

    @Override
    @Deprecated
    public void clear() {
      throw new UnsupportedOperationException();
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy