cz.muni.fi.japanesedictionary.engine.CharacterLoader.java Source code

Java tutorial

Introduction

Here is the source code for cz.muni.fi.japanesedictionary.engine.CharacterLoader.java

Source

/**
 *     JapaneseDictionary - an JMDict browser for Android
 Copyright (C) 2013 Jaroslav Klech
     
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
     
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
    
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package cz.muni.fi.japanesedictionary.engine;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.http.ParseException;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.cjk.CJKAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.util.Log;

import cz.muni.fi.japanesedictionary.Const;
import cz.muni.fi.japanesedictionary.entity.JapaneseCharacter;
import cz.muni.fi.japanesedictionary.fragments.DisplayTranslation;
import cz.muni.fi.japanesedictionary.parser.ParserService;

/**
 * AsyncTask loader for characters. Search for character info in background.
 * @author Jaroslav Klech
 *
 */
public class CharacterLoader extends AsyncTask<String, Void, Map<String, JapaneseCharacter>> {

    private Context mContext;
    private IndexSearcher mSearcher;
    private DisplayTranslation mFragment;

    private static final String LOG_TAG = "CharacterLoader";

    /**
     * Consturctor for CharacterLoader
     * @param _context environment context
     * @param _fragment Translation fragment to which characters are to be returned
     */
    public CharacterLoader(Context _context, DisplayTranslation _fragment) {
        mContext = _context;
        mFragment = _fragment;
    }

    /**
     * Searchs for japanese characters in KanjiDict2.
     * 
     * @param params string which contains characters
     * @return Map<String, JapaneseCharacter> if some characters were found returns map else null
     */
    @SuppressWarnings("MalformedRegex")
    @Override
    protected Map<String, JapaneseCharacter> doInBackground(String... params) {
        String characterList = params[0];
        if (characterList == null || characterList.length() < 1) {
            return null;
        }

        SharedPreferences settings = mContext.getSharedPreferences(ParserService.DICTIONARY_PREFERENCES, 0);
        String pathToDictionary = settings.getString(Const.PREF_KANJIDIC_PATH, null);
        if (pathToDictionary == null) {
            Log.e(LOG_TAG, "No path to kanjidict2 dictionary");
            return null;
        }
        File file = new File(pathToDictionary);
        if (file == null || !file.exists() || !file.canRead()) {
            Log.e(LOG_TAG, "Can't read dictionary directory");
            return null;
        }
        StringBuilder searchBuilder = new StringBuilder();
        final int characterListSize = characterList.length();
        // search string
        for (int i = 0; i < characterListSize; i++) {
            String character = String.valueOf(characterList.charAt(i));
            if (Pattern.matches("\\p{Han}", character)) {
                if (i > 0) { //searchBuilder.length() > 0
                    searchBuilder.append(' '); // in lucene space serve as OR
                }
                searchBuilder.append('"').append(character).append('"');
            }
        }
        String search = searchBuilder.toString();
        if (search.length() == 0) {
            return null;
        }

        Analyzer analyzer = new CJKAnalyzer(Version.LUCENE_36);
        try {
            QueryParser query = new QueryParser(Version.LUCENE_36, "literal", analyzer);
            query.setPhraseSlop(0);

            Query q = query.parse(search);
            if (mSearcher == null) {
                Directory dir = FSDirectory.open(file);
                IndexReader reader = IndexReader.open(dir);
                mSearcher = new IndexSearcher(reader);
            }
            TopScoreDocCollector collector = TopScoreDocCollector.create(100, true);
            mSearcher.search(q, collector);
            ScoreDoc[] hits = collector.topDocs().scoreDocs;

            Map<String, JapaneseCharacter> result = new HashMap<>();
            for (ScoreDoc document : hits) {
                int docId = document.doc;
                Document d = mSearcher.doc(docId);

                JapaneseCharacter japanCharacter = new JapaneseCharacter();
                String literal = d.get("literal");
                if (literal != null && literal.length() > 0) {
                    japanCharacter.setLiteral(literal);
                }
                String radicalClassic = d.get("radicalClassic");
                if (radicalClassic != null && radicalClassic.length() > 0) {
                    try {
                        int radicalClassicInt = Integer.parseInt(radicalClassic);
                        if (radicalClassicInt > 0) {
                            japanCharacter.setRadicalClassic(radicalClassicInt);
                        }
                    } catch (NumberFormatException ex) {
                        Log.w(LOG_TAG, "Couldn't parse radical-classical: " + radicalClassic);
                    }
                }
                String grade = d.get("grade");
                if (grade != null && grade.length() > 0) {
                    try {
                        int gradeInt = Integer.parseInt(grade);
                        if (gradeInt > 0) {
                            japanCharacter.setGrade(gradeInt);
                        }
                    } catch (NumberFormatException ex) {
                        Log.w(LOG_TAG, "Couldn't parse grade: " + grade);
                    }
                }
                String strokeCount = d.get("strokeCount");
                if (strokeCount != null && strokeCount.length() > 0) {
                    try {
                        int strokeCountInt = Integer.parseInt(strokeCount);
                        if (strokeCountInt > 0) {
                            japanCharacter.setStrokeCount(strokeCountInt);
                        }
                    } catch (NumberFormatException ex) {
                        Log.w(LOG_TAG, "Couldn't parse strokeCount: " + strokeCount);
                    }
                }

                String skip = d.get("queryCodeSkip");
                if (skip != null && skip.length() > 0) {
                    japanCharacter.setSkip(skip);
                }

                String dicRef = d.get("dicRef");
                if (dicRef != null && dicRef.length() > 0) {
                    japanCharacter.parseDicRef(dicRef);
                }

                String rmGroupJaOn = d.get("rmGroupJaOn");
                if (rmGroupJaOn != null && rmGroupJaOn.length() > 0) {
                    japanCharacter.parseRmGroupJaOn(rmGroupJaOn);
                }

                String rmGroupJaKun = d.get("rmGroupJaKun");
                if (rmGroupJaKun != null && rmGroupJaKun.length() > 0) {
                    japanCharacter.parseRmGroupJaKun(rmGroupJaKun);
                }

                String meaningEnglish = d.get("meaningEnglish");
                if (meaningEnglish != null && meaningEnglish.length() > 0) {
                    japanCharacter.parseMeaningEnglish(meaningEnglish);
                }

                String meaningFrench = d.get("meaningFrench");
                if (meaningFrench != null && meaningFrench.length() > 0) {
                    japanCharacter.parseMeaningFrench(meaningFrench);
                }

                String meaningDutch = d.get("meaningDutch");
                if (meaningDutch != null && meaningDutch.length() > 0) {
                    japanCharacter.parseMeaningDutch(meaningDutch);
                }

                String meaningGerman = d.get("meaningGerman");
                if (meaningGerman != null && meaningGerman.length() > 0) {
                    japanCharacter.parseMeaningGerman(meaningGerman);
                }

                String meaningRussian = d.get("meaningRussian");
                if (meaningRussian != null && meaningRussian.length() > 0) {
                    japanCharacter.parseMeaningRussian(meaningRussian);
                }

                String nanori = d.get("nanori");
                if (nanori != null && nanori.length() > 0) {
                    japanCharacter.parseNanori(nanori);
                }
                if (japanCharacter.getLiteral() != null && japanCharacter.getLiteral().length() > 0) {
                    result.put(japanCharacter.getLiteral(), japanCharacter);
                }
            }
            return result.size() > 0 ? result : null;

        } catch (ParseException ex) {
            Log.e(LOG_TAG, "Searching for charaters ParseException caught: " + ex);
        } catch (IOException ex) {
            Log.e(LOG_TAG, "Searching for charaters IOException caught: " + ex);
        } catch (Exception ex) {
            Log.e(LOG_TAG, "Searching for charaters Exception caught: " + ex);
        }

        return null;
    }

    /**
     * Called after loading is done. Runs in UI thread and sets characters to fragment.
     */
    @Override
    protected void onPostExecute(Map<String, JapaneseCharacter> result) {
        mFragment.setCharacters(result);

        super.onPostExecute(result);
    }

}