From 0c5b93800e1dcc946a414c4b844c776a711ecc32 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 25 Oct 2012 18:30:26 +0900 Subject: [PATCH] Add the dicttool diff command. (A8) This is an initial implementation, it does not do everything just yet. Bug: 7388857 Change-Id: I11543973a4657e122ca3475225059b06b9a3f2b9 --- .../latin/dicttool/CommandList.java | 1 + .../inputmethod/latin/dicttool/Diff.java | 108 ++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CommandList.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CommandList.java index d16b069fe..889dde685 100644 --- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CommandList.java +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/CommandList.java @@ -19,6 +19,7 @@ package com.android.inputmethod.latin.dicttool; public class CommandList { public static void populate() { Dicttool.addCommand("info", Info.class); + Dicttool.addCommand("diff", Diff.class); Dicttool.addCommand("compress", Compress.Compressor.class); Dicttool.addCommand("uncompress", Compress.Uncompressor.class); Dicttool.addCommand("makedict", Makedict.class); diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java new file mode 100644 index 000000000..60ba9383d --- /dev/null +++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Diff.java @@ -0,0 +1,108 @@ +/** + * Copyright (C) 2012 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.dicttool; + +import com.android.inputmethod.latin.makedict.FusionDictionary; + +import java.util.Arrays; + +public class Diff extends Dicttool.Command { + public static final String COMMAND = "diff"; + + public Diff() { + } + + @Override + public String getHelp() { + return COMMAND + " [-p] : shows differences between two dictionaries.\n" + + " If -p (porcelain) option is given, produce output suitable for a script"; + } + + @Override + public void run() { + if (mArgs.length < 2) { + throw new RuntimeException("Not enough arguments for command " + COMMAND); + } + final boolean porcelain; + if ("-p".equals(mArgs[0])) { + porcelain = true; + mArgs = Arrays.copyOfRange(mArgs, 1, mArgs.length); + if (mArgs.length != 2) { // There should be only 2 arguments left + throw new RuntimeException("Wrong number of arguments for command " + COMMAND); + } + } else { + porcelain = false; + } + final FusionDictionary dict0 = + BinaryDictOffdeviceUtils.getDictionary(mArgs[0], false /* report */); + if (null == dict0) throw new RuntimeException("Can't read dictionary " + mArgs[0]); + final FusionDictionary dict1 = + BinaryDictOffdeviceUtils.getDictionary(mArgs[1], false /* report */); + if (null == dict1) throw new RuntimeException("Can't read dictionary " + mArgs[1]); + if (!porcelain) { + System.out.println("Header :"); + diffHeaders(dict0, dict1); + if (languageDiffers(dict0, dict1)) { + // diffHeaders returns whether the language is different. If it is, we should bail + // to avoid flooding the output with thousands of useless word-level diffs. + return; + } + System.out.println("Body :"); + } + // TODO: implement the word-level diff + } + + private static boolean languageDiffers(final FusionDictionary dict0, + final FusionDictionary dict1) { + // If either of the dictionaries have no locale, assume it's okay + // We only check for the language here. The rationale is that one may meaningfully diff + // a en_US with a en_GB dictionary, but someone who diffs a de dict with a pt_BR dict + // is almost certainly only interested in header-level diff, and the word diff would be very + // large, meaningless, and annoying. + if (null == dict0.mOptions.mAttributes.get("locale")) return true; + if (null == dict1.mOptions.mAttributes.get("locale")) return true; + final String dict0Lang = dict0.mOptions.mAttributes.get("locale").split("_", 3)[0]; + final String dict1Lang = dict1.mOptions.mAttributes.get("locale").split("_", 3)[0]; + return !dict0Lang.equals(dict1Lang); + } + + private static void diffHeaders(final FusionDictionary dict0, final FusionDictionary dict1) { + if (dict0.mOptions.mFrenchLigatureProcessing != dict1.mOptions.mFrenchLigatureProcessing) { + System.out.println(" French ligature processing : " + + dict0.mOptions.mFrenchLigatureProcessing + " <=> " + + dict1.mOptions.mFrenchLigatureProcessing); + } + else if (dict0.mOptions.mGermanUmlautProcessing != dict1.mOptions.mGermanUmlautProcessing) { + System.out.println(" German umlaut processing : " + + dict0.mOptions.mGermanUmlautProcessing + " <=> " + + dict1.mOptions.mGermanUmlautProcessing); + } + for (final String optionKey : dict0.mOptions.mAttributes.keySet()) { + if (!dict0.mOptions.mAttributes.get(optionKey).equals( + dict1.mOptions.mAttributes.get(optionKey))) { + System.out.println(" " + optionKey + " : " + + dict0.mOptions.mAttributes.get(optionKey) + " <=> " + + dict1.mOptions.mAttributes.get(optionKey)); + } + dict1.mOptions.mAttributes.remove(optionKey); + } + for (final String optionKey : dict1.mOptions.mAttributes.keySet()) { + System.out.println(" " + optionKey + " : null <=> " + + dict1.mOptions.mAttributes.get(optionKey)); + } + } +}