Home | History | Annotate | Download | only in debug
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.inputmethod.latin.debug;
     18 
     19 import android.app.AlertDialog;
     20 import android.content.Context;
     21 import android.content.DialogInterface;
     22 import android.content.DialogInterface.OnCancelListener;
     23 import android.content.DialogInterface.OnClickListener;
     24 import android.os.Environment;
     25 
     26 import com.android.inputmethod.latin.BinaryDictionaryFileDumper;
     27 import com.android.inputmethod.latin.BinaryDictionaryGetter;
     28 import com.android.inputmethod.latin.R;
     29 import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
     30 import com.android.inputmethod.latin.utils.CollectionUtils;
     31 import com.android.inputmethod.latin.utils.DictionaryInfoUtils;
     32 import com.android.inputmethod.latin.utils.LocaleUtils;
     33 
     34 import java.io.BufferedInputStream;
     35 import java.io.BufferedOutputStream;
     36 import java.io.File;
     37 import java.io.FileInputStream;
     38 import java.io.FileOutputStream;
     39 import java.io.IOException;
     40 import java.util.ArrayList;
     41 import java.util.Locale;
     42 
     43 /**
     44  * A class to read a local file as a dictionary for debugging purposes.
     45  */
     46 public class ExternalDictionaryGetterForDebug {
     47     private static final String SOURCE_FOLDER = Environment.getExternalStorageDirectory().getPath()
     48             + "/Download";
     49 
     50     private static String[] findDictionariesInTheDownloadedFolder() {
     51         final File[] files = new File(SOURCE_FOLDER).listFiles();
     52         final ArrayList<String> eligibleList = CollectionUtils.newArrayList();
     53         for (File f : files) {
     54             final FileHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(f);
     55             if (null == header) continue;
     56             eligibleList.add(f.getName());
     57         }
     58         return eligibleList.toArray(new String[0]);
     59     }
     60 
     61     public static void chooseAndInstallDictionary(final Context context) {
     62         final String[] fileNames = findDictionariesInTheDownloadedFolder();
     63         if (0 == fileNames.length) {
     64             showNoFileDialog(context);
     65         } else if (1 == fileNames.length) {
     66             askInstallFile(context, SOURCE_FOLDER, fileNames[0], null /* completeRunnable */);
     67         } else {
     68             showChooseFileDialog(context, fileNames);
     69         }
     70     }
     71 
     72     private static void showNoFileDialog(final Context context) {
     73         new AlertDialog.Builder(context)
     74                 .setMessage(R.string.read_external_dictionary_no_files_message)
     75                 .setPositiveButton(android.R.string.ok, new OnClickListener() {
     76                     @Override
     77                     public void onClick(final DialogInterface dialog, final int which) {
     78                         dialog.dismiss();
     79                     }
     80                 }).create().show();
     81     }
     82 
     83     private static void showChooseFileDialog(final Context context, final String[] fileNames) {
     84         final AlertDialog.Builder builder = new AlertDialog.Builder(context);
     85         builder.setTitle(R.string.read_external_dictionary_multiple_files_title)
     86                 .setItems(fileNames, new OnClickListener() {
     87                     @Override
     88                     public void onClick(final DialogInterface dialog, final int which) {
     89                         askInstallFile(context, SOURCE_FOLDER, fileNames[which],
     90                                 null /* completeRunnable */);
     91                     }
     92                 })
     93                 .create().show();
     94     }
     95 
     96     /**
     97      * Shows a dialog which offers the user to install the external dictionary.
     98      */
     99     public static void askInstallFile(final Context context, final String dirPath,
    100             final String fileName, final Runnable completeRunnable) {
    101         final File file = new File(dirPath, fileName.toString());
    102         final FileHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file);
    103         final StringBuilder message = new StringBuilder();
    104         final String locale = header.getLocaleString();
    105         for (String key : header.mDictionaryOptions.mAttributes.keySet()) {
    106             message.append(key + " = " + header.mDictionaryOptions.mAttributes.get(key));
    107             message.append("\n");
    108         }
    109         final String languageName = LocaleUtils.constructLocaleFromString(locale)
    110                 .getDisplayName(Locale.getDefault());
    111         final String title = String.format(
    112                 context.getString(R.string.read_external_dictionary_confirm_install_message),
    113                 languageName);
    114         new AlertDialog.Builder(context)
    115                 .setTitle(title)
    116                 .setMessage(message)
    117                 .setNegativeButton(android.R.string.cancel, new OnClickListener() {
    118                     @Override
    119                     public void onClick(final DialogInterface dialog, final int which) {
    120                         dialog.dismiss();
    121                         if (completeRunnable != null) {
    122                             completeRunnable.run();
    123                         }
    124                     }
    125                 }).setPositiveButton(android.R.string.ok, new OnClickListener() {
    126                     @Override
    127                     public void onClick(final DialogInterface dialog, final int which) {
    128                         installFile(context, file, header);
    129                         dialog.dismiss();
    130                         if (completeRunnable != null) {
    131                             completeRunnable.run();
    132                         }
    133                     }
    134                 }).setOnCancelListener(new OnCancelListener() {
    135                     @Override
    136                     public void onCancel(DialogInterface dialog) {
    137                         // Canceled by the user by hitting the back key
    138                         if (completeRunnable != null) {
    139                             completeRunnable.run();
    140                         }
    141                     }
    142                 }).create().show();
    143     }
    144 
    145     private static void installFile(final Context context, final File file,
    146             final FileHeader header) {
    147         BufferedOutputStream outputStream = null;
    148         File tempFile = null;
    149         try {
    150             final String locale = header.getLocaleString();
    151             // Create the id for a main dictionary for this locale
    152             final String id = BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY
    153                     + BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale;
    154             final String finalFileName = DictionaryInfoUtils.getCacheFileName(id, locale, context);
    155             final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context);
    156             tempFile = new File(tempFileName);
    157             tempFile.delete();
    158             outputStream = new BufferedOutputStream(new FileOutputStream(tempFile));
    159             final BufferedInputStream bufferedStream = new BufferedInputStream(
    160                     new FileInputStream(file));
    161             BinaryDictionaryFileDumper.checkMagicAndCopyFileTo(bufferedStream, outputStream);
    162             outputStream.flush();
    163             final File finalFile = new File(finalFileName);
    164             finalFile.delete();
    165             if (!tempFile.renameTo(finalFile)) {
    166                 throw new IOException("Can't move the file to its final name");
    167             }
    168         } catch (IOException e) {
    169             // There was an error: show a dialog
    170             new AlertDialog.Builder(context)
    171                     .setTitle(R.string.error)
    172                     .setMessage(e.toString())
    173                     .setPositiveButton(android.R.string.ok, new OnClickListener() {
    174                         @Override
    175                         public void onClick(final DialogInterface dialog, final int which) {
    176                             dialog.dismiss();
    177                         }
    178                     }).create().show();
    179             return;
    180         } finally {
    181             try {
    182                 if (null != outputStream) outputStream.close();
    183                 if (null != tempFile) tempFile.delete();
    184             } catch (IOException e) {
    185                 // Don't do anything
    186             }
    187         }
    188     }
    189 }
    190