Add a simple way to input dictionary header attributes

Just add them as an attribute to the root of the XML node.

Bug: 6202812
Change-Id: Idf040bfebf20a72f9e4370930a85d97df593f484
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
index af7f863..010ea68 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java
@@ -26,6 +26,7 @@
 import java.io.RandomAccessFile;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.TreeMap;
@@ -922,7 +923,14 @@
         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 options.
+            for (final String key : dict.mOptions.mAttributes.keySet()) {
+                final String value = dict.mOptions.mAttributes.get(key);
+                index += CharEncoding.writeString(buffer, index, key);
+                index += CharEncoding.writeString(buffer, index, value);
+            }
+
             // Write out the header size.
             buffer[headerSizeOffset] = (byte) (0xFF & (index >> 24));
             buffer[headerSizeOffset + 1] = (byte) (0xFF & (index >> 16));
@@ -1214,12 +1222,17 @@
         source.readUnsignedShort();
 
         final long headerSize;
+        final HashMap<String, String> options = new HashMap<String, String>();
         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
+            while (source.getFilePointer() < headerSize) {
+                final String key = CharEncoding.readString(source);
+                final String value = CharEncoding.readString(source);
+                options.put(key, value);
+            }
             source.seek(headerSize);
         }
 
@@ -1228,7 +1241,7 @@
         final Node root = readNode(source, headerSize, reverseNodeMapping, reverseGroupMapping);
 
         FusionDictionary newDict = new FusionDictionary(root,
-                new FusionDictionary.DictionaryOptions());
+                new FusionDictionary.DictionaryOptions(options));
         if (null != dict) {
             for (Word w : dict) {
                 newDict.add(w.mWord, w.mFrequency, w.mShortcutTargets, w.mBigrams);
diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
index d3ffb47..99b1704 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
@@ -19,6 +19,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 
@@ -250,6 +251,10 @@
      * There are no options at the moment, so this class is empty.
      */
     public static class DictionaryOptions {
+        final HashMap<String, String> mAttributes;
+        public DictionaryOptions(final HashMap<String, String> attributes) {
+            mAttributes = attributes;
+        }
     }
 
 
@@ -257,8 +262,13 @@
     public final Node mRoot;
 
     public FusionDictionary() {
-        mOptions = new DictionaryOptions();
         mRoot = new Node();
+        mOptions = new DictionaryOptions(new HashMap<String, String>());
+    }
+
+    public FusionDictionary(final HashMap<String, String> attributes) {
+        mRoot = new Node();
+        mOptions = new DictionaryOptions(attributes);
     }
 
     public FusionDictionary(final Node root, final DictionaryOptions options) {
@@ -266,6 +276,10 @@
         mOptions = options;
     }
 
+    public void addOptionAttribute(final String key, final String value) {
+        mOptions.mAttributes.put(key, value);
+    }
+
     /**
      * Helper method to convert a String to an int array.
      */
diff --git a/tools/makedict/src/com/android/inputmethod/latin/makedict/XmlDictInputOutput.java b/tools/makedict/src/com/android/inputmethod/latin/makedict/XmlDictInputOutput.java
index 483473b..1d45fd2 100644
--- a/tools/makedict/src/com/android/inputmethod/latin/makedict/XmlDictInputOutput.java
+++ b/tools/makedict/src/com/android/inputmethod/latin/makedict/XmlDictInputOutput.java
@@ -40,6 +40,7 @@
  */
 public class XmlDictInputOutput {
 
+    private static final String ROOT_TAG = "wordlist";
     private static final String WORD_TAG = "w";
     private static final String BIGRAM_TAG = "bigram";
     private static final String SHORTCUT_TAG = "shortcut";
@@ -96,6 +97,11 @@
                         mFreq = Integer.parseInt(attrs.getValue(attrIndex));
                     }
                 }
+            } else if (ROOT_TAG.equals(localName)) {
+                for (int attrIndex = 0; attrIndex < attrs.getLength(); ++attrIndex) {
+                    final String attrName = attrs.getLocalName(attrIndex);
+                    mDictionary.mOptions.mAttributes.put(attrName, attrs.getValue(attrIndex));
+                }
             } else {
                 mState = UNKNOWN;
             }
@@ -275,7 +281,13 @@
             set.add(word);
         }
         // TODO: use an XMLSerializer if this gets big
-        destination.write("<wordlist format=\"2\">\n");
+        destination.write("<wordlist format=\"2\"");
+        final HashMap<String, String> options = dict.mOptions.mAttributes;
+        for (final String key : dict.mOptions.mAttributes.keySet()) {
+            final String value = dict.mOptions.mAttributes.get(key);
+            destination.write(" " + key + "=\"" + value + "\"");
+        }
+        destination.write(">\n");
         destination.write("<!-- Warning: there is no code to read this format yet. -->\n");
         for (Word word : set) {
             destination.write("  <" + WORD_TAG + " " + WORD_ATTR + "=\"" + word.mWord + "\" "