diff --git a/tools/makedict/Android.mk b/tools/makedict/Android.mk
index 6832b1c..facbbf7 100644
--- a/tools/makedict/Android.mk
+++ b/tools/makedict/Android.mk
@@ -13,15 +13,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_SRC_FILES += $(call all-java-files-under,tests)
-LOCAL_JAR_MANIFEST := etc/manifest.txt
-LOCAL_MODULE_TAGS := eng
-LOCAL_MODULE := makedict
-LOCAL_JAVA_LIBRARIES := junit
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-include $(LOCAL_PATH)/etc/Android.mk
+#LOCAL_PATH := $(call my-dir)
+#include $(CLEAR_VARS)
+#
+#LOCAL_SRC_FILES := $(call all-java-files-under,src)
+#LOCAL_SRC_FILES += $(call all-java-files-under,tests)
+#LOCAL_JAR_MANIFEST := etc/manifest.txt
+#LOCAL_MODULE_TAGS := eng
+#LOCAL_MODULE := makedict
+#LOCAL_JAVA_LIBRARIES := junit
+#
+#include $(BUILD_HOST_JAVA_LIBRARY)
+#include $(LOCAL_PATH)/etc/Android.mk
diff --git a/tools/makedict/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/tools/makedict/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
deleted file mode 100644
index 42dd4df..0000000
--- a/tools/makedict/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
+++ /dev/null
@@ -1,1208 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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.android.inputmethod.latin.makedict;
-
-import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup;
-import com.android.inputmethod.latin.makedict.FusionDictionary.Node;
-import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * Reads and writes XML files for a FusionDictionary.
- *
- * All the methods in this class are static.
- */
-public class BinaryDictInputOutput {
-
-    /* Node layout is as follows:
-     *   | addressType                         xx     : mask with MASK_GROUP_ADDRESS_TYPE
-     *                                 2 bits, 00 = no children : FLAG_GROUP_ADDRESS_TYPE_NOADDRESS
-     * f |                                     01 = 1 byte      : FLAG_GROUP_ADDRESS_TYPE_ONEBYTE
-     * l |                                     10 = 2 bytes     : FLAG_GROUP_ADDRESS_TYPE_TWOBYTES
-     * a |                                     11 = 3 bytes     : FLAG_GROUP_ADDRESS_TYPE_THREEBYTES
-     * g | has several chars ?         1 bit, 1 = yes, 0 = no   : FLAG_HAS_MULTIPLE_CHARS
-     * s | has a terminal ?            1 bit, 1 = yes, 0 = no   : FLAG_IS_TERMINAL
-     *   | has shortcut targets ?      1 bit, 1 = yes, 0 = no   : FLAG_HAS_SHORTCUT_TARGETS
-     *   | has bigrams ?               1 bit, 1 = yes, 0 = no   : FLAG_HAS_BIGRAMS
-     *   | is shortcut only ?          1 bit, 1 = yes, 0 = no   : FLAG_IS_SHORTCUT_ONLY
-     *
-     * c | IF FLAG_HAS_MULTIPLE_CHARS
-     * h |   char, char, char, char    n * (1 or 3 bytes) : use CharGroupInfo for i/o helpers
-     * a |   end                       1 byte, = 0
-     * r | ELSE
-     * s |   char                      1 or 3 bytes
-     *   | END
-     *
-     * f |
-     * r | IF FLAG_IS_TERMINAL
-     * e |   frequency                 1 byte
-     * q |
-     *
-     * c | IF 00 = FLAG_GROUP_ADDRESS_TYPE_NOADDRESS = addressType
-     * h |   // nothing
-     * i | ELSIF 01 = FLAG_GROUP_ADDRESS_TYPE_ONEBYTE == addressType
-     * l |   children address, 1 byte
-     * d | ELSIF 10 = FLAG_GROUP_ADDRESS_TYPE_TWOBYTES == addressType
-     * r |   children address, 2 bytes
-     * e | ELSE // 11 = FLAG_GROUP_ADDRESS_TYPE_THREEBYTES = addressType
-     * n |   children address, 3 bytes
-     * A | END
-     * d
-     * dress
-     *
-     *   | IF FLAG_IS_TERMINAL && FLAG_HAS_SHORTCUT_TARGETS
-     *   | shortcut targets address list
-     *   | IF FLAG_IS_TERMINAL && FLAG_HAS_BIGRAMS
-     *   | bigrams address list
-     *
-     * Char format is:
-     * 1 byte = bbbbbbbb match
-     * case 000xxxxx: xxxxx << 16 + next byte << 8 + next byte
-     * else: if 00011111 (= 0x1F) : this is the terminator. This is a relevant choice because
-     *       unicode code points range from 0 to 0x10FFFF, so any 3-byte value starting with
-     *       00011111 would be outside unicode.
-     * else: iso-latin-1 code
-     * This allows for the whole unicode range to be encoded, including chars outside of
-     * the BMP. Also everything in the iso-latin-1 charset is only 1 byte, except control
-     * characters which should never happen anyway (and still work, but take 3 bytes).
-     *
-     * bigram and shortcut address list is:
-     * <flags> = | hasNext = 1 bit, 1 = yes, 0 = no     : FLAG_ATTRIBUTE_HAS_NEXT
-     *           | addressSign = 1 bit,                 : FLAG_ATTRIBUTE_OFFSET_NEGATIVE
-     *           |                      1 = must take -address, 0 = must take +address
-     *           |                         xx : mask with MASK_ATTRIBUTE_ADDRESS_TYPE
-     *           | addressFormat = 2 bits, 00 = unused  : FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE
-     *           |                         01 = 1 byte  : FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE
-     *           |                         10 = 2 bytes : FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES
-     *           |                         11 = 3 bytes : FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES
-     *           | 4 bits : frequency         : mask with FLAG_ATTRIBUTE_FREQUENCY
-     * <address> | IF (01 == FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE == addressFormat)
-     *           |   read 1 byte, add top 4 bits
-     *           | ELSIF (10 == FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES == addressFormat)
-     *           |   read 2 bytes, add top 4 bits
-     *           | ELSE // 11 == FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES == addressFormat
-     *           |   read 3 bytes, add top 4 bits
-     *           | END
-     *           | if (FLAG_ATTRIBUTE_OFFSET_NEGATIVE) then address = -address
-     * if (FLAG_ATTRIBUTE_HAS_NET) goto bigram_and_shortcut_address_list_is
-     *
-     */
-
-    private static final int VERSION_1_MAGIC_NUMBER = 0x78B1;
-    private static final int VERSION_2_MAGIC_NUMBER = 0x9BC13AFE;
-    private static final int MINIMUM_SUPPORTED_VERSION = 1;
-    private static final int MAXIMUM_SUPPORTED_VERSION = 2;
-    private static final int NOT_A_VERSION_NUMBER = -1;
-    private static final int FIRST_VERSION_WITH_HEADER_SIZE = 2;
-
-    // No options yet, reserved for future use.
-    private static final int OPTIONS = 0;
-
-    // TODO: Make this value adaptative to content data, store it in the header, and
-    // use it in the reading code.
-    private static final int MAX_WORD_LENGTH = 48;
-
-    private static final int MASK_GROUP_ADDRESS_TYPE = 0xC0;
-    private static final int FLAG_GROUP_ADDRESS_TYPE_NOADDRESS = 0x00;
-    private static final int FLAG_GROUP_ADDRESS_TYPE_ONEBYTE = 0x40;
-    private static final int FLAG_GROUP_ADDRESS_TYPE_TWOBYTES = 0x80;
-    private static final int FLAG_GROUP_ADDRESS_TYPE_THREEBYTES = 0xC0;
-
-    private static final int FLAG_HAS_MULTIPLE_CHARS = 0x20;
-
-    private static final int FLAG_IS_TERMINAL = 0x10;
-    private static final int FLAG_HAS_SHORTCUT_TARGETS = 0x08;
-    private static final int FLAG_HAS_BIGRAMS = 0x04;
-    private static final int FLAG_IS_SHORTCUT_ONLY = 0x02;
-
-    private static final int FLAG_ATTRIBUTE_HAS_NEXT = 0x80;
-    private static final int FLAG_ATTRIBUTE_OFFSET_NEGATIVE = 0x40;
-    private static final int MASK_ATTRIBUTE_ADDRESS_TYPE = 0x30;
-    private static final int FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE = 0x10;
-    private static final int FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES = 0x20;
-    private static final int FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES = 0x30;
-    private static final int FLAG_ATTRIBUTE_FREQUENCY = 0x0F;
-
-    private static final int GROUP_CHARACTERS_TERMINATOR = 0x1F;
-
-    private static final int GROUP_TERMINATOR_SIZE = 1;
-    private static final int GROUP_FLAGS_SIZE = 1;
-    private static final int GROUP_FREQUENCY_SIZE = 1;
-    private static final int GROUP_MAX_ADDRESS_SIZE = 3;
-    private static final int GROUP_ATTRIBUTE_FLAGS_SIZE = 1;
-    private static final int GROUP_ATTRIBUTE_MAX_ADDRESS_SIZE = 3;
-
-    private static final int NO_CHILDREN_ADDRESS = Integer.MIN_VALUE;
-    private static final int INVALID_CHARACTER = -1;
-
-    private static final int MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT = 0x7F; // 127
-    private static final int MAX_CHARGROUPS_IN_A_NODE = 0x7FFF; // 32767
-
-    private static final int MAX_TERMINAL_FREQUENCY = 255;
-
-    /**
-     * A class grouping utility function for our specific character encoding.
-     */
-    private static class CharEncoding {
-
-        private static final int MINIMAL_ONE_BYTE_CHARACTER_VALUE = 0x20;
-        private static final int MAXIMAL_ONE_BYTE_CHARACTER_VALUE = 0xFF;
-
-        /**
-         * Helper method to find out whether this code fits on one byte
-         */
-        private static boolean fitsOnOneByte(int character) {
-            return character >= MINIMAL_ONE_BYTE_CHARACTER_VALUE
-                    && character <= MAXIMAL_ONE_BYTE_CHARACTER_VALUE;
-        }
-
-        /**
-         * Compute the size of a character given its character code.
-         *
-         * Char format is:
-         * 1 byte = bbbbbbbb match
-         * case 000xxxxx: xxxxx << 16 + next byte << 8 + next byte
-         * else: if 00011111 (= 0x1F) : this is the terminator. This is a relevant choice because
-         *       unicode code points range from 0 to 0x10FFFF, so any 3-byte value starting with
-         *       00011111 would be outside unicode.
-         * else: iso-latin-1 code
-         * This allows for the whole unicode range to be encoded, including chars outside of
-         * the BMP. Also everything in the iso-latin-1 charset is only 1 byte, except control
-         * characters which should never happen anyway (and still work, but take 3 bytes).
-         *
-         * @param character the character code.
-         * @return the size in binary encoded-form, either 1 or 3 bytes.
-         */
-        private static int getCharSize(int character) {
-            // See char encoding in FusionDictionary.java
-            if (fitsOnOneByte(character)) return 1;
-            if (INVALID_CHARACTER == character) return 1;
-            return 3;
-        }
-
-        /**
-         * Compute the byte size of a character array.
-         */
-        private static int getCharArraySize(final int[] chars) {
-            int size = 0;
-            for (int character : chars) size += getCharSize(character);
-            return size;
-        }
-
-        /**
-         * Writes a char array to a byte buffer.
-         *
-         * @param characters the character array to write.
-         * @param buffer the byte buffer to write to.
-         * @param index the index in buffer to write the character array to.
-         * @return the index after the last character.
-         */
-        private static int writeCharArray(int[] characters, byte[] buffer, int index) {
-            for (int character : characters) {
-                if (1 == getCharSize(character)) {
-                    buffer[index++] = (byte)character;
-                } else {
-                    buffer[index++] = (byte)(0xFF & (character >> 16));
-                    buffer[index++] = (byte)(0xFF & (character >> 8));
-                    buffer[index++] = (byte)(0xFF & character);
-                }
-            }
-            return index;
-        }
-
-        /**
-         * Reads a character from the file.
-         *
-         * This follows the character format documented earlier in this source file.
-         *
-         * @param source the file, positioned over an encoded character.
-         * @return the character code.
-         */
-        private static int readChar(RandomAccessFile source) throws IOException {
-            int character = source.readUnsignedByte();
-            if (!fitsOnOneByte(character)) {
-                if (GROUP_CHARACTERS_TERMINATOR == character)
-                    return INVALID_CHARACTER;
-                character <<= 16;
-                character += source.readUnsignedShort();
-            }
-            return character;
-        }
-    }
-
-    /**
-     * Compute the binary size of the character array in a group
-     *
-     * If only one character, this is the size of this character. If many, it's the sum of their
-     * sizes + 1 byte for the terminator.
-     *
-     * @param group the group
-     * @return the size of the char array, including the terminator if any
-     */
-    private static int getGroupCharactersSize(CharGroup group) {
-        int size = CharEncoding.getCharArraySize(group.mChars);
-        if (group.hasSeveralChars()) size += GROUP_TERMINATOR_SIZE;
-        return size;
-    }
-
-    /**
-     * Compute the binary size of the group count
-     * @param count the group count
-     * @return the size of the group count, either 1 or 2 bytes.
-     */
-    private static int getGroupCountSize(final int count) {
-        if (MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT >= count) {
-            return 1;
-        } else if (MAX_CHARGROUPS_IN_A_NODE >= count) {
-            return 2;
-        } else {
-            throw new RuntimeException("Can't have more than " + MAX_CHARGROUPS_IN_A_NODE
-                    + " groups in a node (found " + count +")");
-        }
-    }
-
-    /**
-     * Compute the binary size of the group count for a node
-     * @param node the node
-     * @return the size of the group count, either 1 or 2 bytes.
-     */
-    private static int getGroupCountSize(final Node node) {
-        return getGroupCountSize(node.mData.size());
-    }
-
-    /**
-     * Compute the maximum size of a CharGroup, assuming 3-byte addresses for everything.
-     *
-     * @param group the CharGroup to compute the size of.
-     * @return the maximum size of the group.
-     */
-    private static int getCharGroupMaximumSize(CharGroup group) {
-        int size = getGroupCharactersSize(group) + GROUP_FLAGS_SIZE;
-        // If terminal, one byte for the frequency
-        if (group.isTerminal()) size += GROUP_FREQUENCY_SIZE;
-        size += GROUP_MAX_ADDRESS_SIZE; // For children address
-        if (null != group.mShortcutTargets) {
-            size += (GROUP_ATTRIBUTE_FLAGS_SIZE + GROUP_ATTRIBUTE_MAX_ADDRESS_SIZE)
-                    * group.mShortcutTargets.size();
-        }
-        if (null != group.mBigrams) {
-            size += (GROUP_ATTRIBUTE_FLAGS_SIZE + GROUP_ATTRIBUTE_MAX_ADDRESS_SIZE)
-                    * group.mBigrams.size();
-        }
-        return size;
-    }
-
-    /**
-     * Compute the maximum size of a node, assuming 3-byte addresses for everything, and caches
-     * it in the 'actualSize' member of the node.
-     *
-     * @param node the node to compute the maximum size of.
-     */
-    private static void setNodeMaximumSize(Node node) {
-        int size = getGroupCountSize(node);
-        for (CharGroup g : node.mData) {
-            final int groupSize = getCharGroupMaximumSize(g);
-            g.mCachedSize = groupSize;
-            size += groupSize;
-        }
-        node.mCachedSize = size;
-    }
-
-    /**
-     * Helper method to hide the actual value of the no children address.
-     */
-    private static boolean hasChildrenAddress(int address) {
-        return NO_CHILDREN_ADDRESS != address;
-    }
-
-    /**
-     * Helper method to find out if a character info is a shortcut only.
-     */
-    private static boolean isShortcutOnly(final CharGroupInfo info) {
-        return 0 != (info.mFlags & FLAG_IS_SHORTCUT_ONLY);
-    }
-
-    /**
-     * Compute the size, in bytes, that an address will occupy.
-     *
-     * This can be used either for children addresses (which are always positive) or for
-     * attribute, which may be positive or negative but
-     * store their sign bit separately.
-     *
-     * @param address the address
-     * @return the byte size.
-     */
-    private static int getByteSize(int address) {
-        assert(address < 0x1000000);
-        if (!hasChildrenAddress(address)) {
-            return 0;
-        } else if (Math.abs(address) < 0x100) {
-            return 1;
-        } else if (Math.abs(address) < 0x10000) {
-            return 2;
-        } else {
-            return 3;
-        }
-    }
-    // End utility methods.
-
-    // This method is responsible for finding a nice ordering of the nodes that favors run-time
-    // cache performance and dictionary size.
-    /* package for tests */ static ArrayList<Node> flattenTree(Node root) {
-        final int treeSize = FusionDictionary.countCharGroups(root);
-        MakedictLog.i("Counted nodes : " + treeSize);
-        final ArrayList<Node> flatTree = new ArrayList<Node>(treeSize);
-        return flattenTreeInner(flatTree, root);
-    }
-
-    private static ArrayList<Node> flattenTreeInner(ArrayList<Node> list, Node node) {
-        // Removing the node is necessary if the tails are merged, because we would then
-        // add the same node several times when we only want it once. A number of places in
-        // the code also depends on any node being only once in the list.
-        // Merging tails can only be done if there are no attributes. Searching for attributes
-        // in LatinIME code depends on a total breadth-first ordering, which merging tails
-        // breaks. If there are no attributes, it should be fine (and reduce the file size)
-        // to merge tails, and the following step would be necessary.
-        // If eventually the code runs on Android, searching through the whole array each time
-        // may be a performance concern.
-        list.remove(node);
-        list.add(node);
-        final ArrayList<CharGroup> branches = node.mData;
-        final int nodeSize = branches.size();
-        for (CharGroup group : branches) {
-            if (null != group.mChildren) flattenTreeInner(list, group.mChildren);
-        }
-        return list;
-    }
-
-    /**
-     * Finds the absolute address of a word in the dictionary.
-     *
-     * @param dict the dictionary in which to search.
-     * @param word the word we are searching for.
-     * @return the word address. If it is not found, an exception is thrown.
-     */
-    private static int findAddressOfWord(final FusionDictionary dict, final String word) {
-        return FusionDictionary.findWordInTree(dict.mRoot, word).mCachedAddress;
-    }
-
-    /**
-     * Computes the actual node size, based on the cached addresses of the children nodes.
-     *
-     * Each node stores its tentative address. During dictionary address computing, these
-     * are not final, but they can be used to compute the node size (the node size depends
-     * on the address of the children because the number of bytes necessary to store an
-     * address depends on its numeric value.
-     *
-     * @param node the node to compute the size of.
-     * @param dict the dictionary in which the word/attributes are to be found.
-     */
-    private static void computeActualNodeSize(Node node, FusionDictionary dict) {
-        int size = getGroupCountSize(node);
-        for (CharGroup group : node.mData) {
-            int groupSize = GROUP_FLAGS_SIZE + getGroupCharactersSize(group);
-            if (group.isTerminal()) groupSize += GROUP_FREQUENCY_SIZE;
-            if (null != group.mChildren) {
-                final int offsetBasePoint= groupSize + node.mCachedAddress + size;
-                final int offset = group.mChildren.mCachedAddress - offsetBasePoint;
-                groupSize += getByteSize(offset);
-            }
-            if (null != group.mShortcutTargets) {
-                for (WeightedString target : group.mShortcutTargets) {
-                    final int offsetBasePoint = groupSize + node.mCachedAddress + size
-                            + GROUP_FLAGS_SIZE;
-                    final int addressOfTarget = findAddressOfWord(dict, target.mWord);
-                    final int offset = addressOfTarget - offsetBasePoint;
-                    groupSize += getByteSize(offset) + GROUP_FLAGS_SIZE;
-                }
-            }
-            if (null != group.mBigrams) {
-                for (WeightedString bigram : group.mBigrams) {
-                    final int offsetBasePoint = groupSize + node.mCachedAddress + size
-                            + GROUP_FLAGS_SIZE;
-                    final int addressOfBigram = findAddressOfWord(dict, bigram.mWord);
-                    final int offset = addressOfBigram - offsetBasePoint;
-                    groupSize += getByteSize(offset) + GROUP_FLAGS_SIZE;
-                }
-            }
-            group.mCachedSize = groupSize;
-            size += groupSize;
-        }
-        node.mCachedSize = size;
-    }
-
-    /**
-     * Computes the byte size of a list of nodes and updates each node cached position.
-     *
-     * @param flatNodes the array of nodes.
-     * @return the byte size of the entire stack.
-     */
-    private static int stackNodes(ArrayList<Node> flatNodes) {
-        int nodeOffset = 0;
-        for (Node n : flatNodes) {
-            n.mCachedAddress = nodeOffset;
-            int groupCountSize = getGroupCountSize(n);
-            int groupOffset = 0;
-            for (CharGroup g : n.mData) {
-                g.mCachedAddress = groupCountSize + nodeOffset + groupOffset;
-                groupOffset += g.mCachedSize;
-            }
-            if (groupOffset + groupCountSize != n.mCachedSize) {
-                throw new RuntimeException("Bug : Stored and computed node size differ");
-            }
-            nodeOffset += n.mCachedSize;
-        }
-        return nodeOffset;
-    }
-
-    /**
-     * Compute the addresses and sizes of an ordered node array.
-     *
-     * This method takes a node array and will update its cached address and size values
-     * so that they can be written into a file. It determines the smallest size each of the
-     * nodes can be given the addresses of its children and attributes, and store that into
-     * each node.
-     * The order of the node is given by the order of the array. This method makes no effort
-     * to find a good order; it only mechanically computes the size this order results in.
-     *
-     * @param dict the dictionary
-     * @param flatNodes the ordered array of nodes
-     * @return the same array it was passed. The nodes have been updated for address and size.
-     */
-    private static ArrayList<Node> computeAddresses(FusionDictionary dict,
-            ArrayList<Node> flatNodes) {
-        // First get the worst sizes and offsets
-        for (Node n : flatNodes) setNodeMaximumSize(n);
-        final int offset = stackNodes(flatNodes);
-
-        MakedictLog.i("Compressing the array addresses. Original size : " + offset);
-        MakedictLog.i("(Recursively seen size : " + offset + ")");
-
-        int passes = 0;
-        boolean changesDone = false;
-        do {
-            changesDone = false;
-            for (Node n : flatNodes) {
-                final int oldNodeSize = n.mCachedSize;
-                computeActualNodeSize(n, dict);
-                final int newNodeSize = n.mCachedSize;
-                if (oldNodeSize < newNodeSize) throw new RuntimeException("Increased size ?!");
-                if (oldNodeSize != newNodeSize) changesDone = true;
-            }
-            stackNodes(flatNodes);
-            ++passes;
-        } while (changesDone);
-
-        final Node lastNode = flatNodes.get(flatNodes.size() - 1);
-        MakedictLog.i("Compression complete in " + passes + " passes.");
-        MakedictLog.i("After address compression : "
-                + (lastNode.mCachedAddress + lastNode.mCachedSize));
-
-        return flatNodes;
-    }
-
-    /**
-     * Sanity-checking method.
-     *
-     * This method checks an array of node for juxtaposition, that is, it will do
-     * nothing if each node's cached address is actually the previous node's address
-     * plus the previous node's size.
-     * If this is not the case, it will throw an exception.
-     *
-     * @param array the array node to check
-     */
-    private static void checkFlatNodeArray(ArrayList<Node> array) {
-        int offset = 0;
-        int index = 0;
-        for (Node n : array) {
-            if (n.mCachedAddress != offset) {
-                throw new RuntimeException("Wrong address for node " + index
-                        + " : expected " + offset + ", got " + n.mCachedAddress);
-            }
-            ++index;
-            offset += n.mCachedSize;
-        }
-    }
-
-    /**
-     * Helper method to write a variable-size address to a file.
-     *
-     * @param buffer the buffer to write to.
-     * @param index the index in the buffer to write the address to.
-     * @param address the address to write.
-     * @return the size in bytes the address actually took.
-     */
-    private static int writeVariableAddress(byte[] buffer, int index, int address) {
-        switch (getByteSize(address)) {
-        case 1:
-            buffer[index++] = (byte)address;
-            return 1;
-        case 2:
-            buffer[index++] = (byte)(0xFF & (address >> 8));
-            buffer[index++] = (byte)(0xFF & address);
-            return 2;
-        case 3:
-            buffer[index++] = (byte)(0xFF & (address >> 16));
-            buffer[index++] = (byte)(0xFF & (address >> 8));
-            buffer[index++] = (byte)(0xFF & address);
-            return 3;
-        case 0:
-            return 0;
-        default:
-            throw new RuntimeException("Address " + address + " has a strange size");
-        }
-    }
-
-    private static byte makeCharGroupFlags(final CharGroup group, final int groupAddress,
-            final int childrenOffset) {
-        byte flags = 0;
-        if (group.mChars.length > 1) flags |= FLAG_HAS_MULTIPLE_CHARS;
-        if (group.mFrequency >= 0) {
-            flags |= FLAG_IS_TERMINAL;
-        }
-        if (null != group.mChildren) {
-            switch (getByteSize(childrenOffset)) {
-             case 1:
-                 flags |= FLAG_GROUP_ADDRESS_TYPE_ONEBYTE;
-                 break;
-             case 2:
-                 flags |= FLAG_GROUP_ADDRESS_TYPE_TWOBYTES;
-                 break;
-             case 3:
-                 flags |= FLAG_GROUP_ADDRESS_TYPE_THREEBYTES;
-                 break;
-             default:
-                 throw new RuntimeException("Node with a strange address");
-             }
-        }
-        if (null != group.mShortcutTargets) {
-            if (0 == group.mShortcutTargets.size()) {
-                throw new RuntimeException("0-sized shortcut list must be null");
-            }
-            flags |= FLAG_HAS_SHORTCUT_TARGETS;
-        }
-        if (null != group.mBigrams) {
-            if (0 == group.mBigrams.size()) {
-                throw new RuntimeException("0-sized bigram list must be null");
-            }
-            flags |= FLAG_HAS_BIGRAMS;
-        }
-        if (group.mIsShortcutOnly) {
-            flags |= FLAG_IS_SHORTCUT_ONLY;
-        }
-        return flags;
-    }
-
-    /**
-     * Makes the flag value for an attribute.
-     *
-     * @param more whether there are more attributes after this one.
-     * @param offset the offset of the attribute.
-     * @param frequency the frequency of the attribute, 0..15
-     * @return the flags
-     */
-    private static final int makeAttributeFlags(final boolean more, final int offset,
-            final int frequency) {
-        int bigramFlags = (more ? FLAG_ATTRIBUTE_HAS_NEXT : 0)
-                + (offset < 0 ? FLAG_ATTRIBUTE_OFFSET_NEGATIVE : 0);
-        switch (getByteSize(offset)) {
-        case 1:
-            bigramFlags |= FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE;
-            break;
-        case 2:
-            bigramFlags |= FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES;
-            break;
-        case 3:
-            bigramFlags |= FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES;
-            break;
-        default:
-            throw new RuntimeException("Strange offset size");
-        }
-        bigramFlags += frequency & FLAG_ATTRIBUTE_FREQUENCY;
-        return bigramFlags;
-    }
-
-    /**
-     * Write a node to memory. The node is expected to have its final position cached.
-     *
-     * This can be an empty map, but the more is inside the faster the lookups will be. It can
-     * be carried on as long as nodes do not move.
-     *
-     * @param dict the dictionary the node is a part of (for relative offsets).
-     * @param buffer the memory buffer to write to.
-     * @param node the node to write.
-     * @return the address of the END of the node.
-     */
-    private static int writePlacedNode(FusionDictionary dict, byte[] buffer, Node node) {
-        int index = node.mCachedAddress;
-
-        final int groupCount = node.mData.size();
-        final int countSize = getGroupCountSize(node);
-        if (1 == countSize) {
-            buffer[index++] = (byte)groupCount;
-        } else if (2 == countSize) {
-            // We need to signal 2-byte size by setting the top bit of the MSB to 1, so
-            // we | 0x80 to do this.
-            buffer[index++] = (byte)((groupCount >> 8) | 0x80);
-            buffer[index++] = (byte)(groupCount & 0xFF);
-        } else {
-            throw new RuntimeException("Strange size from getGroupCountSize : " + countSize);
-        }
-        int groupAddress = index;
-        for (int i = 0; i < groupCount; ++i) {
-            CharGroup group = node.mData.get(i);
-            if (index != group.mCachedAddress) throw new RuntimeException("Bug: write index is not "
-                    + "the same as the cached address of the group");
-            groupAddress += GROUP_FLAGS_SIZE + getGroupCharactersSize(group);
-            // Sanity checks.
-            if (group.mFrequency > MAX_TERMINAL_FREQUENCY) {
-                throw new RuntimeException("A node has a frequency > " + MAX_TERMINAL_FREQUENCY
-                        + " : " + group.mFrequency);
-            }
-            if (group.mFrequency >= 0) groupAddress += GROUP_FREQUENCY_SIZE;
-            final int childrenOffset = null == group.mChildren
-                    ? NO_CHILDREN_ADDRESS : group.mChildren.mCachedAddress - groupAddress;
-            byte flags = makeCharGroupFlags(group, groupAddress, childrenOffset);
-            buffer[index++] = flags;
-            index = CharEncoding.writeCharArray(group.mChars, buffer, index);
-            if (group.hasSeveralChars()) {
-                buffer[index++] = GROUP_CHARACTERS_TERMINATOR;
-            }
-            if (group.mFrequency >= 0) {
-                buffer[index++] = (byte) group.mFrequency;
-            }
-            final int shift = writeVariableAddress(buffer, index, childrenOffset);
-            index += shift;
-            groupAddress += shift;
-
-            // Write shortcuts
-            if (null != group.mShortcutTargets) {
-                final Iterator shortcutIterator = group.mShortcutTargets.iterator();
-                while (shortcutIterator.hasNext()) {
-                    final WeightedString target = (WeightedString)shortcutIterator.next();
-                    final int addressOfTarget = findAddressOfWord(dict, target.mWord);
-                    ++groupAddress;
-                    final int offset = addressOfTarget - groupAddress;
-                    int shortcutFlags = makeAttributeFlags(shortcutIterator.hasNext(), offset,
-                            target.mFrequency);
-                    buffer[index++] = (byte)shortcutFlags;
-                    final int shortcutShift = writeVariableAddress(buffer, index, Math.abs(offset));
-                    index += shortcutShift;
-                    groupAddress += shortcutShift;
-                }
-            }
-            // Write bigrams
-            if (null != group.mBigrams) {
-                final Iterator bigramIterator = group.mBigrams.iterator();
-                while (bigramIterator.hasNext()) {
-                    final WeightedString bigram = (WeightedString)bigramIterator.next();
-                    final int addressOfBigram = findAddressOfWord(dict, bigram.mWord);
-                    ++groupAddress;
-                    final int offset = addressOfBigram - groupAddress;
-                    int bigramFlags = makeAttributeFlags(bigramIterator.hasNext(), offset,
-                            bigram.mFrequency);
-                    buffer[index++] = (byte)bigramFlags;
-                    final int bigramShift = writeVariableAddress(buffer, index, Math.abs(offset));
-                    index += bigramShift;
-                    groupAddress += bigramShift;
-                }
-            }
-
-        }
-        if (index != node.mCachedAddress + node.mCachedSize) throw new RuntimeException(
-                "Not the same size : written "
-                + (index - node.mCachedAddress) + " bytes out of a node that should have "
-                + node.mCachedSize + " bytes");
-        return index;
-    }
-
-    /**
-     * Dumps a collection of useful statistics about a node array.
-     *
-     * This prints purely informative stuff, like the total estimated file size, the
-     * number of nodes, of character groups, the repartition of each address size, etc
-     *
-     * @param nodes the node array.
-     */
-    private static void showStatistics(ArrayList<Node> nodes) {
-        int firstTerminalAddress = Integer.MAX_VALUE;
-        int lastTerminalAddress = Integer.MIN_VALUE;
-        int size = 0;
-        int charGroups = 0;
-        int maxGroups = 0;
-        int maxRuns = 0;
-        for (Node n : nodes) {
-            if (maxGroups < n.mData.size()) maxGroups = n.mData.size();
-            for (CharGroup cg : n.mData) {
-                ++charGroups;
-                if (cg.mChars.length > maxRuns) maxRuns = cg.mChars.length;
-                if (cg.mFrequency >= 0) {
-                    if (n.mCachedAddress < firstTerminalAddress)
-                        firstTerminalAddress = n.mCachedAddress;
-                    if (n.mCachedAddress > lastTerminalAddress)
-                        lastTerminalAddress = n.mCachedAddress;
-                }
-            }
-            if (n.mCachedAddress + n.mCachedSize > size) size = n.mCachedAddress + n.mCachedSize;
-        }
-        final int[] groupCounts = new int[maxGroups + 1];
-        final int[] runCounts = new int[maxRuns + 1];
-        for (Node n : nodes) {
-            ++groupCounts[n.mData.size()];
-            for (CharGroup cg : n.mData) {
-                ++runCounts[cg.mChars.length];
-            }
-        }
-
-        MakedictLog.i("Statistics:\n"
-                + "  total file size " + size + "\n"
-                + "  " + nodes.size() + " nodes\n"
-                + "  " + charGroups + " groups (" + ((float)charGroups / nodes.size())
-                        + " groups per node)\n"
-                + "  first terminal at " + firstTerminalAddress + "\n"
-                + "  last terminal at " + lastTerminalAddress + "\n"
-                + "  Group stats : max = " + maxGroups);
-        for (int i = 0; i < groupCounts.length; ++i) {
-            MakedictLog.i("    " + i + " : " + groupCounts[i]);
-        }
-        MakedictLog.i("  Character run stats : max = " + maxRuns);
-        for (int i = 0; i < runCounts.length; ++i) {
-            MakedictLog.i("    " + i + " : " + runCounts[i]);
-        }
-    }
-
-    /**
-     * Dumps a FusionDictionary to a file.
-     *
-     * This is the public entry point to write a dictionary to a file.
-     *
-     * @param destination the stream to write the binary data to.
-     * @param dict the dictionary to write.
-     * @param version the version of the format to write, currently either 1 or 2.
-     */
-    public static void writeDictionaryBinary(final OutputStream destination,
-            final FusionDictionary dict, final int version)
-            throws IOException, UnsupportedFormatException {
-
-        // Addresses are limited to 3 bytes, so we'll just make a 16MB buffer. Since addresses
-        // can be relative to each node, the structure itself is not limited to 16MB at all, but
-        // I doubt this will ever be shot. If it is, deciding the order of the nodes becomes
-        // a quite complicated problem, because though the dictionary itself does not have a
-        // size limit, each node must still be within 16MB of all its children and parents.
-        // As long as this is ensured, the dictionary file may grow to any size.
-        // Anyway, to make a dictionary bigger than 16MB just increase the size of this buffer.
-        final byte[] buffer = new byte[1 << 24];
-        int index = 0;
-
-        if (version < MINIMUM_SUPPORTED_VERSION || version > MAXIMUM_SUPPORTED_VERSION) {
-            throw new UnsupportedFormatException("Requested file format version " + version
-                    + ", but this implementation only supports versions "
-                    + MINIMUM_SUPPORTED_VERSION + " through " + MAXIMUM_SUPPORTED_VERSION);
-        }
-
-        // The magic number in big-endian order.
-        if (version >= FIRST_VERSION_WITH_HEADER_SIZE) {
-            // Magic number for version 2+.
-            buffer[index++] = (byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 24));
-            buffer[index++] = (byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 16));
-            buffer[index++] = (byte) (0xFF & (VERSION_2_MAGIC_NUMBER >> 8));
-            buffer[index++] = (byte) (0xFF & VERSION_2_MAGIC_NUMBER);
-            // Dictionary version.
-            buffer[index++] = (byte) (0xFF & (version >> 8));
-            buffer[index++] = (byte) (0xFF & version);
-        } else {
-            // Magic number for version 1.
-            buffer[index++] = (byte) (0xFF & (VERSION_1_MAGIC_NUMBER >> 8));
-            buffer[index++] = (byte) (0xFF & VERSION_1_MAGIC_NUMBER);
-            // Dictionary version.
-            buffer[index++] = (byte) (0xFF & version);
-        }
-        // Options flags
-        buffer[index++] = (byte) (0xFF & (OPTIONS >> 8));
-        buffer[index++] = (byte) (0xFF & OPTIONS);
-        if (version >= FIRST_VERSION_WITH_HEADER_SIZE) {
-            final int headerSizeOffset = index;
-            index += 4; // Size of the header size
-            // TODO: Write out the header contents here.
-            // Write out the header size.
-            buffer[headerSizeOffset] = (byte) (0xFF & (index >> 24));
-            buffer[headerSizeOffset + 1] = (byte) (0xFF & (index >> 16));
-            buffer[headerSizeOffset + 2] = (byte) (0xFF & (index >> 8));
-            buffer[headerSizeOffset + 3] = (byte) (0xFF & (index >> 0));
-        }
-
-        destination.write(buffer, 0, index);
-        index = 0;
-
-        // Leave the choice of the optimal node order to the flattenTree function.
-        MakedictLog.i("Flattening the tree...");
-        ArrayList<Node> flatNodes = flattenTree(dict.mRoot);
-
-        MakedictLog.i("Computing addresses...");
-        computeAddresses(dict, flatNodes);
-        MakedictLog.i("Checking array...");
-        checkFlatNodeArray(flatNodes);
-
-        MakedictLog.i("Writing file...");
-        int dataEndOffset = 0;
-        for (Node n : flatNodes) {
-            dataEndOffset = writePlacedNode(dict, buffer, n);
-        }
-
-        showStatistics(flatNodes);
-
-        destination.write(buffer, 0, dataEndOffset);
-
-        destination.close();
-        MakedictLog.i("Done");
-    }
-
-
-    // Input methods: Read a binary dictionary to memory.
-    // readDictionaryBinary is the public entry point for them.
-
-    static final int[] characterBuffer = new int[MAX_WORD_LENGTH];
-    private static CharGroupInfo readCharGroup(RandomAccessFile source,
-            final int originalGroupAddress) throws IOException {
-        int addressPointer = originalGroupAddress;
-        final int flags = source.readUnsignedByte();
-        ++addressPointer;
-        final int characters[];
-        if (0 != (flags & FLAG_HAS_MULTIPLE_CHARS)) {
-            int index = 0;
-            int character = CharEncoding.readChar(source);
-            addressPointer += CharEncoding.getCharSize(character);
-            while (-1 != character) {
-                characterBuffer[index++] = character;
-                character = CharEncoding.readChar(source);
-                addressPointer += CharEncoding.getCharSize(character);
-            }
-            characters = Arrays.copyOfRange(characterBuffer, 0, index);
-        } else {
-            final int character = CharEncoding.readChar(source);
-            addressPointer += CharEncoding.getCharSize(character);
-            characters = new int[] { character };
-        }
-        final int frequency;
-        if (0 != (FLAG_IS_TERMINAL & flags)) {
-            ++addressPointer;
-            frequency = source.readUnsignedByte();
-        } else {
-            frequency = CharGroup.NOT_A_TERMINAL;
-        }
-        int childrenAddress = addressPointer;
-        switch (flags & MASK_GROUP_ADDRESS_TYPE) {
-        case FLAG_GROUP_ADDRESS_TYPE_ONEBYTE:
-            childrenAddress += source.readUnsignedByte();
-            addressPointer += 1;
-            break;
-        case FLAG_GROUP_ADDRESS_TYPE_TWOBYTES:
-            childrenAddress += source.readUnsignedShort();
-            addressPointer += 2;
-            break;
-        case FLAG_GROUP_ADDRESS_TYPE_THREEBYTES:
-            childrenAddress += (source.readUnsignedByte() << 16) + source.readUnsignedShort();
-            addressPointer += 3;
-            break;
-        case FLAG_GROUP_ADDRESS_TYPE_NOADDRESS:
-        default:
-            childrenAddress = NO_CHILDREN_ADDRESS;
-            break;
-        }
-        ArrayList<PendingAttribute> shortcutTargets = null;
-        if (0 != (flags & FLAG_HAS_SHORTCUT_TARGETS)) {
-            shortcutTargets = new ArrayList<PendingAttribute>();
-            while (true) {
-                final int targetFlags = source.readUnsignedByte();
-                ++addressPointer;
-                final int sign = 0 == (targetFlags & FLAG_ATTRIBUTE_OFFSET_NEGATIVE) ? 1 : -1;
-                int targetAddress = addressPointer;
-                switch (targetFlags & MASK_ATTRIBUTE_ADDRESS_TYPE) {
-                case FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE:
-                    targetAddress += sign * source.readUnsignedByte();
-                    addressPointer += 1;
-                    break;
-                case FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES:
-                    targetAddress += sign * source.readUnsignedShort();
-                    addressPointer += 2;
-                    break;
-                case FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES:
-                    final int offset = ((source.readUnsignedByte() << 16)
-                            + source.readUnsignedShort());
-                    targetAddress += sign * offset;
-                    addressPointer += 3;
-                    break;
-                default:
-                    throw new RuntimeException("Has shortcut targets with no address");
-                }
-                shortcutTargets.add(new PendingAttribute(targetFlags & FLAG_ATTRIBUTE_FREQUENCY,
-                        targetAddress));
-                if (0 == (targetFlags & FLAG_ATTRIBUTE_HAS_NEXT)) break;
-            }
-        }
-        ArrayList<PendingAttribute> bigrams = null;
-        if (0 != (flags & FLAG_HAS_BIGRAMS)) {
-            bigrams = new ArrayList<PendingAttribute>();
-            while (true) {
-                final int bigramFlags = source.readUnsignedByte();
-                ++addressPointer;
-                final int sign = 0 == (bigramFlags & FLAG_ATTRIBUTE_OFFSET_NEGATIVE) ? 1 : -1;
-                int bigramAddress = addressPointer;
-                switch (bigramFlags & MASK_ATTRIBUTE_ADDRESS_TYPE) {
-                case FLAG_ATTRIBUTE_ADDRESS_TYPE_ONEBYTE:
-                    bigramAddress += sign * source.readUnsignedByte();
-                    addressPointer += 1;
-                    break;
-                case FLAG_ATTRIBUTE_ADDRESS_TYPE_TWOBYTES:
-                    bigramAddress += sign * source.readUnsignedShort();
-                    addressPointer += 2;
-                    break;
-                case FLAG_ATTRIBUTE_ADDRESS_TYPE_THREEBYTES:
-                    final int offset = ((source.readUnsignedByte() << 16)
-                            + source.readUnsignedShort());
-                    bigramAddress += sign * offset;
-                    addressPointer += 3;
-                    break;
-                default:
-                    throw new RuntimeException("Has bigrams with no address");
-                }
-                bigrams.add(new PendingAttribute(bigramFlags & FLAG_ATTRIBUTE_FREQUENCY,
-                        bigramAddress));
-                if (0 == (bigramFlags & FLAG_ATTRIBUTE_HAS_NEXT)) break;
-            }
-        }
-        return new CharGroupInfo(originalGroupAddress, addressPointer, flags, characters, frequency,
-                childrenAddress, shortcutTargets, bigrams);
-    }
-
-    /**
-     * Reads and returns the char group count out of a file and forwards the pointer.
-     */
-    private static int readCharGroupCount(RandomAccessFile source) throws IOException {
-        final int msb = source.readUnsignedByte();
-        if (MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT >= msb) {
-            return msb;
-        } else {
-            return ((MAX_CHARGROUPS_FOR_ONE_BYTE_CHARGROUP_COUNT & msb) << 8)
-                    + source.readUnsignedByte();
-        }
-    }
-
-    /**
-     * Finds, as a string, the word at the address passed as an argument.
-     *
-     * @param source the file to read from.
-     * @param headerSize the size of the header.
-     * @param address the address to seek.
-     * @return the word, as a string.
-     * @throws IOException if the file can't be read.
-     */
-    private static String getWordAtAddress(RandomAccessFile source, long headerSize,
-            int address) throws IOException {
-        final long originalPointer = source.getFilePointer();
-        source.seek(headerSize);
-        final int count = readCharGroupCount(source);
-        int groupOffset = getGroupCountSize(count);
-        final StringBuilder builder = new StringBuilder();
-        String result = null;
-
-        CharGroupInfo last = null;
-        for (int i = count - 1; i >= 0; --i) {
-            CharGroupInfo info = readCharGroup(source, groupOffset);
-            groupOffset = info.mEndAddress;
-            if (info.mOriginalAddress == address) {
-                builder.append(new String(info.mCharacters, 0, info.mCharacters.length));
-                result = builder.toString();
-                break; // and return
-            }
-            if (hasChildrenAddress(info.mChildrenAddress)) {
-                if (info.mChildrenAddress > address) {
-                    if (null == last) continue;
-                    builder.append(new String(last.mCharacters, 0, last.mCharacters.length));
-                    source.seek(last.mChildrenAddress + headerSize);
-                    groupOffset = last.mChildrenAddress + 1;
-                    i = source.readUnsignedByte();
-                    last = null;
-                    continue;
-                }
-                last = info;
-            }
-            if (0 == i && hasChildrenAddress(last.mChildrenAddress)) {
-                builder.append(new String(last.mCharacters, 0, last.mCharacters.length));
-                source.seek(last.mChildrenAddress + headerSize);
-                groupOffset = last.mChildrenAddress + 1;
-                i = source.readUnsignedByte();
-                last = null;
-                continue;
-            }
-        }
-        source.seek(originalPointer);
-        return result;
-    }
-
-    /**
-     * Reads a single node from a binary file.
-     *
-     * This methods reads the file at the current position of its file pointer. A node is
-     * fully expected to start at the current position.
-     * This will recursively read other nodes into the structure, populating the reverse
-     * maps on the fly and using them to keep track of already read nodes.
-     *
-     * @param source the data file, correctly positioned at the start of a node.
-     * @param headerSize the size, in bytes, of the file header.
-     * @param reverseNodeMap a mapping from addresses to already read nodes.
-     * @param reverseGroupMap a mapping from addresses to already read character groups.
-     * @return the read node with all his children already read.
-     */
-    private static Node readNode(RandomAccessFile source, long headerSize,
-            Map<Integer, Node> reverseNodeMap, Map<Integer, CharGroup> reverseGroupMap)
-            throws IOException {
-        final int nodeOrigin = (int)(source.getFilePointer() - headerSize);
-        final int count = readCharGroupCount(source);
-        final ArrayList<CharGroup> nodeContents = new ArrayList<CharGroup>();
-        int groupOffset = nodeOrigin + getGroupCountSize(count);
-        for (int i = count; i > 0; --i) {
-            CharGroupInfo info = readCharGroup(source, groupOffset);
-            ArrayList<WeightedString> shortcutTargets = null;
-            if (null != info.mShortcutTargets) {
-                shortcutTargets = new ArrayList<WeightedString>();
-                for (PendingAttribute target : info.mShortcutTargets) {
-                    final String word = getWordAtAddress(source, headerSize, target.mAddress);
-                    shortcutTargets.add(new WeightedString(word, target.mFrequency));
-                }
-            }
-            ArrayList<WeightedString> bigrams = null;
-            if (null != info.mBigrams) {
-                bigrams = new ArrayList<WeightedString>();
-                for (PendingAttribute bigram : info.mBigrams) {
-                    final String word = getWordAtAddress(source, headerSize, bigram.mAddress);
-                    bigrams.add(new WeightedString(word, bigram.mFrequency));
-                }
-            }
-            if (hasChildrenAddress(info.mChildrenAddress)) {
-                Node children = reverseNodeMap.get(info.mChildrenAddress);
-                if (null == children) {
-                    final long currentPosition = source.getFilePointer();
-                    source.seek(info.mChildrenAddress + headerSize);
-                    children = readNode(source, headerSize, reverseNodeMap, reverseGroupMap);
-                    source.seek(currentPosition);
-                }
-                nodeContents.add(
-                        new CharGroup(info.mCharacters, shortcutTargets, bigrams, info.mFrequency,
-                                children, isShortcutOnly(info)));
-            } else {
-                nodeContents.add(
-                        new CharGroup(info.mCharacters, shortcutTargets, bigrams, info.mFrequency,
-                                isShortcutOnly(info)));
-            }
-            groupOffset = info.mEndAddress;
-        }
-        final Node node = new Node(nodeContents);
-        node.mCachedAddress = nodeOrigin;
-        reverseNodeMap.put(node.mCachedAddress, node);
-        return node;
-    }
-
-    /**
-     * Helper function to get the binary format version from the header.
-     */
-    private static int getFormatVersion(final RandomAccessFile source) throws IOException {
-        final int magic_v1 = source.readUnsignedShort();
-        if (VERSION_1_MAGIC_NUMBER == magic_v1) return source.readUnsignedByte();
-        final int magic_v2 = (magic_v1 << 16) + source.readUnsignedShort();
-        if (VERSION_2_MAGIC_NUMBER == magic_v2) return source.readUnsignedShort();
-        return NOT_A_VERSION_NUMBER;
-    }
-
-    /**
-     * Reads a random access file and returns the memory representation of the dictionary.
-     *
-     * This high-level method takes a binary file and reads its contents, populating a
-     * FusionDictionary structure. The optional dict argument is an existing dictionary to
-     * which words from the file should be added. If it is null, a new dictionary is created.
-     *
-     * @param source the file to read.
-     * @param dict an optional dictionary to add words to, or null.
-     * @return the created (or merged) dictionary.
-     */
-    public static FusionDictionary readDictionaryBinary(final RandomAccessFile source,
-            final FusionDictionary dict) throws IOException, UnsupportedFormatException {
-        // Check file version
-        final int version = getFormatVersion(source);
-        if (version < MINIMUM_SUPPORTED_VERSION || version > MAXIMUM_SUPPORTED_VERSION ) {
-            throw new UnsupportedFormatException("This file has version " + version
-                    + ", but this implementation does not support versions above "
-                    + MAXIMUM_SUPPORTED_VERSION);
-        }
-
-        // Read options
-        source.readUnsignedShort();
-
-        final long headerSize;
-        if (version < FIRST_VERSION_WITH_HEADER_SIZE) {
-            headerSize = source.getFilePointer();
-        } else {
-            headerSize = (source.readUnsignedByte() << 24) + (source.readUnsignedByte() << 16)
-                    + (source.readUnsignedByte() << 8) + source.readUnsignedByte();
-            // read the header body
-            source.seek(headerSize);
-        }
-
-        Map<Integer, Node> reverseNodeMapping = new TreeMap<Integer, Node>();
-        Map<Integer, CharGroup> reverseGroupMapping = new TreeMap<Integer, CharGroup>();
-        final Node root = readNode(source, headerSize, reverseNodeMapping, reverseGroupMapping);
-
-        FusionDictionary newDict = new FusionDictionary(root,
-                new FusionDictionary.DictionaryOptions());
-        if (null != dict) {
-            for (Word w : dict) {
-                newDict.add(w.mWord, w.mFrequency, w.mShortcutTargets, w.mBigrams);
-            }
-        }
-
-        return newDict;
-    }
-
-    /**
-     * Basic test to find out whether the file is a binary dictionary or not.
-     *
-     * Concretely this only tests the magic number.
-     *
-     * @param filename The name of the file to test.
-     * @return true if it's a binary dictionary, false otherwise
-     */
-    public static boolean isBinaryDictionary(final String filename) {
-        try {
-            RandomAccessFile f = new RandomAccessFile(filename, "r");
-            final int version = getFormatVersion(f);
-            return (version >= MINIMUM_SUPPORTED_VERSION && version <= MAXIMUM_SUPPORTED_VERSION);
-        } catch (FileNotFoundException e) {
-            return false;
-        } catch (IOException e) {
-            return false;
-        }
-    }
-}
diff --git a/tools/makedict/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java b/tools/makedict/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java
deleted file mode 100644
index 444b117..0000000
--- a/tools/makedict/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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.android.inputmethod.latin.makedict;
-
-import java.util.ArrayList;
-
-/**
- * Raw char group info straight out of a file. This will contain numbers for addresses.
- */
-public class CharGroupInfo {
-
-    public final int mOriginalAddress;
-    public final int mEndAddress;
-    public final int mFlags;
-    public final int[] mCharacters;
-    public final int mFrequency;
-    public final int mChildrenAddress;
-    public final ArrayList<PendingAttribute> mShortcutTargets;
-    public final ArrayList<PendingAttribute> mBigrams;
-
-    public CharGroupInfo(final int originalAddress, final int endAddress, final int flags,
-            final int[] characters, final int frequency, final int childrenAddress,
-            final ArrayList<PendingAttribute> shortcutTargets,
-            final ArrayList<PendingAttribute> bigrams) {
-        mOriginalAddress = originalAddress;
-        mEndAddress = endAddress;
-        mFlags = flags;
-        mCharacters = characters;
-        mFrequency = frequency;
-        mChildrenAddress = childrenAddress;
-        mShortcutTargets = shortcutTargets;
-        mBigrams = bigrams;
-    }
-}
diff --git a/tools/makedict/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/tools/makedict/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
deleted file mode 100644
index d196721..0000000
--- a/tools/makedict/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
+++ /dev/null
@@ -1,677 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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.android.inputmethod.latin.makedict;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * A dictionary that can fusion heads and tails of words for more compression.
- */
-public class FusionDictionary implements Iterable<Word> {
-
-    /**
-     * A node of the dictionary, containing several CharGroups.
-     *
-     * A node is but an ordered array of CharGroups, which essentially contain all the
-     * real information.
-     * This class also contains fields to cache size and address, to help with binary
-     * generation.
-     */
-    public static class Node {
-        ArrayList<CharGroup> mData;
-        // To help with binary generation
-        int mCachedSize;
-        int mCachedAddress;
-        public Node() {
-            mData = new ArrayList<CharGroup>();
-            mCachedSize = Integer.MIN_VALUE;
-            mCachedAddress = Integer.MIN_VALUE;
-        }
-        public Node(ArrayList<CharGroup> data) {
-            mData = data;
-            mCachedSize = Integer.MIN_VALUE;
-            mCachedAddress = Integer.MIN_VALUE;
-        }
-    }
-
-    /**
-     * A string with a frequency.
-     *
-     * This represents an "attribute", that is either a bigram or a shortcut.
-     */
-    public static class WeightedString {
-        final String mWord;
-        final int mFrequency;
-        public WeightedString(String word, int frequency) {
-            mWord = word;
-            mFrequency = frequency;
-        }
-    }
-
-    /**
-     * A group of characters, with a frequency, shortcut targets, bigrams, and children.
-     *
-     * This is the central class of the in-memory representation. A CharGroup is what can
-     * be seen as a traditional "trie node", except it can hold several characters at the
-     * same time. A CharGroup essentially represents one or several characters in the middle
-     * of the trie trie; as such, it can be a terminal, and it can have children.
-     * In this in-memory representation, whether the CharGroup is a terminal or not is represented
-     * in the frequency, where NOT_A_TERMINAL (= -1) means this is not a terminal and any other
-     * value is the frequency of this terminal. A terminal may have non-null shortcuts and/or
-     * bigrams, but a non-terminal may not. Moreover, children, if present, are null.
-     */
-    public static class CharGroup {
-        public static final int NOT_A_TERMINAL = -1;
-        final int mChars[];
-        final ArrayList<WeightedString> mShortcutTargets;
-        final ArrayList<WeightedString> mBigrams;
-        final int mFrequency; // NOT_A_TERMINAL == mFrequency indicates this is not a terminal.
-        final boolean mIsShortcutOnly; // Only valid if this is a terminal.
-        Node mChildren;
-        // The two following members to help with binary generation
-        int mCachedSize;
-        int mCachedAddress;
-
-        public CharGroup(final int[] chars, final ArrayList<WeightedString> shortcutTargets,
-                final ArrayList<WeightedString> bigrams, final int frequency,
-                final boolean isShortcutOnly) {
-            mChars = chars;
-            mFrequency = frequency;
-            mIsShortcutOnly = isShortcutOnly;
-            if (mIsShortcutOnly && NOT_A_TERMINAL == mFrequency) {
-                throw new RuntimeException("A node must be a terminal to be a shortcut only");
-            }
-            mShortcutTargets = shortcutTargets;
-            mBigrams = bigrams;
-            mChildren = null;
-        }
-
-        public CharGroup(final int[] chars, final ArrayList<WeightedString> shortcutTargets,
-                final ArrayList<WeightedString> bigrams, final int frequency, final Node children,
-                final boolean isShortcutOnly) {
-            mChars = chars;
-            mFrequency = frequency;
-            mIsShortcutOnly = isShortcutOnly;
-            if (mIsShortcutOnly && NOT_A_TERMINAL == mFrequency) {
-                throw new RuntimeException("A node must be a terminal to be a shortcut only");
-            }
-            mShortcutTargets = shortcutTargets;
-            mBigrams = bigrams;
-            mChildren = children;
-        }
-
-        public void addChild(CharGroup n) {
-            if (null == mChildren) {
-                mChildren = new Node();
-            }
-            mChildren.mData.add(n);
-        }
-
-        public boolean isTerminal() {
-            return NOT_A_TERMINAL != mFrequency;
-        }
-
-        public boolean hasSeveralChars() {
-            assert(mChars.length > 0);
-            return 1 < mChars.length;
-        }
-    }
-
-    /**
-     * Options global to the dictionary.
-     *
-     * There are no options at the moment, so this class is empty.
-     */
-    public static class DictionaryOptions {
-    }
-
-
-    public final DictionaryOptions mOptions;
-    public final Node mRoot;
-
-    public FusionDictionary() {
-        mOptions = new DictionaryOptions();
-        mRoot = new Node();
-    }
-
-    public FusionDictionary(final Node root, final DictionaryOptions options) {
-        mRoot = root;
-        mOptions = options;
-    }
-
-    /**
-     * Helper method to convert a String to an int array.
-     */
-    static private int[] getCodePoints(String word) {
-        final int wordLength = word.length();
-        int[] array = new int[word.codePointCount(0, wordLength)];
-        for (int i = 0; i < wordLength; i = word.offsetByCodePoints(i, 1)) {
-            array[i] = word.codePointAt(i);
-        }
-        return array;
-    }
-
-    /**
-     * Helper method to add all words in a list as 0-frequency entries
-     *
-     * These words are added when shortcuts targets or bigrams are not found in the dictionary
-     * yet. The same words may be added later with an actual frequency - this is handled by
-     * the private version of add().
-     */
-    private void addNeutralWords(final ArrayList<WeightedString> words) {
-        if (null != words) {
-            for (WeightedString word : words) {
-                final CharGroup t = findWordInTree(mRoot, word.mWord);
-                if (null == t) {
-                    add(getCodePoints(word.mWord), 0, null, null, false /* isShortcutOnly */);
-                }
-            }
-        }
-    }
-
-    /**
-     * Helper method to add a word as a string.
-     *
-     * This method adds a word to the dictionary with the given frequency. Optional
-     * lists of bigrams and shortcuts can be passed here. For each word inside,
-     * they will be added to the dictionary as necessary.
-     *
-     * @param word the word to add.
-     * @param frequency the frequency of the word, in the range [0..255].
-     * @param shortcutTargets a list of shortcut targets for this word, or null.
-     * @param bigrams a list of bigrams, or null.
-     */
-    public void add(final String word, final int frequency,
-            final ArrayList<WeightedString> shortcutTargets,
-            final ArrayList<WeightedString> bigrams) {
-        if (null != shortcutTargets) {
-            addNeutralWords(shortcutTargets);
-        }
-        if (null != bigrams) {
-            addNeutralWords(bigrams);
-        }
-        add(getCodePoints(word), frequency, shortcutTargets, bigrams, false /* isShortcutOnly */);
-    }
-
-    /**
-     * Sanity check for a node.
-     *
-     * This method checks that all CharGroups in a node are ordered as expected.
-     * If they are, nothing happens. If they aren't, an exception is thrown.
-     */
-    private void checkStack(Node node) {
-        ArrayList<CharGroup> stack = node.mData;
-        int lastValue = -1;
-        for (int i = 0; i < stack.size(); ++i) {
-            int currentValue = stack.get(i).mChars[0];
-            if (currentValue <= lastValue)
-                throw new RuntimeException("Invalid stack");
-            else
-                lastValue = currentValue;
-        }
-    }
-
-    /**
-     * Helper method to add a shortcut that should not be a dictionary word.
-     *
-     * @param word the word to add.
-     * @param frequency the frequency of the word, in the range [0..255].
-     * @param shortcutTargets a list of shortcut targets. May not be null.
-     */
-    public void addShortcutOnly(final String word, final int frequency,
-            final ArrayList<WeightedString> shortcutTargets) {
-        if (null == shortcutTargets) {
-            throw new RuntimeException("Can't add a shortcut without targets");
-        }
-        addNeutralWords(shortcutTargets);
-        add(getCodePoints(word), frequency, shortcutTargets, null, true /* isShortcutOnly */);
-    }
-
-    /**
-     * Add a word to this dictionary.
-     *
-     * The shortcuts and bigrams, if any, have to be in the dictionary already. If they aren't,
-     * an exception is thrown.
-     *
-     * @param word the word, as an int array.
-     * @param frequency the frequency of the word, in the range [0..255].
-     * @param shortcutTargets an optional list of shortcut targets for this word (null if none).
-     * @param bigrams an optional list of bigrams for this word (null if none).
-     * @param isShortcutOnly whether this should be a shortcut only.
-     */
-    private void add(final int[] word, final int frequency,
-            final ArrayList<WeightedString> shortcutTargets,
-            final ArrayList<WeightedString> bigrams,
-            final boolean isShortcutOnly) {
-        assert(frequency >= 0 && frequency <= 255);
-        Node currentNode = mRoot;
-        int charIndex = 0;
-
-        CharGroup currentGroup = null;
-        int differentCharIndex = 0; // Set by the loop to the index of the char that differs
-        int nodeIndex = findIndexOfChar(mRoot, word[charIndex]);
-        while (CHARACTER_NOT_FOUND != nodeIndex) {
-            currentGroup = currentNode.mData.get(nodeIndex);
-            differentCharIndex = compareArrays(currentGroup.mChars, word, charIndex);
-            if (ARRAYS_ARE_EQUAL != differentCharIndex
-                    && differentCharIndex < currentGroup.mChars.length) break;
-            if (null == currentGroup.mChildren) break;
-            charIndex += currentGroup.mChars.length;
-            if (charIndex >= word.length) break;
-            currentNode = currentGroup.mChildren;
-            nodeIndex = findIndexOfChar(currentNode, word[charIndex]);
-        }
-
-        if (-1 == nodeIndex) {
-            // No node at this point to accept the word. Create one.
-            final int insertionIndex = findInsertionIndex(currentNode, word[charIndex]);
-            final CharGroup newGroup = new CharGroup(
-                    Arrays.copyOfRange(word, charIndex, word.length),
-                    shortcutTargets, bigrams, frequency, isShortcutOnly);
-            currentNode.mData.add(insertionIndex, newGroup);
-            checkStack(currentNode);
-        } else {
-            // There is a word with a common prefix.
-            if (differentCharIndex == currentGroup.mChars.length) {
-                if (charIndex + differentCharIndex >= word.length) {
-                    // The new word is a prefix of an existing word, but the node on which it
-                    // should end already exists as is.
-                    if (currentGroup.mFrequency > 0) {
-                        throw new RuntimeException("Such a word already exists in the dictionary : "
-                                + new String(word, 0, word.length));
-                    } else {
-                        final CharGroup newNode = new CharGroup(currentGroup.mChars,
-                                shortcutTargets, bigrams, frequency, currentGroup.mChildren,
-                                isShortcutOnly);
-                        currentNode.mData.set(nodeIndex, newNode);
-                        checkStack(currentNode);
-                    }
-                } else {
-                    // The new word matches the full old word and extends past it.
-                    // We only have to create a new node and add it to the end of this.
-                    final CharGroup newNode = new CharGroup(
-                            Arrays.copyOfRange(word, charIndex + differentCharIndex, word.length),
-                                    shortcutTargets, bigrams, frequency, isShortcutOnly);
-                    currentGroup.mChildren = new Node();
-                    currentGroup.mChildren.mData.add(newNode);
-                }
-            } else {
-                if (0 == differentCharIndex) {
-                    // Exact same word. Check the frequency is 0 or NOT_A_TERMINAL, and update.
-                    if (0 != frequency) {
-                        if (0 < currentGroup.mFrequency) {
-                            throw new RuntimeException("This word already exists with frequency "
-                                    + currentGroup.mFrequency + " : "
-                                    + new String(word, 0, word.length));
-                        }
-                        final CharGroup newGroup = new CharGroup(word,
-                                currentGroup.mShortcutTargets, currentGroup.mBigrams,
-                                frequency, currentGroup.mChildren,
-                                currentGroup.mIsShortcutOnly && isShortcutOnly);
-                        currentNode.mData.set(nodeIndex, newGroup);
-                    }
-                } else {
-                    // Partial prefix match only. We have to replace the current node with a node
-                    // containing the current prefix and create two new ones for the tails.
-                    Node newChildren = new Node();
-                    final CharGroup newOldWord = new CharGroup(
-                            Arrays.copyOfRange(currentGroup.mChars, differentCharIndex,
-                                    currentGroup.mChars.length), currentGroup.mShortcutTargets,
-                            currentGroup.mBigrams, currentGroup.mFrequency, currentGroup.mChildren,
-                            currentGroup.mIsShortcutOnly);
-                    newChildren.mData.add(newOldWord);
-
-                    final CharGroup newParent;
-                    if (charIndex + differentCharIndex >= word.length) {
-                        newParent = new CharGroup(
-                                Arrays.copyOfRange(currentGroup.mChars, 0, differentCharIndex),
-                                shortcutTargets, bigrams, frequency, newChildren, isShortcutOnly);
-                    } else {
-                        // isShortcutOnly makes no sense for non-terminal nodes. The following node
-                        // is non-terminal (frequency 0 in FusionDictionary representation) so we
-                        // pass false for isShortcutOnly
-                        newParent = new CharGroup(
-                                Arrays.copyOfRange(currentGroup.mChars, 0, differentCharIndex),
-                                null, null, -1, newChildren, false /* isShortcutOnly */);
-                        final CharGroup newWord = new CharGroup(
-                                Arrays.copyOfRange(word, charIndex + differentCharIndex,
-                                        word.length), shortcutTargets, bigrams, frequency,
-                                        isShortcutOnly);
-                        final int addIndex = word[charIndex + differentCharIndex]
-                                > currentGroup.mChars[differentCharIndex] ? 1 : 0;
-                        newChildren.mData.add(addIndex, newWord);
-                    }
-                    currentNode.mData.set(nodeIndex, newParent);
-                }
-                checkStack(currentNode);
-            }
-        }
-    }
-
-    /**
-     * Custom comparison of two int arrays taken to contain character codes.
-     *
-     * This method compares the two arrays passed as an argument in a lexicographic way,
-     * with an offset in the dst string.
-     * This method does NOT test for the first character. It is taken to be equal.
-     * I repeat: this method starts the comparison at 1 <> dstOffset + 1.
-     * The index where the strings differ is returned. ARRAYS_ARE_EQUAL = 0 is returned if the
-     * strings are equal. This works BECAUSE we don't look at the first character.
-     *
-     * @param src the left-hand side string of the comparison.
-     * @param dst the right-hand side string of the comparison.
-     * @param dstOffset the offset in the right-hand side string.
-     * @return the index at which the strings differ, or ARRAYS_ARE_EQUAL = 0 if they don't.
-     */
-    private static int ARRAYS_ARE_EQUAL = 0;
-    private static int compareArrays(final int[] src, final int[] dst, int dstOffset) {
-        // We do NOT test the first char, because we come from a method that already
-        // tested it.
-        for (int i = 1; i < src.length; ++i) {
-            if (dstOffset + i >= dst.length) return i;
-            if (src[i] != dst[dstOffset + i]) return i;
-        }
-        if (dst.length > src.length) return src.length;
-        return ARRAYS_ARE_EQUAL;
-    }
-
-    /**
-     * Helper class that compares and sorts two chargroups according to their
-     * first element only. I repeat: ONLY the first element is considered, the rest
-     * is ignored.
-     * This comparator imposes orderings that are inconsistent with equals.
-     */
-    static private class CharGroupComparator implements java.util.Comparator {
-        public int compare(Object o1, Object o2) {
-            final CharGroup c1 = (CharGroup)o1;
-            final CharGroup c2 = (CharGroup)o2;
-            if (c1.mChars[0] == c2.mChars[0]) return 0;
-            return c1.mChars[0] < c2.mChars[0] ? -1 : 1;
-        }
-        public boolean equals(Object o) {
-            return o instanceof CharGroupComparator;
-        }
-    }
-    final static private CharGroupComparator CHARGROUP_COMPARATOR = new CharGroupComparator();
-
-    /**
-     * Finds the insertion index of a character within a node.
-     */
-    private static int findInsertionIndex(final Node node, int character) {
-        final List data = node.mData;
-        final CharGroup reference = new CharGroup(new int[] { character }, null, null, 0,
-                false /* isShortcutOnly */);
-        int result = Collections.binarySearch(data, reference, CHARGROUP_COMPARATOR);
-        return result >= 0 ? result : -result - 1;
-    }
-
-    /**
-     * Find the index of a char in a node, if it exists.
-     *
-     * @param node the node to search in.
-     * @param character the character to search for.
-     * @return the position of the character if it's there, or CHARACTER_NOT_FOUND = -1 else.
-     */
-    private static int CHARACTER_NOT_FOUND = -1;
-    private static int findIndexOfChar(final Node node, int character) {
-        final int insertionIndex = findInsertionIndex(node, character);
-        if (node.mData.size() <= insertionIndex) return CHARACTER_NOT_FOUND;
-        return character == node.mData.get(insertionIndex).mChars[0] ? insertionIndex
-                : CHARACTER_NOT_FOUND;
-    }
-
-    /**
-     * Helper method to find a word in a given branch.
-     */
-    public static CharGroup findWordInTree(Node node, final String s) {
-        int index = 0;
-        final StringBuilder checker = new StringBuilder();
-
-        CharGroup currentGroup;
-        do {
-            int indexOfGroup = findIndexOfChar(node, s.codePointAt(index));
-            if (CHARACTER_NOT_FOUND == indexOfGroup) return null;
-            currentGroup = node.mData.get(indexOfGroup);
-            checker.append(new String(currentGroup.mChars, 0, currentGroup.mChars.length));
-            index += currentGroup.mChars.length;
-            if (index < s.length()) {
-                node = currentGroup.mChildren;
-            }
-        } while (null != node && index < s.length());
-
-        if (!s.equals(checker.toString())) return null;
-        return currentGroup;
-    }
-
-    /**
-     * Helper method to find out whether a word is in the dict or not.
-     */
-    public boolean hasWord(final String s) {
-        if (null == s || "".equals(s)) {
-            throw new RuntimeException("Can't search for a null or empty string");
-        }
-        return null != findWordInTree(mRoot, s);
-    }
-
-    /**
-     * Recursively count the number of character groups in a given branch of the trie.
-     *
-     * @param node the parent node.
-     * @return the number of char groups in all the branch under this node.
-     */
-    public static int countCharGroups(final Node node) {
-        final int nodeSize = node.mData.size();
-        int size = nodeSize;
-        for (int i = nodeSize - 1; i >= 0; --i) {
-            CharGroup group = node.mData.get(i);
-            if (null != group.mChildren)
-                size += countCharGroups(group.mChildren);
-        }
-        return size;
-    }
-
-    /**
-     * Recursively count the number of nodes in a given branch of the trie.
-     *
-     * @param node the node to count.
-     * @result the number of nodes in this branch.
-     */
-    public static int countNodes(final Node node) {
-        int size = 1;
-        for (int i = node.mData.size() - 1; i >= 0; --i) {
-            CharGroup group = node.mData.get(i);
-            if (null != group.mChildren)
-                size += countNodes(group.mChildren);
-        }
-        return size;
-    }
-
-    // Historically, the tails of the words were going to be merged to save space.
-    // However, that would prevent the code to search for a specific address in log(n)
-    // time so this was abandoned.
-    // The code is still of interest as it does add some compression to any dictionary
-    // that has no need for attributes. Implementations that does not read attributes should be
-    // able to read a dictionary with merged tails.
-    // Also, the following code does support frequencies, as in, it will only merges
-    // tails that share the same frequency. Though it would result in the above loss of
-    // performance while searching by address, it is still technically possible to merge
-    // tails that contain attributes, but this code does not take that into account - it does
-    // not compare attributes and will merge terminals with different attributes regardless.
-    public void mergeTails() {
-        MakedictLog.i("Do not merge tails");
-        return;
-
-//        MakedictLog.i("Merging nodes. Number of nodes : " + countNodes(root));
-//        MakedictLog.i("Number of groups : " + countCharGroups(root));
-//
-//        final HashMap<String, ArrayList<Node>> repository =
-//                  new HashMap<String, ArrayList<Node>>();
-//        mergeTailsInner(repository, root);
-//
-//        MakedictLog.i("Number of different pseudohashes : " + repository.size());
-//        int size = 0;
-//        for (ArrayList<Node> a : repository.values()) {
-//            size += a.size();
-//        }
-//        MakedictLog.i("Number of nodes after merge : " + (1 + size));
-//        MakedictLog.i("Recursively seen nodes : " + countNodes(root));
-    }
-
-    // The following methods are used by the deactivated mergeTails()
-//   private static boolean isEqual(Node a, Node b) {
-//       if (null == a && null == b) return true;
-//       if (null == a || null == b) return false;
-//       if (a.data.size() != b.data.size()) return false;
-//       final int size = a.data.size();
-//       for (int i = size - 1; i >= 0; --i) {
-//           CharGroup aGroup = a.data.get(i);
-//           CharGroup bGroup = b.data.get(i);
-//           if (aGroup.frequency != bGroup.frequency) return false;
-//           if (aGroup.alternates == null && bGroup.alternates != null) return false;
-//           if (aGroup.alternates != null && !aGroup.equals(bGroup.alternates)) return false;
-//           if (!Arrays.equals(aGroup.chars, bGroup.chars)) return false;
-//           if (!isEqual(aGroup.children, bGroup.children)) return false;
-//       }
-//       return true;
-//   }
-
-//   static private HashMap<String, ArrayList<Node>> mergeTailsInner(
-//           final HashMap<String, ArrayList<Node>> map, final Node node) {
-//       final ArrayList<CharGroup> branches = node.data;
-//       final int nodeSize = branches.size();
-//       for (int i = 0; i < nodeSize; ++i) {
-//           CharGroup group = branches.get(i);
-//           if (null != group.children) {
-//               String pseudoHash = getPseudoHash(group.children);
-//               ArrayList<Node> similarList = map.get(pseudoHash);
-//               if (null == similarList) {
-//                   similarList = new ArrayList<Node>();
-//                   map.put(pseudoHash, similarList);
-//               }
-//               boolean merged = false;
-//               for (Node similar : similarList) {
-//                   if (isEqual(group.children, similar)) {
-//                       group.children = similar;
-//                       merged = true;
-//                       break;
-//                   }
-//               }
-//               if (!merged) {
-//                   similarList.add(group.children);
-//               }
-//               mergeTailsInner(map, group.children);
-//           }
-//       }
-//       return map;
-//   }
-
-//  private static String getPseudoHash(final Node node) {
-//      StringBuilder s = new StringBuilder();
-//      for (CharGroup g : node.data) {
-//          s.append(g.frequency);
-//          for (int ch : g.chars){
-//              s.append(Character.toChars(ch));
-//          }
-//      }
-//      return s.toString();
-//  }
-
-    /**
-     * Iterator to walk through a dictionary.
-     *
-     * This is purely for convenience.
-     */
-    public static class DictionaryIterator implements Iterator<Word> {
-
-        private static class Position {
-            public Iterator<CharGroup> pos;
-            public int length;
-            public Position(ArrayList<CharGroup> groups) {
-                pos = groups.iterator();
-                length = 0;
-            }
-        }
-        final StringBuilder mCurrentString;
-        final LinkedList<Position> mPositions;
-
-        public DictionaryIterator(ArrayList<CharGroup> root) {
-            mCurrentString = new StringBuilder();
-            mPositions = new LinkedList<Position>();
-            final Position rootPos = new Position(root);
-            mPositions.add(rootPos);
-        }
-
-        @Override
-        public boolean hasNext() {
-            for (Position p : mPositions) {
-                if (p.pos.hasNext()) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public Word next() {
-            Position currentPos = mPositions.getLast();
-            mCurrentString.setLength(mCurrentString.length() - currentPos.length);
-
-            do {
-                if (currentPos.pos.hasNext()) {
-                    final CharGroup currentGroup = currentPos.pos.next();
-                    currentPos.length = currentGroup.mChars.length;
-                    for (int i : currentGroup.mChars)
-                        mCurrentString.append(Character.toChars(i));
-                    if (null != currentGroup.mChildren) {
-                        currentPos = new Position(currentGroup.mChildren.mData);
-                        mPositions.addLast(currentPos);
-                    }
-                    if (currentGroup.mFrequency >= 0)
-                        return new Word(mCurrentString.toString(), currentGroup.mFrequency,
-                                currentGroup.mShortcutTargets, currentGroup.mBigrams,
-                                currentGroup.mIsShortcutOnly);
-                } else {
-                    mPositions.removeLast();
-                    currentPos = mPositions.getLast();
-                    mCurrentString.setLength(mCurrentString.length() - mPositions.getLast().length);
-                }
-            } while(true);
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException("Unsupported yet");
-        }
-
-    }
-
-    /**
-     * Method to return an iterator.
-     *
-     * This method enables Java's enhanced for loop. With this you can have a FusionDictionary x
-     * and say : for (Word w : x) {}
-     */
-    @Override
-    public Iterator<Word> iterator() {
-        return new DictionaryIterator(mRoot.mData);
-    }
-}
diff --git a/tools/makedict/src/com/android/inputmethod/latin/makedict/MakedictLog.java b/tools/makedict/src/com/android/inputmethod/latin/makedict/MakedictLog.java
deleted file mode 100644
index cff8d6f..0000000
--- a/tools/makedict/src/com/android/inputmethod/latin/makedict/MakedictLog.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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.android.inputmethod.latin.makedict;
-
-/**
- * Wrapper to redirect log events to the right output medium.
- */
-public class MakedictLog {
-
-    private static void print(String message) {
-        System.out.println(message);
-    }
-
-    public static void d(String message) {
-        print(message);
-    }
-    public static void e(String message) {
-        print(message);
-    }
-    public static void i(String message) {
-        print(message);
-    }
-    public static void w(String message) {
-        print(message);
-    }
-}
diff --git a/tools/makedict/src/com/android/inputmethod/latin/makedict/PendingAttribute.java b/tools/makedict/src/com/android/inputmethod/latin/makedict/PendingAttribute.java
deleted file mode 100644
index 5b41d27..0000000
--- a/tools/makedict/src/com/android/inputmethod/latin/makedict/PendingAttribute.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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.android.inputmethod.latin.makedict;
-
-/**
- * A not-yet-resolved attribute.
- *
- * An attribute is either a bigram or a shortcut.
- * All instances of this class are always immutable.
- */
-public class PendingAttribute {
-    public final int mFrequency;
-    public final int mAddress;
-    public PendingAttribute(final int frequency, final int address) {
-        mFrequency = frequency;
-        mAddress = address;
-    }
-}
diff --git a/tools/makedict/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java b/tools/makedict/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java
deleted file mode 100644
index bd42fb8..0000000
--- a/tools/makedict/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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.android.inputmethod.latin.makedict;
-
-/**
- * Simple exception thrown when a file format is not recognized.
- */
-public class UnsupportedFormatException extends Exception {
-    public UnsupportedFormatException(String description) {
-        super(description);
-    }
-}
diff --git a/tools/makedict/src/com/android/inputmethod/latin/makedict/Word.java b/tools/makedict/src/com/android/inputmethod/latin/makedict/Word.java
deleted file mode 100644
index c2c01e1..0000000
--- a/tools/makedict/src/com/android/inputmethod/latin/makedict/Word.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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.android.inputmethod.latin.makedict;
-
-import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString;
-
-import java.util.ArrayList;
-
-/**
- * Utility class for a word with a frequency.
- *
- * This is chiefly used to iterate a dictionary.
- */
-public class Word implements Comparable<Word> {
-    final String mWord;
-    final int mFrequency;
-    final boolean mIsShortcutOnly;
-    final ArrayList<WeightedString> mShortcutTargets;
-    final ArrayList<WeightedString> mBigrams;
-
-    public Word(final String word, final int frequency,
-            final ArrayList<WeightedString> shortcutTargets,
-            final ArrayList<WeightedString> bigrams, final boolean isShortcutOnly) {
-        mWord = word;
-        mFrequency = frequency;
-        mShortcutTargets = shortcutTargets;
-        mBigrams = bigrams;
-        mIsShortcutOnly = isShortcutOnly;
-    }
-
-    /**
-     * Three-way comparison.
-     *
-     * A Word x is greater than a word y if x has a higher frequency. If they have the same
-     * frequency, they are sorted in lexicographic order.
-     */
-    @Override
-    public int compareTo(Word w) {
-        if (mFrequency < w.mFrequency) return 1;
-        if (mFrequency > w.mFrequency) return -1;
-        return mWord.compareTo(w.mWord);
-    }
-
-    /**
-     * Equality test.
-     *
-     * Words are equal if they have the same frequency, the same spellings, and the same
-     * attributes.
-     */
-    @Override
-    public boolean equals(Object o) {
-        if (!(o instanceof Word)) return false;
-        Word w = (Word)o;
-        return mFrequency == w.mFrequency && mWord.equals(w.mWord)
-                && mShortcutTargets.equals(w.mShortcutTargets)
-                && mBigrams.equals(w.mBigrams);
-    }
-}
