From 3d72bc11d5ef9d58e62b5beb4e33a437da28d4b8 Mon Sep 17 00:00:00 2001 From: Thad Hughes Date: Thu, 26 Dec 2013 11:52:34 -0800 Subject: [PATCH] Auto-format everything. --- .../android/dictionary/AboutActivity.java | 16 +- .../dictionary/DictionaryActivity.java | 297 +++---- .../dictionary/DictionaryApplication.java | 774 +++++++++--------- .../android/dictionary/DictionaryInfo.java | 147 ++-- .../android/dictionary/DictionaryLink.java | 23 +- .../dictionary/DictionaryManagerActivity.java | 141 ++-- .../dictionary/HtmlDisplayActivity.java | 129 +-- .../hughes/android/dictionary/MyWebView.java | 9 +- .../dictionary/PreferenceActivity.java | 73 +- .../dictionary/engine/AbstractEntry.java | 44 +- .../android/dictionary/engine/Dictionary.java | 264 +++--- .../dictionary/engine/EntrySource.java | 90 +- .../dictionary/engine/EntryTypeName.java | 108 +-- .../android/dictionary/engine/HtmlEntry.java | 262 +++--- .../android/dictionary/engine/Index.java | 752 +++++++++-------- .../android/dictionary/engine/Language.java | 437 +++++----- .../engine/NormalizeComparator.java | 38 +- .../android/dictionary/engine/PairEntry.java | 375 ++++----- .../android/dictionary/engine/RowBase.java | 308 +++---- .../android/dictionary/engine/TextEntry.java | 125 +-- .../android/dictionary/engine/TokenRow.java | 102 +-- .../engine/TransliteratorManager.java | 88 +- .../hughes/android/util/IntentLauncher.java | 44 +- .../android/util/NonLinkClickableSpan.java | 4 +- .../android/util/PersistentObjectCache.java | 127 +-- 25 files changed, 2484 insertions(+), 2293 deletions(-) diff --git a/src/com/hughes/android/dictionary/AboutActivity.java b/src/com/hughes/android/dictionary/AboutActivity.java index 36fe640..863b997 100644 --- a/src/com/hughes/android/dictionary/AboutActivity.java +++ b/src/com/hughes/android/dictionary/AboutActivity.java @@ -19,15 +19,15 @@ import android.os.Bundle; public final class AboutActivity extends Activity { - public static final String CURRENT_DICT_INFO = "currentDictInfo"; + public static final String CURRENT_DICT_INFO = "currentDictInfo"; - /** Called when the activity is first created. */ - @Override - public void onCreate(final Bundle savedInstanceState) { - setTheme(((DictionaryApplication)getApplication()).getSelectedTheme().themeId); + /** Called when the activity is first created. */ + @Override + public void onCreate(final Bundle savedInstanceState) { + setTheme(((DictionaryApplication) getApplication()).getSelectedTheme().themeId); - super.onCreate(savedInstanceState); - setContentView(R.layout.about_activity); - } + super.onCreate(savedInstanceState); + setContentView(R.layout.about_activity); + } } diff --git a/src/com/hughes/android/dictionary/DictionaryActivity.java b/src/com/hughes/android/dictionary/DictionaryActivity.java index ed50824..5d0c9c6 100644 --- a/src/com/hughes/android/dictionary/DictionaryActivity.java +++ b/src/com/hughes/android/dictionary/DictionaryActivity.java @@ -124,7 +124,7 @@ public class DictionaryActivity extends SherlockListActivity { List rowsToShow = null; // if not null, just show these rows. final Handler uiHandler = new Handler(); - + private final Executor searchExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable r) { @@ -179,7 +179,7 @@ public class DictionaryActivity extends SherlockListActivity { @Override protected void onSaveInstanceState(final Bundle outState) { - super.onSaveInstanceState(outState); + super.onSaveInstanceState(outState); Log.d(LOG, "onSaveInstanceState: " + searchView.getQuery().toString()); outState.putString(C.INDEX_SHORT_NAME, index.shortName); outState.putString(C.SEARCH_TOKEN, searchView.getQuery().toString()); @@ -196,11 +196,11 @@ public class DictionaryActivity extends SherlockListActivity { public void onCreate(Bundle savedInstanceState) { Log.d(LOG, "onCreate:" + this); super.onCreate(savedInstanceState); - + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - + // Don't auto-launch if this fails. - prefs.edit().remove(C.DICT_FILE).commit(); + prefs.edit().remove(C.DICT_FILE).commit(); setTheme(((DictionaryApplication) getApplication()).getSelectedTheme().themeId); @@ -211,89 +211,97 @@ public class DictionaryActivity extends SherlockListActivity { final Intent intent = getIntent(); String intentAction = intent.getAction(); /** - * @author Dominik Köppl - * Querying the Intent - * com.hughes.action.ACTION_SEARCH_DICT is the advanced query - * Arguments: - * SearchManager.QUERY -> the phrase to search - * from -> language in which the phrase is written - * to -> to which language shall be translated + * @author Dominik Köppl Querying the Intent + * com.hughes.action.ACTION_SEARCH_DICT is the advanced query + * Arguments: SearchManager.QUERY -> the phrase to search from + * -> language in which the phrase is written to -> to which + * language shall be translated */ - if(intentAction != null && intentAction.equals("com.hughes.action.ACTION_SEARCH_DICT")) + if (intentAction != null && intentAction.equals("com.hughes.action.ACTION_SEARCH_DICT")) { - String query = intent.getStringExtra(SearchManager.QUERY); - String from = intent.getStringExtra("from"); - if(from != null) from = from.toLowerCase(Locale.US); - String to = intent.getStringExtra("to"); - if(to != null) to = to.toLowerCase(Locale.US); - if(query != null) - { - getIntent().putExtra(C.SEARCH_TOKEN, query); - } - if(intent.getStringExtra(C.DICT_FILE) == null && (from != null || to != null)) - { - Log.d(LOG, "DictSearch: from: " + from + " to " + to); - List dicts = application.getDictionariesOnDevice(null); - for(DictionaryInfo info : dicts) - { - boolean hasFrom = from == null; - boolean hasTo = to == null; - for(IndexInfo index : info.indexInfos) - { - if(!hasFrom && index.shortName.toLowerCase(Locale.US).equals(from)) hasFrom = true; - if(!hasTo && index.shortName.toLowerCase(Locale.US).equals(to)) hasTo = true; - } - if(hasFrom && hasTo) - { - if(from != null) - { - int which_index = 0; - for(;which_index < info.indexInfos.size(); ++which_index) - { - if(info.indexInfos.get(which_index).shortName.toLowerCase(Locale.US).equals(from)) - break; - } - intent.putExtra(C.INDEX_SHORT_NAME, info.indexInfos.get(which_index).shortName); - - } - intent.putExtra(C.DICT_FILE, application.getPath(info.uncompressedFilename).toString()); - break; - } - } - - } + String query = intent.getStringExtra(SearchManager.QUERY); + String from = intent.getStringExtra("from"); + if (from != null) + from = from.toLowerCase(Locale.US); + String to = intent.getStringExtra("to"); + if (to != null) + to = to.toLowerCase(Locale.US); + if (query != null) + { + getIntent().putExtra(C.SEARCH_TOKEN, query); + } + if (intent.getStringExtra(C.DICT_FILE) == null && (from != null || to != null)) + { + Log.d(LOG, "DictSearch: from: " + from + " to " + to); + List dicts = application.getDictionariesOnDevice(null); + for (DictionaryInfo info : dicts) + { + boolean hasFrom = from == null; + boolean hasTo = to == null; + for (IndexInfo index : info.indexInfos) + { + if (!hasFrom && index.shortName.toLowerCase(Locale.US).equals(from)) + hasFrom = true; + if (!hasTo && index.shortName.toLowerCase(Locale.US).equals(to)) + hasTo = true; + } + if (hasFrom && hasTo) + { + if (from != null) + { + int which_index = 0; + for (; which_index < info.indexInfos.size(); ++which_index) + { + if (info.indexInfos.get(which_index).shortName.toLowerCase( + Locale.US).equals(from)) + break; + } + intent.putExtra(C.INDEX_SHORT_NAME, + info.indexInfos.get(which_index).shortName); + + } + intent.putExtra(C.DICT_FILE, application.getPath(info.uncompressedFilename) + .toString()); + break; + } + } + + } } /** - * @author Dominik Köppl - * Querying the Intent - * Intent.ACTION_SEARCH is a simple query - * Arguments follow from android standard (see documentation) + * @author Dominik Köppl Querying the Intent Intent.ACTION_SEARCH is a + * simple query Arguments follow from android standard (see + * documentation) */ - if (intentAction != null && intentAction.equals(Intent.ACTION_SEARCH)) + if (intentAction != null && intentAction.equals(Intent.ACTION_SEARCH)) { String query = intent.getStringExtra(SearchManager.QUERY); - if(query != null) getIntent().putExtra(C.SEARCH_TOKEN,query); + if (query != null) + getIntent().putExtra(C.SEARCH_TOKEN, query); } /** - * @author Dominik Köppl - * If no dictionary is chosen, use the default dictionary specified in the preferences - * If this step does fail (no default directory specified), show a toast and abort. + * @author Dominik Köppl If no dictionary is chosen, use the default + * dictionary specified in the preferences If this step does + * fail (no default directory specified), show a toast and + * abort. */ - if(intent.getStringExtra(C.DICT_FILE) == null) + if (intent.getStringExtra(C.DICT_FILE) == null) { - String dictfile = prefs.getString(getString(R.string.defaultDicKey), null); - if(dictfile != null) intent.putExtra(C.DICT_FILE, application.getPath(dictfile).toString()); + String dictfile = prefs.getString(getString(R.string.defaultDicKey), null); + if (dictfile != null) + intent.putExtra(C.DICT_FILE, application.getPath(dictfile).toString()); } String dictFilename = intent.getStringExtra(C.DICT_FILE); - - if(dictFilename == null) + + if (dictFilename == null) { Toast.makeText(this, getString(R.string.no_dict_file), Toast.LENGTH_LONG).show(); startActivity(DictionaryManagerActivity.getLaunchIntent()); finish(); return; } - if(dictFilename != null) dictFile = new File(dictFilename); + if (dictFilename != null) + dictFile = new File(dictFilename); ttsReady = false; textToSpeech = new TextToSpeech(getApplicationContext(), new OnInitListener() { @@ -303,7 +311,7 @@ public class DictionaryActivity extends SherlockListActivity { updateTTSLanguage(); } }); - + try { final String name = application.getDictionaryName(dictFile.getName()); this.setTitle("QuickDic: " + name); @@ -411,7 +419,7 @@ public class DictionaryActivity extends SherlockListActivity { Log.d(LOG, "wordList=" + wordList + ", saveOnlyFirstSubentry=" + saveOnlyFirstSubentry); onCreateSetupActionBarAndSearchView(); - + // Set the search text from the intent, then the saved state. String text = getIntent().getStringExtra(C.SEARCH_TOKEN); if (savedInstanceState != null) { @@ -432,7 +440,7 @@ public class DictionaryActivity extends SherlockListActivity { private void onCreateSetupActionBarAndSearchView() { ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayShowTitleEnabled(false); - + searchView = new SearchView(getSupportActionBar().getThemedContext()); searchView.setIconifiedByDefault(false); // searchView.setIconified(false); // puts the magnifying glass in the @@ -560,7 +568,7 @@ public class DictionaryActivity extends SherlockListActivity { private void showKeyboard() { // For some reason, this doesn't always work the first time. // One way to replicate the problem: - // Press the "task switch" button repeatedly to pause and resume + // Press the "task switch" button repeatedly to pause and resume for (int delay = 1; delay <= 101; delay += 100) { searchView.postDelayed(new Runnable() { @Override @@ -573,7 +581,8 @@ public class DictionaryActivity extends SherlockListActivity { if (!searchTextHadFocus) { defocusSearchText(); } - }}, delay); + } + }, delay); } } @@ -590,7 +599,7 @@ public class DictionaryActivity extends SherlockListActivity { } } updateTTSLanguage(); - } + } private void updateTTSLanguage() { if (!ttsReady || index == null || textToSpeech == null) { @@ -600,8 +609,8 @@ public class DictionaryActivity extends SherlockListActivity { final Locale locale = new Locale(index.sortLanguage.getIsoCode()); Log.d(LOG, "Setting TTS locale to: " + locale); final int ttsResult = textToSpeech.setLanguage(locale); - if (ttsResult != TextToSpeech.LANG_AVAILABLE || - ttsResult != TextToSpeech.LANG_COUNTRY_AVAILABLE) { + if (ttsResult != TextToSpeech.LANG_AVAILABLE || + ttsResult != TextToSpeech.LANG_COUNTRY_AVAILABLE) { Log.e(LOG, "TTS not available in this language: ttsResult=" + ttsResult); } } @@ -615,7 +624,7 @@ public class DictionaryActivity extends SherlockListActivity { currentSearchOperation.interrupted.set(true); currentSearchOperation = null; } - setIndexAndSearchText((indexIndex + 1) % dictionary.indices.size(), + setIndexAndSearchText((indexIndex + 1) % dictionary.indices.size(), searchView.getQuery().toString()); } @@ -650,7 +659,8 @@ public class DictionaryActivity extends SherlockListActivity { for (int i = 0; i < dictionaryInfo.indexInfos.size(); ++i) { final IndexInfo indexInfo = dictionaryInfo.indexInfos.get(i); - final View button = application.createButton(parent.getContext(), dictionaryInfo, indexInfo); + final View button = application.createButton(parent.getContext(), + dictionaryInfo, indexInfo); final IntentLauncher intentLauncher = new IntentLauncher(parent.getContext(), getLaunchIntent( application.getPath(dictionaryInfo.uncompressedFilename), @@ -726,35 +736,35 @@ public class DictionaryActivity extends SherlockListActivity { // -------------------------------------------------------------------------- final Random random = new Random(); - + @Override public boolean onCreateOptionsMenu(final Menu menu) { - + if (PreferenceManager.getDefaultSharedPreferences(this) .getBoolean(getString(R.string.showPrevNextButtonsKey), true)) { // Next word. nextWordMenuItem = menu.add(getString(R.string.nextWord)) - .setIcon(R.drawable.arrow_down_float); + .setIcon(R.drawable.arrow_down_float); nextWordMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); nextWordMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - onUpDownButton(false); - return true; - } - }); - + @Override + public boolean onMenuItemClick(MenuItem item) { + onUpDownButton(false); + return true; + } + }); + // Previous word. previousWordMenuItem = menu.add(getString(R.string.previousWord)) - .setIcon(R.drawable.arrow_up_float); + .setIcon(R.drawable.arrow_up_float); previousWordMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); previousWordMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - onUpDownButton(true); - return true; - } - }); + @Override + public boolean onMenuItemClick(MenuItem item) { + onUpDownButton(true); + return true; + } + }); } application.onCreateGlobalOptionsMenu(this, menu); @@ -839,20 +849,23 @@ public class DictionaryActivity extends SherlockListActivity { final android.view.MenuItem addToWordlist = menu.add(getString(R.string.addToWordList, wordList.getName())); - addToWordlist.setOnMenuItemClickListener(new android.view.MenuItem.OnMenuItemClickListener() { - public boolean onMenuItemClick(android.view.MenuItem item) { - onAppendToWordList(row); - return false; - } - }); + addToWordlist + .setOnMenuItemClickListener(new android.view.MenuItem.OnMenuItemClickListener() { + public boolean onMenuItemClick(android.view.MenuItem item) { + onAppendToWordList(row); + return false; + } + }); final android.view.MenuItem share = menu.add("Share"); share.setOnMenuItemClickListener(new android.view.MenuItem.OnMenuItemClickListener() { public boolean onMenuItemClick(android.view.MenuItem item) { Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND); shareIntent.setType("text/plain"); - shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, row.getTokenRow(true).getToken()); - shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, row.getRawText(saveOnlyFirstSubentry)); + shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, row.getTokenRow(true) + .getToken()); + shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, + row.getRawText(saveOnlyFirstSubentry)); startActivity(shareIntent); return false; } @@ -868,14 +881,16 @@ public class DictionaryActivity extends SherlockListActivity { if (selectedSpannableText != null) { final String selectedText = selectedSpannableText; - final android.view.MenuItem searchForSelection = menu.add(getString(R.string.searchForSelection, + final android.view.MenuItem searchForSelection = menu.add(getString( + R.string.searchForSelection, selectedSpannableText)); - searchForSelection.setOnMenuItemClickListener(new android.view.MenuItem.OnMenuItemClickListener() { - public boolean onMenuItemClick(android.view.MenuItem item) { - jumpToTextFromHyperLink(selectedText, selectedSpannableIndex); - return false; - } - }); + searchForSelection + .setOnMenuItemClickListener(new android.view.MenuItem.OnMenuItemClickListener() { + public boolean onMenuItemClick(android.view.MenuItem item) { + jumpToTextFromHyperLink(selectedText, selectedSpannableIndex); + return false; + } + }); } if (row instanceof TokenRow && ttsReady) { @@ -924,7 +939,7 @@ public class DictionaryActivity extends SherlockListActivity { } }, 100); } - + /** * Called when user clicks outside of search text, so that they can start * typing again immediately. @@ -937,7 +952,7 @@ public class DictionaryActivity extends SherlockListActivity { // Visual indication that a new keystroke will clear the search text. // Doesn't seem to work unless earchText has focus. -// searchView.selectAll(); + // searchView.selectAll(); } @Override @@ -1009,7 +1024,7 @@ public class DictionaryActivity extends SherlockListActivity { } return super.onKeyDown(keyCode, event); } - + private void setIndexAndSearchText(int newIndex, String newSearchText) { Log.d(LOG, "Changing index to: " + newIndex); if (newIndex == -1) { @@ -1040,21 +1055,22 @@ public class DictionaryActivity extends SherlockListActivity { } } -// private long cursorDelayMillis = 100; + // private long cursorDelayMillis = 100; private void moveCursorToRight() { -// if (searchText.getLayout() != null) { -// cursorDelayMillis = 100; -// // Surprising, but this can crash when you rotate... -// Selection.moveToRightEdge(searchView.getQuery(), searchText.getLayout()); -// } else { -// uiHandler.postDelayed(new Runnable() { -// @Override -// public void run() { -// moveCursorToRight(); -// } -// }, cursorDelayMillis); -// cursorDelayMillis = Math.min(10 * 1000, 2 * cursorDelayMillis); -// } + // if (searchText.getLayout() != null) { + // cursorDelayMillis = 100; + // // Surprising, but this can crash when you rotate... + // Selection.moveToRightEdge(searchView.getQuery(), + // searchText.getLayout()); + // } else { + // uiHandler.postDelayed(new Runnable() { + // @Override + // public void run() { + // moveCursorToRight(); + // } + // }, cursorDelayMillis); + // cursorDelayMillis = Math.min(10 * 1000, 2 * cursorDelayMillis); + // } } // -------------------------------------------------------------------------- @@ -1099,7 +1115,7 @@ public class DictionaryActivity extends SherlockListActivity { private final void jumpToRow(final int row) { Log.d(LOG, "jumpToRow: " + row + ", refocusSearchText=" + false); -// getListView().requestFocusFromTouch(); + // getListView().requestFocusFromTouch(); getListView().setSelectionFromTop(row, 0); getListView().setSelected(true); } @@ -1142,7 +1158,8 @@ public class DictionaryActivity extends SherlockListActivity { searchResult = index.findInsertionPoint(searchText, interrupted); } else { searchTokens = Arrays.asList(searchTokenArray); - multiWordSearchResult = index.multiWordSearch(searchText, searchTokens, interrupted); + multiWordSearchResult = index.multiWordSearch(searchText, searchTokens, + interrupted); } Log.d(LOG, "searchText=" + searchText + ", searchDuration=" @@ -1369,7 +1386,7 @@ public class DictionaryActivity extends SherlockListActivity { 0); textView.setOnLongClickListener(textViewLongClickListenerIndex0); result.setLongClickable(true); - + // Doesn't work: // textView.setTextColor(android.R.color.secondary_text_light); textView.setTypeface(typeface); @@ -1391,7 +1408,8 @@ public class DictionaryActivity extends SherlockListActivity { public void onClick(View widget) { } }; - ((Spannable) textView.getText()).setSpan(clickableSpan, 0, text.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); + ((Spannable) textView.getText()).setSpan(clickableSpan, 0, text.length(), + Spannable.SPAN_INCLUSIVE_INCLUSIVE); result.setClickable(true); textView.setClickable(true); textView.setMovementMethod(LinkMovementMethod.getInstance()); @@ -1399,7 +1417,7 @@ public class DictionaryActivity extends SherlockListActivity { @Override public void onClick(View v) { String html = HtmlEntry.htmlBody(htmlEntries, index.shortName); - //Log.d(LOG, "html=" + html); + // Log.d(LOG, "html=" + html); startActivityForResult( HtmlDisplayActivity.getHtmlIntent(String.format( "%s", html), @@ -1429,7 +1447,7 @@ public class DictionaryActivity extends SherlockListActivity { } static final Pattern CHAR_DASH = Pattern.compile("['\\p{L}\\p{M}\\p{N}]+"); - + private void createTokenLinkSpans(final TextView textView, final Spannable spannable, final String text) { // Saw from the source code that LinkMovementMethod sets the selection! @@ -1437,7 +1455,8 @@ public class DictionaryActivity extends SherlockListActivity { textView.setMovementMethod(LinkMovementMethod.getInstance()); final Matcher matcher = CHAR_DASH.matcher(text); while (matcher.find()) { - spannable.setSpan(new NonLinkClickableSpan(textColorFg), matcher.start(), matcher.end(), + spannable.setSpan(new NonLinkClickableSpan(textColorFg), matcher.start(), + matcher.end(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); } } @@ -1503,10 +1522,10 @@ public class DictionaryActivity extends SherlockListActivity { Log.d(LOG, "searchText changed during shutdown, doing nothing."); return; } -// if (!searchView.hasFocus()) { -// Log.d(LOG, "searchText changed without focus, doing nothing."); -// return; -// } + // if (!searchView.hasFocus()) { + // Log.d(LOG, "searchText changed without focus, doing nothing."); + // return; + // } Log.d(LOG, "onSearchTextChange: " + text); if (currentSearchOperation != null) { Log.d(LOG, "Interrupting currentSearchOperation."); diff --git a/src/com/hughes/android/dictionary/DictionaryApplication.java b/src/com/hughes/android/dictionary/DictionaryApplication.java index 30d8067..9c068a8 100644 --- a/src/com/hughes/android/dictionary/DictionaryApplication.java +++ b/src/com/hughes/android/dictionary/DictionaryApplication.java @@ -59,403 +59,429 @@ import java.util.Locale; import java.util.Map; public class DictionaryApplication extends Application { - - static final String LOG = "QuickDicApp"; - - // Static, determined by resources (and locale). - // Unordered. - static Map DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO = null; - - static final class DictionaryConfig implements Serializable { - private static final long serialVersionUID = -1444177164708201263L; - // User-ordered list, persisted, just the ones that are/have been present. - final List dictionaryFilesOrdered = new ArrayList(); - - final Map uncompressedFilenameToDictionaryInfo = new LinkedHashMap(); - } - DictionaryConfig dictionaryConfig = null; - - - int languageButtonPixels = 22; - -// static final class DictionaryHistory implements Serializable { -// private static final long serialVersionUID = -4842995032541390284L; -// // User-ordered list, persisted, just the ones that are/have been present. -// final List dictionaryLinks = new ArrayList(); -// } -// DictionaryHistory dictionaryHistory = null; - - static synchronized void staticInit(final Context context) { - if (DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO != null) { - return; + + static final String LOG = "QuickDicApp"; + + // Static, determined by resources (and locale). + // Unordered. + static Map DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO = null; + + static final class DictionaryConfig implements Serializable { + private static final long serialVersionUID = -1444177164708201263L; + // User-ordered list, persisted, just the ones that are/have been + // present. + final List dictionaryFilesOrdered = new ArrayList(); + + final Map uncompressedFilenameToDictionaryInfo = new LinkedHashMap(); } - DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO = new LinkedHashMap(); - final BufferedReader reader = new BufferedReader( - new InputStreamReader(context.getResources().openRawResource(R.raw.dictionary_info))); - try { - String line; - while ((line = reader.readLine()) != null) { - if (line.startsWith("#") || line.length() == 0) { - continue; + + DictionaryConfig dictionaryConfig = null; + + int languageButtonPixels = 22; + + // static final class DictionaryHistory implements Serializable { + // private static final long serialVersionUID = -4842995032541390284L; + // // User-ordered list, persisted, just the ones that are/have been + // present. + // final List dictionaryLinks = new + // ArrayList(); + // } + // DictionaryHistory dictionaryHistory = null; + + static synchronized void staticInit(final Context context) { + if (DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO != null) { + return; + } + DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO = new LinkedHashMap(); + final BufferedReader reader = new BufferedReader( + new InputStreamReader(context.getResources().openRawResource(R.raw.dictionary_info))); + try { + String line; + while ((line = reader.readLine()) != null) { + if (line.startsWith("#") || line.length() == 0) { + continue; + } + final DictionaryInfo dictionaryInfo = new DictionaryInfo(line); + DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.put( + dictionaryInfo.uncompressedFilename, dictionaryInfo); + } + reader.close(); + } catch (IOException e) { + Log.e(LOG, "Failed to load downloadable dictionary lists.", e); } - final DictionaryInfo dictionaryInfo = new DictionaryInfo(line); - DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.put( - dictionaryInfo.uncompressedFilename, dictionaryInfo); - } - reader.close(); - } catch (IOException e) { - Log.e(LOG, "Failed to load downloadable dictionary lists.", e); } - } - - - private File dictDir; - - @Override - public void onCreate() { - super.onCreate(); - Log.d("QuickDic", "Application: onCreate"); - TransliteratorManager.init(null); - staticInit(getApplicationContext()); - - languageButtonPixels = (int) TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, 60, getResources().getDisplayMetrics()); - - // Load the dictionaries we know about. - dictionaryConfig = PersistentObjectCache.init(getApplicationContext()).read( - C.DICTIONARY_CONFIGS, DictionaryConfig.class); - if (dictionaryConfig == null) { - dictionaryConfig = new DictionaryConfig(); + + private File dictDir; + + @Override + public void onCreate() { + super.onCreate(); + Log.d("QuickDic", "Application: onCreate"); + TransliteratorManager.init(null); + staticInit(getApplicationContext()); + + languageButtonPixels = (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, 60, getResources().getDisplayMetrics()); + + // Load the dictionaries we know about. + dictionaryConfig = PersistentObjectCache.init(getApplicationContext()).read( + C.DICTIONARY_CONFIGS, DictionaryConfig.class); + if (dictionaryConfig == null) { + dictionaryConfig = new DictionaryConfig(); + } + + // Theme stuff. + setTheme(getSelectedTheme().themeId); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + prefs.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + Log.d("QuickDic", "prefs changed: " + key); + if (key.equals(getString(R.string.themeKey))) { + setTheme(getSelectedTheme().themeId); + } + } + }); } - - // Theme stuff. - setTheme(getSelectedTheme().themeId); - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - prefs.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() { - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, - String key) { - Log.d("QuickDic", "prefs changed: " + key); - if (key.equals(getString(R.string.themeKey))) { - setTheme(getSelectedTheme().themeId); + + public void onCreateGlobalOptionsMenu( + final Context context, final Menu menu) { + final MenuItem about = menu.add(getString(R.string.about)); + about.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); + about.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(final MenuItem menuItem) { + final Intent intent = new Intent().setClassName(AboutActivity.class + .getPackage().getName(), AboutActivity.class.getCanonicalName()); + context.startActivity(intent); + return false; + } + }); + + final MenuItem help = menu.add(getString(R.string.help)); + help.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); + help.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(final MenuItem menuItem) { + context.startActivity(HtmlDisplayActivity.getHelpLaunchIntent()); + return false; + } + }); + + final MenuItem preferences = menu.add(getString(R.string.settings)); + preferences.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); + preferences.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(final MenuItem menuItem) { + PreferenceActivity.prefsMightHaveChanged = true; + final Intent intent = new Intent().setClassName(PreferenceActivity.class + .getPackage().getName(), PreferenceActivity.class.getCanonicalName()); + context.startActivity(intent); + return false; + } + }); + + final MenuItem reportIssue = menu.add(getString(R.string.reportIssue)); + reportIssue.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); + reportIssue.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(final MenuItem menuItem) { + final Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri + .parse("http://code.google.com/p/quickdic-dictionary/issues/entry")); + context.startActivity(intent); + return false; + } + }); + } + + public synchronized File getDictDir() { + // This metaphor doesn't work, because we've already reset + // prefsMightHaveChanged. + // if (dictDir == null || PreferenceActivity.prefsMightHaveChanged) { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + final File defaultDictDir = new File(Environment.getExternalStorageDirectory(), "quickDic"); + String dir = prefs.getString(getString(R.string.quickdicDirectoryKey), + defaultDictDir.getAbsolutePath()); + if (dir.isEmpty()) { + dir = defaultDictDir.getAbsolutePath(); } - } - }); - } - - public void onCreateGlobalOptionsMenu( - final Context context, final Menu menu) { - final MenuItem about = menu.add(getString(R.string.about)); - about.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - about.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(final MenuItem menuItem) { - final Intent intent = new Intent().setClassName(AboutActivity.class - .getPackage().getName(), AboutActivity.class.getCanonicalName()); - context.startActivity(intent); - return false; - } - }); - - final MenuItem help = menu.add(getString(R.string.help)); - help.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - help.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(final MenuItem menuItem) { - context.startActivity(HtmlDisplayActivity.getHelpLaunchIntent()); - return false; - } - }); - - final MenuItem preferences = menu.add(getString(R.string.settings)); - preferences.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - preferences.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(final MenuItem menuItem) { - PreferenceActivity.prefsMightHaveChanged = true; - final Intent intent = new Intent().setClassName(PreferenceActivity.class - .getPackage().getName(), PreferenceActivity.class.getCanonicalName()); - context.startActivity(intent); - return false; - } - }); - - - final MenuItem reportIssue = menu.add(getString(R.string.reportIssue)); - reportIssue.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - reportIssue.setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(final MenuItem menuItem) { - final Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(Uri.parse("http://code.google.com/p/quickdic-dictionary/issues/entry")); - context.startActivity(intent); - return false; - } - }); - } - - public synchronized File getDictDir() { - // This metaphor doesn't work, because we've already reset prefsMightHaveChanged. -// if (dictDir == null || PreferenceActivity.prefsMightHaveChanged) { - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - final File defaultDictDir = new File(Environment.getExternalStorageDirectory(), "quickDic"); - String dir = prefs.getString(getString(R.string.quickdicDirectoryKey), defaultDictDir.getAbsolutePath()); - if (dir.isEmpty()) { - dir = defaultDictDir.getAbsolutePath(); - } - dictDir = new File(dir); - dictDir.mkdirs(); - return dictDir; - } - - public C.Theme getSelectedTheme() { - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - final String theme = prefs.getString(getString(R.string.themeKey), "themeLight"); - if (theme.equals("themeLight")) { - return C.Theme.LIGHT; - } else { - return C.Theme.DEFAULT; + dictDir = new File(dir); + dictDir.mkdirs(); + return dictDir; } - } - - public File getPath(String uncompressedFilename) { - return new File(getDictDir(), uncompressedFilename); - } - - - String defaultLangISO2 = Locale.getDefault().getLanguage().toLowerCase(); - String defaultLangName = null; - final Map fileToNameCache = new LinkedHashMap(); - - public String isoCodeToLocalizedLanguageName(final String isoCode) { - final Language.LanguageResources languageResources = Language.isoCodeToResources.get(isoCode); - final String lang = languageResources != null ? getApplicationContext().getString(languageResources.nameId) : isoCode; - return lang; - } - - public List sortedIndexInfos(List indexInfos) { - // Hack to put the default locale first in the name. - if (indexInfos.size() > 1 && - indexInfos.get(1).shortName.toLowerCase().equals(defaultLangISO2)) { - List result = new ArrayList(indexInfos); - ListUtil.swap(result, 0, 1); - return result; - } - return indexInfos; - } - - - public synchronized String getDictionaryName(final String uncompressedFilename) { - final String currentLocale = Locale.getDefault().getLanguage().toLowerCase(); - if (!currentLocale.equals(defaultLangISO2)) { - defaultLangISO2 = currentLocale; - fileToNameCache.clear(); - defaultLangName = null; + + public C.Theme getSelectedTheme() { + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + final String theme = prefs.getString(getString(R.string.themeKey), "themeLight"); + if (theme.equals("themeLight")) { + return C.Theme.LIGHT; + } else { + return C.Theme.DEFAULT; + } } - if (defaultLangName == null) { - defaultLangName = isoCodeToLocalizedLanguageName(defaultLangISO2); + + public File getPath(String uncompressedFilename) { + return new File(getDictDir(), uncompressedFilename); } - - String name = fileToNameCache.get(uncompressedFilename); - if (name != null) { - return name; + + String defaultLangISO2 = Locale.getDefault().getLanguage().toLowerCase(); + String defaultLangName = null; + final Map fileToNameCache = new LinkedHashMap(); + + public String isoCodeToLocalizedLanguageName(final String isoCode) { + final Language.LanguageResources languageResources = Language.isoCodeToResources + .get(isoCode); + final String lang = languageResources != null ? getApplicationContext().getString( + languageResources.nameId) : isoCode; + return lang; } - - final DictionaryInfo dictionaryInfo = DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.get(uncompressedFilename); - if (dictionaryInfo != null) { - final StringBuilder nameBuilder = new StringBuilder(); - - List sortedIndexInfos = sortedIndexInfos(dictionaryInfo.indexInfos); - for (int i = 0; i < sortedIndexInfos.size(); ++i) { - if (i > 0) { - nameBuilder.append("-"); + + public List sortedIndexInfos(List indexInfos) { + // Hack to put the default locale first in the name. + if (indexInfos.size() > 1 && + indexInfos.get(1).shortName.toLowerCase().equals(defaultLangISO2)) { + List result = new ArrayList(indexInfos); + ListUtil.swap(result, 0, 1); + return result; } - nameBuilder.append(isoCodeToLocalizedLanguageName(sortedIndexInfos.get(i).shortName)); - } - name = nameBuilder.toString(); - } else { - name = uncompressedFilename.replace(".quickdic", ""); + return indexInfos; } - fileToNameCache.put(uncompressedFilename, name); - return name; - } - - public View createButton(final Context context, final DictionaryInfo dictionaryInfo, - final IndexInfo indexInfo) { - LanguageResources languageResources = Language.isoCodeToResources.get(indexInfo.shortName); - View result; - - if (languageResources == null || languageResources.flagId <= 0) { - Button button = new Button(context); - button.setText(indexInfo.shortName); - result = button; - } else { - ImageButton button = new ImageButton(context); - button.setImageResource(languageResources.flagId); - button.setScaleType(ScaleType.FIT_CENTER); - result = button; - } - result.setMinimumWidth(languageButtonPixels); - result.setMinimumHeight(languageButtonPixels * 2 / 3); -// result.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); - return result; - } - - - public synchronized void moveDictionaryToTop(final DictionaryInfo dictionaryInfo) { - dictionaryConfig.dictionaryFilesOrdered.remove(dictionaryInfo.uncompressedFilename); - dictionaryConfig.dictionaryFilesOrdered.add(0, dictionaryInfo.uncompressedFilename); - PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); - } - - public synchronized void deleteDictionary(final DictionaryInfo dictionaryInfo) { - while (dictionaryConfig.dictionaryFilesOrdered.remove(dictionaryInfo.uncompressedFilename)) {}; - dictionaryConfig.uncompressedFilenameToDictionaryInfo.remove(dictionaryInfo.uncompressedFilename); - getPath(dictionaryInfo.uncompressedFilename).delete(); - PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); - } - - final Collator collator = Collator.getInstance(); - final Comparator uncompressedFilenameComparator = new Comparator() { - @Override - public int compare(String uncompressedFilename1, String uncompressedFilename2) { - final String name1 = getDictionaryName(uncompressedFilename1); - final String name2 = getDictionaryName(uncompressedFilename2); - if (defaultLangName.length() > 0) { - if (name1.startsWith(defaultLangName + "-") && !name2.startsWith(defaultLangName + "-")) { - return -1; - } else if (name2.startsWith(defaultLangName + "-") && !name1.startsWith(defaultLangName + "-")) { - return 1; + + public synchronized String getDictionaryName(final String uncompressedFilename) { + final String currentLocale = Locale.getDefault().getLanguage().toLowerCase(); + if (!currentLocale.equals(defaultLangISO2)) { + defaultLangISO2 = currentLocale; + fileToNameCache.clear(); + defaultLangName = null; } - } - return collator.compare(name1, name2); - } - }; - final Comparator dictionaryInfoComparator = new Comparator() { - @Override - public int compare(DictionaryInfo d1, DictionaryInfo d2) { - // Single-index dictionaries first. - if (d1.indexInfos.size() != d2.indexInfos.size()) { - return d1.indexInfos.size() - d2.indexInfos.size(); - } - return uncompressedFilenameComparator.compare(d1.uncompressedFilename, d2.uncompressedFilename); - } - }; - - public void backgroundUpdateDictionaries(final Runnable onUpdateFinished) { - new Thread(new Runnable() { - @Override - public void run() { - final DictionaryConfig oldDictionaryConfig = new DictionaryConfig(); - synchronized(this) { - oldDictionaryConfig.dictionaryFilesOrdered.addAll(dictionaryConfig.dictionaryFilesOrdered); + if (defaultLangName == null) { + defaultLangName = isoCodeToLocalizedLanguageName(defaultLangISO2); } - final DictionaryConfig newDictionaryConfig = new DictionaryConfig(); - for (final String uncompressedFilename : oldDictionaryConfig.dictionaryFilesOrdered) { - final File dictFile = getPath(uncompressedFilename); - final DictionaryInfo dictionaryInfo = Dictionary.getDictionaryInfo(dictFile); - if (dictionaryInfo != null) { - newDictionaryConfig.dictionaryFilesOrdered.add(uncompressedFilename); - newDictionaryConfig.uncompressedFilenameToDictionaryInfo.put(uncompressedFilename, dictionaryInfo); - } + + String name = fileToNameCache.get(uncompressedFilename); + if (name != null) { + return name; } - - // Are there dictionaries on the device that we didn't know about already? - // Pick them up and put them at the end of the list. - final List toAddSorted = new ArrayList(); - final File[] dictDirFiles = getDictDir().listFiles(); - if (dictDirFiles != null) { - for (final File file : dictDirFiles) { - if (file.getName().endsWith(".zip")) { - if (DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.containsKey(file.getName().replace(".zip", ""))) { - file.delete(); - } + + final DictionaryInfo dictionaryInfo = DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO + .get(uncompressedFilename); + if (dictionaryInfo != null) { + final StringBuilder nameBuilder = new StringBuilder(); + + List sortedIndexInfos = sortedIndexInfos(dictionaryInfo.indexInfos); + for (int i = 0; i < sortedIndexInfos.size(); ++i) { + if (i > 0) { + nameBuilder.append("-"); + } + nameBuilder + .append(isoCodeToLocalizedLanguageName(sortedIndexInfos.get(i).shortName)); } - if (!file.getName().endsWith(".quickdic")) { - continue; + name = nameBuilder.toString(); + } else { + name = uncompressedFilename.replace(".quickdic", ""); + } + fileToNameCache.put(uncompressedFilename, name); + return name; + } + + public View createButton(final Context context, final DictionaryInfo dictionaryInfo, + final IndexInfo indexInfo) { + LanguageResources languageResources = Language.isoCodeToResources.get(indexInfo.shortName); + View result; + + if (languageResources == null || languageResources.flagId <= 0) { + Button button = new Button(context); + button.setText(indexInfo.shortName); + result = button; + } else { + ImageButton button = new ImageButton(context); + button.setImageResource(languageResources.flagId); + button.setScaleType(ScaleType.FIT_CENTER); + result = button; + } + result.setMinimumWidth(languageButtonPixels); + result.setMinimumHeight(languageButtonPixels * 2 / 3); + // result.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, + // LayoutParams.WRAP_CONTENT)); + return result; + } + + public synchronized void moveDictionaryToTop(final DictionaryInfo dictionaryInfo) { + dictionaryConfig.dictionaryFilesOrdered.remove(dictionaryInfo.uncompressedFilename); + dictionaryConfig.dictionaryFilesOrdered.add(0, dictionaryInfo.uncompressedFilename); + PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); + } + + public synchronized void deleteDictionary(final DictionaryInfo dictionaryInfo) { + while (dictionaryConfig.dictionaryFilesOrdered.remove(dictionaryInfo.uncompressedFilename)) { + } + ; + dictionaryConfig.uncompressedFilenameToDictionaryInfo + .remove(dictionaryInfo.uncompressedFilename); + getPath(dictionaryInfo.uncompressedFilename).delete(); + PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, dictionaryConfig); + } + + final Collator collator = Collator.getInstance(); + final Comparator uncompressedFilenameComparator = new Comparator() { + @Override + public int compare(String uncompressedFilename1, String uncompressedFilename2) { + final String name1 = getDictionaryName(uncompressedFilename1); + final String name2 = getDictionaryName(uncompressedFilename2); + if (defaultLangName.length() > 0) { + if (name1.startsWith(defaultLangName + "-") + && !name2.startsWith(defaultLangName + "-")) { + return -1; + } else if (name2.startsWith(defaultLangName + "-") + && !name1.startsWith(defaultLangName + "-")) { + return 1; + } } - if (newDictionaryConfig.uncompressedFilenameToDictionaryInfo.containsKey(file.getName())) { - // We have it in our list already. - continue; + return collator.compare(name1, name2); + } + }; + final Comparator dictionaryInfoComparator = new Comparator() { + @Override + public int compare(DictionaryInfo d1, DictionaryInfo d2) { + // Single-index dictionaries first. + if (d1.indexInfos.size() != d2.indexInfos.size()) { + return d1.indexInfos.size() - d2.indexInfos.size(); } - final DictionaryInfo dictionaryInfo = Dictionary.getDictionaryInfo(file); - if (dictionaryInfo == null) { - Log.e(LOG, "Unable to parse dictionary: " + file.getPath()); - continue; + return uncompressedFilenameComparator.compare(d1.uncompressedFilename, + d2.uncompressedFilename); + } + }; + + public void backgroundUpdateDictionaries(final Runnable onUpdateFinished) { + new Thread(new Runnable() { + @Override + public void run() { + final DictionaryConfig oldDictionaryConfig = new DictionaryConfig(); + synchronized (this) { + oldDictionaryConfig.dictionaryFilesOrdered + .addAll(dictionaryConfig.dictionaryFilesOrdered); + } + final DictionaryConfig newDictionaryConfig = new DictionaryConfig(); + for (final String uncompressedFilename : oldDictionaryConfig.dictionaryFilesOrdered) { + final File dictFile = getPath(uncompressedFilename); + final DictionaryInfo dictionaryInfo = Dictionary.getDictionaryInfo(dictFile); + if (dictionaryInfo != null) { + newDictionaryConfig.dictionaryFilesOrdered.add(uncompressedFilename); + newDictionaryConfig.uncompressedFilenameToDictionaryInfo.put( + uncompressedFilename, dictionaryInfo); + } + } + + // Are there dictionaries on the device that we didn't know + // about already? + // Pick them up and put them at the end of the list. + final List toAddSorted = new ArrayList(); + final File[] dictDirFiles = getDictDir().listFiles(); + if (dictDirFiles != null) { + for (final File file : dictDirFiles) { + if (file.getName().endsWith(".zip")) { + if (DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO + .containsKey(file.getName().replace(".zip", ""))) { + file.delete(); + } + } + if (!file.getName().endsWith(".quickdic")) { + continue; + } + if (newDictionaryConfig.uncompressedFilenameToDictionaryInfo + .containsKey(file.getName())) { + // We have it in our list already. + continue; + } + final DictionaryInfo dictionaryInfo = Dictionary.getDictionaryInfo(file); + if (dictionaryInfo == null) { + Log.e(LOG, "Unable to parse dictionary: " + file.getPath()); + continue; + } + + toAddSorted.add(file.getName()); + newDictionaryConfig.uncompressedFilenameToDictionaryInfo.put( + file.getName(), dictionaryInfo); + } + } else { + Log.w(LOG, "dictDir is not a diretory: " + getDictDir().getPath()); + } + if (!toAddSorted.isEmpty()) { + Collections.sort(toAddSorted, uncompressedFilenameComparator); + newDictionaryConfig.dictionaryFilesOrdered.addAll(toAddSorted); + } + + PersistentObjectCache.getInstance() + .write(C.DICTIONARY_CONFIGS, newDictionaryConfig); + synchronized (this) { + dictionaryConfig = newDictionaryConfig; + } + + try { + onUpdateFinished.run(); + } catch (Exception e) { + Log.e(LOG, "Exception running callback.", e); + } } - - toAddSorted.add(file.getName()); - newDictionaryConfig.uncompressedFilenameToDictionaryInfo.put(file.getName(), dictionaryInfo); - } - } else { - Log.w(LOG, "dictDir is not a diretory: " + getDictDir().getPath()); + }).start(); + } + + public boolean matchesFilters(final DictionaryInfo dictionaryInfo, final String[] filters) { + if (filters == null) { + return true; } - if (!toAddSorted.isEmpty()) { - Collections.sort(toAddSorted, uncompressedFilenameComparator); - newDictionaryConfig.dictionaryFilesOrdered.addAll(toAddSorted); + for (final String filter : filters) { + if (!getDictionaryName(dictionaryInfo.uncompressedFilename).toLowerCase().contains( + filter)) { + return false; + } } + return true; + } - PersistentObjectCache.getInstance().write(C.DICTIONARY_CONFIGS, newDictionaryConfig); - synchronized (this) { - dictionaryConfig = newDictionaryConfig; + public synchronized List getDictionariesOnDevice(String[] filters) { + final List result = new ArrayList( + dictionaryConfig.dictionaryFilesOrdered.size()); + for (final String uncompressedFilename : dictionaryConfig.dictionaryFilesOrdered) { + final DictionaryInfo dictionaryInfo = dictionaryConfig.uncompressedFilenameToDictionaryInfo + .get(uncompressedFilename); + if (dictionaryInfo != null && matchesFilters(dictionaryInfo, filters)) { + result.add(dictionaryInfo); + } } - - try { - onUpdateFinished.run(); - } catch (Exception e) { - Log.e(LOG, "Exception running callback.", e); + return result; + } + + public List getDownloadableDictionaries(String[] filters) { + final List result = new ArrayList( + dictionaryConfig.dictionaryFilesOrdered.size()); + + final Map remaining = new LinkedHashMap( + DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO); + remaining.keySet().removeAll(dictionaryConfig.dictionaryFilesOrdered); + for (final DictionaryInfo dictionaryInfo : remaining.values()) { + if (matchesFilters(dictionaryInfo, filters)) { + result.add(dictionaryInfo); + } } - }}).start(); - } - - public boolean matchesFilters(final DictionaryInfo dictionaryInfo, final String[] filters) { - if (filters == null) { - return true; - } - for (final String filter : filters) { - if (!getDictionaryName(dictionaryInfo.uncompressedFilename).toLowerCase().contains(filter)) { - return false; - } - } - return true; - } - - public synchronized List getDictionariesOnDevice(String[] filters) { - final List result = new ArrayList(dictionaryConfig.dictionaryFilesOrdered.size()); - for (final String uncompressedFilename : dictionaryConfig.dictionaryFilesOrdered) { - final DictionaryInfo dictionaryInfo = dictionaryConfig.uncompressedFilenameToDictionaryInfo.get(uncompressedFilename); - if (dictionaryInfo != null && matchesFilters(dictionaryInfo, filters)) { - result.add(dictionaryInfo); - } + Collections.sort(result, dictionaryInfoComparator); + return result; + } + + public synchronized boolean isDictionaryOnDevice(String uncompressedFilename) { + return dictionaryConfig.uncompressedFilenameToDictionaryInfo.get(uncompressedFilename) != null; + } + + public boolean updateAvailable(final DictionaryInfo dictionaryInfo) { + final DictionaryInfo downloadable = + DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.get( + dictionaryInfo.uncompressedFilename); + return downloadable != null && + downloadable.creationMillis > dictionaryInfo.creationMillis; + } + + public DictionaryInfo getDownloadable(final String uncompressedFilename) { + final DictionaryInfo downloadable = DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO + .get(uncompressedFilename); + return downloadable; } - return result; - } - - public List getDownloadableDictionaries(String[] filters) { - final List result = new ArrayList(dictionaryConfig.dictionaryFilesOrdered.size()); - - final Map remaining = new LinkedHashMap(DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO); - remaining.keySet().removeAll(dictionaryConfig.dictionaryFilesOrdered); - for (final DictionaryInfo dictionaryInfo : remaining.values()) { - if (matchesFilters(dictionaryInfo, filters)) { - result.add(dictionaryInfo); - } - } - Collections.sort(result, dictionaryInfoComparator); - return result; - } - - public synchronized boolean isDictionaryOnDevice(String uncompressedFilename) { - return dictionaryConfig.uncompressedFilenameToDictionaryInfo.get(uncompressedFilename) != null; - } - - public boolean updateAvailable(final DictionaryInfo dictionaryInfo) { - final DictionaryInfo downloadable = - DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.get( - dictionaryInfo.uncompressedFilename); - return downloadable != null && - downloadable.creationMillis > dictionaryInfo.creationMillis; - } - - public DictionaryInfo getDownloadable(final String uncompressedFilename) { - final DictionaryInfo downloadable = DOWNLOADABLE_UNCOMPRESSED_FILENAME_NAME_TO_DICTIONARY_INFO.get(uncompressedFilename); - return downloadable; - } } diff --git a/src/com/hughes/android/dictionary/DictionaryInfo.java b/src/com/hughes/android/dictionary/DictionaryInfo.java index 5d90589..efc0bfd 100644 --- a/src/com/hughes/android/dictionary/DictionaryInfo.java +++ b/src/com/hughes/android/dictionary/DictionaryInfo.java @@ -19,85 +19,84 @@ import java.util.ArrayList; import java.util.List; public class DictionaryInfo implements Serializable { - - private static final long serialVersionUID = -6850863377577700388L; - - public static final class IndexInfo implements Serializable { - private static final long serialVersionUID = 6524751236198309438L; - - public static final int NUM_CSV_FIELDS = 3; - - public final String shortName; // Often LangISO. - public final int allTokenCount; - public final int mainTokenCount; - - public IndexInfo(String shortName, int allTokenCount, int mainTokenCount) { - this.shortName = shortName; - this.allTokenCount = allTokenCount; - this.mainTokenCount = mainTokenCount; - } - - public StringBuilder append(StringBuilder result) { - result.append(shortName); - result.append("\t").append(allTokenCount); - result.append("\t").append(mainTokenCount); - return result; - } - public IndexInfo(final String[] fields, int i) { - shortName = fields[i++]; - allTokenCount = Integer.parseInt(fields[i++]); - mainTokenCount = Integer.parseInt(fields[i++]); + private static final long serialVersionUID = -6850863377577700388L; + + public static final class IndexInfo implements Serializable { + private static final long serialVersionUID = 6524751236198309438L; + + public static final int NUM_CSV_FIELDS = 3; + + public final String shortName; // Often LangISO. + public final int allTokenCount; + public final int mainTokenCount; + + public IndexInfo(String shortName, int allTokenCount, int mainTokenCount) { + this.shortName = shortName; + this.allTokenCount = allTokenCount; + this.mainTokenCount = mainTokenCount; + } + + public StringBuilder append(StringBuilder result) { + result.append(shortName); + result.append("\t").append(allTokenCount); + result.append("\t").append(mainTokenCount); + return result; + } + + public IndexInfo(final String[] fields, int i) { + shortName = fields[i++]; + allTokenCount = Integer.parseInt(fields[i++]); + mainTokenCount = Integer.parseInt(fields[i++]); + } } - } - - // Stuff populated from the text file. - public String uncompressedFilename; // used as a key throughout the program. - public String downloadUrl; - public long uncompressedBytes; - public long zipBytes; - public long creationMillis; - public final List indexInfos = new ArrayList(); - public String dictInfo; - - public DictionaryInfo() { - // Blank object. - } - - public StringBuilder append(final StringBuilder result) { - result.append(uncompressedFilename); - result.append("\t").append(downloadUrl); - result.append("\t").append(creationMillis); - result.append("\t").append(uncompressedBytes); - result.append("\t").append(zipBytes); - result.append("\t").append(indexInfos.size()); - for (final IndexInfo indexInfo : indexInfos) { - indexInfo.append(result.append("\t")); + + // Stuff populated from the text file. + public String uncompressedFilename; // used as a key throughout the program. + public String downloadUrl; + public long uncompressedBytes; + public long zipBytes; + public long creationMillis; + public final List indexInfos = new ArrayList(); + public String dictInfo; + + public DictionaryInfo() { + // Blank object. } - result.append("\t").append(dictInfo.replaceAll("\n", "\\\\n")); - return result; - } - - public DictionaryInfo(final String line) { - final String[] fields = line.split("\t"); - int i = 0; - uncompressedFilename = fields[i++]; - downloadUrl = fields[i++]; - creationMillis = Long.parseLong(fields[i++]); - uncompressedBytes = Long.parseLong(fields[i++]); - zipBytes = Long.parseLong(fields[i++]); - final int size = Integer.parseInt(fields[i++]); - for (int j = 0; j < size; ++j) { - indexInfos.add(new IndexInfo(fields, i)); - i += IndexInfo.NUM_CSV_FIELDS; + + public StringBuilder append(final StringBuilder result) { + result.append(uncompressedFilename); + result.append("\t").append(downloadUrl); + result.append("\t").append(creationMillis); + result.append("\t").append(uncompressedBytes); + result.append("\t").append(zipBytes); + result.append("\t").append(indexInfos.size()); + for (final IndexInfo indexInfo : indexInfos) { + indexInfo.append(result.append("\t")); + } + result.append("\t").append(dictInfo.replaceAll("\n", "\\\\n")); + return result; } - dictInfo = fields[i++].replaceAll("\\\\n", "\n"); - } - @Override - public String toString() { - return uncompressedFilename; - } + public DictionaryInfo(final String line) { + final String[] fields = line.split("\t"); + int i = 0; + uncompressedFilename = fields[i++]; + downloadUrl = fields[i++]; + creationMillis = Long.parseLong(fields[i++]); + uncompressedBytes = Long.parseLong(fields[i++]); + zipBytes = Long.parseLong(fields[i++]); + final int size = Integer.parseInt(fields[i++]); + for (int j = 0; j < size; ++j) { + indexInfos.add(new IndexInfo(fields, i)); + i += IndexInfo.NUM_CSV_FIELDS; + } + dictInfo = fields[i++].replaceAll("\\\\n", "\n"); + } + @Override + public String toString() { + return uncompressedFilename; + } } diff --git a/src/com/hughes/android/dictionary/DictionaryLink.java b/src/com/hughes/android/dictionary/DictionaryLink.java index f740047..c5a4b1d 100644 --- a/src/com/hughes/android/dictionary/DictionaryLink.java +++ b/src/com/hughes/android/dictionary/DictionaryLink.java @@ -1,20 +1,21 @@ + package com.hughes.android.dictionary; import java.io.Serializable; public class DictionaryLink implements Serializable { - - private static final long serialVersionUID = -3842984045642836981L; - final String uncompressedFilename; - final int index; - final String searchText; + private static final long serialVersionUID = -3842984045642836981L; + + final String uncompressedFilename; + final int index; + final String searchText; - private DictionaryLink(String uncompressedFilename, int index, - String searchText) { - this.uncompressedFilename = uncompressedFilename; - this.index = index; - this.searchText = searchText; - } + private DictionaryLink(String uncompressedFilename, int index, + String searchText) { + this.uncompressedFilename = uncompressedFilename; + this.index = index; + this.searchText = searchText; + } } diff --git a/src/com/hughes/android/dictionary/DictionaryManagerActivity.java b/src/com/hughes/android/dictionary/DictionaryManagerActivity.java index 85e1373..fa0bf8a 100644 --- a/src/com/hughes/android/dictionary/DictionaryManagerActivity.java +++ b/src/com/hughes/android/dictionary/DictionaryManagerActivity.java @@ -91,7 +91,7 @@ public class DictionaryManagerActivity extends SherlockListActivity { LinearLayout downloadableDictionariesHeaderRow; Handler uiHandler; - + Runnable dictionaryUpdater = new Runnable() { @Override public void run() { @@ -106,7 +106,7 @@ public class DictionaryManagerActivity extends SherlockListActivity { }); } }; - + final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -182,19 +182,22 @@ public class DictionaryManagerActivity extends SherlockListActivity { Log.d(LOG, "onCreate:" + this); application = (DictionaryApplication) getApplication(); - + blockAutoLaunch = false; - + // UI init. setContentView(R.layout.dictionary_manager_activity); - dictionariesOnDeviceHeaderRow = (LinearLayout) LayoutInflater.from(getListView().getContext()).inflate( + dictionariesOnDeviceHeaderRow = (LinearLayout) LayoutInflater.from( + getListView().getContext()).inflate( R.layout.dictionary_manager_header_row_on_device, getListView(), false); - downloadableDictionariesHeaderRow = (LinearLayout) LayoutInflater.from(getListView().getContext()).inflate( + downloadableDictionariesHeaderRow = (LinearLayout) LayoutInflater.from( + getListView().getContext()).inflate( R.layout.dictionary_manager_header_row_downloadable, getListView(), false); - showDownloadable = (ToggleButton) downloadableDictionariesHeaderRow.findViewById(R.id.hideDownloadable); + showDownloadable = (ToggleButton) downloadableDictionariesHeaderRow + .findViewById(R.id.hideDownloadable); showDownloadable.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { @@ -211,37 +214,37 @@ public class DictionaryManagerActivity extends SherlockListActivity { prefs.edit().putString(C.THANKS_FOR_UPDATING_VERSION, thanksForUpdatingLatestVersion) .commit(); } - - + registerReceiver(broadcastReceiver, new IntentFilter( DownloadManager.ACTION_DOWNLOAD_COMPLETE)); - + setListAdapater(); registerForContextMenu(getListView()); - + final File dictDir = application.getDictDir(); if (!dictDir.canRead() || !dictDir.canExecute()) { blockAutoLaunch = true; - + AlertDialog.Builder builder = new AlertDialog.Builder(getListView().getContext()); builder.setTitle(getString(R.string.error)); builder.setMessage(getString( - R.string.unableToReadDictionaryDir, - dictDir.getAbsolutePath(), + R.string.unableToReadDictionaryDir, + dictDir.getAbsolutePath(), Environment.getExternalStorageDirectory())); builder.create().show(); } - + onCreateSetupActionBar(); } - + private void onCreateSetupActionBar() { ActionBar actionBar = getSupportActionBar(); actionBar.setDisplayShowTitleEnabled(false); - + filterSearchView = new SearchView(getSupportActionBar().getThemedContext()); filterSearchView.setIconifiedByDefault(false); - // filterSearchView.setIconified(false); // puts the magnifying glass in the + // filterSearchView.setIconified(false); // puts the magnifying glass in + // the // wrong place. filterSearchView.setQueryHint(getString(R.string.searchText)); filterSearchView.setSubmitButtonEnabled(false); @@ -258,13 +261,13 @@ public class DictionaryManagerActivity extends SherlockListActivity { // 11 EditorInfo.IME_MASK_ACTION | EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS); - + filterSearchView.setOnQueryTextListener(new OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return true; } - + @Override public boolean onQueryTextChange(String filterText) { setListAdapater(); @@ -277,13 +280,12 @@ public class DictionaryManagerActivity extends SherlockListActivity { actionBar.setDisplayShowCustomEnabled(true); } - @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(broadcastReceiver); } - + private static int copyStream(final InputStream in, final OutputStream out) throws IOException { int bytesRead; @@ -327,12 +329,13 @@ public class DictionaryManagerActivity extends SherlockListActivity { prefs.contains(C.INDEX_SHORT_NAME)) { Log.d(LOG, "Skipping DictionaryManager, going straight to dictionary."); startActivity(DictionaryActivity.getLaunchIntent( - new File(prefs.getString(C.DICT_FILE, "")), prefs.getString(C.INDEX_SHORT_NAME, ""), + new File(prefs.getString(C.DICT_FILE, "")), + prefs.getString(C.INDEX_SHORT_NAME, ""), prefs.getString(C.SEARCH_TOKEN, ""))); finish(); return; } - + // Remove the active dictionary from the prefs so we won't autolaunch // next time. final Editor editor = prefs.edit(); @@ -362,7 +365,7 @@ public class DictionaryManagerActivity extends SherlockListActivity { (AdapterContextMenuInfo) menuInfo; final int position = adapterContextMenuInfo.position; final MyListAdapter.Row row = (MyListAdapter.Row) getListAdapter().getItem(position); - + if (row.dictionaryInfo == null) { return; } @@ -391,7 +394,7 @@ public class DictionaryManagerActivity extends SherlockListActivity { setListAdapater(); return true; } - }); + }); } } @@ -406,18 +409,17 @@ public class DictionaryManagerActivity extends SherlockListActivity { List dictionariesOnDevice; List downloadableDictionaries; - + class Row { DictionaryInfo dictionaryInfo; boolean onDevice; - + private Row(DictionaryInfo dictinoaryInfo, boolean onDevice) { this.dictionaryInfo = dictinoaryInfo; this.onDevice = onDevice; } } - private MyListAdapter(final String[] filters) { dictionariesOnDevice = application.getDictionariesOnDevice(filters); if (showDownloadable.isChecked()) { @@ -438,17 +440,17 @@ public class DictionaryManagerActivity extends SherlockListActivity { return new Row(null, true); } position -= 1; - + if (position < dictionariesOnDevice.size()) { return new Row(dictionariesOnDevice.get(position), true); } position -= dictionariesOnDevice.size(); - + if (position == 0) { return new Row(null, false); } position -= 1; - + assert position < downloadableDictionaries.size(); return new Row(downloadableDictionaries.get(position), false); } @@ -460,40 +462,43 @@ public class DictionaryManagerActivity extends SherlockListActivity { @Override public View getView(int position, View convertView, ViewGroup parent) { - if (convertView instanceof LinearLayout && - convertView != dictionariesOnDeviceHeaderRow && + if (convertView instanceof LinearLayout && + convertView != dictionariesOnDeviceHeaderRow && convertView != downloadableDictionariesHeaderRow) { - /* This is done to try to avoid leaking memory that used to - * happen on Android 4.0.3 */ - ((LinearLayout)convertView).removeAllViews(); + /* + * This is done to try to avoid leaking memory that used to + * happen on Android 4.0.3 + */ + ((LinearLayout) convertView).removeAllViews(); } - + final Row row = getItem(position); - + if (row.onDevice) { if (row.dictionaryInfo == null) { return dictionariesOnDeviceHeaderRow; } return createDictionaryRow(row.dictionaryInfo, parent, true); } - + if (row.dictionaryInfo == null) { return downloadableDictionariesHeaderRow; } return createDictionaryRow(row.dictionaryInfo, parent, false); } - + } - + private void setListAdapater() { - final String filter = filterSearchView == null ? "" : filterSearchView.getQuery().toString(); + final String filter = filterSearchView == null ? "" : filterSearchView.getQuery() + .toString(); final String[] filters = filter.trim().toLowerCase().split("(\\s|-)+"); setListAdapter(new MyListAdapter(filters)); } - private View createDictionaryRow(final DictionaryInfo dictionaryInfo, + private View createDictionaryRow(final DictionaryInfo dictionaryInfo, final ViewGroup parent, final boolean canLaunch) { - + View row = LayoutInflater.from(parent.getContext()).inflate( R.layout.dictionary_manager_row, parent, false); final TextView name = (TextView) row.findViewById(R.id.dictionaryName); @@ -503,7 +508,10 @@ public class DictionaryManagerActivity extends SherlockListActivity { final boolean updateAvailable = application.updateAvailable(dictionaryInfo); final Button downloadButton = (Button) row.findViewById(R.id.downloadButton); if (!canLaunch || updateAvailable) { - downloadButton.setText(getString(R.string.downloadButton, application.getDownloadable(dictionaryInfo.uncompressedFilename).zipBytes / 1024.0 / 1024.0)); + downloadButton + .setText(getString( + R.string.downloadButton, + application.getDownloadable(dictionaryInfo.uncompressedFilename).zipBytes / 1024.0 / 1024.0)); downloadButton.setMinWidth(application.languageButtonPixels * 3 / 2); downloadButton.setOnClickListener(new OnClickListener() { @Override @@ -516,21 +524,23 @@ public class DictionaryManagerActivity extends SherlockListActivity { } LinearLayout buttons = (LinearLayout) row.findViewById(R.id.dictionaryLauncherButtons); - final List sortedIndexInfos = application.sortedIndexInfos(dictionaryInfo.indexInfos); + final List sortedIndexInfos = application + .sortedIndexInfos(dictionaryInfo.indexInfos); final StringBuilder builder = new StringBuilder(); if (updateAvailable) { builder.append(getString(R.string.updateButton)); } for (IndexInfo indexInfo : sortedIndexInfos) { - final View button = application.createButton(buttons.getContext(), dictionaryInfo, indexInfo); + final View button = application.createButton(buttons.getContext(), dictionaryInfo, + indexInfo); buttons.addView(button); - + if (canLaunch) { button.setOnClickListener( - new IntentLauncher(buttons.getContext(), - DictionaryActivity.getLaunchIntent( - application.getPath(dictionaryInfo.uncompressedFilename), - indexInfo.shortName, ""))); + new IntentLauncher(buttons.getContext(), + DictionaryActivity.getLaunchIntent( + application.getPath(dictionaryInfo.uncompressedFilename), + indexInfo.shortName, ""))); } else { button.setEnabled(false); @@ -538,33 +548,36 @@ public class DictionaryManagerActivity extends SherlockListActivity { if (builder.length() != 0) { builder.append("; "); } - builder.append(getString(R.string.indexInfo, indexInfo.shortName, indexInfo.mainTokenCount)); + builder.append(getString(R.string.indexInfo, indexInfo.shortName, + indexInfo.mainTokenCount)); } details.setText(builder.toString()); - + if (canLaunch) { row.setClickable(true); - row.setOnClickListener(new IntentLauncher(parent.getContext(), - DictionaryActivity.getLaunchIntent( - application.getPath(dictionaryInfo.uncompressedFilename), - dictionaryInfo.indexInfos.get(0).shortName, ""))); + row.setOnClickListener(new IntentLauncher(parent.getContext(), + DictionaryActivity.getLaunchIntent( + application.getPath(dictionaryInfo.uncompressedFilename), + dictionaryInfo.indexInfos.get(0).shortName, ""))); row.setFocusable(true); row.setLongClickable(true); } row.setBackgroundResource(android.R.drawable.menuitem_background); - + return row; } - + private void downloadDictionary(final DictionaryInfo dictionaryInfo) { DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); Request request = new Request( Uri.parse(dictionaryInfo.downloadUrl)); try { - final String destFile = new File(new URL(dictionaryInfo.downloadUrl).getFile()).getName(); + final String destFile = new File(new URL(dictionaryInfo.downloadUrl).getFile()) + .getName(); Log.d(LOG, "Downloading to: " + destFile); - - request.setDestinationUri(Uri.fromFile(new File(Environment.getExternalStorageDirectory(), destFile))); + + request.setDestinationUri(Uri.fromFile(new File(Environment + .getExternalStorageDirectory(), destFile))); } catch (MalformedURLException e) { throw new RuntimeException(e); } diff --git a/src/com/hughes/android/dictionary/HtmlDisplayActivity.java b/src/com/hughes/android/dictionary/HtmlDisplayActivity.java index 9ed1454..7059356 100644 --- a/src/com/hughes/android/dictionary/HtmlDisplayActivity.java +++ b/src/com/hughes/android/dictionary/HtmlDisplayActivity.java @@ -25,75 +25,78 @@ import android.widget.Button; import com.hughes.util.StringUtil; public final class HtmlDisplayActivity extends Activity { - - static final String LOG = "QuickDic"; - - static final String HTML_RES = "html_res"; - static final String HTML = "html"; - static final String TEXT_TO_HIGHLIGHT = "textToHighlight"; - static final String SHOW_OK_BUTTON = "showOKButton"; - - public static Intent getHelpLaunchIntent() { - final Intent intent = new Intent(); - intent.setClassName(HtmlDisplayActivity.class.getPackage().getName(), HtmlDisplayActivity.class.getName()); - intent.putExtra(HTML_RES, R.raw.help); - return intent; - } + static final String LOG = "QuickDic"; - public static Intent getWhatsNewLaunchIntent() { - final Intent intent = new Intent(); - intent.setClassName(HtmlDisplayActivity.class.getPackage().getName(), HtmlDisplayActivity.class.getName()); - intent.putExtra(HTML_RES, R.raw.whats_new); - return intent; - } + static final String HTML_RES = "html_res"; + static final String HTML = "html"; + static final String TEXT_TO_HIGHLIGHT = "textToHighlight"; + static final String SHOW_OK_BUTTON = "showOKButton"; - public static Intent getHtmlIntent(final String html, final String textToHighlight, final boolean showOkButton) { - final Intent intent = new Intent(); - intent.setClassName(HtmlDisplayActivity.class.getPackage().getName(), HtmlDisplayActivity.class.getName()); - intent.putExtra(HTML, html); - intent.putExtra(TEXT_TO_HIGHLIGHT, textToHighlight); - intent.putExtra(SHOW_OK_BUTTON, showOkButton); - return intent; - } - - /** Called when the activity is first created. */ - @Override - public void onCreate(final Bundle savedInstanceState) { - setTheme(((DictionaryApplication)getApplication()).getSelectedTheme().themeId); + public static Intent getHelpLaunchIntent() { + final Intent intent = new Intent(); + intent.setClassName(HtmlDisplayActivity.class.getPackage().getName(), + HtmlDisplayActivity.class.getName()); + intent.putExtra(HTML_RES, R.raw.help); + return intent; + } - super.onCreate(savedInstanceState); - setContentView(R.layout.html_display_activity); - - final int htmlRes = getIntent().getIntExtra(HTML_RES, -1); - final String html; - if (htmlRes != -1) { - html = StringUtil.readToString(getResources().openRawResource(htmlRes)); - } else { - html = getIntent().getStringExtra(HTML); + public static Intent getWhatsNewLaunchIntent() { + final Intent intent = new Intent(); + intent.setClassName(HtmlDisplayActivity.class.getPackage().getName(), + HtmlDisplayActivity.class.getName()); + intent.putExtra(HTML_RES, R.raw.whats_new); + return intent; } - final MyWebView webView = (MyWebView) findViewById(R.id.webView); - webView.loadData(html, "text/html", "utf-8"); - webView.activity = this; - - final String textToHighlight = getIntent().getStringExtra(TEXT_TO_HIGHLIGHT); - if (textToHighlight != null && !"".equals(textToHighlight)) { - Log.d(LOG, "NOT Highlighting text: " + textToHighlight); - // This isn't working: - // webView.findAll(textToHighlight); - //webView.showFindDialog(textToHighlight, false); + + public static Intent getHtmlIntent(final String html, final String textToHighlight, + final boolean showOkButton) { + final Intent intent = new Intent(); + intent.setClassName(HtmlDisplayActivity.class.getPackage().getName(), + HtmlDisplayActivity.class.getName()); + intent.putExtra(HTML, html); + intent.putExtra(TEXT_TO_HIGHLIGHT, textToHighlight); + intent.putExtra(SHOW_OK_BUTTON, showOkButton); + return intent; } - - final Button okButton = (Button) findViewById(R.id.okButton); - okButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - finish(); - } - }); - if (!getIntent().getBooleanExtra(SHOW_OK_BUTTON, true)) { - okButton.setVisibility(Button.GONE); + + /** Called when the activity is first created. */ + @Override + public void onCreate(final Bundle savedInstanceState) { + setTheme(((DictionaryApplication) getApplication()).getSelectedTheme().themeId); + + super.onCreate(savedInstanceState); + setContentView(R.layout.html_display_activity); + + final int htmlRes = getIntent().getIntExtra(HTML_RES, -1); + final String html; + if (htmlRes != -1) { + html = StringUtil.readToString(getResources().openRawResource(htmlRes)); + } else { + html = getIntent().getStringExtra(HTML); + } + final MyWebView webView = (MyWebView) findViewById(R.id.webView); + webView.loadData(html, "text/html", "utf-8"); + webView.activity = this; + + final String textToHighlight = getIntent().getStringExtra(TEXT_TO_HIGHLIGHT); + if (textToHighlight != null && !"".equals(textToHighlight)) { + Log.d(LOG, "NOT Highlighting text: " + textToHighlight); + // This isn't working: + // webView.findAll(textToHighlight); + // webView.showFindDialog(textToHighlight, false); + } + + final Button okButton = (Button) findViewById(R.id.okButton); + okButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + if (!getIntent().getBooleanExtra(SHOW_OK_BUTTON, true)) { + okButton.setVisibility(Button.GONE); + } } - } } diff --git a/src/com/hughes/android/dictionary/MyWebView.java b/src/com/hughes/android/dictionary/MyWebView.java index ebec47c..4e30faf 100644 --- a/src/com/hughes/android/dictionary/MyWebView.java +++ b/src/com/hughes/android/dictionary/MyWebView.java @@ -1,3 +1,4 @@ + package com.hughes.android.dictionary; import android.app.Activity; @@ -12,20 +13,20 @@ import android.webkit.WebViewClient; import com.hughes.android.dictionary.engine.HtmlEntry; public class MyWebView extends WebView { - + static final String LOG = "MyWebView"; - + HtmlDisplayActivity activity; public MyWebView(Context context) { super(context); } - + public MyWebView(Context context, AttributeSet attrs) { super(context, attrs); getSettings().setSupportZoom(true); getSettings().setBuiltInZoomControls(true); - + final WebViewClient webViewClient = new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { diff --git a/src/com/hughes/android/dictionary/PreferenceActivity.java b/src/com/hughes/android/dictionary/PreferenceActivity.java index c99aa96..8b1e2f7 100644 --- a/src/com/hughes/android/dictionary/PreferenceActivity.java +++ b/src/com/hughes/android/dictionary/PreferenceActivity.java @@ -20,40 +20,41 @@ import android.os.Bundle; import android.preference.ListPreference; public class PreferenceActivity extends android.preference.PreferenceActivity { - - static boolean prefsMightHaveChanged = false; - - @SuppressWarnings("deprecation") - @Override - public void onCreate(Bundle savedInstanceState) { - setTheme(((DictionaryApplication)getApplication()).getSelectedTheme().themeId); - - /** - * @author Dominik Köppl - * Preference: select default dictionary - * As this list is dynamically generated, we have to do it in this fashion - */ - super.onCreate(savedInstanceState); - addPreferencesFromResource(R.xml.preferences); - ListPreference defaultDic = (ListPreference) findPreference(getResources().getString(R.string.defaultDicKey)); - DictionaryApplication application = (DictionaryApplication) getApplication(); - List dicts = application.getDictionariesOnDevice(null); - - final CharSequence[] entries = new CharSequence[dicts.size()]; - final CharSequence[] entryvalues = new CharSequence[dicts.size()]; - - for(int i = 0; i < entries.length; ++i) - { - entries[i] = dicts.get(i).dictInfo; - entryvalues[i] = dicts.get(i).uncompressedFilename; - } - - defaultDic.setEntries(entries); - defaultDic.setEntryValues(entryvalues); - } - - @Override - public void onContentChanged() { - super.onContentChanged(); - } + + static boolean prefsMightHaveChanged = false; + + @SuppressWarnings("deprecation") + @Override + public void onCreate(Bundle savedInstanceState) { + setTheme(((DictionaryApplication) getApplication()).getSelectedTheme().themeId); + + /** + * @author Dominik Köppl Preference: select default dictionary As this + * list is dynamically generated, we have to do it in this + * fashion + */ + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preferences); + ListPreference defaultDic = (ListPreference) findPreference(getResources().getString( + R.string.defaultDicKey)); + DictionaryApplication application = (DictionaryApplication) getApplication(); + List dicts = application.getDictionariesOnDevice(null); + + final CharSequence[] entries = new CharSequence[dicts.size()]; + final CharSequence[] entryvalues = new CharSequence[dicts.size()]; + + for (int i = 0; i < entries.length; ++i) + { + entries[i] = dicts.get(i).dictInfo; + entryvalues[i] = dicts.get(i).uncompressedFilename; + } + + defaultDic.setEntries(entries); + defaultDic.setEntryValues(entryvalues); + } + + @Override + public void onContentChanged() { + super.onContentChanged(); + } } diff --git a/src/com/hughes/android/dictionary/engine/AbstractEntry.java b/src/com/hughes/android/dictionary/engine/AbstractEntry.java index f5d0c8d..931f9a1 100644 --- a/src/com/hughes/android/dictionary/engine/AbstractEntry.java +++ b/src/com/hughes/android/dictionary/engine/AbstractEntry.java @@ -19,32 +19,32 @@ import com.hughes.util.IndexedObject; import java.io.IOException; import java.io.RandomAccessFile; - public abstract class AbstractEntry extends IndexedObject { - - public final EntrySource entrySource; - - protected AbstractEntry(EntrySource entrySource) { - super(-1); - this.entrySource = entrySource; - } - - public AbstractEntry(Dictionary dictionary, RandomAccessFile raf, final int index) throws IOException { - super(index); - if (dictionary.dictFileVersion >= 1) { - final int entrySouceIdx = raf.readShort(); - this.entrySource = dictionary.sources.get(entrySouceIdx); - } else { - this.entrySource = null; + + public final EntrySource entrySource; + + protected AbstractEntry(EntrySource entrySource) { + super(-1); + this.entrySource = entrySource; } - } - public void write(RandomAccessFile raf) throws IOException { - raf.writeShort(entrySource.index()); - } + public AbstractEntry(Dictionary dictionary, RandomAccessFile raf, final int index) + throws IOException { + super(index); + if (dictionary.dictFileVersion >= 1) { + final int entrySouceIdx = raf.readShort(); + this.entrySource = dictionary.sources.get(entrySouceIdx); + } else { + this.entrySource = null; + } + } + + public void write(RandomAccessFile raf) throws IOException { + raf.writeShort(entrySource.index()); + } - public abstract void addToDictionary(final Dictionary dictionary); + public abstract void addToDictionary(final Dictionary dictionary); - public abstract RowBase CreateRow(int rowIndex, Index dictionaryIndex); + public abstract RowBase CreateRow(int rowIndex, Index dictionaryIndex); } diff --git a/src/com/hughes/android/dictionary/engine/Dictionary.java b/src/com/hughes/android/dictionary/engine/Dictionary.java index 2b63be8..309ee60 100644 --- a/src/com/hughes/android/dictionary/engine/Dictionary.java +++ b/src/com/hughes/android/dictionary/engine/Dictionary.java @@ -28,154 +28,164 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; - public class Dictionary implements RAFSerializable { - - static final int CACHE_SIZE = 5000; - - static final int CURRENT_DICT_VERSION = 6; - static final String END_OF_DICTIONARY = "END OF DICTIONARY"; - - // persisted - final int dictFileVersion; - final long creationMillis; - public final String dictInfo; - public final List pairEntries; - public final List textEntries; - public final List htmlEntries; - public final List sources; - public final List indices; - - /** - * dictFileVersion 1 adds: - *
  • links to sources? - * - * dictFileVersion 2 adds: - *
  • counts of tokens in indices. - */ - - public Dictionary(final String dictInfo) { - this.dictFileVersion = CURRENT_DICT_VERSION; - this.creationMillis = System.currentTimeMillis(); - this.dictInfo = dictInfo; - pairEntries = new ArrayList(); - textEntries = new ArrayList(); - htmlEntries = new ArrayList(); - sources = new ArrayList(); - indices = new ArrayList(); - } - - public Dictionary(final RandomAccessFile raf) throws IOException { - dictFileVersion = raf.readInt(); - if (dictFileVersion < 0 || dictFileVersion > CURRENT_DICT_VERSION) { - throw new IOException("Invalid dictionary version: " + dictFileVersion); - } - creationMillis = raf.readLong(); - dictInfo = raf.readUTF(); - - // Load the sources, then seek past them, because reading them later disrupts the offset. - try { - final RAFList rafSources = RAFList.create(raf, new EntrySource.Serializer(this), raf.getFilePointer()); - sources = new ArrayList(rafSources); - raf.seek(rafSources.getEndOffset()); - - pairEntries = CachingList.create(RAFList.create(raf, new PairEntry.Serializer(this), raf.getFilePointer()), CACHE_SIZE); - textEntries = CachingList.create(RAFList.create(raf, new TextEntry.Serializer(this), raf.getFilePointer()), CACHE_SIZE); - if (dictFileVersion >= 5) { - htmlEntries = CachingList.create(RAFList.create(raf, new HtmlEntry.Serializer(this), raf.getFilePointer()), CACHE_SIZE); - } else { - htmlEntries = Collections.emptyList(); - } - indices = CachingList.createFullyCached(RAFList.create(raf, indexSerializer, raf.getFilePointer())); - } catch (RuntimeException e) { - final IOException ioe = new IOException("RuntimeException loading dictionary"); - ioe.initCause(e); - throw ioe; + + static final int CACHE_SIZE = 5000; + + static final int CURRENT_DICT_VERSION = 6; + static final String END_OF_DICTIONARY = "END OF DICTIONARY"; + + // persisted + final int dictFileVersion; + final long creationMillis; + public final String dictInfo; + public final List pairEntries; + public final List textEntries; + public final List htmlEntries; + public final List sources; + public final List indices; + + /** + * dictFileVersion 1 adds:
  • links to sources? dictFileVersion 2 adds:
  • + * counts of tokens in indices. + */ + + public Dictionary(final String dictInfo) { + this.dictFileVersion = CURRENT_DICT_VERSION; + this.creationMillis = System.currentTimeMillis(); + this.dictInfo = dictInfo; + pairEntries = new ArrayList(); + textEntries = new ArrayList(); + htmlEntries = new ArrayList(); + sources = new ArrayList(); + indices = new ArrayList(); } - final String end = raf.readUTF(); - if (!end.equals(END_OF_DICTIONARY)) { - throw new IOException("Dictionary seems corrupt: " + end); + + public Dictionary(final RandomAccessFile raf) throws IOException { + dictFileVersion = raf.readInt(); + if (dictFileVersion < 0 || dictFileVersion > CURRENT_DICT_VERSION) { + throw new IOException("Invalid dictionary version: " + dictFileVersion); + } + creationMillis = raf.readLong(); + dictInfo = raf.readUTF(); + + // Load the sources, then seek past them, because reading them later + // disrupts the offset. + try { + final RAFList rafSources = RAFList.create(raf, new EntrySource.Serializer( + this), raf.getFilePointer()); + sources = new ArrayList(rafSources); + raf.seek(rafSources.getEndOffset()); + + pairEntries = CachingList.create( + RAFList.create(raf, new PairEntry.Serializer(this), raf.getFilePointer()), + CACHE_SIZE); + textEntries = CachingList.create( + RAFList.create(raf, new TextEntry.Serializer(this), raf.getFilePointer()), + CACHE_SIZE); + if (dictFileVersion >= 5) { + htmlEntries = CachingList.create( + RAFList.create(raf, new HtmlEntry.Serializer(this), raf.getFilePointer()), + CACHE_SIZE); + } else { + htmlEntries = Collections.emptyList(); + } + indices = CachingList.createFullyCached(RAFList.create(raf, indexSerializer, + raf.getFilePointer())); + } catch (RuntimeException e) { + final IOException ioe = new IOException("RuntimeException loading dictionary"); + ioe.initCause(e); + throw ioe; + } + final String end = raf.readUTF(); + if (!end.equals(END_OF_DICTIONARY)) { + throw new IOException("Dictionary seems corrupt: " + end); + } } - } - - @Override - public void write(RandomAccessFile raf) throws IOException { - raf.writeInt(dictFileVersion); - raf.writeLong(creationMillis); - raf.writeUTF(dictInfo); - RAFList.write(raf, sources, new EntrySource.Serializer(this)); - RAFList.write(raf, pairEntries, new PairEntry.Serializer(this)); - RAFList.write(raf, textEntries, new TextEntry.Serializer(this)); - RAFList.write(raf, htmlEntries, new HtmlEntry.Serializer(this)); - RAFList.write(raf, indices, indexSerializer); - raf.writeUTF(END_OF_DICTIONARY); - } - - private final RAFListSerializer indexSerializer = new RAFListSerializer() { + @Override - public Index read(RandomAccessFile raf, final int readIndex) throws IOException { - return new Index(Dictionary.this, raf); + public void write(RandomAccessFile raf) throws IOException { + raf.writeInt(dictFileVersion); + raf.writeLong(creationMillis); + raf.writeUTF(dictInfo); + RAFList.write(raf, sources, new EntrySource.Serializer(this)); + RAFList.write(raf, pairEntries, new PairEntry.Serializer(this)); + RAFList.write(raf, textEntries, new TextEntry.Serializer(this)); + RAFList.write(raf, htmlEntries, new HtmlEntry.Serializer(this)); + RAFList.write(raf, indices, indexSerializer); + raf.writeUTF(END_OF_DICTIONARY); } - @Override - public void write(RandomAccessFile raf, Index t) throws IOException { - t.write(raf); - }}; - + + private final RAFListSerializer indexSerializer = new RAFListSerializer() { + @Override + public Index read(RandomAccessFile raf, final int readIndex) throws IOException { + return new Index(Dictionary.this, raf); + } + + @Override + public void write(RandomAccessFile raf, Index t) throws IOException { + t.write(raf); + } + }; + final RAFListSerializer htmlEntryIndexSerializer = new RAFListSerializer() { @Override public void write(RandomAccessFile raf, HtmlEntry t) throws IOException { - if (t.index() == -1) throw new IndexOutOfBoundsException(); + if (t.index() == -1) + throw new IndexOutOfBoundsException(); raf.writeInt(t.index()); } + @Override public HtmlEntry read(RandomAccessFile raf, int readIndex) throws IOException { return htmlEntries.get(raf.readInt()); - }}; - + } + }; + public void print(final PrintStream out) { - out.println("dictInfo=" + dictInfo); - for (final EntrySource entrySource : sources) { - out.printf("EntrySource: %s %d\n", entrySource.name, entrySource.numEntries); - } - out.println(); - for (final Index index : indices) { - out.printf("Index: %s %s\n", index.shortName, index.longName); - index.print(out); + out.println("dictInfo=" + dictInfo); + for (final EntrySource entrySource : sources) { + out.printf("EntrySource: %s %d\n", entrySource.name, entrySource.numEntries); + } out.println(); - } + for (final Index index : indices) { + out.printf("Index: %s %s\n", index.shortName, index.longName); + index.print(out); + out.println(); + } } public DictionaryInfo getDictionaryInfo() { - final DictionaryInfo result = new DictionaryInfo(); - result.creationMillis = this.creationMillis; - result.dictInfo = this.dictInfo; - for (final Index index : indices) { - result.indexInfos.add(index.getIndexInfo()); - } - return result; + final DictionaryInfo result = new DictionaryInfo(); + result.creationMillis = this.creationMillis; + result.dictInfo = this.dictInfo; + for (final Index index : indices) { + result.indexInfos.add(index.getIndexInfo()); + } + return result; } - + public static DictionaryInfo getDictionaryInfo(final File file) { - RandomAccessFile raf = null; - try { - raf = new RandomAccessFile(file, "r"); - final Dictionary dict = new Dictionary(raf); - final DictionaryInfo dictionaryInfo = dict.getDictionaryInfo(); - dictionaryInfo.uncompressedFilename = file.getName(); - dictionaryInfo.uncompressedBytes = file.length(); - raf.close(); - return dictionaryInfo; - } catch (IOException e) { - return null; - } finally { - if (raf != null) { - try { + RandomAccessFile raf = null; + try { + raf = new RandomAccessFile(file, "r"); + final Dictionary dict = new Dictionary(raf); + final DictionaryInfo dictionaryInfo = dict.getDictionaryInfo(); + dictionaryInfo.uncompressedFilename = file.getName(); + dictionaryInfo.uncompressedBytes = file.length(); raf.close(); - } catch (IOException e) { - e.printStackTrace(); - } + return dictionaryInfo; + } catch (IOException e) { + return null; + } finally { + if (raf != null) { + try { + raf.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } } - } } -} \ No newline at end of file +} diff --git a/src/com/hughes/android/dictionary/engine/EntrySource.java b/src/com/hughes/android/dictionary/engine/EntrySource.java index 7991fdc..7f9fce6 100644 --- a/src/com/hughes/android/dictionary/engine/EntrySource.java +++ b/src/com/hughes/android/dictionary/engine/EntrySource.java @@ -22,56 +22,52 @@ import java.io.RandomAccessFile; import java.io.Serializable; public class EntrySource extends IndexedObject implements Serializable { - - private static final long serialVersionUID = -1323165134846120269L; - - final String name; - int numEntries; - - public EntrySource(final int index, final String name, int numEntries) { - super(index); - this.name = name; - this.numEntries = numEntries; - } - - @Override - public String toString() { - return name; - } - - - - - public int getNumEntries() { - return numEntries; - } - - public String getName() { - return name; - } - - - public static final class Serializer implements RAFListSerializer { - - final Dictionary dictionary; - - Serializer(Dictionary dictionary) { - this.dictionary = dictionary; + + private static final long serialVersionUID = -1323165134846120269L; + + final String name; + int numEntries; + + public EntrySource(final int index, final String name, int numEntries) { + super(index); + this.name = name; + this.numEntries = numEntries; } @Override - public EntrySource read(RandomAccessFile raf, int readIndex) - throws IOException { - final String name = raf.readUTF(); - final int numEntries = dictionary.dictFileVersion >= 3 ? raf.readInt() : 0; - return new EntrySource(readIndex, name, numEntries); + public String toString() { + return name; } - @Override - public void write(RandomAccessFile raf, EntrySource t) throws IOException { - raf.writeUTF(t.name); - raf.writeInt(t.numEntries); - } - }; - + public int getNumEntries() { + return numEntries; + } + + public String getName() { + return name; + } + + public static final class Serializer implements RAFListSerializer { + + final Dictionary dictionary; + + Serializer(Dictionary dictionary) { + this.dictionary = dictionary; + } + + @Override + public EntrySource read(RandomAccessFile raf, int readIndex) + throws IOException { + final String name = raf.readUTF(); + final int numEntries = dictionary.dictFileVersion >= 3 ? raf.readInt() : 0; + return new EntrySource(readIndex, name, numEntries); + } + + @Override + public void write(RandomAccessFile raf, EntrySource t) throws IOException { + raf.writeUTF(t.name); + raf.writeInt(t.numEntries); + } + }; + } diff --git a/src/com/hughes/android/dictionary/engine/EntryTypeName.java b/src/com/hughes/android/dictionary/engine/EntryTypeName.java index 7436817..d1136e4 100644 --- a/src/com/hughes/android/dictionary/engine/EntryTypeName.java +++ b/src/com/hughes/android/dictionary/engine/EntryTypeName.java @@ -14,71 +14,71 @@ package com.hughes.android.dictionary.engine; - public enum EntryTypeName { - WIKTIONARY_TITLE_SINGLE_DETAIL(true, true, null), - WIKTIONARY_TITLE_SINGLE(true, true, null), - WIKTIONARY_INFLECTD_FORM_SINGLE(false, true, null), + WIKTIONARY_TITLE_SINGLE_DETAIL(true, true, null), + WIKTIONARY_TITLE_SINGLE(true, true, null), + WIKTIONARY_INFLECTD_FORM_SINGLE(false, true, null), + + ONE_WORD(true, true, null), + MULTIROW_HEAD_ONE_WORD(true, true, null), + MULTIROW_TAIL_ONE_WORD(false, true, null), + SYNONYM_SINGLE(false, true, null), + ANTONYM_SINGLE(false, true, null), - ONE_WORD(true, true, null), - MULTIROW_HEAD_ONE_WORD(true, true, null), - MULTIROW_TAIL_ONE_WORD(false, true, null), + WIKTIONARY_TITLE_MULTI_DETAIL(false, true, WIKTIONARY_TITLE_SINGLE_DETAIL), + WIKTIONARY_TITLE_MULTI(false, true, WIKTIONARY_TITLE_SINGLE), + WIKTIONARY_TRANSLITERATION(), + // How we file "casa {f}, case {pl}" under "case" + WIKTIONARY_INFLECTED_FORM_MULTI(false, true, WIKTIONARY_INFLECTD_FORM_SINGLE), + WIKTIONARY_ENGLISH_DEF_WIKI_LINK(), + WIKTIONARY_ENGLISH_DEF_OTHER_LANG(), + WIKTIONARY_ENGLISH_DEF(), - SYNONYM_SINGLE(false, true, null), - ANTONYM_SINGLE(false, true, null), + SYNONYM_MULTI(false, true, SYNONYM_SINGLE), + ANTONYM_MULTI(false, true, ANTONYM_SINGLE), + DERIVED_TERM(false, true, null), - WIKTIONARY_TITLE_MULTI_DETAIL(false, true, WIKTIONARY_TITLE_SINGLE_DETAIL), - WIKTIONARY_TITLE_MULTI(false, true, WIKTIONARY_TITLE_SINGLE), - WIKTIONARY_TRANSLITERATION(), - // How we file "casa {f}, case {pl}" under "case" - WIKTIONARY_INFLECTED_FORM_MULTI(false, true, WIKTIONARY_INFLECTD_FORM_SINGLE), - WIKTIONARY_ENGLISH_DEF_WIKI_LINK(), - WIKTIONARY_ENGLISH_DEF_OTHER_LANG(), - WIKTIONARY_ENGLISH_DEF(), - - SYNONYM_MULTI(false, true, SYNONYM_SINGLE), - ANTONYM_MULTI(false, true, ANTONYM_SINGLE), - DERIVED_TERM(false, true, null), + TWO_WORDS(), + THREE_WORDS(), + FOUR_WORDS(), + FIVE_OR_MORE_WORDS(), + WIKTIONARY_TRANSLATION_WIKI_TEXT(), + WIKTIONARY_TRANSLATION_OTHER_TEXT(), - TWO_WORDS(), - THREE_WORDS(), - FOUR_WORDS(), - FIVE_OR_MORE_WORDS(), - WIKTIONARY_TRANSLATION_WIKI_TEXT(), - WIKTIONARY_TRANSLATION_OTHER_TEXT(), + // How we file entries like: "sono: {form of|essere}" under "sono.". + WIKTIONARY_IS_FORM_OF_SOMETHING_ELSE(false, true, null), - // How we file entries like: "sono: {form of|essere}" under "sono.". - WIKTIONARY_IS_FORM_OF_SOMETHING_ELSE(false, true, null), + MULTIROW_HEAD_MANY_WORDS(), + MULTIROW_TAIL_MANY_WORDS(), + WIKTIONARY_EXAMPLE(), - MULTIROW_HEAD_MANY_WORDS(), - MULTIROW_TAIL_MANY_WORDS(), - WIKTIONARY_EXAMPLE(), + // The next two are how we file entries like: "sono: {form of|essere}" under + // "essere". + WIKTIONARY_BASE_FORM_SINGLE(), // These two should be eligible for removal + // if the links are otherwise present. + WIKTIONARY_BASE_FORM_MULTI(false, false, WIKTIONARY_BASE_FORM_SINGLE), + PART_OF_HYPHENATED(), + BRACKETED(), + PARENTHESIZED(), + WIKTIONARY_TRANSLATION_SENSE(), + SEE_ALSO(), + WIKTIONARY_MENTIONED(false, true, null), ; - // The next two are how we file entries like: "sono: {form of|essere}" under "essere". - WIKTIONARY_BASE_FORM_SINGLE(), // These two should be eligible for removal if the links are otherwise present. - WIKTIONARY_BASE_FORM_MULTI(false, false, WIKTIONARY_BASE_FORM_SINGLE), - PART_OF_HYPHENATED(), - BRACKETED(), - PARENTHESIZED(), - WIKTIONARY_TRANSLATION_SENSE(), - SEE_ALSO(), - WIKTIONARY_MENTIONED(false, true, null), - ; + final boolean mainWord; + final boolean overridesStopList; + final EntryTypeName singleWordInstance; - final boolean mainWord; - final boolean overridesStopList; - final EntryTypeName singleWordInstance; - - private EntryTypeName() { - this(false, false, null); - } + private EntryTypeName() { + this(false, false, null); + } - private EntryTypeName(final boolean mainWord, final boolean overridesStopList, final EntryTypeName singleWordInstance) { - this.mainWord = mainWord; - this.overridesStopList = overridesStopList; - this.singleWordInstance = singleWordInstance == null ? this : singleWordInstance; - } + private EntryTypeName(final boolean mainWord, final boolean overridesStopList, + final EntryTypeName singleWordInstance) { + this.mainWord = mainWord; + this.overridesStopList = overridesStopList; + this.singleWordInstance = singleWordInstance == null ? this : singleWordInstance; + } } diff --git a/src/com/hughes/android/dictionary/engine/HtmlEntry.java b/src/com/hughes/android/dictionary/engine/HtmlEntry.java index 612c6c1..24424aa 100644 --- a/src/com/hughes/android/dictionary/engine/HtmlEntry.java +++ b/src/com/hughes/android/dictionary/engine/HtmlEntry.java @@ -1,3 +1,4 @@ + package com.hughes.android.dictionary.engine; import android.content.Intent; @@ -16,185 +17,189 @@ import java.lang.ref.SoftReference; import java.util.List; import java.util.regex.Pattern; -public class HtmlEntry extends AbstractEntry implements RAFSerializable, Comparable { - - // Title is not HTML escaped. - public final String title; - public final LazyHtmlLoader lazyHtmlLoader; - public String html; - - public HtmlEntry(final EntrySource entrySource, String title) { - super(entrySource); - this.title = title; - lazyHtmlLoader = null; - } - - public HtmlEntry(Dictionary dictionary, RandomAccessFile raf, final int index) throws IOException { - super(dictionary, raf, index); - title = raf.readUTF(); - lazyHtmlLoader = new LazyHtmlLoader(raf); - html = null; - } - - @Override - public void write(RandomAccessFile raf) throws IOException { - super.write(raf); - raf.writeUTF(title); - - final byte[] bytes = getHtml().getBytes("UTF-8"); - final byte[] zipBytes = StringUtil.zipBytes(bytes); - raf.writeInt(bytes.length); - raf.writeInt(zipBytes.length); - raf.write(zipBytes); - } - - String getHtml() { - return html != null ? html : lazyHtmlLoader.getHtml(); - } - - @Override - public void addToDictionary(Dictionary dictionary) { - assert index == -1; - dictionary.htmlEntries.add(this); - index = dictionary.htmlEntries.size() - 1; - } - - @Override - public RowBase CreateRow(int rowIndex, Index dictionaryIndex) { - return new Row(this.index, rowIndex, dictionaryIndex); - } - - static final class Serializer implements RAFListSerializer { - - final Dictionary dictionary; - - Serializer(Dictionary dictionary) { - this.dictionary = dictionary; - } +public class HtmlEntry extends AbstractEntry implements RAFSerializable, + Comparable { - @Override - public HtmlEntry read(RandomAccessFile raf, final int index) throws IOException { - return new HtmlEntry(dictionary, raf, index); + // Title is not HTML escaped. + public final String title; + public final LazyHtmlLoader lazyHtmlLoader; + public String html; + + public HtmlEntry(final EntrySource entrySource, String title) { + super(entrySource); + this.title = title; + lazyHtmlLoader = null; } - @Override - public void write(RandomAccessFile raf, HtmlEntry t) throws IOException { - t.write(raf); + public HtmlEntry(Dictionary dictionary, RandomAccessFile raf, final int index) + throws IOException { + super(dictionary, raf, index); + title = raf.readUTF(); + lazyHtmlLoader = new LazyHtmlLoader(raf); + html = null; } - }; - public String getRawText(final boolean compact) { - return title + ":\n" + getHtml(); - } + @Override + public void write(RandomAccessFile raf) throws IOException { + super.write(raf); + raf.writeUTF(title); - - @Override - public int compareTo(HtmlEntry another) { - if (title.compareTo(another.title) != 0) { - return title.compareTo(another.title); + final byte[] bytes = getHtml().getBytes("UTF-8"); + final byte[] zipBytes = StringUtil.zipBytes(bytes); + raf.writeInt(bytes.length); + raf.writeInt(zipBytes.length); + raf.write(zipBytes); } - return getHtml().compareTo(another.getHtml()); - } - - @Override - public String toString() { - return getRawText(false); - } - - // -------------------------------------------------------------------- - - - public static class Row extends RowBase { - - boolean isExpanded = false; - - Row(final RandomAccessFile raf, final int thisRowIndex, - final Index index) throws IOException { - super(raf, thisRowIndex, index); + + String getHtml() { + return html != null ? html : lazyHtmlLoader.getHtml(); } - Row(final int referenceIndex, final int thisRowIndex, - final Index index) { - super(referenceIndex, thisRowIndex, index); + @Override + public void addToDictionary(Dictionary dictionary) { + assert index == -1; + dictionary.htmlEntries.add(this); + index = dictionary.htmlEntries.size() - 1; } - + @Override - public String toString() { - return getRawText(false); + public RowBase CreateRow(int rowIndex, Index dictionaryIndex) { + return new Row(this.index, rowIndex, dictionaryIndex); } - public HtmlEntry getEntry() { - return index.dict.htmlEntries.get(referenceIndex); + static final class Serializer implements RAFListSerializer { + + final Dictionary dictionary; + + Serializer(Dictionary dictionary) { + this.dictionary = dictionary; + } + + @Override + public HtmlEntry read(RandomAccessFile raf, final int index) throws IOException { + return new HtmlEntry(dictionary, raf, index); + } + + @Override + public void write(RandomAccessFile raf, HtmlEntry t) throws IOException { + t.write(raf); + } + }; + + public String getRawText(final boolean compact) { + return title + ":\n" + getHtml(); } - + @Override - public void print(PrintStream out) { - final HtmlEntry entry = getEntry(); - out.println("See also HtmlEntry:" + entry.title); + public int compareTo(HtmlEntry another) { + if (title.compareTo(another.title) != 0) { + return title.compareTo(another.title); + } + return getHtml().compareTo(another.getHtml()); } @Override - public String getRawText(boolean compact) { - final HtmlEntry entry = getEntry(); - return entry.getRawText(compact); + public String toString() { + return getRawText(false); } - @Override - public RowMatchType matches(final List searchTokens, final Pattern orderedMatchPattern, final Transliterator normalizer, final boolean swapPairEntries) { - final String text = normalizer.transform(getRawText(false)); - if (orderedMatchPattern.matcher(text).find()) { - return RowMatchType.ORDERED_MATCH; - } - for (int i = searchTokens.size() - 1; i >= 0; --i) { - final String searchToken = searchTokens.get(i); - if (!text.contains(searchToken)) { - return RowMatchType.NO_MATCH; + // -------------------------------------------------------------------- + + public static class Row extends RowBase { + + boolean isExpanded = false; + + Row(final RandomAccessFile raf, final int thisRowIndex, + final Index index) throws IOException { + super(raf, thisRowIndex, index); + } + + Row(final int referenceIndex, final int thisRowIndex, + final Index index) { + super(referenceIndex, thisRowIndex, index); + } + + @Override + public String toString() { + return getRawText(false); + } + + public HtmlEntry getEntry() { + return index.dict.htmlEntries.get(referenceIndex); + } + + @Override + public void print(PrintStream out) { + final HtmlEntry entry = getEntry(); + out.println("See also HtmlEntry:" + entry.title); + } + + @Override + public String getRawText(boolean compact) { + final HtmlEntry entry = getEntry(); + return entry.getRawText(compact); + } + + @Override + public RowMatchType matches(final List searchTokens, + final Pattern orderedMatchPattern, final Transliterator normalizer, + final boolean swapPairEntries) { + final String text = normalizer.transform(getRawText(false)); + if (orderedMatchPattern.matcher(text).find()) { + return RowMatchType.ORDERED_MATCH; + } + for (int i = searchTokens.size() - 1; i >= 0; --i) { + final String searchToken = searchTokens.get(i); + if (!text.contains(searchToken)) { + return RowMatchType.NO_MATCH; + } + } + return RowMatchType.BAG_OF_WORDS_MATCH; } - } - return RowMatchType.BAG_OF_WORDS_MATCH; } - } public static String htmlBody(final List htmlEntries, final String indexShortName) { final StringBuilder result = new StringBuilder(); for (final HtmlEntry htmlEntry : htmlEntries) { final String titleEscaped = StringUtil.escapeUnicodeToPureHtml(htmlEntry.title); - result.append(String.format("

    %s

    \n

    %s\n", + result.append(String.format("

    %s

    \n

    %s\n", formatQuickdicUrl(indexShortName, htmlEntry.title), titleEscaped, htmlEntry.getHtml())); } return result.toString(); } - + public static String formatQuickdicUrl(final String indexShortName, final String text) { assert !indexShortName.contains(":"); assert text.length() > 0; return String.format("q://d?%s&%s", indexShortName, StringUtil.encodeForUrl(text)); } - + public static boolean isQuickdicUrl(String url) { return url.startsWith("q://d?"); } - + public static void quickdicUrlToIntent(final String url, final Intent intent) { int firstColon = url.indexOf("?"); - if (firstColon == -1) return; + if (firstColon == -1) + return; int secondColon = url.indexOf("&", firstColon + 1); - if (secondColon == -1) return; + if (secondColon == -1) + return; intent.putExtra(C.SEARCH_TOKEN, StringUtil.decodeFromUrl(url.substring(secondColon + 1))); } - + // -------------------------------------------------------------------- - + public static final class LazyHtmlLoader { final RandomAccessFile raf; final long offset; final int numBytes; final int numZipBytes; - + // Not sure this volatile is right, but oh well. volatile SoftReference htmlRef = new SoftReference(null); - + private LazyHtmlLoader(final RandomAccessFile raf) throws IOException { this.raf = raf; numBytes = raf.readInt(); @@ -202,13 +207,14 @@ public class HtmlEntry extends AbstractEntry implements RAFSerializable= 2) { - mainTokenCount = raf.readInt(); - } - sortedIndexEntries = CachingList.create(RAFList.create(raf, indexEntrySerializer, raf.getFilePointer()), CACHE_SIZE); - if (dict.dictFileVersion >= 4) { - stoplist = new SerializableSerializer>().read(raf); - } else { - stoplist = Collections.emptySet(); - } - rows = CachingList.create(UniformRAFList.create(raf, new RowBase.Serializer(this), raf.getFilePointer()), CACHE_SIZE); - } - - @Override - public void write(final RandomAccessFile raf) throws IOException { - raf.writeUTF(shortName); - raf.writeUTF(longName); - raf.writeUTF(sortLanguage.getIsoCode()); - raf.writeUTF(normalizerRules); - raf.writeBoolean(swapPairEntries); - if (dict.dictFileVersion >= 2) { - raf.writeInt(mainTokenCount); + + static final int CACHE_SIZE = 5000; + + public final Dictionary dict; + + public final String shortName; // Typically the ISO code for the language. + public final String longName; + + // persisted: tells how the entries are sorted. + public final Language sortLanguage; + final String normalizerRules; + + // Built from the two above. + private Transliterator normalizer; + + // persisted + public final List sortedIndexEntries; + + // persisted. + public final Set stoplist; + + // One big list! + // Various sub-types. + // persisted + public final List rows; + public final boolean swapPairEntries; + + // Version 2: + int mainTokenCount = -1; + + // -------------------------------------------------------------------------- + + public Index(final Dictionary dict, final String shortName, final String longName, + final Language sortLanguage, final String normalizerRules, + final boolean swapPairEntries, final Set stoplist) { + this.dict = dict; + this.shortName = shortName; + this.longName = longName; + this.sortLanguage = sortLanguage; + this.normalizerRules = normalizerRules; + this.swapPairEntries = swapPairEntries; + sortedIndexEntries = new ArrayList(); + this.stoplist = stoplist; + rows = new ArrayList(); + + normalizer = null; } - RAFList.write(raf, sortedIndexEntries, indexEntrySerializer); - new SerializableSerializer>().write(raf, stoplist); - UniformRAFList.write(raf, (Collection) rows, new RowBase.Serializer(this), 5 /* bytes per entry */); - } - - public void print(final PrintStream out) { - for (final RowBase row : rows) { - row.print(out); + + /** + * Deferred initialization because it can be slow. + */ + public synchronized Transliterator normalizer() { + if (normalizer == null) { + normalizer = Transliterator + .createFromRules("", normalizerRules, Transliterator.FORWARD); + } + return normalizer; } - } - - private final RAFSerializer indexEntrySerializer = new RAFSerializer () { - @Override - public IndexEntry read(RandomAccessFile raf) throws IOException { - return new IndexEntry(Index.this, raf); - } - @Override - public void write(RandomAccessFile raf, IndexEntry t) throws IOException { - t.write(raf); - }}; - - - public static final class IndexEntry implements RAFSerializable { - private final Index index; - public final String token; - private final String normalizedToken; - public final int startRow; - public final int numRows; // doesn't count the token row! - public final List htmlEntries; - - - public IndexEntry(final Index index, final String token, final String normalizedToken, final int startRow, final int numRows) { - this.index = index; - assert token.equals(token.trim()); - assert token.length() > 0; - this.token = token; - this.normalizedToken = normalizedToken; - this.startRow = startRow; - this.numRows = numRows; - this.htmlEntries = new ArrayList(); + + /** + * Note that using this comparator probably involves doing too many text + * normalizations. + */ + public NormalizeComparator getSortComparator() { + return new NormalizeComparator(normalizer(), sortLanguage.getCollator()); } - - public IndexEntry(final Index index, final RandomAccessFile raf) throws IOException { - this.index = index; - token = raf.readUTF(); - startRow = raf.readInt(); - numRows = raf.readInt(); - final boolean hasNormalizedForm = raf.readBoolean(); - normalizedToken = hasNormalizedForm ? raf.readUTF() : token; - if (index.dict.dictFileVersion >= 6) { - this.htmlEntries = CachingList.create(RAFList.create(raf, index.dict.htmlEntryIndexSerializer, raf.getFilePointer()), 1); - } else { - this.htmlEntries = Collections.emptyList(); - } + + public Index(final Dictionary dict, final RandomAccessFile raf) throws IOException { + this.dict = dict; + shortName = raf.readUTF(); + longName = raf.readUTF(); + final String languageCode = raf.readUTF(); + sortLanguage = Language.lookup(languageCode); + normalizerRules = raf.readUTF(); + swapPairEntries = raf.readBoolean(); + if (sortLanguage == null) { + throw new IOException("Unsupported language: " + languageCode); + } + if (dict.dictFileVersion >= 2) { + mainTokenCount = raf.readInt(); + } + sortedIndexEntries = CachingList.create( + RAFList.create(raf, indexEntrySerializer, raf.getFilePointer()), CACHE_SIZE); + if (dict.dictFileVersion >= 4) { + stoplist = new SerializableSerializer>().read(raf); + } else { + stoplist = Collections.emptySet(); + } + rows = CachingList.create( + UniformRAFList.create(raf, new RowBase.Serializer(this), raf.getFilePointer()), + CACHE_SIZE); } - - public void write(RandomAccessFile raf) throws IOException { - raf.writeUTF(token); - raf.writeInt(startRow); - raf.writeInt(numRows); - final boolean hasNormalizedForm = !token.equals(normalizedToken); - raf.writeBoolean(hasNormalizedForm); - if (hasNormalizedForm) { - raf.writeUTF(normalizedToken); - } - RAFList.write(raf, htmlEntries, index.dict.htmlEntryIndexSerializer); + + @Override + public void write(final RandomAccessFile raf) throws IOException { + raf.writeUTF(shortName); + raf.writeUTF(longName); + raf.writeUTF(sortLanguage.getIsoCode()); + raf.writeUTF(normalizerRules); + raf.writeBoolean(swapPairEntries); + if (dict.dictFileVersion >= 2) { + raf.writeInt(mainTokenCount); + } + RAFList.write(raf, sortedIndexEntries, indexEntrySerializer); + new SerializableSerializer>().write(raf, stoplist); + UniformRAFList.write(raf, (Collection) rows, new RowBase.Serializer(this), 5 /* + * bytes + * per + * entry + */); } - public String toString() { - return String.format("%s@%d(%d)", token, startRow, numRows); + public void print(final PrintStream out) { + for (final RowBase row : rows) { + row.print(out); + } } - public String normalizedToken() { - return normalizedToken; + private final RAFSerializer indexEntrySerializer = new RAFSerializer() { + @Override + public IndexEntry read(RandomAccessFile raf) throws IOException { + return new IndexEntry(Index.this, raf); + } + + @Override + public void write(RandomAccessFile raf, IndexEntry t) throws IOException { + t.write(raf); + } + }; + + public static final class IndexEntry implements RAFSerializable { + private final Index index; + public final String token; + private final String normalizedToken; + public final int startRow; + public final int numRows; // doesn't count the token row! + public final List htmlEntries; + + public IndexEntry(final Index index, final String token, final String normalizedToken, + final int startRow, final int numRows) { + this.index = index; + assert token.equals(token.trim()); + assert token.length() > 0; + this.token = token; + this.normalizedToken = normalizedToken; + this.startRow = startRow; + this.numRows = numRows; + this.htmlEntries = new ArrayList(); + } + + public IndexEntry(final Index index, final RandomAccessFile raf) throws IOException { + this.index = index; + token = raf.readUTF(); + startRow = raf.readInt(); + numRows = raf.readInt(); + final boolean hasNormalizedForm = raf.readBoolean(); + normalizedToken = hasNormalizedForm ? raf.readUTF() : token; + if (index.dict.dictFileVersion >= 6) { + this.htmlEntries = CachingList.create( + RAFList.create(raf, index.dict.htmlEntryIndexSerializer, + raf.getFilePointer()), 1); + } else { + this.htmlEntries = Collections.emptyList(); + } + } + + public void write(RandomAccessFile raf) throws IOException { + raf.writeUTF(token); + raf.writeInt(startRow); + raf.writeInt(numRows); + final boolean hasNormalizedForm = !token.equals(normalizedToken); + raf.writeBoolean(hasNormalizedForm); + if (hasNormalizedForm) { + raf.writeUTF(normalizedToken); + } + RAFList.write(raf, htmlEntries, index.dict.htmlEntryIndexSerializer); + } + + public String toString() { + return String.format("%s@%d(%d)", token, startRow, numRows); + } + + public String normalizedToken() { + return normalizedToken; + } } - } - - static final TransformingList.Transformer INDEX_ENTRY_TO_TOKEN = new TransformingList.Transformer() { - @Override - public String transform(IndexEntry t1) { - return t1.token; + + static final TransformingList.Transformer INDEX_ENTRY_TO_TOKEN = new TransformingList.Transformer() { + @Override + public String transform(IndexEntry t1) { + return t1.token; + } + }; + + public IndexEntry findExact(final String exactToken) { + final int result = Collections.binarySearch( + TransformingList.create(sortedIndexEntries, INDEX_ENTRY_TO_TOKEN), exactToken, + getSortComparator()); + if (result >= 0) { + return sortedIndexEntries.get(result); + } + return null; } - }; - - public IndexEntry findExact(final String exactToken) { - final int result = Collections.binarySearch(TransformingList.create(sortedIndexEntries, INDEX_ENTRY_TO_TOKEN), exactToken, getSortComparator()); - if (result >= 0) { - return sortedIndexEntries.get(result); + + public IndexEntry findInsertionPoint(String token, final AtomicBoolean interrupted) { + final int index = findInsertionPointIndex(token, interrupted); + return index != -1 ? sortedIndexEntries.get(index) : null; } - return null; - } - - public IndexEntry findInsertionPoint(String token, final AtomicBoolean interrupted) { - final int index = findInsertionPointIndex(token, interrupted); - return index != -1 ? sortedIndexEntries.get(index) : null; - } - - public int findInsertionPointIndex(String token, final AtomicBoolean interrupted) { - token = normalizeToken(token); - - int start = 0; - int end = sortedIndexEntries.size(); - - final Collator sortCollator = sortLanguage.getCollator(); - while (start < end) { - final int mid = (start + end) / 2; - if (interrupted.get()) { - return -1; - } - final IndexEntry midEntry = sortedIndexEntries.get(mid); - - final int comp = sortCollator.compare(token, midEntry.normalizedToken()); - if (comp == 0) { - final int result = windBackCase(token, mid, interrupted); + + public int findInsertionPointIndex(String token, final AtomicBoolean interrupted) { + token = normalizeToken(token); + + int start = 0; + int end = sortedIndexEntries.size(); + + final Collator sortCollator = sortLanguage.getCollator(); + while (start < end) { + final int mid = (start + end) / 2; + if (interrupted.get()) { + return -1; + } + final IndexEntry midEntry = sortedIndexEntries.get(mid); + + final int comp = sortCollator.compare(token, midEntry.normalizedToken()); + if (comp == 0) { + final int result = windBackCase(token, mid, interrupted); + return result; + } else if (comp < 0) { + // System.out.println("Upper bound: " + midEntry + ", norm=" + + // midEntry.normalizedToken() + ", mid=" + mid); + end = mid; + } else { + // System.out.println("Lower bound: " + midEntry + ", norm=" + + // midEntry.normalizedToken() + ", mid=" + mid); + start = mid + 1; + } + } + + // If we search for a substring of a string that's in there, return + // that. + int result = Math.min(start, sortedIndexEntries.size() - 1); + result = windBackCase(sortedIndexEntries.get(result).normalizedToken(), result, interrupted); return result; - } else if (comp < 0) { - // System.out.println("Upper bound: " + midEntry + ", norm=" + midEntry.normalizedToken() + ", mid=" + mid); - end = mid; - } else { - // System.out.println("Lower bound: " + midEntry + ", norm=" + midEntry.normalizedToken() + ", mid=" + mid); - start = mid + 1; - } } - // If we search for a substring of a string that's in there, return that. - int result = Math.min(start, sortedIndexEntries.size() - 1); - result = windBackCase(sortedIndexEntries.get(result).normalizedToken(), result, interrupted); - return result; - } - - private final int windBackCase(final String token, int result, final AtomicBoolean interrupted) { - while (result > 0 && sortedIndexEntries.get(result - 1).normalizedToken().equals(token)) { - --result; - if (interrupted.get()) { + private final int windBackCase(final String token, int result, final AtomicBoolean interrupted) { + while (result > 0 && sortedIndexEntries.get(result - 1).normalizedToken().equals(token)) { + --result; + if (interrupted.get()) { + return result; + } + } return result; - } } - return result; - } - - public IndexInfo getIndexInfo() { - return new DictionaryInfo.IndexInfo(shortName, sortedIndexEntries.size(), mainTokenCount); - } - - private static final int MAX_SEARCH_ROWS = 1000; - - private final Map prefixToNumRows = new LinkedHashMap(); - private synchronized final int getUpperBoundOnRowsStartingWith(final String normalizedPrefix, final int maxRows, final AtomicBoolean interrupted) { - final Integer numRows = prefixToNumRows.get(normalizedPrefix); - if (numRows != null) { - return numRows; + + public IndexInfo getIndexInfo() { + return new DictionaryInfo.IndexInfo(shortName, sortedIndexEntries.size(), mainTokenCount); } - final int insertionPointIndex = findInsertionPointIndex(normalizedPrefix, interrupted); - - int rowCount = 0; - for (int index = insertionPointIndex; index < sortedIndexEntries.size(); ++index) { - if (interrupted.get()) { return -1; } - final IndexEntry indexEntry = sortedIndexEntries.get(index); - if (!indexEntry.normalizedToken.startsWith(normalizedPrefix)) { - break; - } - rowCount += indexEntry.numRows + indexEntry.htmlEntries.size(); - if (rowCount > maxRows) { - System.out.println("Giving up, too many words with prefix: " + normalizedPrefix); - break; - } + + private static final int MAX_SEARCH_ROWS = 1000; + + private final Map prefixToNumRows = new LinkedHashMap(); + + private synchronized final int getUpperBoundOnRowsStartingWith(final String normalizedPrefix, + final int maxRows, final AtomicBoolean interrupted) { + final Integer numRows = prefixToNumRows.get(normalizedPrefix); + if (numRows != null) { + return numRows; + } + final int insertionPointIndex = findInsertionPointIndex(normalizedPrefix, interrupted); + + int rowCount = 0; + for (int index = insertionPointIndex; index < sortedIndexEntries.size(); ++index) { + if (interrupted.get()) { + return -1; + } + final IndexEntry indexEntry = sortedIndexEntries.get(index); + if (!indexEntry.normalizedToken.startsWith(normalizedPrefix)) { + break; + } + rowCount += indexEntry.numRows + indexEntry.htmlEntries.size(); + if (rowCount > maxRows) { + System.out.println("Giving up, too many words with prefix: " + normalizedPrefix); + break; + } + } + prefixToNumRows.put(normalizedPrefix, numRows); + return rowCount; } - prefixToNumRows.put(normalizedPrefix, numRows); - return rowCount; - } - - - public final List multiWordSearch( - final String searchText, final List searchTokens, final AtomicBoolean interrupted) { - final long startMills = System.currentTimeMillis(); - final List result = new ArrayList(); - - final Set normalizedNonStoplist = new LinkedHashSet(); - - String bestPrefix = null; - int leastRows = Integer.MAX_VALUE; - final StringBuilder searchTokensRegex = new StringBuilder(); - for (int i = 0; i < searchTokens.size(); ++i) { - if (interrupted.get()) { return null; } - final String searchToken = searchTokens.get(i); - final String normalized = normalizeToken(searchTokens.get(i)); - // Normalize them all. - searchTokens.set(i, normalized); - - if (!stoplist.contains(searchToken)) { - if (normalizedNonStoplist.add(normalized)) { - final int numRows = getUpperBoundOnRowsStartingWith(normalized, MAX_SEARCH_ROWS, interrupted); - if (numRows != -1 && numRows < leastRows) { - if (numRows == 0) { - // We really are done here. - return Collections.emptyList(); + + public final List multiWordSearch( + final String searchText, final List searchTokens, + final AtomicBoolean interrupted) { + final long startMills = System.currentTimeMillis(); + final List result = new ArrayList(); + + final Set normalizedNonStoplist = new LinkedHashSet(); + + String bestPrefix = null; + int leastRows = Integer.MAX_VALUE; + final StringBuilder searchTokensRegex = new StringBuilder(); + for (int i = 0; i < searchTokens.size(); ++i) { + if (interrupted.get()) { + return null; } - leastRows = numRows; - bestPrefix = normalized; - } + final String searchToken = searchTokens.get(i); + final String normalized = normalizeToken(searchTokens.get(i)); + // Normalize them all. + searchTokens.set(i, normalized); + + if (!stoplist.contains(searchToken)) { + if (normalizedNonStoplist.add(normalized)) { + final int numRows = getUpperBoundOnRowsStartingWith(normalized, + MAX_SEARCH_ROWS, interrupted); + if (numRows != -1 && numRows < leastRows) { + if (numRows == 0) { + // We really are done here. + return Collections.emptyList(); + } + leastRows = numRows; + bestPrefix = normalized; + } + } + } + + if (searchTokensRegex.length() > 0) { + searchTokensRegex.append("[\\s]*"); + } + searchTokensRegex.append(Pattern.quote(normalized)); } - } + final Pattern pattern = Pattern.compile(searchTokensRegex.toString()); - if (searchTokensRegex.length() > 0) { - searchTokensRegex.append("[\\s]*"); - } - searchTokensRegex.append(Pattern.quote(normalized)); - } - final Pattern pattern = Pattern.compile(searchTokensRegex.toString()); - - if (bestPrefix == null) { - bestPrefix = searchTokens.get(0); - System.out.println("Everything was in the stoplist!"); - } - System.out.println("Searching using prefix: " + bestPrefix + ", leastRows=" + leastRows + ", searchTokens=" + searchTokens); - - // Place to store the things that match. - final Map> matches = new EnumMap>(RowMatchType.class); - for (final RowMatchType rowMatchType : RowMatchType.values()) { - if (rowMatchType != RowMatchType.NO_MATCH) { - matches.put(rowMatchType, new ArrayList()); - } - } - - int matchCount = 0; - - final int exactMatchIndex = findInsertionPointIndex(searchText, interrupted); - if (exactMatchIndex != -1) { - final IndexEntry exactMatch = sortedIndexEntries.get(exactMatchIndex); - if (pattern.matcher(exactMatch.token).find()) { - matches.get(RowMatchType.TITLE_MATCH).add(rows.get(exactMatch.startRow)); + if (bestPrefix == null) { + bestPrefix = searchTokens.get(0); + System.out.println("Everything was in the stoplist!"); } - } - - final String searchToken = bestPrefix; - final int insertionPointIndex = findInsertionPointIndex(searchToken, interrupted); - final Set rowsAlreadySeen = new HashSet(); - for (int index = insertionPointIndex; - index < sortedIndexEntries.size() && matchCount < MAX_SEARCH_ROWS; - ++index) { - if (interrupted.get()) { return null; } - final IndexEntry indexEntry = sortedIndexEntries.get(index); - if (!indexEntry.normalizedToken.startsWith(searchToken)) { - break; + System.out.println("Searching using prefix: " + bestPrefix + ", leastRows=" + leastRows + + ", searchTokens=" + searchTokens); + + // Place to store the things that match. + final Map> matches = new EnumMap>( + RowMatchType.class); + for (final RowMatchType rowMatchType : RowMatchType.values()) { + if (rowMatchType != RowMatchType.NO_MATCH) { + matches.put(rowMatchType, new ArrayList()); + } + } + + int matchCount = 0; + + final int exactMatchIndex = findInsertionPointIndex(searchText, interrupted); + if (exactMatchIndex != -1) { + final IndexEntry exactMatch = sortedIndexEntries.get(exactMatchIndex); + if (pattern.matcher(exactMatch.token).find()) { + matches.get(RowMatchType.TITLE_MATCH).add(rows.get(exactMatch.startRow)); + } + } + + final String searchToken = bestPrefix; + final int insertionPointIndex = findInsertionPointIndex(searchToken, interrupted); + final Set rowsAlreadySeen = new HashSet(); + for (int index = insertionPointIndex; index < sortedIndexEntries.size() + && matchCount < MAX_SEARCH_ROWS; ++index) { + if (interrupted.get()) { + return null; + } + final IndexEntry indexEntry = sortedIndexEntries.get(index); + if (!indexEntry.normalizedToken.startsWith(searchToken)) { + break; + } + + // System.out.println("Searching indexEntry: " + indexEntry.token); + + // Extra +1 to skip token row. + for (int rowIndex = indexEntry.startRow + 1; rowIndex < indexEntry.startRow + 1 + + indexEntry.numRows + && rowIndex < rows.size(); ++rowIndex) { + if (interrupted.get()) { + return null; + } + final RowBase row = rows.get(rowIndex); + final RowBase.RowKey rowKey = row.getRowKey(); + if (rowsAlreadySeen.contains(rowKey)) { + continue; + } + rowsAlreadySeen.add(rowKey); + final RowMatchType matchType = row.matches(searchTokens, pattern, normalizer(), + swapPairEntries); + if (matchType != RowMatchType.NO_MATCH) { + matches.get(matchType).add(row); + ++matchCount; + } + } } + // } // searchTokens -// System.out.println("Searching indexEntry: " + indexEntry.token); - - // Extra +1 to skip token row. - for (int rowIndex = indexEntry.startRow + 1; - rowIndex < indexEntry.startRow + 1 + indexEntry.numRows && rowIndex < rows.size(); - ++rowIndex) { - if (interrupted.get()) { return null; } - final RowBase row = rows.get(rowIndex); - final RowBase.RowKey rowKey = row.getRowKey(); - if (rowsAlreadySeen.contains(rowKey)) { - continue; - } - rowsAlreadySeen.add(rowKey); - final RowMatchType matchType = row.matches(searchTokens, pattern, normalizer(), swapPairEntries); - if (matchType != RowMatchType.NO_MATCH) { - matches.get(matchType).add(row); - ++matchCount; - } + // Sort them into a reasonable order. + final RowBase.LengthComparator lengthComparator = new RowBase.LengthComparator( + swapPairEntries); + for (final Collection rows : matches.values()) { + final List ordered = new ArrayList(rows); + Collections.sort(ordered, lengthComparator); + result.addAll(ordered); } - } -// } // searchTokens - - // Sort them into a reasonable order. - final RowBase.LengthComparator lengthComparator = new RowBase.LengthComparator(swapPairEntries); - for (final Collection rows : matches.values()) { - final List ordered = new ArrayList(rows); - Collections.sort(ordered, lengthComparator); - result.addAll(ordered); + + System.out.println("searchDuration: " + (System.currentTimeMillis() - startMills)); + return result; } - - System.out.println("searchDuration: " + (System.currentTimeMillis() - startMills)); - return result; - } - - private String normalizeToken(final String searchToken) { - if (TransliteratorManager.init(null)) { - final Transliterator normalizer = normalizer(); - return normalizer.transliterate(searchToken); - } else { - // Do our best since the Transliterators aren't up yet. - return searchToken.toLowerCase(); + + private String normalizeToken(final String searchToken) { + if (TransliteratorManager.init(null)) { + final Transliterator normalizer = normalizer(); + return normalizer.transliterate(searchToken); + } else { + // Do our best since the Transliterators aren't up yet. + return searchToken.toLowerCase(); + } } - } -} \ No newline at end of file +} diff --git a/src/com/hughes/android/dictionary/engine/Language.java b/src/com/hughes/android/dictionary/engine/Language.java index 36b74db..a4c884f 100644 --- a/src/com/hughes/android/dictionary/engine/Language.java +++ b/src/com/hughes/android/dictionary/engine/Language.java @@ -24,199 +24,266 @@ import java.util.Map; import java.util.regex.Pattern; public class Language { - - public static final class LanguageResources { - public final String englishName; - public final int nameId; - public final int flagId; - - private LanguageResources(final String englishName, int nameId, int flagId) { - this.englishName = englishName; - this.nameId = nameId; - this.flagId = flagId; + + public static final class LanguageResources { + public final String englishName; + public final int nameId; + public final int flagId; + + private LanguageResources(final String englishName, int nameId, int flagId) { + this.englishName = englishName; + this.nameId = nameId; + this.flagId = flagId; + } + + private LanguageResources(final String englishName, int nameId) { + this(englishName, nameId, 0); + } } - private LanguageResources(final String englishName, int nameId) { - this(englishName, nameId, 0); + // Useful: + // http://www.loc.gov/standards/iso639-2/php/code_list.php + public static final Map isoCodeToResources = new LinkedHashMap(); + static { + isoCodeToResources.put("AF", new LanguageResources("Afrikaans", R.string.AF, + R.drawable.flag_of_south_africa)); + isoCodeToResources.put("SQ", new LanguageResources("Albanian", R.string.SQ, + R.drawable.flag_of_albania)); + isoCodeToResources.put("AR", + new LanguageResources("Arabic", R.string.AR, R.drawable.arabic)); + isoCodeToResources.put("HY", new LanguageResources("Armenian", R.string.HY, + R.drawable.flag_of_armenia)); + isoCodeToResources.put("BE", new LanguageResources("Belarusian", R.string.BE, + R.drawable.flag_of_belarus)); + isoCodeToResources.put("BN", new LanguageResources("Bengali", R.string.BN)); + isoCodeToResources.put("BS", new LanguageResources("Bosnian", R.string.BS, + R.drawable.flag_of_bosnia_and_herzegovina)); + isoCodeToResources.put("BG", new LanguageResources("Bulgarian", R.string.BG, + R.drawable.flag_of_bulgaria)); + isoCodeToResources.put("MY", new LanguageResources("Burmese", R.string.MY, + R.drawable.flag_of_myanmar)); + isoCodeToResources.put("ZH", new LanguageResources("Chinese", R.string.ZH, + R.drawable.flag_of_the_peoples_republic_of_china)); + isoCodeToResources.put("cmn", new LanguageResources("Mandarin", R.string.cmn, + R.drawable.flag_of_the_peoples_republic_of_china)); + isoCodeToResources.put("yue", new LanguageResources("Cantonese", R.string.yue, + R.drawable.flag_of_hong_kong)); + isoCodeToResources.put("CA", new LanguageResources("Catalan", R.string.CA)); + isoCodeToResources.put("HR", new LanguageResources("Croatian", R.string.HR, + R.drawable.flag_of_croatia)); + isoCodeToResources.put("CS", new LanguageResources("Czech", R.string.CS, + R.drawable.flag_of_the_czech_republic)); + isoCodeToResources.put("DA", new LanguageResources("Danish", R.string.DA, + R.drawable.flag_of_denmark)); + isoCodeToResources.put("NL", new LanguageResources("Dutch", R.string.NL, + R.drawable.flag_of_the_netherlands)); + isoCodeToResources.put("EN", new LanguageResources("English", R.string.EN, + R.drawable.flag_of_the_united_kingdom)); + isoCodeToResources.put("EO", new LanguageResources("Esperanto", R.string.EO, + R.drawable.flag_of_esperanto)); + isoCodeToResources.put("ET", new LanguageResources("Estonian", R.string.ET, + R.drawable.flag_of_estonia)); + isoCodeToResources.put("FI", new LanguageResources("Finnish", R.string.FI, + R.drawable.flag_of_finland)); + isoCodeToResources.put("FR", new LanguageResources("French", R.string.FR, + R.drawable.flag_of_france)); + isoCodeToResources.put("DE", new LanguageResources("German", R.string.DE, + R.drawable.flag_of_germany)); + isoCodeToResources.put("EL", new LanguageResources("Greek", R.string.EL, + R.drawable.flag_of_greece)); + isoCodeToResources.put("grc", new LanguageResources("Ancient Greek", R.string.grc)); + isoCodeToResources.put("haw", new LanguageResources("Hawaiian", R.string.haw, + R.drawable.flag_of_hawaii)); + isoCodeToResources.put("HE", new LanguageResources("Hebrew", R.string.HE, + R.drawable.flag_of_israel)); + isoCodeToResources.put("HI", new LanguageResources("Hindi", R.string.HI, R.drawable.hindi)); + isoCodeToResources.put("HU", new LanguageResources("Hungarian", R.string.HU, + R.drawable.flag_of_hungary)); + isoCodeToResources.put("IS", new LanguageResources("Icelandic", R.string.IS, + R.drawable.flag_of_iceland)); + isoCodeToResources.put("ID", new LanguageResources("Indonesian", R.string.ID, + R.drawable.flag_of_indonesia)); + isoCodeToResources.put("GA", new LanguageResources("Irish", R.string.GA, + R.drawable.flag_of_ireland)); + isoCodeToResources.put("GD", new LanguageResources("Scottish Gaelic", R.string.GD, + R.drawable.flag_of_scotland)); + isoCodeToResources.put("GV", new LanguageResources("Manx", R.string.GV, + R.drawable.flag_of_the_isle_of_man)); + isoCodeToResources.put("IT", new LanguageResources("Italian", R.string.IT, + R.drawable.flag_of_italy)); + isoCodeToResources.put("LA", new LanguageResources("Latin", R.string.LA)); + isoCodeToResources.put("LV", new LanguageResources("Latvian", R.string.LV, + R.drawable.flag_of_latvia)); + isoCodeToResources.put("LT", new LanguageResources("Lithuanian", R.string.LT, + R.drawable.flag_of_lithuania)); + isoCodeToResources.put("JA", new LanguageResources("Japanese", R.string.JA, + R.drawable.flag_of_japan)); + isoCodeToResources.put("KO", new LanguageResources("Korean", R.string.KO, + R.drawable.flag_of_south_korea)); + isoCodeToResources.put("KU", new LanguageResources("Kurdish", R.string.KU)); + isoCodeToResources.put("MS", new LanguageResources("Malay", R.string.MS, + R.drawable.flag_of_malaysia)); + isoCodeToResources.put("MI", new LanguageResources("Maori", R.string.MI, + R.drawable.flag_of_new_zealand)); + isoCodeToResources.put("MN", new LanguageResources("Mongolian", R.string.MN, + R.drawable.flag_of_mongolia)); + isoCodeToResources.put("NE", new LanguageResources("Nepali", R.string.NE, + R.drawable.flag_of_nepal)); + isoCodeToResources.put("NO", new LanguageResources("Norwegian", R.string.NO, + R.drawable.flag_of_norway)); + isoCodeToResources.put("FA", new LanguageResources("Persian", R.string.FA, + R.drawable.flag_of_iran)); + isoCodeToResources.put("PL", new LanguageResources("Polish", R.string.PL, + R.drawable.flag_of_poland)); + isoCodeToResources.put("PT", new LanguageResources("Portuguese", R.string.PT, + R.drawable.flag_of_portugal)); + isoCodeToResources.put("PA", new LanguageResources("Punjabi", R.string.PA)); + isoCodeToResources.put("RO", new LanguageResources("Romanian", R.string.RO, + R.drawable.flag_of_romania)); + isoCodeToResources.put("RU", new LanguageResources("Russian", R.string.RU, + R.drawable.flag_of_russia)); + isoCodeToResources.put("SA", new LanguageResources("Sanskrit", R.string.SA)); + isoCodeToResources.put("SR", new LanguageResources("Serbian", R.string.SR, + R.drawable.flag_of_serbia)); + isoCodeToResources.put("SK", new LanguageResources("Slovak", R.string.SK, + R.drawable.flag_of_slovakia)); + isoCodeToResources.put("SL", new LanguageResources("Slovenian", R.string.SL, + R.drawable.flag_of_slovenia)); + isoCodeToResources.put("SO", new LanguageResources("Somali", R.string.SO, + R.drawable.flag_of_somalia)); + isoCodeToResources.put("ES", new LanguageResources("Spanish", R.string.ES, + R.drawable.flag_of_spain)); + isoCodeToResources.put("SW", new LanguageResources("Swahili", R.string.SW)); + isoCodeToResources.put("SV", new LanguageResources("Swedish", R.string.SV, + R.drawable.flag_of_sweden)); + isoCodeToResources.put("TL", new LanguageResources("Tagalog", R.string.TL)); + isoCodeToResources.put("TG", new LanguageResources("Tajik", R.string.TG, + R.drawable.flag_of_tajikistan)); + isoCodeToResources.put("TH", new LanguageResources("Thai", R.string.TH, + R.drawable.flag_of_thailand)); + isoCodeToResources.put("BO", new LanguageResources("Tibetan", R.string.BO)); + isoCodeToResources.put("TR", new LanguageResources("Turkish", R.string.TR, + R.drawable.flag_of_turkey)); + isoCodeToResources.put("UK", new LanguageResources("Ukrainian", R.string.UK, + R.drawable.flag_of_ukraine)); + isoCodeToResources.put("UR", new LanguageResources("Urdu", R.string.UR)); + isoCodeToResources.put("VI", new LanguageResources("Vietnamese", R.string.VI, + R.drawable.flag_of_vietnam)); + isoCodeToResources.put("CI", new LanguageResources("Welsh", R.string.CI, + R.drawable.flag_of_wales_2)); + isoCodeToResources.put("YI", new LanguageResources("Yiddish", R.string.YI)); + isoCodeToResources.put("ZU", new LanguageResources("Zulu", R.string.ZU)); + isoCodeToResources.put("AZ", new LanguageResources("Azeri", R.string.AZ, + R.drawable.flag_of_azerbaijan)); + isoCodeToResources.put("EU", new LanguageResources("Basque", R.string.EU, + R.drawable.flag_of_the_basque_country)); + isoCodeToResources.put("BR", new LanguageResources("Breton", R.string.BR)); + isoCodeToResources.put("MR", new LanguageResources("Marathi", R.string.MR)); + isoCodeToResources.put("FO", new LanguageResources("Faroese", R.string.FO)); + isoCodeToResources.put("GL", new LanguageResources("Galician", R.string.GL, + R.drawable.flag_of_galicia)); + isoCodeToResources.put("KA", new LanguageResources("Georgian", R.string.KA, + R.drawable.flag_of_georgia)); + isoCodeToResources.put("HT", new LanguageResources("Haitian Creole", R.string.HT, + R.drawable.flag_of_haiti)); + isoCodeToResources.put("LB", new LanguageResources("Luxembourgish", R.string.LB, + R.drawable.flag_of_luxembourg)); + isoCodeToResources.put("MK", new LanguageResources("Macedonian", R.string.MK, + R.drawable.flag_of_macedonia)); + isoCodeToResources.put("LO", new LanguageResources("Lao", R.string.LO, + R.drawable.flag_of_laos)); + isoCodeToResources.put("ML", new LanguageResources("Malayalam", R.string.ML)); + isoCodeToResources.put("SL", new LanguageResources("Slovenian", R.string.SL, + R.drawable.flag_of_slovenia)); + isoCodeToResources.put("TA", new LanguageResources("Tamil", R.string.TA)); + isoCodeToResources.put("SH", new LanguageResources("Serbo-Croatian", R.string.SH)); + + // Hack to allow lower-case ISO codes to work: + for (final String isoCode : new ArrayList(isoCodeToResources.keySet())) { + isoCodeToResources.put(isoCode.toLowerCase(), isoCodeToResources.get(isoCode)); + } + } - } - - // Useful: - // http://www.loc.gov/standards/iso639-2/php/code_list.php - public static final Map isoCodeToResources = new LinkedHashMap(); - static { - isoCodeToResources.put("AF", new LanguageResources("Afrikaans", R.string.AF, R.drawable.flag_of_south_africa)); - isoCodeToResources.put("SQ", new LanguageResources("Albanian", R.string.SQ, R.drawable.flag_of_albania)); - isoCodeToResources.put("AR", new LanguageResources("Arabic", R.string.AR, R.drawable.arabic)); - isoCodeToResources.put("HY", new LanguageResources("Armenian", R.string.HY, R.drawable.flag_of_armenia)); - isoCodeToResources.put("BE", new LanguageResources("Belarusian", R.string.BE, R.drawable.flag_of_belarus)); - isoCodeToResources.put("BN", new LanguageResources("Bengali", R.string.BN)); - isoCodeToResources.put("BS", new LanguageResources("Bosnian", R.string.BS, R.drawable.flag_of_bosnia_and_herzegovina)); - isoCodeToResources.put("BG", new LanguageResources("Bulgarian", R.string.BG, R.drawable.flag_of_bulgaria)); - isoCodeToResources.put("MY", new LanguageResources("Burmese", R.string.MY, R.drawable.flag_of_myanmar)); - isoCodeToResources.put("ZH", new LanguageResources("Chinese", R.string.ZH, R.drawable.flag_of_the_peoples_republic_of_china)); - isoCodeToResources.put("cmn", new LanguageResources("Mandarin", R.string.cmn, R.drawable.flag_of_the_peoples_republic_of_china)); - isoCodeToResources.put("yue", new LanguageResources("Cantonese", R.string.yue, R.drawable.flag_of_hong_kong)); - isoCodeToResources.put("CA", new LanguageResources("Catalan", R.string.CA)); - isoCodeToResources.put("HR", new LanguageResources("Croatian", R.string.HR, R.drawable.flag_of_croatia)); - isoCodeToResources.put("CS", new LanguageResources("Czech", R.string.CS, R.drawable.flag_of_the_czech_republic)); - isoCodeToResources.put("DA", new LanguageResources("Danish", R.string.DA, R.drawable.flag_of_denmark)); - isoCodeToResources.put("NL", new LanguageResources("Dutch", R.string.NL, R.drawable.flag_of_the_netherlands)); - isoCodeToResources.put("EN", new LanguageResources("English", R.string.EN, R.drawable.flag_of_the_united_kingdom)); - isoCodeToResources.put("EO", new LanguageResources("Esperanto", R.string.EO, R.drawable.flag_of_esperanto)); - isoCodeToResources.put("ET", new LanguageResources("Estonian", R.string.ET, R.drawable.flag_of_estonia)); - isoCodeToResources.put("FI", new LanguageResources("Finnish", R.string.FI, R.drawable.flag_of_finland)); - isoCodeToResources.put("FR", new LanguageResources("French", R.string.FR, R.drawable.flag_of_france)); - isoCodeToResources.put("DE", new LanguageResources("German", R.string.DE, R.drawable.flag_of_germany)); - isoCodeToResources.put("EL", new LanguageResources("Greek", R.string.EL, R.drawable.flag_of_greece)); - isoCodeToResources.put("grc", new LanguageResources("Ancient Greek", R.string.grc)); - isoCodeToResources.put("haw", new LanguageResources("Hawaiian", R.string.haw, R.drawable.flag_of_hawaii)); - isoCodeToResources.put("HE", new LanguageResources("Hebrew", R.string.HE, R.drawable.flag_of_israel)); - isoCodeToResources.put("HI", new LanguageResources("Hindi", R.string.HI, R.drawable.hindi)); - isoCodeToResources.put("HU", new LanguageResources("Hungarian", R.string.HU, R.drawable.flag_of_hungary)); - isoCodeToResources.put("IS", new LanguageResources("Icelandic", R.string.IS, R.drawable.flag_of_iceland)); - isoCodeToResources.put("ID", new LanguageResources("Indonesian", R.string.ID, R.drawable.flag_of_indonesia)); - isoCodeToResources.put("GA", new LanguageResources("Irish", R.string.GA, R.drawable.flag_of_ireland)); - isoCodeToResources.put("GD", new LanguageResources("Scottish Gaelic", R.string.GD, R.drawable.flag_of_scotland)); - isoCodeToResources.put("GV", new LanguageResources("Manx", R.string.GV, R.drawable.flag_of_the_isle_of_man)); - isoCodeToResources.put("IT", new LanguageResources("Italian", R.string.IT, R.drawable.flag_of_italy)); - isoCodeToResources.put("LA", new LanguageResources("Latin", R.string.LA)); - isoCodeToResources.put("LV", new LanguageResources("Latvian", R.string.LV, R.drawable.flag_of_latvia)); - isoCodeToResources.put("LT", new LanguageResources("Lithuanian", R.string.LT, R.drawable.flag_of_lithuania)); - isoCodeToResources.put("JA", new LanguageResources("Japanese", R.string.JA, R.drawable.flag_of_japan)); - isoCodeToResources.put("KO", new LanguageResources("Korean", R.string.KO, R.drawable.flag_of_south_korea)); - isoCodeToResources.put("KU", new LanguageResources("Kurdish", R.string.KU)); - isoCodeToResources.put("MS", new LanguageResources("Malay", R.string.MS, R.drawable.flag_of_malaysia)); - isoCodeToResources.put("MI", new LanguageResources("Maori", R.string.MI, R.drawable.flag_of_new_zealand)); - isoCodeToResources.put("MN", new LanguageResources("Mongolian", R.string.MN, R.drawable.flag_of_mongolia)); - isoCodeToResources.put("NE", new LanguageResources("Nepali", R.string.NE, R.drawable.flag_of_nepal)); - isoCodeToResources.put("NO", new LanguageResources("Norwegian", R.string.NO, R.drawable.flag_of_norway)); - isoCodeToResources.put("FA", new LanguageResources("Persian", R.string.FA, R.drawable.flag_of_iran)); - isoCodeToResources.put("PL", new LanguageResources("Polish", R.string.PL, R.drawable.flag_of_poland)); - isoCodeToResources.put("PT", new LanguageResources("Portuguese", R.string.PT, R.drawable.flag_of_portugal)); - isoCodeToResources.put("PA", new LanguageResources("Punjabi", R.string.PA)); - isoCodeToResources.put("RO", new LanguageResources("Romanian", R.string.RO, R.drawable.flag_of_romania)); - isoCodeToResources.put("RU", new LanguageResources("Russian", R.string.RU, R.drawable.flag_of_russia)); - isoCodeToResources.put("SA", new LanguageResources("Sanskrit", R.string.SA)); - isoCodeToResources.put("SR", new LanguageResources("Serbian", R.string.SR, R.drawable.flag_of_serbia)); - isoCodeToResources.put("SK", new LanguageResources("Slovak", R.string.SK, R.drawable.flag_of_slovakia)); - isoCodeToResources.put("SL", new LanguageResources("Slovenian", R.string.SL, R.drawable.flag_of_slovenia)); - isoCodeToResources.put("SO", new LanguageResources("Somali", R.string.SO, R.drawable.flag_of_somalia)); - isoCodeToResources.put("ES", new LanguageResources("Spanish", R.string.ES, R.drawable.flag_of_spain)); - isoCodeToResources.put("SW", new LanguageResources("Swahili", R.string.SW)); - isoCodeToResources.put("SV", new LanguageResources("Swedish", R.string.SV, R.drawable.flag_of_sweden)); - isoCodeToResources.put("TL", new LanguageResources("Tagalog", R.string.TL)); - isoCodeToResources.put("TG", new LanguageResources("Tajik", R.string.TG, R.drawable.flag_of_tajikistan)); - isoCodeToResources.put("TH", new LanguageResources("Thai", R.string.TH, R.drawable.flag_of_thailand)); - isoCodeToResources.put("BO", new LanguageResources("Tibetan", R.string.BO)); - isoCodeToResources.put("TR", new LanguageResources("Turkish", R.string.TR, R.drawable.flag_of_turkey)); - isoCodeToResources.put("UK", new LanguageResources("Ukrainian", R.string.UK, R.drawable.flag_of_ukraine)); - isoCodeToResources.put("UR", new LanguageResources("Urdu", R.string.UR)); - isoCodeToResources.put("VI", new LanguageResources("Vietnamese", R.string.VI, R.drawable.flag_of_vietnam)); - isoCodeToResources.put("CI", new LanguageResources("Welsh", R.string.CI, R.drawable.flag_of_wales_2)); - isoCodeToResources.put("YI", new LanguageResources("Yiddish", R.string.YI)); - isoCodeToResources.put("ZU", new LanguageResources("Zulu", R.string.ZU)); - isoCodeToResources.put("AZ", new LanguageResources("Azeri", R.string.AZ, R.drawable.flag_of_azerbaijan)); - isoCodeToResources.put("EU", new LanguageResources("Basque", R.string.EU, R.drawable.flag_of_the_basque_country)); - isoCodeToResources.put("BR", new LanguageResources("Breton", R.string.BR)); - isoCodeToResources.put("MR", new LanguageResources("Marathi", R.string.MR)); - isoCodeToResources.put("FO", new LanguageResources("Faroese", R.string.FO)); - isoCodeToResources.put("GL", new LanguageResources("Galician", R.string.GL, R.drawable.flag_of_galicia)); - isoCodeToResources.put("KA", new LanguageResources("Georgian", R.string.KA, R.drawable.flag_of_georgia)); - isoCodeToResources.put("HT", new LanguageResources("Haitian Creole", R.string.HT, R.drawable.flag_of_haiti)); - isoCodeToResources.put("LB", new LanguageResources("Luxembourgish", R.string.LB, R.drawable.flag_of_luxembourg)); - isoCodeToResources.put("MK", new LanguageResources("Macedonian", R.string.MK, R.drawable.flag_of_macedonia)); - isoCodeToResources.put("LO", new LanguageResources("Lao", R.string.LO, R.drawable.flag_of_laos)); - isoCodeToResources.put("ML", new LanguageResources("Malayalam", R.string.ML)); - isoCodeToResources.put("SL", new LanguageResources("Slovenian", R.string.SL, R.drawable.flag_of_slovenia)); - isoCodeToResources.put("TA", new LanguageResources("Tamil", R.string.TA)); - isoCodeToResources.put("SH", new LanguageResources("Serbo-Croatian", R.string.SH)); - - // Hack to allow lower-case ISO codes to work: - for (final String isoCode : new ArrayList(isoCodeToResources.keySet())) { - isoCodeToResources.put(isoCode.toLowerCase(), isoCodeToResources.get(isoCode)); + + private static final Map registry = new LinkedHashMap(); + + final String isoCode; + final Locale locale; + + private Collator collator; + + private Language(final Locale locale, final String isoCode) { + this.locale = locale; + this.isoCode = isoCode; + + registry.put(isoCode.toLowerCase(), this); } - } - - - private static final Map registry = new LinkedHashMap(); - - final String isoCode; - final Locale locale; - - private Collator collator; - - private Language(final Locale locale, final String isoCode) { - this.locale = locale; - this.isoCode = isoCode; - - registry.put(isoCode.toLowerCase(), this); - } - - @Override - public String toString() { - return locale.toString(); - } - - public String getIsoCode() { - return isoCode; - } - - public synchronized Collator getCollator() { - // Don't think this is thread-safe... -// if (collator == null) { - this.collator = Collator.getInstance(locale); - this.collator.setStrength(Collator.IDENTICAL); -// } - return collator; - } - - public String getDefaultNormalizerRules() { - return ":: Any-Latin; ' ' > ; :: Lower; :: NFD; :: [:Nonspacing Mark:] Remove; :: NFC ;"; - } - - /** - * A practical pattern to identify strong RTL characters. This pattern is not - * completely correct according to the Unicode standard. It is simplified for - * performance and small code size. - */ - private static final String rtlChars = - "\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC"; - - private static final String puncChars = - "\\[\\]\\(\\)\\{\\}\\="; - - private static final Pattern RTL_LEFT_BOUNDARY = Pattern.compile("(["+ puncChars +"])([" + rtlChars + "])"); - private static final Pattern RTL_RIGHT_BOUNDARY = Pattern.compile("([" + rtlChars + "])(["+ puncChars +"])"); - - public static String fixBidiText(String text) { -// text = RTL_LEFT_BOUNDARY.matcher(text).replaceAll("$1\u200e $2"); -// text = RTL_RIGHT_BOUNDARY.matcher(text).replaceAll("$1 \u200e$2"); - return text; - } - - // ---------------------------------------------------------------- - - public static final Language en = new Language(Locale.ENGLISH, "EN"); - public static final Language fr = new Language(Locale.FRENCH, "FR"); - public static final Language it = new Language(Locale.ITALIAN, "IT"); - - public static final Language de = new Language(Locale.GERMAN, "DE") { @Override + public String toString() { + return locale.toString(); + } + + public String getIsoCode() { + return isoCode; + } + + public synchronized Collator getCollator() { + // Don't think this is thread-safe... + // if (collator == null) { + this.collator = Collator.getInstance(locale); + this.collator.setStrength(Collator.IDENTICAL); + // } + return collator; + } + public String getDefaultNormalizerRules() { - return ":: Lower; 'ae' > 'ä'; 'oe' > 'ö'; 'ue' > 'ü'; 'ß' > 'ss'; "; + return ":: Any-Latin; ' ' > ; :: Lower; :: NFD; :: [:Nonspacing Mark:] Remove; :: NFC ;"; } - }; - - // ---------------------------------------------------------------- - - public static synchronized Language lookup(final String isoCode) { - Language lang = registry.get(isoCode.toLowerCase()); - if (lang == null) { - lang = new Language(new Locale(isoCode), isoCode); + + /** + * A practical pattern to identify strong RTL characters. This pattern is + * not completely correct according to the Unicode standard. It is + * simplified for performance and small code size. + */ + private static final String rtlChars = + "\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC"; + + private static final String puncChars = + "\\[\\]\\(\\)\\{\\}\\="; + + private static final Pattern RTL_LEFT_BOUNDARY = Pattern.compile("([" + puncChars + "])([" + + rtlChars + "])"); + private static final Pattern RTL_RIGHT_BOUNDARY = Pattern.compile("([" + rtlChars + "])([" + + puncChars + "])"); + + public static String fixBidiText(String text) { + // text = RTL_LEFT_BOUNDARY.matcher(text).replaceAll("$1\u200e $2"); + // text = RTL_RIGHT_BOUNDARY.matcher(text).replaceAll("$1 \u200e$2"); + return text; + } + + // ---------------------------------------------------------------- + + public static final Language en = new Language(Locale.ENGLISH, "EN"); + public static final Language fr = new Language(Locale.FRENCH, "FR"); + public static final Language it = new Language(Locale.ITALIAN, "IT"); + + public static final Language de = new Language(Locale.GERMAN, "DE") { + @Override + public String getDefaultNormalizerRules() { + return ":: Lower; 'ae' > 'ä'; 'oe' > 'ö'; 'ue' > 'ü'; 'ß' > 'ss'; "; + } + }; + + // ---------------------------------------------------------------- + + public static synchronized Language lookup(final String isoCode) { + Language lang = registry.get(isoCode.toLowerCase()); + if (lang == null) { + lang = new Language(new Locale(isoCode), isoCode); + } + return lang; } - return lang; - } } diff --git a/src/com/hughes/android/dictionary/engine/NormalizeComparator.java b/src/com/hughes/android/dictionary/engine/NormalizeComparator.java index 6583d49..c0fef4f 100644 --- a/src/com/hughes/android/dictionary/engine/NormalizeComparator.java +++ b/src/com/hughes/android/dictionary/engine/NormalizeComparator.java @@ -19,25 +19,25 @@ import com.ibm.icu.text.Transliterator; import java.util.Comparator; public class NormalizeComparator implements Comparator { - - final Transliterator normalizer; - final Comparator comparator; - - public NormalizeComparator(final Transliterator normalizer, - final Comparator comparator) { - this.normalizer = normalizer; - this.comparator = comparator; - } - - @Override - public int compare(final String s1, final String s2) { - final String n1 = normalizer.transform(s1); - final String n2 = normalizer.transform(s2); - final int cn = comparator.compare(n1, n2); - if (cn != 0) { - return cn; + + final Transliterator normalizer; + final Comparator comparator; + + public NormalizeComparator(final Transliterator normalizer, + final Comparator comparator) { + this.normalizer = normalizer; + this.comparator = comparator; + } + + @Override + public int compare(final String s1, final String s2) { + final String n1 = normalizer.transform(s1); + final String n2 = normalizer.transform(s2); + final int cn = comparator.compare(n1, n2); + if (cn != 0) { + return cn; + } + return comparator.compare(s1, s2); } - return comparator.compare(s1, s2); - } } diff --git a/src/com/hughes/android/dictionary/engine/PairEntry.java b/src/com/hughes/android/dictionary/engine/PairEntry.java index 3453dc3..be61289 100644 --- a/src/com/hughes/android/dictionary/engine/PairEntry.java +++ b/src/com/hughes/android/dictionary/engine/PairEntry.java @@ -25,217 +25,220 @@ import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; -public class PairEntry extends AbstractEntry implements RAFSerializable, Comparable { - - public final List pairs; - - public PairEntry(final EntrySource entrySource) { - super(entrySource); - pairs = new ArrayList(1); - } - - public PairEntry(final EntrySource entrySource, final String lang1, final String lang2) { - this(entrySource); - this.pairs.add(new Pair(lang1, lang2)); - } - - public PairEntry(final Dictionary dictionary, final RandomAccessFile raf, final int index) throws IOException { - super(dictionary, raf, index); - final int size = raf.readInt(); - pairs = new ArrayList(size); - for (int i = 0; i < size; ++i) { - pairs.add(new Pair(raf.readUTF(), raf.readUTF())); +public class PairEntry extends AbstractEntry implements RAFSerializable, + Comparable { + + public final List pairs; + + public PairEntry(final EntrySource entrySource) { + super(entrySource); + pairs = new ArrayList(1); } - } - @Override - public void write(RandomAccessFile raf) throws IOException { - super.write(raf); - // TODO: this could be a short. - raf.writeInt(pairs.size()); - for (int i = 0; i < pairs.size(); ++i) { - assert pairs.get(i).lang1.length() > 0; - raf.writeUTF(pairs.get(i).lang1); - raf.writeUTF(pairs.get(i).lang2); + + public PairEntry(final EntrySource entrySource, final String lang1, final String lang2) { + this(entrySource); + this.pairs.add(new Pair(lang1, lang2)); } - } - - static final class Serializer implements RAFListSerializer { - - final Dictionary dictionary; - - Serializer(Dictionary dictionary) { - this.dictionary = dictionary; + + public PairEntry(final Dictionary dictionary, final RandomAccessFile raf, final int index) + throws IOException { + super(dictionary, raf, index); + final int size = raf.readInt(); + pairs = new ArrayList(size); + for (int i = 0; i < size; ++i) { + pairs.add(new Pair(raf.readUTF(), raf.readUTF())); + } } @Override - public PairEntry read(RandomAccessFile raf, int index) throws IOException { - return new PairEntry(dictionary, raf, index); + public void write(RandomAccessFile raf) throws IOException { + super.write(raf); + // TODO: this could be a short. + raf.writeInt(pairs.size()); + for (int i = 0; i < pairs.size(); ++i) { + assert pairs.get(i).lang1.length() > 0; + raf.writeUTF(pairs.get(i).lang1); + raf.writeUTF(pairs.get(i).lang2); + } } + static final class Serializer implements RAFListSerializer { + + final Dictionary dictionary; + + Serializer(Dictionary dictionary) { + this.dictionary = dictionary; + } + + @Override + public PairEntry read(RandomAccessFile raf, int index) throws IOException { + return new PairEntry(dictionary, raf, index); + } + + @Override + public void write(RandomAccessFile raf, PairEntry t) throws IOException { + t.write(raf); + } + }; + @Override - public void write(RandomAccessFile raf, PairEntry t) throws IOException { - t.write(raf); - } - }; - - @Override - public void addToDictionary(final Dictionary dictionary) { - assert index == -1; - dictionary.pairEntries.add(this); - index = dictionary.pairEntries.size() - 1; - } - - @Override - public RowBase CreateRow(int rowIndex, Index dictionaryIndex) { - return new Row(this.index, rowIndex, dictionaryIndex); - } - - - // -------------------------------------------------------------------- - - - public static class Row extends RowBase { - - Row(final RandomAccessFile raf, final int thisRowIndex, - final Index index) throws IOException { - super(raf, thisRowIndex, index); + public void addToDictionary(final Dictionary dictionary) { + assert index == -1; + dictionary.pairEntries.add(this); + index = dictionary.pairEntries.size() - 1; } - Row(final int referenceIndex, final int thisRowIndex, - final Index index) { - super(referenceIndex, thisRowIndex, index); - } - @Override - public String toString() { - return getRawText(false); + public RowBase CreateRow(int rowIndex, Index dictionaryIndex) { + return new Row(this.index, rowIndex, dictionaryIndex); } - public PairEntry getEntry() { - return index.dict.pairEntries.get(referenceIndex); - } - - @Override - public void print(PrintStream out) { - final PairEntry pairEntry = getEntry(); - for (int i = 0; i < pairEntry.pairs.size(); ++i) { - out.print((i == 0 ? " " : " ") + pairEntry.pairs.get(i)); - out.println(); - } + // -------------------------------------------------------------------- + + public static class Row extends RowBase { + + Row(final RandomAccessFile raf, final int thisRowIndex, + final Index index) throws IOException { + super(raf, thisRowIndex, index); + } + + Row(final int referenceIndex, final int thisRowIndex, + final Index index) { + super(referenceIndex, thisRowIndex, index); + } + + @Override + public String toString() { + return getRawText(false); + } + + public PairEntry getEntry() { + return index.dict.pairEntries.get(referenceIndex); + } + + @Override + public void print(PrintStream out) { + final PairEntry pairEntry = getEntry(); + for (int i = 0; i < pairEntry.pairs.size(); ++i) { + out.print((i == 0 ? " " : " ") + pairEntry.pairs.get(i)); + out.println(); + } + } + + @Override + public String getRawText(boolean compact) { + final PairEntry pairEntry = getEntry(); + return pairEntry.getRawText(compact); + } + + @Override + public RowMatchType matches(final List searchTokens, + final Pattern orderedMatchPattern, final Transliterator normalizer, + final boolean swapPairEntries) { + final int side = swapPairEntries ? 1 : 0; + final List pairs = getEntry().pairs; + final String[] pairSides = new String[pairs.size()]; + for (int i = 0; i < pairs.size(); ++i) { + pairSides[i] = normalizer.transform(pairs.get(i).get(side)); + } + for (int i = searchTokens.size() - 1; i >= 0; --i) { + final String searchToken = searchTokens.get(i); + boolean found = false; + for (final String pairSide : pairSides) { + found |= pairSide.contains(searchToken); + } + if (!found) { + return RowMatchType.NO_MATCH; + } + } + for (final String pairSide : pairSides) { + if (orderedMatchPattern.matcher(pairSide).find()) { + return RowMatchType.ORDERED_MATCH; + } + } + return RowMatchType.BAG_OF_WORDS_MATCH; + } + + @Override + public int getSideLength(boolean swapPairEntries) { + int result = 0; + final int side = swapPairEntries ? 1 : 0; + for (final Pair pair : getEntry().pairs) { + result += pair.get(side).length(); + } + return result; + } + } - @Override - public String getRawText(boolean compact) { - final PairEntry pairEntry = getEntry(); - return pairEntry.getRawText(compact); + public String getRawText(final boolean compact) { + if (compact) { + return this.pairs.get(0).toStringTab(); + } + final StringBuilder builder = new StringBuilder(); + for (int i = 0; i < this.pairs.size(); ++i) { + if (i > 0) { + builder.append(" | "); + } + builder.append(this.pairs.get(i).lang1); + } + builder.append("\t"); + for (int i = 0; i < this.pairs.size(); ++i) { + if (i > 0) { + builder.append(" | "); + } + builder.append(this.pairs.get(i).lang2); + } + return builder.toString(); } @Override - public RowMatchType matches(final List searchTokens, final Pattern orderedMatchPattern, final Transliterator normalizer, final boolean swapPairEntries) { - final int side = swapPairEntries ? 1 : 0; - final List pairs = getEntry().pairs; - final String[] pairSides = new String[pairs.size()]; - for (int i = 0; i < pairs.size(); ++i) { - pairSides[i] = normalizer.transform(pairs.get(i).get(side)); - } - for (int i = searchTokens.size() - 1; i >= 0; --i) { - final String searchToken = searchTokens.get(i); - boolean found = false; - for (final String pairSide : pairSides) { - found |= pairSide.contains(searchToken); - } - if (!found) { - return RowMatchType.NO_MATCH; - } - } - for (final String pairSide : pairSides) { - if (orderedMatchPattern.matcher(pairSide).find()) { - return RowMatchType.ORDERED_MATCH; - } - } - return RowMatchType.BAG_OF_WORDS_MATCH; + public int compareTo(final PairEntry that) { + return this.getRawText(false).compareTo(that.getRawText(false)); } - + @Override - public int getSideLength(boolean swapPairEntries) { - int result = 0; - final int side = swapPairEntries ? 1 : 0; - for (final Pair pair : getEntry().pairs) { - result += pair.get(side).length(); - } - return result; + public String toString() { + return getRawText(false); } - - } - public String getRawText(final boolean compact) { - if (compact) { - return this.pairs.get(0).toStringTab(); - } - final StringBuilder builder = new StringBuilder(); - for (int i = 0; i < this.pairs.size(); ++i) { - if (i > 0) { - builder.append(" | "); - } - builder.append(this.pairs.get(i).lang1); - } - builder.append("\t"); - for (int i = 0; i < this.pairs.size(); ++i) { - if (i > 0) { - builder.append(" | "); - } - builder.append(this.pairs.get(i).lang2); - } - return builder.toString(); - } - - @Override - public int compareTo(final PairEntry that) { - return this.getRawText(false).compareTo(that.getRawText(false)); - } - - @Override - public String toString() { - return getRawText(false); - } - - // ----------------------------------------------------------------------- - - public static final class Pair { - - public final String lang1; - public final String lang2; - - public Pair(final String lang1, final String lang2) { - this.lang1 = lang1; - this.lang2 = lang2; - if (!(lang1.trim().length() > 0 && lang2.trim().length() > 0)) { - System.err.println("poop"); - } - assert lang1.trim().length() > 0 || lang2.trim().length() > 0 : "Empty pair!!!"; - assert lang1.trim().length() > 0 && lang2.trim().length() > 0 : "Empty pair!!!"; - } + // ----------------------------------------------------------------------- - public Pair(final String lang1, final String lang2, final boolean swap) { - this(swap ? lang2 : lang1, swap ? lang1 : lang2); - } + public static final class Pair { - public String toString() { - return lang1 + " :: " + lang2; - } + public final String lang1; + public final String lang2; - public String toStringTab() { - return lang1 + "\t" + lang2; - } + public Pair(final String lang1, final String lang2) { + this.lang1 = lang1; + this.lang2 = lang2; + if (!(lang1.trim().length() > 0 && lang2.trim().length() > 0)) { + System.err.println("poop"); + } + assert lang1.trim().length() > 0 || lang2.trim().length() > 0 : "Empty pair!!!"; + assert lang1.trim().length() > 0 && lang2.trim().length() > 0 : "Empty pair!!!"; + } - public String get(int i) { - if (i == 0) { - return lang1; - } else if (i == 1) { - return lang2; - } - throw new IllegalArgumentException(); - } + public Pair(final String lang1, final String lang2, final boolean swap) { + this(swap ? lang2 : lang1, swap ? lang1 : lang2); + } - } + public String toString() { + return lang1 + " :: " + lang2; + } + + public String toStringTab() { + return lang1 + "\t" + lang2; + } + + public String get(int i) { + if (i == 0) { + return lang1; + } else if (i == 1) { + return lang2; + } + throw new IllegalArgumentException(); + } + + } } diff --git a/src/com/hughes/android/dictionary/engine/RowBase.java b/src/com/hughes/android/dictionary/engine/RowBase.java index 2e094a4..d76eb30 100644 --- a/src/com/hughes/android/dictionary/engine/RowBase.java +++ b/src/com/hughes/android/dictionary/engine/RowBase.java @@ -26,171 +26,175 @@ import java.util.List; import java.util.regex.Pattern; public abstract class RowBase extends IndexedObject { - /** - * the Index owning this RowBase. - */ - public final Index index; - - /** - * Where this RowBase points to. - */ - public final int referenceIndex; - - /** - * the TokenRow above this RowBase, populated on demand. - */ - private TokenRow tokenRow = null; - - RowBase(final RandomAccessFile raf, final int thisRowIndex, final Index index) throws IOException { - super(thisRowIndex); - this.index = index; - this.referenceIndex = raf.readInt(); // what this points to. - } - - public RowBase(final int referenceIndex, final int thisRowIndex, final Index index) { - super(thisRowIndex); - this.index = index; - this.referenceIndex = referenceIndex; - } - - static final class RowKey { - final Class rowClass; - final int referenceIndex; - - private RowKey(Class rowClass, int referenceIndex) { - this.rowClass = rowClass; - this.referenceIndex = referenceIndex; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof RowKey)) { - return false; - } - final RowKey that = (RowKey) o; - return this.referenceIndex == that.referenceIndex && this.rowClass.equals(that.rowClass); + /** + * the Index owning this RowBase. + */ + public final Index index; + + /** + * Where this RowBase points to. + */ + public final int referenceIndex; + + /** + * the TokenRow above this RowBase, populated on demand. + */ + private TokenRow tokenRow = null; + + RowBase(final RandomAccessFile raf, final int thisRowIndex, final Index index) + throws IOException { + super(thisRowIndex); + this.index = index; + this.referenceIndex = raf.readInt(); // what this points to. } - - @Override - public int hashCode() { - return rowClass.hashCode() + referenceIndex; + + public RowBase(final int referenceIndex, final int thisRowIndex, final Index index) { + super(thisRowIndex); + this.index = index; + this.referenceIndex = referenceIndex; } - } - - public RowKey getRowKey() { - return new RowKey(this.getClass(), referenceIndex); - } - - /** - * @return the TokenRow that this row is "filed under". - */ - public TokenRow getTokenRow(final boolean search) { - if (tokenRow == null && search) { - int r = index() - 1; - int rUp = index() + 1; - while (r >= 0) { - final RowBase row = index.rows.get(r); - final TokenRow candidate = row.getTokenRow(false); - if (candidate != null) { - for (++r; r <= index(); ++r) { - index.rows.get(r).setTokenRow(candidate); - } - break; + + static final class RowKey { + final Class rowClass; + final int referenceIndex; + + private RowKey(Class rowClass, int referenceIndex) { + this.rowClass = rowClass; + this.referenceIndex = referenceIndex; } - if (rUp < index.rows.size()) { - final RowBase rowUp = index.rows.get(rUp); - TokenRow candidateUp = rowUp.getTokenRow(false); - if (candidateUp != null) { - // Did we hit the next set of TokenRows? - if (candidateUp.index() > this.index()) { - final int tokenIndex = index.sortedIndexEntries.get(candidateUp.referenceIndex - 1).startRow; - candidateUp = (TokenRow) index.rows.get(tokenIndex); - } - for (--rUp; rUp >= index(); --rUp) { - index.rows.get(rUp).setTokenRow(candidateUp); + + @Override + public boolean equals(Object o) { + if (!(o instanceof RowKey)) { + return false; } - break; - } - rUp++; + final RowKey that = (RowKey) o; + return this.referenceIndex == that.referenceIndex + && this.rowClass.equals(that.rowClass); } - --r; - } - assert tokenRow != null; + + @Override + public int hashCode() { + return rowClass.hashCode() + referenceIndex; + } + } + + public RowKey getRowKey() { + return new RowKey(this.getClass(), referenceIndex); } - return tokenRow; - } - - public void setTokenRow(TokenRow tokenRow) { - assert this.tokenRow == null; - assert tokenRow != null; - this.tokenRow = tokenRow; - } - - public abstract void print(PrintStream out); - - public abstract String getRawText(final boolean compact); - - public abstract RowMatchType matches(final List searchTokens, final Pattern orderedMatch, final Transliterator normalizer, boolean swapPairEntries); - - // RowBase must manage "disk-based" polymorphism. All other polymorphism is - // dealt with in the normal manner. - static class Serializer implements RAFListSerializer { - - final Index index; - - Serializer(final Index index) { - this.index = index; + + /** + * @return the TokenRow that this row is "filed under". + */ + public TokenRow getTokenRow(final boolean search) { + if (tokenRow == null && search) { + int r = index() - 1; + int rUp = index() + 1; + while (r >= 0) { + final RowBase row = index.rows.get(r); + final TokenRow candidate = row.getTokenRow(false); + if (candidate != null) { + for (++r; r <= index(); ++r) { + index.rows.get(r).setTokenRow(candidate); + } + break; + } + if (rUp < index.rows.size()) { + final RowBase rowUp = index.rows.get(rUp); + TokenRow candidateUp = rowUp.getTokenRow(false); + if (candidateUp != null) { + // Did we hit the next set of TokenRows? + if (candidateUp.index() > this.index()) { + final int tokenIndex = index.sortedIndexEntries + .get(candidateUp.referenceIndex - 1).startRow; + candidateUp = (TokenRow) index.rows.get(tokenIndex); + } + for (--rUp; rUp >= index(); --rUp) { + index.rows.get(rUp).setTokenRow(candidateUp); + } + break; + } + rUp++; + } + --r; + } + assert tokenRow != null; + } + return tokenRow; } - @Override - public RowBase read(RandomAccessFile raf, final int listIndex) throws IOException { - final byte rowType = raf.readByte(); - if (rowType == 0) { - return new PairEntry.Row(raf, listIndex, index); - } else if (rowType == 1 || rowType == 3) { - return new TokenRow(raf, listIndex, index, /* hasMainEntry */ rowType == 1); - } else if (rowType == 2) { - return new TextEntry.Row(raf, listIndex, index); - } else if (rowType == 4) { - return new HtmlEntry.Row(raf, listIndex, index); - } - throw new RuntimeException("Invalid rowType:" + rowType); + public void setTokenRow(TokenRow tokenRow) { + assert this.tokenRow == null; + assert tokenRow != null; + this.tokenRow = tokenRow; } - @Override - public void write(RandomAccessFile raf, RowBase t) throws IOException { - if (t instanceof PairEntry.Row) { - raf.writeByte(0); - } else if (t instanceof TokenRow) { - final TokenRow tokenRow = (TokenRow) t; - raf.writeByte(tokenRow.hasMainEntry ? 1 : 3); - } else if (t instanceof TextEntry.Row) { - raf.writeByte(2); - } else if (t instanceof HtmlEntry.Row) { - raf.writeByte(4); - } - raf.writeInt(t.referenceIndex); + public abstract void print(PrintStream out); + + public abstract String getRawText(final boolean compact); + + public abstract RowMatchType matches(final List searchTokens, + final Pattern orderedMatch, final Transliterator normalizer, boolean swapPairEntries); + + // RowBase must manage "disk-based" polymorphism. All other polymorphism is + // dealt with in the normal manner. + static class Serializer implements RAFListSerializer { + + final Index index; + + Serializer(final Index index) { + this.index = index; + } + + @Override + public RowBase read(RandomAccessFile raf, final int listIndex) throws IOException { + final byte rowType = raf.readByte(); + if (rowType == 0) { + return new PairEntry.Row(raf, listIndex, index); + } else if (rowType == 1 || rowType == 3) { + return new TokenRow(raf, listIndex, index, /* hasMainEntry */rowType == 1); + } else if (rowType == 2) { + return new TextEntry.Row(raf, listIndex, index); + } else if (rowType == 4) { + return new HtmlEntry.Row(raf, listIndex, index); + } + throw new RuntimeException("Invalid rowType:" + rowType); + } + + @Override + public void write(RandomAccessFile raf, RowBase t) throws IOException { + if (t instanceof PairEntry.Row) { + raf.writeByte(0); + } else if (t instanceof TokenRow) { + final TokenRow tokenRow = (TokenRow) t; + raf.writeByte(tokenRow.hasMainEntry ? 1 : 3); + } else if (t instanceof TextEntry.Row) { + raf.writeByte(2); + } else if (t instanceof HtmlEntry.Row) { + raf.writeByte(4); + } + raf.writeInt(t.referenceIndex); + } } - } - - public static final class LengthComparator implements Comparator { - - final boolean swapPairEntries; - - public LengthComparator(boolean swapPairEntries) { - this.swapPairEntries = swapPairEntries; + + public static final class LengthComparator implements Comparator { + + final boolean swapPairEntries; + + public LengthComparator(boolean swapPairEntries) { + this.swapPairEntries = swapPairEntries; + } + + @Override + public int compare(RowBase row1, RowBase row2) { + final int l1 = row1.getSideLength(swapPairEntries); + final int l2 = row2.getSideLength(swapPairEntries); + return l1 < l2 ? -1 : l1 == l2 ? 0 : 1; + } } - @Override - public int compare(RowBase row1, RowBase row2) { - final int l1 = row1.getSideLength(swapPairEntries); - final int l2 = row2.getSideLength(swapPairEntries); - return l1 < l2 ? -1 : l1 == l2 ? 0 : 1; + public int getSideLength(boolean swapPairEntries) { + return getRawText(false).length(); } - } - public int getSideLength(boolean swapPairEntries) { - return getRawText(false).length(); - } - } diff --git a/src/com/hughes/android/dictionary/engine/TextEntry.java b/src/com/hughes/android/dictionary/engine/TextEntry.java index a003ca9..2837626 100644 --- a/src/com/hughes/android/dictionary/engine/TextEntry.java +++ b/src/com/hughes/android/dictionary/engine/TextEntry.java @@ -25,79 +25,80 @@ import java.util.List; import java.util.regex.Pattern; public class TextEntry extends AbstractEntry implements RAFSerializable { - - final String text; - - public TextEntry(final Dictionary dictionary, final RandomAccessFile raf, final int index) throws IOException { - super(dictionary, raf, index); - text = raf.readUTF(); - throw new RuntimeException(); - } - @Override - public void write(RandomAccessFile raf) throws IOException { - super.write(raf); - raf.writeUTF(text); - } - - static final class Serializer implements RAFListSerializer { - - final Dictionary dictionary; - - Serializer(Dictionary dictionary) { - this.dictionary = dictionary; - } - @Override - public TextEntry read(RandomAccessFile raf, final int index) throws IOException { - return new TextEntry(dictionary, raf, index); - } + final String text; - @Override - public void write(RandomAccessFile raf, TextEntry t) throws IOException { - t.write(raf); - } - }; - - - @Override - public void addToDictionary(final Dictionary dictionary) { - assert index == -1; - dictionary.textEntries.add(this); - index = dictionary.textEntries.size() - 1; - } - - @Override - public RowBase CreateRow(int rowIndex, Index dictionaryIndex) { - throw new UnsupportedOperationException("TextEntry's don't really exist."); - } - - public static class Row extends RowBase { - - Row(final RandomAccessFile raf, final int thisRowIndex, - final Index index) throws IOException { - super(raf, thisRowIndex, index); + public TextEntry(final Dictionary dictionary, final RandomAccessFile raf, final int index) + throws IOException { + super(dictionary, raf, index); + text = raf.readUTF(); + throw new RuntimeException(); } - - public TextEntry getEntry() { - return index.dict.textEntries.get(referenceIndex); - } - + @Override - public void print(PrintStream out) { - out.println(" " + getEntry().text); + public void write(RandomAccessFile raf) throws IOException { + super.write(raf); + raf.writeUTF(text); } + static final class Serializer implements RAFListSerializer { + + final Dictionary dictionary; + + Serializer(Dictionary dictionary) { + this.dictionary = dictionary; + } + + @Override + public TextEntry read(RandomAccessFile raf, final int index) throws IOException { + return new TextEntry(dictionary, raf, index); + } + + @Override + public void write(RandomAccessFile raf, TextEntry t) throws IOException { + t.write(raf); + } + }; + @Override - public String getRawText(boolean compact) { - return getEntry().text; + public void addToDictionary(final Dictionary dictionary) { + assert index == -1; + dictionary.textEntries.add(this); + index = dictionary.textEntries.size() - 1; } - + @Override - public RowMatchType matches(final List searchTokens, final Pattern orderedMatchPattern, Transliterator normalizer, boolean swapPairEntries) { - return null; + public RowBase CreateRow(int rowIndex, Index dictionaryIndex) { + throw new UnsupportedOperationException("TextEntry's don't really exist."); } - } + public static class Row extends RowBase { + + Row(final RandomAccessFile raf, final int thisRowIndex, + final Index index) throws IOException { + super(raf, thisRowIndex, index); + } + public TextEntry getEntry() { + return index.dict.textEntries.get(referenceIndex); + } + + @Override + public void print(PrintStream out) { + out.println(" " + getEntry().text); + } + + @Override + public String getRawText(boolean compact) { + return getEntry().text; + } + + @Override + public RowMatchType matches(final List searchTokens, + final Pattern orderedMatchPattern, Transliterator normalizer, + boolean swapPairEntries) { + return null; + } + } } diff --git a/src/com/hughes/android/dictionary/engine/TokenRow.java b/src/com/hughes/android/dictionary/engine/TokenRow.java index d4acc23..2f31fec 100644 --- a/src/com/hughes/android/dictionary/engine/TokenRow.java +++ b/src/com/hughes/android/dictionary/engine/TokenRow.java @@ -24,59 +24,61 @@ import java.util.List; import java.util.regex.Pattern; public class TokenRow extends RowBase { - - public final boolean hasMainEntry; - - TokenRow(final RandomAccessFile raf, final int thisRowIndex, final Index index, final boolean hasMainEntry) throws IOException { - super(raf, thisRowIndex, index); - this.hasMainEntry = hasMainEntry; - } - - TokenRow(final int referenceIndex, final int thisRowIndex, final Index index, final boolean hasMainEntry) { - super(referenceIndex, thisRowIndex, index); - this.hasMainEntry = hasMainEntry; - } - - public String toString() { - return getToken() + "@" + referenceIndex; - } - - @Override - public TokenRow getTokenRow(final boolean search) { - return this; - } - - @Override - public void setTokenRow(TokenRow tokenRow) { - throw new RuntimeException("Shouldn't be setting TokenRow's TokenRow!"); - } - - public String getToken() { - return getIndexEntry().token; - } - - public IndexEntry getIndexEntry() { - return index.sortedIndexEntries.get(referenceIndex); - } - - @Override - public void print(final PrintStream out) { - final String surrounder = hasMainEntry ? "***" : "==="; - out.println(surrounder + getToken() + surrounder); - for (final HtmlEntry htmlEntry : index.sortedIndexEntries.get(referenceIndex).htmlEntries) { - out.println("HtmlEntry: " + htmlEntry.title + " <<<" + htmlEntry.getHtml() + ">>>"); + + public final boolean hasMainEntry; + + TokenRow(final RandomAccessFile raf, final int thisRowIndex, final Index index, + final boolean hasMainEntry) throws IOException { + super(raf, thisRowIndex, index); + this.hasMainEntry = hasMainEntry; } - } - @Override - public String getRawText(boolean compact) { - return getToken(); - } + TokenRow(final int referenceIndex, final int thisRowIndex, final Index index, + final boolean hasMainEntry) { + super(referenceIndex, thisRowIndex, index); + this.hasMainEntry = hasMainEntry; + } - @Override - public RowMatchType matches(List searchTokens, final Pattern orderedMatchPattern, Transliterator normalizer, boolean swapPairEntries) { - return RowMatchType.NO_MATCH; - } + public String toString() { + return getToken() + "@" + referenceIndex; + } + @Override + public TokenRow getTokenRow(final boolean search) { + return this; + } + + @Override + public void setTokenRow(TokenRow tokenRow) { + throw new RuntimeException("Shouldn't be setting TokenRow's TokenRow!"); + } + + public String getToken() { + return getIndexEntry().token; + } + + public IndexEntry getIndexEntry() { + return index.sortedIndexEntries.get(referenceIndex); + } + + @Override + public void print(final PrintStream out) { + final String surrounder = hasMainEntry ? "***" : "==="; + out.println(surrounder + getToken() + surrounder); + for (final HtmlEntry htmlEntry : index.sortedIndexEntries.get(referenceIndex).htmlEntries) { + out.println("HtmlEntry: " + htmlEntry.title + " <<<" + htmlEntry.getHtml() + ">>>"); + } + } + + @Override + public String getRawText(boolean compact) { + return getToken(); + } + + @Override + public RowMatchType matches(List searchTokens, final Pattern orderedMatchPattern, + Transliterator normalizer, boolean swapPairEntries) { + return RowMatchType.NO_MATCH; + } } diff --git a/src/com/hughes/android/dictionary/engine/TransliteratorManager.java b/src/com/hughes/android/dictionary/engine/TransliteratorManager.java index c7ef4a2..d211bd8 100644 --- a/src/com/hughes/android/dictionary/engine/TransliteratorManager.java +++ b/src/com/hughes/android/dictionary/engine/TransliteratorManager.java @@ -21,51 +21,53 @@ import java.util.List; public class TransliteratorManager { - private static boolean starting = false; - private static boolean ready = false; - - // Whom to notify when we're all set up and ready to go. - private static List callbacks = new ArrayList(); - - public static synchronized boolean init(final Callback callback) { - if (ready) { - return true; - } - if (callback != null) { - callbacks.add(callback); - } - if (!starting) { - starting = true; - new Thread(init).start(); + private static boolean starting = false; + private static boolean ready = false; + + // Whom to notify when we're all set up and ready to go. + private static List callbacks = new ArrayList(); + + public static synchronized boolean init(final Callback callback) { + if (ready) { + return true; + } + if (callback != null) { + callbacks.add(callback); + } + if (!starting) { + starting = true; + new Thread(init).start(); + } + return false; } - return false; - } - - private static final Runnable init = new Runnable() { - @Override - public void run() { - System.out.println("Starting Transliterator load."); - final String transliterated = - Transliterator.createFromRules("", ":: Any-Latin; :: Lower; :: NFD; :: [:Nonspacing Mark:] Remove; :: NFC ;", - Transliterator.FORWARD).transliterate("Îñţérñåţîöñåļîžåţîờñ"); - if (!"internationalization".equals(transliterated)) { - System.out.println("Wrong transliteratation: " + transliterated); - } - final List callbacks = new ArrayList(); - synchronized (TransliteratorManager.class) { - callbacks.addAll(TransliteratorManager.callbacks); - ready = true; - } - for (final Callback callback : callbacks) { - callback.onTransliteratorReady(); - } + private static final Runnable init = new Runnable() { + @Override + public void run() { + System.out.println("Starting Transliterator load."); + final String transliterated = + Transliterator + .createFromRules( + "", + ":: Any-Latin; :: Lower; :: NFD; :: [:Nonspacing Mark:] Remove; :: NFC ;", + Transliterator.FORWARD).transliterate("Îñţérñåţîöñåļîžåţîờñ"); + if (!"internationalization".equals(transliterated)) { + System.out.println("Wrong transliteratation: " + transliterated); + } + + final List callbacks = new ArrayList(); + synchronized (TransliteratorManager.class) { + callbacks.addAll(TransliteratorManager.callbacks); + ready = true; + } + for (final Callback callback : callbacks) { + callback.onTransliteratorReady(); + } + } + }; + + public interface Callback { + void onTransliteratorReady(); } - }; - - - public interface Callback { - void onTransliteratorReady(); - } } diff --git a/src/com/hughes/android/util/IntentLauncher.java b/src/com/hughes/android/util/IntentLauncher.java index 036f46c..edb1195 100644 --- a/src/com/hughes/android/util/IntentLauncher.java +++ b/src/com/hughes/android/util/IntentLauncher.java @@ -1,3 +1,4 @@ + package com.hughes.android.util; import android.content.Context; @@ -6,27 +7,26 @@ import android.view.View; import android.view.View.OnClickListener; public class IntentLauncher implements OnClickListener { - - final Context context; - final Intent intent; - - public IntentLauncher(final Context context, final Intent intent) { - this.context = context; - this.intent = intent; - } - - protected void onGo() { - } - - - private void go() { - onGo(); - context.startActivity(intent); - } - - @Override - public void onClick(View v) { - go(); - } + + final Context context; + final Intent intent; + + public IntentLauncher(final Context context, final Intent intent) { + this.context = context; + this.intent = intent; + } + + protected void onGo() { + } + + private void go() { + onGo(); + context.startActivity(intent); + } + + @Override + public void onClick(View v) { + go(); + } } diff --git a/src/com/hughes/android/util/NonLinkClickableSpan.java b/src/com/hughes/android/util/NonLinkClickableSpan.java index a590d38..46857d7 100644 --- a/src/com/hughes/android/util/NonLinkClickableSpan.java +++ b/src/com/hughes/android/util/NonLinkClickableSpan.java @@ -24,7 +24,7 @@ public class NonLinkClickableSpan extends ClickableSpan { // each span. final int color; - + public NonLinkClickableSpan(int color) { this.color = color; } @@ -32,7 +32,7 @@ public class NonLinkClickableSpan extends ClickableSpan { // Won't see these on a long-click. @Override public void onClick(View widget) { - // Don't need to do anything. These spans are just used to see where + // Don't need to do anything. These spans are just used to see where // the user long-pressed. } diff --git a/src/com/hughes/android/util/PersistentObjectCache.java b/src/com/hughes/android/util/PersistentObjectCache.java index a4b8cbf..388eb7a 100644 --- a/src/com/hughes/android/util/PersistentObjectCache.java +++ b/src/com/hughes/android/util/PersistentObjectCache.java @@ -28,74 +28,77 @@ import java.util.Map; public class PersistentObjectCache { - private final File dir; - private final Map objects = new LinkedHashMap(); - - public synchronized T read(final String filename, final Class resultClass) { - try { - Object object = (objects.get(filename)); - if (object != null) { - return resultClass.cast(object); - } - Log.d(getClass().getSimpleName(), "Cache miss."); - final File src = new File(dir, filename); - if (!src.canRead()) { - Log.d(getClass().getSimpleName(), "File empty: " + src); - return null; - } - try { - final ObjectInputStream in = new ObjectInputStream(new FileInputStream(src)); - object = in.readObject(); - in.close(); - } catch (Exception e) { - Log.e(getClass().getSimpleName(), "Deserialization failed: " + src, e); - return null; - } - objects.put(filename, object); - return resultClass.cast(object); - } catch (ClassCastException e) { - return null; + private final File dir; + private final Map objects = new LinkedHashMap(); + + public synchronized T read(final String filename, final Class resultClass) { + try { + Object object = (objects.get(filename)); + if (object != null) { + return resultClass.cast(object); + } + Log.d(getClass().getSimpleName(), "Cache miss."); + final File src = new File(dir, filename); + if (!src.canRead()) { + Log.d(getClass().getSimpleName(), "File empty: " + src); + return null; + } + try { + final ObjectInputStream in = new ObjectInputStream(new FileInputStream(src)); + object = in.readObject(); + in.close(); + } catch (Exception e) { + Log.e(getClass().getSimpleName(), "Deserialization failed: " + src, e); + return null; + } + objects.put(filename, object); + return resultClass.cast(object); + } catch (ClassCastException e) { + return null; + } } - } - - public synchronized void write(final String filename, final Object object) { - objects.put(filename, object); - final File dest = new File(dir, filename); - try { - final ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(dest)); - out.writeObject(object); - out.close(); - } catch (Exception e) { - Log.e(getClass().getSimpleName(), "Serialization failed: " + dest, e); + + public synchronized void write(final String filename, final Object object) { + objects.put(filename, object); + final File dest = new File(dir, filename); + try { + final ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(dest)); + out.writeObject(object); + out.close(); + } catch (Exception e) { + Log.e(getClass().getSimpleName(), "Serialization failed: " + dest, e); + } } - } - private PersistentObjectCache(final Context context) { - final File filesDir = context.getFilesDir(); - dir = filesDir != null ? filesDir : Environment.getExternalStorageDirectory(); - if (dir == null) { - throw new RuntimeException("context.getFilesDir() == " + context.getFilesDir() + ", Environment.getExternalStorageDirectory()=" + Environment.getExternalStorageDirectory()); + private PersistentObjectCache(final Context context) { + final File filesDir = context.getFilesDir(); + dir = filesDir != null ? filesDir : Environment.getExternalStorageDirectory(); + if (dir == null) { + throw new RuntimeException("context.getFilesDir() == " + context.getFilesDir() + + ", Environment.getExternalStorageDirectory()=" + + Environment.getExternalStorageDirectory()); + } } - } - - public static synchronized PersistentObjectCache getInstance() { - if (instance == null) { - throw new RuntimeException("getInstance called before init."); + + public static synchronized PersistentObjectCache getInstance() { + if (instance == null) { + throw new RuntimeException("getInstance called before init."); + } + return instance; } - return instance; - } - public static synchronized PersistentObjectCache init(final Context context) { - if (instance == null) { - instance = new PersistentObjectCache(context); - } else { - if (!instance.dir.equals(context.getFilesDir())) { - throw new RuntimeException("File dir changed. old=" + instance.dir + ", new=" + context.getFilesDir()); + public static synchronized PersistentObjectCache init(final Context context) { + if (instance == null) { + instance = new PersistentObjectCache(context); + } else { + if (!instance.dir.equals(context.getFilesDir())) { + throw new RuntimeException("File dir changed. old=" + instance.dir + ", new=" + + context.getFilesDir()); + } } - } - return instance; - } - - private static PersistentObjectCache instance = null; + return instance; + } + + private static PersistentObjectCache instance = null; } -- 2.43.0