From: Thad Hughes Date: Fri, 8 Oct 2010 22:15:14 +0000 (-0700) Subject: go X-Git-Url: https://gitweb.fperrin.net/?a=commitdiff_plain;h=63dc6ebb11356f45e95fe59069dc39649b592cfa;p=Dictionary.git go --- diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 5bff2e3..17f77d0 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,30 +1,39 @@ - - - - - - - - - - - + + + + + + + + + + + + + + - - - - + + + + + + diff --git a/default.properties b/default.properties index a1ef8e9..19c9665 100644 --- a/default.properties +++ b/default.properties @@ -10,4 +10,4 @@ # Indicates whether an apk should be generated for each density. split.density=false # Project target. -target=android-3 +target=android-4 diff --git a/res/layout/about.xml b/res/layout/about_activity.xml similarity index 100% rename from res/layout/about.xml rename to res/layout/about_activity.xml diff --git a/res/layout/main.xml b/res/layout/dictionary_activity.xml similarity index 100% rename from res/layout/main.xml rename to res/layout/dictionary_activity.xml diff --git a/res/layout/download.xml b/res/layout/download_activity.xml similarity index 100% rename from res/layout/download.xml rename to res/layout/download_activity.xml diff --git a/res/layout/edit_activity.xml b/res/layout/edit_activity.xml new file mode 100755 index 0000000..58e4b35 --- /dev/null +++ b/res/layout/edit_activity.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + String localFile = ""; + String wordList = ""; + + int openIndex = 0; + String openWord = ""; + + + + \ No newline at end of file diff --git a/res/layout/list_activity.xml b/res/layout/list_activity.xml new file mode 100644 index 0000000..037e137 --- /dev/null +++ b/res/layout/list_activity.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 3b2e929..c7925a1 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3,7 +3,22 @@ QuickDic QuickDic\nby Thad Hughes - + + + + Add dictionary + Edit dictionary config + Delete dictionary + Move up + New Dictionary + + + Dictionary name + Dictionary download URL + Dictionary file + Word list file + Search Text Download dictionary... diff --git a/res/values/theme.xml b/res/values/theme.xml new file mode 100644 index 0000000..720baa9 --- /dev/null +++ b/res/values/theme.xml @@ -0,0 +1,13 @@ + + + + diff --git a/src/com/hughes/android/dictionary/AboutActivity.java b/src/com/hughes/android/dictionary/AboutActivity.java index 065b0c4..9697ae6 100755 --- a/src/com/hughes/android/dictionary/AboutActivity.java +++ b/src/com/hughes/android/dictionary/AboutActivity.java @@ -6,19 +6,19 @@ import android.os.Bundle; import android.widget.TextView; public final class AboutActivity extends Activity { - + public static final String CURRENT_DICT_INFO = "currentDictInfo"; /** Called when the activity is first created. */ @Override public void onCreate(final Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.about); - - final Intent intent = getIntent(); - - final TextView currentDictInfo = (TextView) findViewById(R.id.currentDictInfo); - currentDictInfo.setText(intent.getStringExtra(CURRENT_DICT_INFO)); + super.onCreate(savedInstanceState); + setContentView(R.layout.about_activity); + + final Intent intent = getIntent(); + + final TextView currentDictInfo = (TextView) findViewById(R.id.currentDictInfo); + currentDictInfo.setText(intent.getStringExtra(CURRENT_DICT_INFO)); } } diff --git a/src/com/hughes/android/dictionary/Dictionary.java b/src/com/hughes/android/dictionary/Dictionary.java index 3133e28..c0a3588 100755 --- a/src/com/hughes/android/dictionary/Dictionary.java +++ b/src/com/hughes/android/dictionary/Dictionary.java @@ -18,8 +18,7 @@ public final class Dictionary implements RAFSerializable { private static final String VERSION_CODE = "DictionaryVersion=2.0"; - static final RAFSerializer ENTRY_SERIALIZER = new RAFSerializableSerializer( - SimpleEntry.RAF_FACTORY); + static final RAFSerializer ENTRY_SERIALIZER = null; static final RAFSerializer ROW_SERIALIZER = new RAFSerializableSerializer( Row.RAF_FACTORY); static final RAFSerializer INDEX_ENTRY_SERIALIZER = new RAFSerializableSerializer( @@ -41,8 +40,7 @@ public final class Dictionary implements RAFSerializable { public Dictionary(final RandomAccessFile raf) throws IOException { dictionaryInfo = raf.readUTF(); sources = new ArrayList(RAFList.create(raf, RAFSerializer.STRING, raf.getFilePointer())); - entries = CachingList.create(RAFList.create(raf, ENTRY_SERIALIZER, raf - .getFilePointer()), 10000); + entries = null; languageDatas[0] = new LanguageData(this, raf, SimpleEntry.LANG1); languageDatas[1] = new LanguageData(this, raf, SimpleEntry.LANG2); final String version = raf.readUTF(); @@ -54,7 +52,7 @@ public final class Dictionary implements RAFSerializable { public void write(RandomAccessFile raf) throws IOException { raf.writeUTF(dictionaryInfo); RAFList.write(raf, sources, RAFSerializer.STRING); - RAFList.write(raf, entries, ENTRY_SERIALIZER); + //RAFList.write(raf, entries, ENTRY_SERIALIZER); languageDatas[0].write(raf); languageDatas[1].write(raf); raf.writeUTF(VERSION_CODE); @@ -95,8 +93,9 @@ public final class Dictionary implements RAFSerializable { } String rowToString(final Row row, final boolean onlyFirstSubentry) { - return row.isToken() ? sortedIndex.get(row.getIndex()).word : entries - .get(row.getIndex()).getRawText(onlyFirstSubentry); + return null; + //return row.isToken() ? sortedIndex.get(row.getIndex()).word : entries + // .get(row.getIndex()).getRawText(onlyFirstSubentry); } int lookup(String word, final AtomicBoolean interrupted) { diff --git a/src/com/hughes/android/dictionary/DictionaryActivity.java b/src/com/hughes/android/dictionary/DictionaryActivity.java index e8d188f..d6a6ff1 100644 --- a/src/com/hughes/android/dictionary/DictionaryActivity.java +++ b/src/com/hughes/android/dictionary/DictionaryActivity.java @@ -55,6 +55,7 @@ import com.ibm.icu.text.Collator; public class DictionaryActivity extends ListActivity { // TO DO: + // * Easy reverse lookup. // * Download latest dicts. // * http://ftp.tu-chemnitz.de/pub/Local/urz/ding/de-en-devel/ // * http://www1.dict.cc/translation_file_request.php?l=e @@ -118,7 +119,7 @@ public class DictionaryActivity extends ListActivity { // UI init. - setContentView(R.layout.main); + setContentView(R.layout.dictionary_activity); searchText = (EditText) findViewById(R.id.SearchText); langButton = (Button) findViewById(R.id.LangButton); @@ -592,7 +593,7 @@ public class DictionaryActivity extends ListActivity { // Entry row(s). final TableLayout result = new TableLayout(parent.getContext()); - final SimpleEntry entry = dictionary.entries.get(row.getIndex()); + final SimpleEntry entry = new SimpleEntry(null, null);//.entries.get(row.getIndex()); final int rowCount = entry.getRowCount(); for (int r = 0; r < rowCount; ++r) { final TableRow tableRow = new TableRow(result.getContext()); diff --git a/src/com/hughes/android/dictionary/DictionaryConfig.java b/src/com/hughes/android/dictionary/DictionaryConfig.java new file mode 100644 index 0000000..1c2458b --- /dev/null +++ b/src/com/hughes/android/dictionary/DictionaryConfig.java @@ -0,0 +1,26 @@ +package com.hughes.android.dictionary; + +import java.io.Serializable; + +public class DictionaryConfig implements Serializable { + + private static final long serialVersionUID = -6850863377577700387L; + + String name = ""; + String localFile = "/sdcard/quickDic/"; + String wordList = "/sdcard/quickDic/"; + String downloadUrl = "http://"; + + int openIndex = 0; + String openWord = ""; + + static DictionaryConfig defaultConfig() { + final DictionaryConfig result = new DictionaryConfig(); + result.name = "DE<->EN"; + result.downloadUrl = "http://www.stanford.edu/~egirard/dict/de-en.2.dict"; + result.localFile = "/sdcard/quickDic/de-en.dict"; + result.wordList = "/sdcard/quickDict/wordlist_de-en.txt"; + return result; + } + +} diff --git a/src/com/hughes/android/dictionary/DictionaryEditActivity.java b/src/com/hughes/android/dictionary/DictionaryEditActivity.java new file mode 100644 index 0000000..3c2f5a0 --- /dev/null +++ b/src/com/hughes/android/dictionary/DictionaryEditActivity.java @@ -0,0 +1,79 @@ +package com.hughes.android.dictionary; + +import java.util.List; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; +import android.widget.EditText; + +import com.hughes.android.util.PersistentObjectCache; + +public class DictionaryEditActivity extends Activity { + + List dictionaryConfigs; + private DictionaryConfig dictionaryConfig; + + public static final String DICT_INDEX = "dictIndex"; + + /** Called when the activity is first created. */ + @SuppressWarnings("unchecked") + @Override + public void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.edit_activity); + + PersistentObjectCache.init(this); + dictionaryConfigs = (List) PersistentObjectCache.init( + this).read(DictionaryListActivity.DICTIONARY_CONFIGS); + + final Intent intent = getIntent(); + dictionaryConfig = dictionaryConfigs.get(intent.getIntExtra(DICT_INDEX, 0)); + + // Write stuff from object into fields. + + ((EditText) findViewById(R.id.dictionaryName)).setText(dictionaryConfig.name); + ((EditText) findViewById(R.id.localFile)).setText(dictionaryConfig.localFile); + ((EditText) findViewById(R.id.wordListFile)).setText(dictionaryConfig.wordList); + ((EditText) findViewById(R.id.downloadUrl)).setText(dictionaryConfig.downloadUrl); + } + + @Override + protected void onPause() { + super.onPause(); + + // Read stuff from fields into object. + dictionaryConfig.name = ((EditText) findViewById(R.id.dictionaryName)).getText().toString(); + dictionaryConfig.localFile = ((EditText) findViewById(R.id.localFile)).getText().toString(); + dictionaryConfig.wordList = ((EditText) findViewById(R.id.wordListFile)).getText().toString(); + dictionaryConfig.downloadUrl = ((EditText) findViewById(R.id.downloadUrl)).getText().toString(); + + PersistentObjectCache.getInstance().write( + DictionaryListActivity.DICTIONARY_CONFIGS, dictionaryConfigs); + } + + public boolean onCreateOptionsMenu(final Menu menu) { + final MenuItem newDictionaryMenuItem = menu.add(R.string.downloadDictionary); + newDictionaryMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(final MenuItem menuItem) { + startDownloadDictActivity(DictionaryEditActivity.this, dictionaryConfig); + return false; + } + }); + + return true; + } + + static void startDownloadDictActivity(final Context context, final DictionaryConfig dictionaryConfig) { + final Intent intent = new Intent(context, DownloadActivity.class); + intent.putExtra(DownloadActivity.SOURCE, dictionaryConfig.downloadUrl); + intent.putExtra(DownloadActivity.DEST, dictionaryConfig.localFile); + context.startActivity(intent); + } + + +} diff --git a/src/com/hughes/android/dictionary/DictionaryListActivity.java b/src/com/hughes/android/dictionary/DictionaryListActivity.java new file mode 100644 index 0000000..faeb8fe --- /dev/null +++ b/src/com/hughes/android/dictionary/DictionaryListActivity.java @@ -0,0 +1,192 @@ +package com.hughes.android.dictionary; + +import java.util.ArrayList; +import java.util.List; + +import android.app.ListActivity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.ContextMenu; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.view.ContextMenu.ContextMenuInfo; +import android.view.MenuItem.OnMenuItemClickListener; +import android.view.View.OnFocusChangeListener; +import android.widget.AdapterView; +import android.widget.BaseAdapter; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.TableLayout; +import android.widget.TextView; +import android.widget.AdapterView.AdapterContextMenuInfo; + +import com.hughes.android.util.PersistentObjectCache; + +public class DictionaryListActivity extends ListActivity { + + static final String LOG = "QuickDic"; + + static final String DICTIONARY_CONFIGS = "dictionaryConfigs"; + + List dictionaries = new ArrayList(); + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.d(LOG, "onCreate:" + this); + + // UI init. + setContentView(R.layout.list_activity); + + getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { + public boolean onItemLongClick(AdapterView arg0, View arg1, int row, + long arg3) { + return false; + } + }); + + // ContextMenu. + registerForContextMenu(getListView()); + + getListView().setItemsCanFocus(true); + } + + @SuppressWarnings("unchecked") + @Override + protected void onResume() { + super.onResume(); + + dictionaries = (List) PersistentObjectCache.init(this).read(DICTIONARY_CONFIGS); + if (dictionaries == null) { + dictionaries = new ArrayList(); + } + if (dictionaries.size() == 0) { + final DictionaryConfig dictionaryConfig = DictionaryConfig.defaultConfig(); + dictionaries.add(dictionaryConfig); + PersistentObjectCache.getInstance().write(DICTIONARY_CONFIGS, dictionaries); + } + + setListAdapter(new Adapter()); + } + + public boolean onCreateOptionsMenu(final Menu menu) { + final MenuItem newDictionaryMenuItem = menu.add(R.string.addDictionary); + newDictionaryMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { + public boolean onMenuItemClick(final MenuItem menuItem) { + final DictionaryConfig dictionaryConfig = new DictionaryConfig(); + dictionaryConfig.name = getString(R.string.newDictionary); + dictionaries.add(0, dictionaryConfig); + dictionaryConfigsChanged(); + return false; + } + }); + + return true; + } + + + @Override + public void onCreateContextMenu(final ContextMenu menu, final View view, + final ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, view, menuInfo); + + final AdapterContextMenuInfo adapterContextMenuInfo = (AdapterContextMenuInfo) menuInfo; + + final MenuItem editMenuItem = menu.add(R.string.editDictionary); + editMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + final Intent intent = new Intent(DictionaryListActivity.this, DictionaryEditActivity.class); + intent.putExtra(DictionaryEditActivity.DICT_INDEX, adapterContextMenuInfo.position); + startActivity(intent); + return true; + } + }); + + if (adapterContextMenuInfo.position > 0) { + final MenuItem moveUpMenuItem = menu.add(R.string.moveUp); + moveUpMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + final DictionaryConfig dictionaryConfig = dictionaries.remove(adapterContextMenuInfo.position); + dictionaries.add(adapterContextMenuInfo.position - 1, dictionaryConfig); + dictionaryConfigsChanged(); + return true; + } + }); + } + + final MenuItem deleteMenuItem = menu.add(R.string.deleteDictionary); + deleteMenuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + dictionaries.remove(adapterContextMenuInfo.position); + dictionaryConfigsChanged(); + return true; + } + }); + + } + + private void dictionaryConfigsChanged() { + PersistentObjectCache.getInstance().write(DICTIONARY_CONFIGS, dictionaries); + setListAdapter(getListAdapter()); + } + + static final OnFocusChangeListener focusListener = new OnFocusChangeListener() { + @Override + public void onFocusChange(View v, boolean hasFocus) { + final TextView textView = (TextView) v; + if (hasFocus) { + textView.setTextAppearance(v.getContext(), R.style.Theme_QuickDic); + } else { + //textView.setTextAppearance(v.getContext(), android.R.style.TextAppearance_Medium); + } + } + }; + + + class Adapter extends BaseAdapter { + + @Override + public int getCount() { + return dictionaries.size(); + } + + @Override + public DictionaryConfig getItem(int position) { + return dictionaries.get(position); + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + final DictionaryConfig dictionaryConfig = getItem(position); + final TableLayout tableLayout = new TableLayout(parent.getContext()); + final TextView view = new TextView(parent.getContext()); + + view.setText(dictionaryConfig.name); + view.setTextSize(20); + view.setFocusable(true); + view.setOnFocusChangeListener(focusListener); + tableLayout.addView(view); + + final EditText view2 = new EditText(parent.getContext()); + view2.setText(dictionaryConfig.name + "2"); + view2.setFocusable(true); + view2.setOnFocusChangeListener(focusListener); + tableLayout.addView(view2); + + return tableLayout; + } + + } + + +} diff --git a/src/com/hughes/android/dictionary/DownloadActivity.java b/src/com/hughes/android/dictionary/DownloadActivity.java index cff7463..fca603a 100755 --- a/src/com/hughes/android/dictionary/DownloadActivity.java +++ b/src/com/hughes/android/dictionary/DownloadActivity.java @@ -43,7 +43,7 @@ public class DownloadActivity extends Activity { if (source == null || dest == null) { throw new RuntimeException("null source or dest."); } - setContentView(R.layout.download); + setContentView(R.layout.download_activity); final TextView sourceTextView = (TextView) findViewById(R.id.source); sourceTextView.setText(source); diff --git a/src/com/hughes/android/dictionary/Entry.java b/src/com/hughes/android/dictionary/Entry.java index fb95f4c..b5ba715 100644 --- a/src/com/hughes/android/dictionary/Entry.java +++ b/src/com/hughes/android/dictionary/Entry.java @@ -6,7 +6,7 @@ import java.io.RandomAccessFile; import com.hughes.util.raf.RAFFactory; import com.hughes.util.raf.RAFSerializable; -public abstract class Entry implements RAFSerializable { +public interface Entry extends RAFSerializable { public static final RAFFactory RAF_FACTORY = new RAFFactory() { public Entry create(RandomAccessFile raf) throws IOException { diff --git a/src/com/hughes/android/dictionary/Language.java b/src/com/hughes/android/dictionary/Language.java index 0f53d7f..9732efa 100755 --- a/src/com/hughes/android/dictionary/Language.java +++ b/src/com/hughes/android/dictionary/Language.java @@ -11,7 +11,6 @@ public class Language { static final Map symbolToLangauge = new LinkedHashMap(); - final String symbol; final Locale locale; @@ -53,7 +52,7 @@ public class Language { return symbol; } - synchronized Collator getFindCollator() { + public synchronized Collator getFindCollator() { if (findCollator == null) { findCollator = Collator.getInstance(locale); findCollator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); @@ -62,7 +61,7 @@ public class Language { return findCollator; } - synchronized Collator getSortCollator() { + public synchronized Collator getSortCollator() { if (sortCollator == null) { sortCollator = Collator.getInstance(locale); sortCollator.setDecomposition(Collator.CANONICAL_DECOMPOSITION); @@ -113,7 +112,7 @@ public class Language { // ---------------------------------------------------------------- - static Language lookup(final String symbol) { + public static Language lookup(final String symbol) { return symbolToLangauge.get(symbol.toLowerCase()); } diff --git a/src/com/hughes/android/dictionary/SimpleEntry.java b/src/com/hughes/android/dictionary/SimpleEntry.java index d90d51f..4ee8dd4 100755 --- a/src/com/hughes/android/dictionary/SimpleEntry.java +++ b/src/com/hughes/android/dictionary/SimpleEntry.java @@ -2,18 +2,15 @@ package com.hughes.android.dictionary; import java.io.IOException; import java.io.RandomAccessFile; -import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.LinkedHashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.hughes.util.raf.RAFFactory; -import com.hughes.util.raf.RAFSerializable; public final class SimpleEntry implements Entry { @@ -177,7 +174,7 @@ Zp Separator, Paragraph // This used to be called WHITESPACE. static final Pattern NON_TOKEN_CHAR = Pattern.compile("\\s+"); - public Map getIndexableTokens(final byte lang) { + public Set getIndexableTokens(final byte lang) { final Set result = new LinkedHashSet(); String text = " "; for (final String subentry : getAllText(lang)) { diff --git a/src/com/hughes/android/dictionary/engine/Dictionary.java b/src/com/hughes/android/dictionary/engine/Dictionary.java index cea0c7d..1472d31 100644 --- a/src/com/hughes/android/dictionary/engine/Dictionary.java +++ b/src/com/hughes/android/dictionary/engine/Dictionary.java @@ -1,48 +1,74 @@ package com.hughes.android.dictionary.engine; import java.io.IOException; +import java.io.PrintStream; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.List; +import com.hughes.util.CachingList; import com.hughes.util.raf.RAFList; -import com.hughes.util.raf.RAFSerializer; +import com.hughes.util.raf.RAFListSerializer; +import com.hughes.util.raf.RAFSerializable; -public class Dictionary { +public class Dictionary implements RAFSerializable { // persisted + final String dictInfo; final List pairEntries; - - // persisted + final List textEntries; final List sources; - - // persisted final List indices; - public Dictionary() { + public Dictionary(final String dictInfo) { + this.dictInfo = dictInfo; pairEntries = new ArrayList(); + textEntries = new ArrayList(); sources = new ArrayList(); indices = new ArrayList(); } public Dictionary(final RandomAccessFile raf) throws IOException { - pairEntries = RAFList.create(raf, PairEntry.SERIALIZER, raf.getFilePointer()); - sources = new ArrayList(); + dictInfo = raf.readUTF(); - final RAFSerializer indexSerializer = new RAFSerializer() { + sources = RAFList.create(raf, EntrySource.SERIALIZER, raf.getFilePointer()); - @Override - public Index read(RandomAccessFile raf) throws IOException { - return new Index(Dictionary.this, raf); - } + // TODO: caching + pairEntries = RAFList.create(raf, PairEntry.SERIALIZER, raf.getFilePointer()); - @Override - public void write(RandomAccessFile raf, Index t) throws IOException { - t.write(raf); - - }}; - indices = RAFList.create(raf, indexSerializer, raf.getFilePointer()); + // TODO: caching + textEntries = RAFList.create(raf, TextEntry.SERIALIZER, raf.getFilePointer()); + + final List rawIndices = RAFList.create(raf, indexSerializer, raf.getFilePointer()); + indices = CachingList.create(rawIndices, rawIndices.size()); } + public void print(final PrintStream out) { + out.println("dictInfo=" + dictInfo); + for (final Index index : indices) { + index.print(out); + out.println(); + } + } + + @Override + public void write(RandomAccessFile raf) throws IOException { + raf.writeUTF(dictInfo); + RAFList.write(raf, sources, EntrySource.SERIALIZER); + RAFList.write(raf, pairEntries, PairEntry.SERIALIZER); + RAFList.write(raf, textEntries, TextEntry.SERIALIZER); + RAFList.write(raf, indices, indexSerializer); + } + + 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); + }}; + } \ No newline at end of file diff --git a/src/com/hughes/android/dictionary/engine/Entry.java b/src/com/hughes/android/dictionary/engine/Entry.java index af279c1..9efd1f5 100644 --- a/src/com/hughes/android/dictionary/engine/Entry.java +++ b/src/com/hughes/android/dictionary/engine/Entry.java @@ -1,12 +1,8 @@ package com.hughes.android.dictionary.engine; -import java.util.List; public abstract class Entry { EntrySource entrySource; - - abstract List getMainTokens(); - abstract List getOtherTokens(); - + } diff --git a/src/com/hughes/android/dictionary/engine/EntrySource.java b/src/com/hughes/android/dictionary/engine/EntrySource.java index f773f60..914cf8f 100644 --- a/src/com/hughes/android/dictionary/engine/EntrySource.java +++ b/src/com/hughes/android/dictionary/engine/EntrySource.java @@ -1,8 +1,11 @@ package com.hughes.android.dictionary.engine; +import java.io.IOException; +import java.io.RandomAccessFile; import java.io.Serializable; import com.hughes.util.IndexedObject; +import com.hughes.util.raf.RAFListSerializer; public class EntrySource extends IndexedObject implements Serializable { @@ -10,8 +13,25 @@ public class EntrySource extends IndexedObject implements Serializable { final String name; - public EntrySource(final String name) { + public EntrySource(final int index, final String name) { + super(index); this.name = name; } + public static RAFListSerializer SERIALIZER = new RAFListSerializer() { + + @Override + public EntrySource read(RandomAccessFile raf, int readIndex) + throws IOException { + final String name = raf.readUTF(); + return new EntrySource(readIndex, name); + } + + @Override + public void write(RandomAccessFile raf, EntrySource t) throws IOException { + raf.writeUTF(t.name); + } + + }; + } diff --git a/src/com/hughes/android/dictionary/engine/EntryTypeName.java b/src/com/hughes/android/dictionary/engine/EntryTypeName.java new file mode 100644 index 0000000..008da6a --- /dev/null +++ b/src/com/hughes/android/dictionary/engine/EntryTypeName.java @@ -0,0 +1,34 @@ +package com.hughes.android.dictionary.engine; + + +public enum EntryTypeName { + + NOUN(0), + VERB(0), + ADJ(0), + ADV(0), + ONE_WORD(0), + MULTIROW_HEAD_ONE_WORD(0), + MULTIROW_TAIL_ONE_WORD(0), + + TWO_WORDS(0), + THREE_WORDS(0), + FOUR_WORDS(0), + FIVE_OR_MORE_WORDS(0), + + WIKTIONARY_DE_MAIN(0), + MULTIROW_HEAD_MANY_WORDS(0), + MULTIROW_TAIL_MANY_WORDS(0), + PART_OF_HYPHENATED(0), + BRACKETED(0), + PARENTHESIZED(0), + SEE_ALSO(0), + ; + + final int nameResId; + + private EntryTypeName(final int nameResId) { + this.nameResId = nameResId; + } + +} diff --git a/src/com/hughes/android/dictionary/engine/Index.java b/src/com/hughes/android/dictionary/engine/Index.java index 9185d9d..4953600 100644 --- a/src/com/hughes/android/dictionary/engine/Index.java +++ b/src/com/hughes/android/dictionary/engine/Index.java @@ -4,23 +4,29 @@ package com.hughes.android.dictionary.engine; import java.io.IOException; +import java.io.PrintStream; import java.io.RandomAccessFile; +import java.util.ArrayList; import java.util.Collection; import java.util.List; +import com.hughes.android.dictionary.Language; import com.hughes.util.raf.RAFList; import com.hughes.util.raf.RAFSerializable; import com.hughes.util.raf.RAFSerializer; import com.hughes.util.raf.UniformRAFList; -final class Index implements RAFSerializable { +public final class Index implements RAFSerializable { final Dictionary dict; final String shortName; final String longName; + + // persisted: tells how the entries are sorted. + final Language sortLanguage; // persisted - final List sortedIndexEntries; + final List sortedIndexEntries; // One big list! // Various sub-types. @@ -29,18 +35,40 @@ final class Index implements RAFSerializable { // -------------------------------------------------------------------------- + public Index(final Dictionary dict, final String shortName, final String longName, final Language sortLanguage) { + this.dict = dict; + this.shortName = shortName; + this.longName = longName; + this.sortLanguage = sortLanguage; + sortedIndexEntries = new ArrayList(); + rows = new ArrayList(); + } + 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); + if (sortLanguage == null) { + throw new IOException("Unsupported language: " + languageCode); + } // TODO: caching sortedIndexEntries = RAFList.create(raf, IndexEntry.SERIALIZER, raf.getFilePointer()); rows = UniformRAFList.create(raf, new RowBase.Serializer(this), raf.getFilePointer()); } + + public void print(final PrintStream out) { + for (final RowBase row : rows) { + row.print(out); + } + } + @Override public void write(final RandomAccessFile raf) throws IOException { raf.writeUTF(shortName); raf.writeUTF(longName); + raf.writeUTF(sortLanguage.getSymbol()); RAFList.write(raf, sortedIndexEntries, IndexEntry.SERIALIZER); UniformRAFList.write(raf, (Collection) rows, new RowBase.Serializer(this), 5); } @@ -49,6 +77,7 @@ final class Index implements RAFSerializable { static final class IndexEntry implements RAFSerializable { String token; int startRow; + static final RAFSerializer SERIALIZER = new RAFSerializer () { @Override public IndexEntry read(RandomAccessFile raf) throws IOException { @@ -58,10 +87,19 @@ final class Index implements RAFSerializable { public void write(RandomAccessFile raf, IndexEntry t) throws IOException { t.write(raf); }}; + + public IndexEntry(final String token, final int startRow) { + assert token.equals(token.trim()); + assert token.length() > 0; + this.token = token; + this.startRow = startRow; + } + public IndexEntry(final RandomAccessFile raf) throws IOException { token = raf.readUTF(); startRow = raf.readInt(); } + public void write(RandomAccessFile raf) throws IOException { raf.writeUTF(token); raf.write(startRow); diff --git a/src/com/hughes/android/dictionary/engine/PairEntry.java b/src/com/hughes/android/dictionary/engine/PairEntry.java index e22969e..55c32d0 100644 --- a/src/com/hughes/android/dictionary/engine/PairEntry.java +++ b/src/com/hughes/android/dictionary/engine/PairEntry.java @@ -1,18 +1,46 @@ package com.hughes.android.dictionary.engine; import java.io.IOException; +import java.io.PrintStream; import java.io.RandomAccessFile; -import java.util.List; import com.hughes.util.raf.RAFSerializable; import com.hughes.util.raf.RAFSerializer; public class PairEntry extends Entry implements RAFSerializable { - public PairEntry(final RandomAccessFile raf) { + public static final class Pair { + final String lang1; + final String lang2; + public Pair(final String lang1, final String lang2) { + this.lang1 = lang1; + this.lang2 = lang2; + } + public String toString() { + return lang1 + "\t" + lang2; + } + } + + final Pair[] pairs; + + public PairEntry(final Pair[] pairs) { + this.pairs = pairs; + } + + public PairEntry(final RandomAccessFile raf) throws IOException { + pairs = new Pair[raf.readInt()]; + for (int i = 0; i < pairs.length; ++i) { + pairs[i] = new Pair(raf.readUTF(), raf.readUTF()); + } } @Override public void write(RandomAccessFile raf) throws IOException { + // TODO: this couls be a short. + raf.writeInt(pairs.length); + for (int i = 0; i < pairs.length; ++i) { + raf.writeUTF(pairs[i].lang1); + raf.writeUTF(pairs[i].lang2); + } } static final RAFSerializer SERIALIZER = new RAFSerializer() { @@ -28,26 +56,18 @@ public class PairEntry extends Entry implements RAFSerializable { }; - @Override - List getMainTokens() { - return null; - } - - @Override - List getOtherTokens() { - return null; - } - - - - 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); + } + public PairEntry getEntry() { return index.dict.pairEntries.get(referenceIndex); } @@ -57,6 +77,14 @@ public class PairEntry extends Entry implements RAFSerializable { // TODO Auto-generated method stub return null; } + + @Override + public void print(PrintStream out) { + final PairEntry pairEntry = getEntry(); + for (int i = 0; i < pairEntry.pairs.length; ++i) { + out.println((i == 0 ? " " : " ") + pairEntry.pairs[i]); + } + } } diff --git a/src/com/hughes/android/dictionary/engine/RowBase.java b/src/com/hughes/android/dictionary/engine/RowBase.java index 95c2267..61ff4e0 100644 --- a/src/com/hughes/android/dictionary/engine/RowBase.java +++ b/src/com/hughes/android/dictionary/engine/RowBase.java @@ -1,21 +1,18 @@ package com.hughes.android.dictionary.engine; import java.io.IOException; +import java.io.PrintStream; import java.io.RandomAccessFile; +import com.hughes.util.IndexedObject; import com.hughes.util.raf.RAFListSerializer; -public abstract class RowBase { +public abstract class RowBase extends IndexedObject { /** * the Index owning this RowBase. */ final Index index; - /** - * Where this row lives within the list of Rows. - */ - int thisRowIndex; - /** * Where this RowBase points to. */ @@ -27,26 +24,28 @@ public abstract class RowBase { TokenRow tokenRow = null; RowBase(final RandomAccessFile raf, final int thisRowIndex, final Index index) throws IOException { + super(thisRowIndex); this.index = index; - this.thisRowIndex = thisRowIndex; // where this was inside the list. this.referenceIndex = raf.readInt(); // what this points to. } - public void write(RandomAccessFile raf) throws IOException { - raf.writeInt(referenceIndex); + public RowBase(final int referenceIndex, final int thisRowIndex, final Index index) { + super(thisRowIndex); + this.index = index; + this.referenceIndex = referenceIndex; } - + /** * @return the TokenRow that this row is "filed under". */ public TokenRow getTokenRow(final boolean search) { if (tokenRow == null && search) { - int r = thisRowIndex - 1; + int r = index() - 1; while (r >= 0) { final RowBase row = index.rows.get(r); final TokenRow candidate = row.getTokenRow(false); if (candidate != null) { - for (++r; r <= thisRowIndex; ++r) { + for (++r; r <= index(); ++r) { index.rows.get(r).setTokenRow(candidate); } } @@ -62,6 +61,8 @@ public abstract class RowBase { this.tokenRow = tokenRow; } + + public abstract void print(PrintStream out); public abstract Object draw(final String searchText); @@ -94,9 +95,9 @@ public abstract class RowBase { } else if (t instanceof TokenRow) { raf.writeByte(1); } - t.write(raf); + raf.writeInt(t.referenceIndex); } - }; + } } diff --git a/src/com/hughes/android/dictionary/engine/TextEntry.java b/src/com/hughes/android/dictionary/engine/TextEntry.java new file mode 100644 index 0000000..87d29d7 --- /dev/null +++ b/src/com/hughes/android/dictionary/engine/TextEntry.java @@ -0,0 +1,60 @@ +package com.hughes.android.dictionary.engine; + +import java.io.IOException; +import java.io.PrintStream; +import java.io.RandomAccessFile; + +import com.hughes.util.raf.RAFSerializable; +import com.hughes.util.raf.RAFSerializer; + +public class TextEntry extends Entry implements RAFSerializable { + + final String text; + + public TextEntry(final RandomAccessFile raf) throws IOException { + text = raf.readUTF(); + } + @Override + public void write(RandomAccessFile raf) throws IOException { + raf.writeUTF(text); + } + + static final RAFSerializer SERIALIZER = new RAFSerializer() { + @Override + public TextEntry read(RandomAccessFile raf) throws IOException { + return new TextEntry(raf); + } + + @Override + public void write(RandomAccessFile raf, TextEntry t) throws IOException { + t.write(raf); + } + }; + + + 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 Object draw(String searchText) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void print(PrintStream out) { + out.println(" " + getEntry().text); + } + } + + + +} diff --git a/src/com/hughes/android/dictionary/engine/TokenRow.java b/src/com/hughes/android/dictionary/engine/TokenRow.java index 7a9f5d9..06a1aa8 100644 --- a/src/com/hughes/android/dictionary/engine/TokenRow.java +++ b/src/com/hughes/android/dictionary/engine/TokenRow.java @@ -1,6 +1,7 @@ package com.hughes.android.dictionary.engine; import java.io.IOException; +import java.io.PrintStream; import java.io.RandomAccessFile; public class TokenRow extends RowBase { @@ -9,6 +10,10 @@ public class TokenRow extends RowBase { super(raf, thisRowIndex, index); } + TokenRow(final int referenceIndex, final int thisRowIndex, final Index index) { + super(referenceIndex, thisRowIndex, index); + } + @Override public TokenRow getTokenRow(final boolean search) { return this; @@ -29,5 +34,10 @@ public class TokenRow extends RowBase { return null; } + @Override + public void print(final PrintStream out) { + out.println(getToken()); + } + } diff --git a/src/com/hughes/android/util/PersistentObjectCache.java b/src/com/hughes/android/util/PersistentObjectCache.java new file mode 100644 index 0000000..2d9d2ff --- /dev/null +++ b/src/com/hughes/android/util/PersistentObjectCache.java @@ -0,0 +1,78 @@ +package com.hughes.android.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.LinkedHashMap; +import java.util.Map; + +import android.content.Context; +import android.util.Log; + +public class PersistentObjectCache { + + private final File dir; + private final Map objects = new LinkedHashMap(); + + public synchronized Object read(final String filename) { + Object object = (objects.get(filename)); + if (object != null) { + return 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 object; + } + + 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) { + dir = context.getFilesDir(); + } + + public static synchronized PersistentObjectCache getInstance() { + if (instance == null) { + throw new RuntimeException("getInstance called before init."); + } + 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()); + } + } + return instance; + } + + private static PersistentObjectCache instance = null; + +}