Package eu.danieldk.dictomaton.collections

Source Code of eu.danieldk.dictomaton.collections.ImmutableStringStringMap

// Copyright 2013 Daniel de Kok
//
// 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 eu.danieldk.dictomaton.collections;

import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import eu.danieldk.dictomaton.DictionaryBuilder;
import eu.danieldk.dictomaton.DictionaryBuilderException;
import eu.danieldk.dictomaton.PerfectHashDictionary;

/**
* An immutable mapping from {@link String} to {@link String}, where both keys an values are compactly stored
* using a finite state automaton.
*/
public class ImmutableStringStringMap extends AbstractMap<String, String>
{
  private final PerfectHashDictionary d_keys;
  private final PerfectHashDictionary d_values;
  private int[] d_link;

  /**
   * A builder for {@link ImmutableStringStringMap}. Mappings
   * can be added to the builder using the {@link #put} and {@link #putAll} methods. The
   * {@link ImmutableStringStringMap} can then be constructed using the {@link #build} method.
   */
  public static class Builder
  {
    private TreeMap<String, String> d_map;

    public Builder()
    {
      d_map = new TreeMap<String, String>();
    }

    /**
     * Put a key/value pair.
     */
    public synchronized Builder put(String key, String value)
    {
      d_map.put(key, value);
      return this;
    }

    /**
     * Put all key/value pairs from a {@link java.util.Map}.
     */
    public synchronized Builder putAll(Map<String, String> map)
    {
      d_map.putAll(map);
      return this;
    }

    /**
     * Construct a {@link ImmutableStringStringMap}.
     */
    public synchronized ImmutableStringStringMap build() throws DictionaryBuilderException
    {
      PerfectHashDictionary keyDict = new DictionaryBuilder().addAll(d_map.keySet()).buildPerfectHash(false);
      PerfectHashDictionary valueDict = new DictionaryBuilder().addAll(new TreeSet<String>(d_map.values()))
          .buildPerfectHash(false);

      int links[] = new int[keyDict.size()];

      for (Map.Entry<String, String> entry : d_map.entrySet())
      {
        int keyHashCode = keyDict.number(entry.getKey());
        int valueHashCode = valueDict.number(entry.getValue());

        links[keyHashCode - 1] = valueHashCode;
      }

      return new ImmutableStringStringMap(keyDict, valueDict, links);
    }

  }

  private class EntrySet extends AbstractSet<Entry<String, String>>
  {
    private class EntrySetIterator implements Iterator<Entry<String, String>>
    {
      private final Iterator<String> d_keyIter;

      public EntrySetIterator()
      {
        d_keyIter = d_keys.iterator();
      }

      @Override
      public boolean hasNext()
      {
        return d_keyIter.hasNext();
      }

      @Override
      public Entry<String, String> next()
      {
        String key = d_keyIter.next();
        int idx = d_keys.number(key) - 1;
        return new SimpleEntry<String, String>(key, d_values.sequence(d_link[idx]));
      }

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

    @Override
    public boolean contains(Object o)
    {
      if (o == null)
        return false;

      if (!(o instanceof Entry))
        return false;

      Entry e = (Entry) o;

      // Null keys and values are not supported.
      if (e.getKey() == null || e.getKey() == null)
        return false;

      if (!(e.getKey() instanceof String) || !(e.getValue() instanceof String))
        return false;

      String key = (String) e.getKey();
      String value = (String) e.getValue();

      int hash = d_keys.number(key);

      // Does not contain the key.
      if (hash == -1)
        return false;

      return d_values.sequence(d_link[hash - 1]).equals(value);
    }

    @Override
    public boolean isEmpty()
    {
      return d_keys.isEmpty();
    }

    @Override
    public Iterator<Entry<String, String>> iterator()
    {
      return new EntrySetIterator();
    }

    @Override
    public int size()
    {
      return d_keys.size();
    }
  }

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

  @Override
  public boolean containsKey(Object o)
  {
    return d_keys.contains(o);
  }

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

  @Override
  public String get(Object o)
  {
    if (!(o instanceof String))
      return null;

    String key = (String) o;

    int hashcode = d_keys.number(key);
    if (hashcode == -1)
      return null;

    return d_values.sequence(d_link[hashcode - 1]);
  }

  @Override
  public boolean isEmpty()
  {
    return d_keys.isEmpty();
  }

  @Override
  public Set<String> keySet()
  {
    return d_keys;
  }

  @Override
  public String put(String k, String v)
  {
    throw new UnsupportedOperationException();
  }

  @Override
  public void putAll(Map<? extends String, ? extends String> m)
  {
    throw new UnsupportedOperationException();
  }

  @Override
  public String remove(Object key)
  {
    throw new UnsupportedOperationException();
  }

  @Override
  public int size()
  {
    return d_keys.size();
  }

  /**
   * Get an iterator over the keys in the mapping.
   */
  public Iterator<String> keyIterator()
  {
    return d_keys.iterator();
  }

  @Override
  public Collection<String> values()
  {
        // Note: check that this is in correspondence to the contract of this method. We might
        // have to return duplicate values, although they don't exist in our case.
    return d_values;
  }

  private ImmutableStringStringMap(PerfectHashDictionary keys, PerfectHashDictionary values, int[] link)
  {
    this.d_keys = keys;
    this.d_values = values;
    this.d_link = link;
  }
}
TOP

Related Classes of eu.danieldk.dictomaton.collections.ImmutableStringStringMap

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.