com.osfans.trime.DictionaryHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.osfans.trime.DictionaryHelper.java

Source

/*
 * Copyright 2010 Google Inc.
 *
 * 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.osfans.trime;

import java.io.*;
import java.util.Map;

import android.content.Context;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import android.text.format.Time;
import android.util.Log;

import android.content.Intent;
import android.app.PendingIntent;
import android.app.Notification;
import android.app.NotificationManager;
import android.support.v4.app.NotificationCompat;

import org.yaml.snakeyaml.Yaml;

public class DictionaryHelper extends SQLiteOpenHelper {

    private final Context mContext;
    private SQLiteDatabase mDatabase;
    private static final String DB_NAME = "trime.db";
    private static final File sd = new File("/sdcard");
    private static final File dbFile = new File("/data/data/com.osfans.trime/databases/", DB_NAME);
    private static final int DB_VER = 2;
    private static final int BLK_SIZE = 1024;
    private static final String fs = "...";
    private static final String comment = "#";
    private static final String newline = "\n";

    NotificationManager mNotifyManager;
    NotificationCompat.Builder mBuilder;
    PendingIntent pendingIntent;
    int notify_id = 1;

    DictionaryHelper(Context context) {
        super(context, DB_NAME, null, DB_VER);
        mContext = context;
        initProgress();
        loadAssetsDB();
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // mDatabase = db;
    }

    private void initProgress() {
        pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), Intent.FLAG_ACTIVITY_NEW_TASK);
        mNotifyManager = (NotificationManager) mContext.getSystemService(mContext.NOTIFICATION_SERVICE);
        mBuilder = new NotificationCompat.Builder(mContext).setContentIntent(pendingIntent)
                .setSmallIcon(R.drawable.smallicon);
    }

    private void loadAssetsDB() {
        if (dbFile.exists())
            return;
        try {
            dbFile.getParentFile().mkdir();
            mBuilder.setContentTitle(mContext.getString(R.string.initdb_message));
            copyDatabase(mContext.getAssets().open(DB_NAME), null);
        } catch (IOException e) {
            throw new RuntimeException("Error creating source database", e);
        }
    }

    static String[] getImportNames() {
        FilenameFilter ff = new FilenameFilter() {
            public boolean accept(File dir, String fn) {
                return fn.endsWith(".db") || fn.endsWith(".schema.yaml") || fn.endsWith(".dict.yaml");
            }
        };
        return sd.list(ff);
    }

    static String getExportName() {
        Time t = new Time();
        t.setToNow();
        return String.format("trime_%s.db", t.format2445());
    }

    private boolean copyDatabase(InputStream is, String s) {
        boolean success = false;
        mNotifyManager.notify(notify_id, mBuilder.build());
        try {
            if (is == null)
                is = new FileInputStream(dbFile);

            OutputStream os = null;
            if (s == null) {
                close();
                os = new FileOutputStream(dbFile);
            } else {
                os = new FileOutputStream(new File(sd, s));
            }

            int max = is.available();
            int count = 0;
            int progress = 0;
            byte[] buffer = new byte[BLK_SIZE];
            while (is.read(buffer) > 0) {
                os.write(buffer);
                count++;
                if ((count % 100) == 0) {
                    progress = count * BLK_SIZE;
                    mBuilder.setProgress(max, progress, false)
                            .setContentText(String.format("%d / 100", progress * 100 / max));
                    mNotifyManager.notify(notify_id, mBuilder.build());
                }
            }
            os.flush();
            os.close();
            is.close();
            success = true;
        } catch (Exception e) {
            throw new RuntimeException("Error copy database", e);
        } finally {
            mNotifyManager.cancel(notify_id);
        }
        return success;
    }

    private boolean importSchema(InputStream is) {
        boolean success = false;
        SQLiteDatabase db = getWritableDatabase();
        db.beginTransaction();
        try {
            Yaml yaml = new Yaml();
            Map<String, Object> y = (Map<String, Object>) (yaml.load(is));
            Map<String, Object> m = (Map<String, Object>) y.get("schema");
            String schema_id = (String) m.get("schema_id");
            String name = (String) m.get("name");
            String full = yaml.dump(y);
            is.close();

            ContentValues initialValues = new ContentValues();
            initialValues.put("schema_id", schema_id);
            initialValues.put("name", name);
            initialValues.put("full", full);

            long r = db.update("schema", initialValues, "schema_id = ?", new String[] { schema_id });
            if (r == 0)
                r = db.insert("schema", null, initialValues);
            db.setTransactionSuccessful();
            success = true;
        } catch (Exception e) {
            throw new RuntimeException("Error import schema", e);
        } finally {
            db.endTransaction();
        }
        return success;
    }

    private boolean importDict(InputStream is) {
        boolean success = false;
        SQLiteDatabase db = getWritableDatabase();
        db.beginTransaction();
        try {
            String line;
            StringBuilder content = new StringBuilder();
            InputStreamReader ir = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(ir);
            while ((line = br.readLine()) != null && !line.contentEquals(fs)) {
                content.append(line);
                content.append(newline);
            }

            Yaml yaml = new Yaml();
            Map<String, Object> y = (Map<String, Object>) (yaml.load(content.toString()));
            String table = (String) y.get("name");

            db.execSQL("DROP TABLE IF EXISTS " + table);
            db.execSQL(String.format("CREATE VIRTUAL TABLE %s USING fts3(hz, py)", table));

            ContentValues initialValues = new ContentValues(2);
            int max = is.available();
            int progress = 0;
            int count = 0;
            while ((line = br.readLine()) != null) {
                if (line.startsWith(comment))
                    continue;
                String[] s = line.split("\t");
                if (s.length < 2)
                    continue;
                initialValues.put("hz", s[0]);
                initialValues.put("py", s[1]);
                db.insert(table, null, initialValues);
                initialValues.clear();
                count++;
                if ((count % 1000) == 0) {
                    progress = max - is.available();
                    mBuilder.setProgress(max, progress, false)
                            .setContentText(String.format("%d / 100", progress * 100 / max));
                    mNotifyManager.notify(notify_id, mBuilder.build());
                }
            }
            is.close();
            db.setTransactionSuccessful();
            success = true;
        } catch (Exception e) {
            throw new RuntimeException("Error import dict", e);
        } finally {
            db.endTransaction();
            mNotifyManager.cancel(notify_id);
        }
        return success;
    }

    private void toast(String t, String s) {
        mBuilder.setContentTitle(t).setContentText(s).setProgress(0, 0, false);
        mNotifyManager.notify(notify_id, mBuilder.build());
    }

    public void importDatabase(final String s) {
        try {
            final InputStream is = new FileInputStream(new File(sd, s));
            mBuilder.setContentTitle(String.format(mContext.getString(R.string.importdb_message), s));
            if (s.endsWith(".db") || s.endsWith(".schema.yaml")) {
                boolean success = s.endsWith(".db") ? copyDatabase(is, null) : importSchema(is);
                if (success)
                    toast(mContext.getString(R.string.importdb_success), s);
                else
                    toast(mContext.getString(R.string.importdb_failure), s);
            } else if (s.endsWith(".dict.yaml")) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        boolean success = importDict(is);
                        if (success)
                            toast(mContext.getString(R.string.importdb_success), s);
                        else
                            toast(mContext.getString(R.string.importdb_failure), s);
                    }
                }).start();
            }
        } catch (Exception e) {
            throw new RuntimeException("Error import Database", e);
        }
    }

    public void exportDatabase(final String s) {
        mBuilder.setContentTitle(mContext.getString(R.string.exportdb_message));
        boolean success = copyDatabase(null, s);
        if (success)
            toast(mContext.getString(R.string.exportdb_success), s);
        else
            toast(mContext.getString(R.string.exportdb_failure), null);
    }
}