package org.madore.android.unicodeMap; import java.util.Collections; import java.util.Iterator; import java.util.Comparator; import java.util.List; import java.util.ArrayList; import java.util.NoSuchElementException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.BufferedReader; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.sql.SQLException; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.content.Context; import android.content.res.AssetManager; import android.app.Activity; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteStatement; import android.database.sqlite.SQLiteOpenHelper; public class UnicodeDatabase { protected static final String DATABASE_NAME = "unicode.db"; protected static final int DATABASE_VERSION = 1; protected static final String UNICODE_TABLE_NAME = "unicode"; protected boolean needPopulate; protected class DatabaseInit extends SQLiteOpenHelper { final Context context; DatabaseInit(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); this.context = context; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE "+UNICODE_TABLE_NAME+" ( " +"id INTEGER PRIMARY KEY , " +"name TEXT , " +"category TEXT )"); UnicodeDatabase.this.needPopulate = true; } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS "+UNICODE_TABLE_NAME); onCreate(db); } } Activity activity; DatabaseInit dbinit; SQLiteDatabase db; public UnicodeDatabase(Activity activity) { this.activity = activity; this.dbinit = new DatabaseInit(activity); db = dbinit.getReadableDatabase(); if ( ! this.needPopulate ) { Cursor c = db.rawQuery("SELECT count(*) FROM "+UNICODE_TABLE_NAME, null); c.moveToFirst(); int lineCnt = c.getInt(0); c.close(); if ( lineCnt == 0 ) this.needPopulate = true; } } public boolean needPopulate() { return this.needPopulate; } protected static void reportProgress(Handler progressHandler, int done, int total) { Message msg = progressHandler.obtainMessage(); Bundle b = new Bundle(); b.putInt("done", done); b.putInt("total", total); msg.setData(b); progressHandler.sendMessage(msg); } public void populate(Handler progressHandler) { SQLiteDatabase db = dbinit.getWritableDatabase(); db.beginTransaction(); db.execSQL("DELETE FROM "+UNICODE_TABLE_NAME); AssetManager amgr = activity.getAssets(); SQLiteStatement cmd = db.compileStatement("INSERT INTO "+UNICODE_TABLE_NAME +" VALUES ( ? , ? , ? )"); final String[] pieces = { "UnicodeData-00.txt", "UnicodeData-01.txt", "UnicodeData-02.txt", "UnicodeData-03.txt", "UnicodeData-04.txt", "UnicodeData-05.txt", "UnicodeData-06.txt", "UnicodeData-07.txt", "UnicodeData-08.txt", "UnicodeData-09.txt", "UnicodeData-10.txt", "UnicodeData-11.txt", "UnicodeData-12.txt", "UnicodeData-13.txt", "UnicodeData-14.txt", "UnicodeData-15.txt", "UnicodeData-16.txt", "UnicodeData-16b.txt", "UnicodeData-17.txt", "UnicodeData-18.txt", "UnicodeData-19.txt" }; try { for ( int cnt=0 ; cnt 0 ) { c.moveToFirst(); ch = new UnicodeCharacter(c.getInt(0), c.getString(1), UnicodeCharacter.Category.fromCode(c.getString(2))); } else ch = null; c.close(); return ch; } public int countRange(int from, int to) { int extra = 0; for ( UnicodeCharacter.SpecialRange rng : UnicodeCharacter.SpecialRange.values() ) extra += rng.interCount(from, to); final Cursor c = db.rawQuery("SELECT count(*) FROM "+UNICODE_TABLE_NAME +" WHERE id >= ? AND id < ?", new String[] { Integer.toString(from), Integer.toString(to) }); if ( c.getCount() != 1 ) throw new AssertionError("\"SELECT count(*)\" returned no result"); c.moveToFirst(); int cnt = c.getInt(0); c.close(); return cnt + extra; } private static class CursorIterable implements Iterable { protected final Cursor c; public CursorIterable(Cursor c) { this.c = c; } public Iterator iterator() { final boolean hasData = c.getCount() > 0; if ( hasData ) c.moveToFirst(); else c.close(); return (new Iterator() { boolean hasNext = hasData; public boolean hasNext() { return hasNext; } public UnicodeCharacter next() { if ( hasNext ) { UnicodeCharacter ch = new UnicodeCharacter(c.getInt(0), c.getString(1), UnicodeCharacter.Category.fromCode(c.getString(2))); if ( c.isLast() ) { hasNext = false; c.close(); } else c.moveToNext(); return ch; } else throw new NoSuchElementException(); } public void remove() { throw new UnsupportedOperationException(); } }); } } private static class SpecialRangeIterable implements Iterable { protected final UnicodeCharacter.SpecialRange rng; protected final int from; protected final int to; public SpecialRangeIterable(UnicodeCharacter.SpecialRange rng, int from, int to) { this.rng = rng; this.from = from; this.to = to; } public Iterator iterator() { return (new Iterator() { int i = from; public boolean hasNext() { return i < to; } public UnicodeCharacter next() { if ( i < to ) return getSingleSpecial(rng, i++); else throw new NoSuchElementException(); } public void remove() { throw new UnsupportedOperationException(); } }); } } public Iterable getRange(int from, int to) { List annoyance = null; boolean muchAnnoyance = false; for ( UnicodeCharacter.SpecialRange rng : UnicodeCharacter.SpecialRange.values() ) { if ( rng.inside(from, to) ) { return new SpecialRangeIterable(rng, from, to); } else if ( rng.interCount(from, to) > 0 ) { if ( annoyance == null ) annoyance = new ArrayList(rng.interCount(from, to)); else muchAnnoyance = true; int from0 = Math.max(rng.getFrom(), from); int to0 = Math.min(rng.getTo(), to); Iterable rangeIt = new SpecialRangeIterable(rng, from0, to0); for ( UnicodeCharacter ch : rangeIt ) annoyance.add(ch); } } final Cursor c = db.query(UNICODE_TABLE_NAME, queryColumns, "id >= ? AND id < ?", new String[] { Integer.toString(from), Integer.toString(to) }, null, null, "id", null); if ( annoyance != null ) { Iterable cursorIt = new CursorIterable(c); for ( UnicodeCharacter ch : cursorIt ) { annoyance.add(ch); muchAnnoyance = true; } if ( muchAnnoyance ) Collections.sort(annoyance, new Comparator() { public int compare(UnicodeCharacter ch1, UnicodeCharacter ch2) { int cp1 = ch1.getCodePoint(); int cp2 = ch2.getCodePoint(); return (cp1cp2)?1:0; } }); return annoyance; } return new CursorIterable(c); } public Iterable searchNames(String like, int limit) { final Cursor c = db.query(UNICODE_TABLE_NAME, queryColumns, "name LIKE ?", new String[] { like }, null, null, "id", (limit>0)?Integer.toString(limit):null); return new CursorIterable(c); } public void close() { db.close(); db = null; } }