Remove duplicates into Search results

In schema version 100, we were using data_title and data_summary for
storing a normalized version of the title and summary.

This was leading to have duplicate results.

Now (in schema version 101), we are introducing two new colums for
storing normalized title and summary. We are also doing a new MATCH
query on those two new columns and that fixes the duplicates issue.

Change-Id: I609675cdd1a47a1a29595f0fe8b87ad96c6e4522
diff --git a/src/com/android/settings/indexer/Index.java b/src/com/android/settings/indexer/Index.java
index 414c4d6..5139e0c 100644
--- a/src/com/android/settings/indexer/Index.java
+++ b/src/com/android/settings/indexer/Index.java
@@ -68,7 +68,9 @@
 
     private static final String[] MATCH_COLUMNS = {
             IndexColumns.DATA_TITLE,
+            IndexColumns.DATA_TITLE_NORMALIZED,
             IndexColumns.DATA_SUMMARY,
+            IndexColumns.DATA_SUMMARY_NORMALIZED,
             IndexColumns.DATA_KEYWORDS
     };
 
@@ -280,8 +282,7 @@
 
                 final int outerDepth = parser.getDepth();
                 final AttributeSet attrs = Xml.asAttributeSet(parser);
-                final String fragmentTitle = getData(attrs,
-                        com.android.internal.R.styleable.Preference, com.android.internal.R.styleable.Preference_title);
+                final String fragmentTitle = getDataTitle(attrs);
 
                 String title = getDataTitle(attrs);
                 String summary = getDataSummary(attrs);
@@ -290,9 +291,7 @@
                 // Insert rows for the main PreferenceScreen node. Rewrite the data for removing
                 // hyphens.
                 inserOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
-                        fragmentTitle, iconResId, rank, keywords, NON_BREAKING_HYPHEN, EMPTY);
-                inserOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
-                        fragmentTitle, iconResId, rank, keywords, NON_BREAKING_HYPHEN, HYPHEN);
+                        fragmentTitle, iconResId, rank, keywords);
 
                 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                         && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -306,9 +305,7 @@
 
                     // Insert rows for the child nodes of PreferenceScreen
                     inserOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
-                            fragmentTitle, iconResId, rank, keywords, NON_BREAKING_HYPHEN, EMPTY);
-                    inserOneRowWithFilteredData(database, localeStr, title, summary, fragmentName,
-                            fragmentTitle, iconResId, rank, keywords, NON_BREAKING_HYPHEN, HYPHEN);
+                            fragmentTitle, iconResId, rank, keywords);
                 }
 
             } catch (XmlPullParserException e) {
@@ -322,37 +319,47 @@
 
         private void inserOneRowWithFilteredData(SQLiteDatabase database, String locale,
                 String title, String summary, String fragmentName, String fragmentTitle,
-                int iconResId, int rank, String keywords, String seq, String replacement) {
+                int iconResId, int rank, String keywords) {
 
             String updatedTitle;
-            String updateSummary;
-            if (title != null && title.contains(seq)) {
-                updatedTitle = title.replaceAll(seq, replacement);
-            } else {
-                updatedTitle = title;
+            if (title != null) {
+                updatedTitle = title.replaceAll(NON_BREAKING_HYPHEN, HYPHEN);
             }
-            if (summary != null && summary.contains(seq)) {
-                updateSummary = summary.replaceAll(seq, replacement);
-            } else {
-                updateSummary = summary;
+            else {
+                updatedTitle = EMPTY;
             }
+
+            String updatedSummary;
+            if (summary != null) {
+                updatedSummary = summary.replaceAll(NON_BREAKING_HYPHEN, HYPHEN);
+            } else {
+                updatedSummary = EMPTY;
+            }
+
+            String normalizedTitle = updatedTitle.replaceAll(HYPHEN, EMPTY);
+            String normalizedSummary = updatedSummary.replaceAll(HYPHEN, EMPTY);
+
             insertOneRow(database, locale,
-                    updatedTitle, updateSummary,
+                    updatedTitle, normalizedTitle, updatedSummary, normalizedSummary,
                     fragmentName, fragmentTitle, iconResId, rank, keywords);
         }
 
-        private void insertOneRow(SQLiteDatabase database, String locale, String title,
-                                  String summary, String fragmentName, String fragmentTitle,
+        private void insertOneRow(SQLiteDatabase database, String locale,
+                                  String updatedTitle, String normalizedTitle,
+                                  String updatedSummary, String normalizedSummary,
+                                  String fragmentName, String fragmentTitle,
                                   int iconResId, int rank, String keywords) {
 
-            if (TextUtils.isEmpty(title)) {
+            if (TextUtils.isEmpty(updatedTitle)) {
                 return;
             }
             ContentValues values = new ContentValues();
             values.put(IndexColumns.LOCALE, locale);
             values.put(IndexColumns.DATA_RANK, rank);
-            values.put(IndexColumns.DATA_TITLE, title);
-            values.put(IndexColumns.DATA_SUMMARY, summary);
+            values.put(IndexColumns.DATA_TITLE, updatedTitle);
+            values.put(IndexColumns.DATA_TITLE_NORMALIZED, normalizedTitle);
+            values.put(IndexColumns.DATA_SUMMARY, updatedSummary);
+            values.put(IndexColumns.DATA_SUMMARY_NORMALIZED, normalizedSummary);
             values.put(IndexColumns.DATA_KEYWORDS, keywords);
             values.put(IndexColumns.FRAGMENT_NAME, fragmentName);
             values.put(IndexColumns.FRAGMENT_TITLE, fragmentTitle);
diff --git a/src/com/android/settings/indexer/IndexDatabaseHelper.java b/src/com/android/settings/indexer/IndexDatabaseHelper.java
index 243f7b8..3e6396e 100644
--- a/src/com/android/settings/indexer/IndexDatabaseHelper.java
+++ b/src/com/android/settings/indexer/IndexDatabaseHelper.java
@@ -28,7 +28,7 @@
     private static final String TAG = "IndexDatabaseHelper";
 
     private static final String DATABASE_NAME = "search_index.db";
-    private static final int DATABASE_VERSION = 100;
+    private static final int DATABASE_VERSION = 101;
 
     public interface Tables {
         public static final String TABLE_PREFS_INDEX = "prefs_index";
@@ -39,7 +39,9 @@
         public static final String LOCALE = "locale";
         public static final String DATA_RANK = "data_rank";
         public static final String DATA_TITLE = "data_title";
+        public static final String DATA_TITLE_NORMALIZED = "data_title_normalized";
         public static final String DATA_SUMMARY = "data_summary";
+        public static final String DATA_SUMMARY_NORMALIZED = "data_summary_normalized";
         public static final String DATA_KEYWORDS = "data_keywords";
         public static final String FRAGMENT_NAME = "fragment_name";
         public static final String FRAGMENT_TITLE = "fragment_title";
@@ -60,8 +62,12 @@
                     ", " +
                     IndexColumns.DATA_TITLE +
                     ", " +
+                    IndexColumns.DATA_TITLE_NORMALIZED +
+                    ", " +
                     IndexColumns.DATA_SUMMARY +
                     ", " +
+                    IndexColumns.DATA_SUMMARY_NORMALIZED +
+                    ", " +
                     IndexColumns.DATA_KEYWORDS +
                     ", " +
                     IndexColumns.FRAGMENT_NAME +
@@ -113,6 +119,13 @@
 
     @Override
     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+        if (newVersion > 100) {
+            Log.w(TAG, "Detected schema version 100. " +
+                    "Index needs to be rebuilt for schema version 101");
+            // We need to drop the tables and recreate them
+            dropTables(db);
+            bootstrapDB(db);
+        }
     }
 
     private String getBuildVersion(SQLiteDatabase db) {
@@ -144,8 +157,10 @@
     public void onOpen(SQLiteDatabase db) {
         super.onOpen(db);
 
+        Log.i(TAG, "Using schema version: " + db.getVersion());
+
         if (!Build.VERSION.INCREMENTAL.equals(getBuildVersion(db))) {
-            Log.w(TAG, "Index needs to be rebuilt");
+            Log.w(TAG, "Index needs to be rebuilt as build-version is not the same");
             // We need to drop the tables and recreate them
             dropTables(db);
             bootstrapDB(db);