Package eu.danieldk.dictomaton.collections

Source Code of eu.danieldk.dictomaton.collections.ImmutableStringByteMap$EntrySet$EntrySetIterator

// 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 eu.danieldk.dictomaton.DictionaryBuilder;
import eu.danieldk.dictomaton.DictionaryBuilderException;
import eu.danieldk.dictomaton.PerfectHashDictionary;

import java.io.Serializable;
import java.util.*;

/**
* An immutable mapping from {@link String} to <tt>byte</tt>.
*/
public class ImmutableStringByteMap extends AbstractMap<String, Byte> implements Serializable {
    private static final long serialVersionUID = 1L;

    private final PerfectHashDictionary d_keys;
    private final byte[] d_values;

    /**
     * A builder for {@link ImmutableStringByteMap}. Mappings
     * can be added to the builder using the {@link #put} and
     * {@link #putAll} methods. The {@link ImmutableStringByteMap}
     * can then be constructed using the {@link #build} method.
     */
    public static class Builder {

        private final TreeMap<String, Byte> d_map;

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

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

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

        /**
         * Construct a {@link ImmutableStringByteMap}.
         */
        public synchronized ImmutableStringByteMap build() throws DictionaryBuilderException {
            PerfectHashDictionary dict = new DictionaryBuilder().addAll(d_map.keySet()).buildPerfectHash(false);

            byte[] values = new byte[d_map.size()];

            int i = 0;
            for (byte value : d_map.values())
                values[i++] = value;

            return new ImmutableStringByteMap(dict, values);
        }

    }

    /**
     * A builder for {@link ImmutableStringByteMap}. Mappings can be added to the builder using the {@link #put} and
     * {@link #putAll} methods. The {@link ImmutableStringByteMap} can then be constructed using the {@link #build}
     * method. <b>Note:</b> This builder assumes that entries are put in key order. This additional assumption makes
     * the builder more efficient than {@link Builder}.
     */
    public static class OrderedBuilder {
        private final DictionaryBuilder dictionaryBuilder;

        private final ArrayList<Byte> values;

        public OrderedBuilder() {
            this.dictionaryBuilder = new DictionaryBuilder();
            this.values = new ArrayList<Byte>();
        }

        /**
         * Put a key/value pair.
         */
        public synchronized OrderedBuilder put(String key, Byte value) throws DictionaryBuilderException {
            dictionaryBuilder.add(key);
            values.add(value);
            return this;
        }

        /**
         * Put all key/value pairs from a {@link Map}. The map should be an ordered map (by key). If
         * not, a {@link IllegalArgumentException} is thrown.
         */
        public synchronized OrderedBuilder putAll(SortedMap<String, Byte> map) throws DictionaryBuilderException {
            if (map.comparator() != null)
                throw new IllegalArgumentException("SortedMap does not use the natural ordering of its keys");

            values.ensureCapacity(values.size() + map.size());

            for (SortedMap.Entry<String, Byte> entry: map.entrySet()) {
                dictionaryBuilder.add(entry.getKey());
                values.add(entry.getValue());
            }

            return this;
        }

        /**
         * Construct a {@link ImmutableStringByteMap}.
         */
        public synchronized ImmutableStringByteMap build() throws DictionaryBuilderException {
            PerfectHashDictionary dict = dictionaryBuilder.buildPerfectHash(false);

            byte[] arr = new byte[values.size()];

            for (int i = 0; i < values.size(); ++i)
                arr[i] = values.get(i);

            return new ImmutableStringByteMap(dict, arr);
        }
    }

    private class EntrySet extends AbstractSet<Entry<String, Byte>> {
        private class EntrySetIterator implements Iterator<Entry<String, Byte>> {
            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, Byte> next() {
                String key = d_keyIter.next();
                int idx = d_keys.number(key) - 1;
                return new SimpleEntry<String, Byte>(key, d_values[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;

            // Values are primitive and cannot be null.
            if (e.getKey() == null || e.getKey() == null)
                return false;

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

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

            int hash = d_keys.number(key);

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

            return d_values[hash - 1] == value.byteValue();

        }

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

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

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


    private class ByteArrayList extends AbstractList<Byte> {
        @Override
        public Byte get(int index) {
            return d_values[index];
        }

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

    private ImmutableStringByteMap(PerfectHashDictionary keys, byte[] values) {
        d_keys = keys;
        d_values = values;
    }

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

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

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

    @Override
    public Byte 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[hashcode - 1];
    }

    /**
     * Get the value associated with a key, returning a default value is it
     * is not in the mapping.
     */
    public byte getOrElse(String key, byte defaultValue) {
        int hash = d_keys.number(key);
        if (hash == -1)
            return defaultValue;

        return d_values[hash - 1];
    }

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

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

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

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

    @Override
    public Byte 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<Byte> values() {
        return new ByteArrayList();
    }
}
TOP

Related Classes of eu.danieldk.dictomaton.collections.ImmutableStringByteMap$EntrySet$EntrySetIterator

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.