Merge "Import translations. DO NOT MERGE"
diff --git a/src/com/android/dialer/dialpad/SmartDialNameMatcher.java b/src/com/android/dialer/dialpad/SmartDialNameMatcher.java
index 53f5642..6f0f354 100644
--- a/src/com/android/dialer/dialpad/SmartDialNameMatcher.java
+++ b/src/com/android/dialer/dialpad/SmartDialNameMatcher.java
@@ -44,6 +44,13 @@
         '9', '9', '9', '9' // W,X,Y,Z -> 9
     };
 
+    // Whether or not we allow matches like 57 - (J)ohn (S)mith
+    private static final boolean ALLOW_INITIAL_MATCH = true;
+
+    // The maximum length of the initial we will match - typically set to 1 to minimize false
+    // positives
+    private static final int INITIAL_LENGTH_LIMIT = 1;
+
     /*
      * The switch statement in this function was generated using the python code:
      * from unidecode import unidecode
@@ -511,6 +518,34 @@
                         matchList.add(new SmartDialMatchPosition(
                                 tokenStart, queryLength + tokenStart + seperatorCount));
                         return true;
+                    } else if (ALLOW_INITIAL_MATCH && queryStart < INITIAL_LENGTH_LIMIT) {
+                        // we matched the first character.
+                        // branch off and see if we can find another match with the remaining
+                        // characters in the query string and the remaining tokens
+                        //find the next space in the query string
+                        int j = nameStart;
+                        while (j < nameLength && displayName.charAt(j) != ' ') {
+                            j++;
+                        }
+                        // this means there is at least one character left after the space
+                        if (j < nameLength - 1) {
+                            final String remainder = displayName.substring(j + 1);
+                            final ArrayList<SmartDialMatchPosition> partialTemp =
+                                    Lists.newArrayList();
+                            if (matchesCombination(
+                                    remainder, query.substring(queryStart + 1), partialTemp)) {
+
+                                // store the list of possible match positions
+                                SmartDialMatchPosition.advanceMatchPositions(partialTemp, j + 1);
+                                partialTemp.add(0,
+                                        new SmartDialMatchPosition(nameStart, nameStart + 1));
+
+                                // we found a partial token match, store the data in a
+                                // temp buffer and return it if we end up not finding a full
+                                // token match
+                                partial = partialTemp;
+                            }
+                        }
                     }
                     nameStart++;
                     queryStart++;
@@ -532,6 +567,13 @@
                 }
             }
         }
+        // if we have no complete match at this point, then we attempt to fall back to the partial
+        // token match(if any). If we don't allow initial matching (ALLOW_INITIAL_MATCH = false)
+        // then partial will always be empty.
+        if (!partial.isEmpty()) {
+            matchList.addAll(partial);
+            return true;
+        }
         return false;
     }
 
diff --git a/tests/src/com/android/dialer/dialpad/SmartDialNameMatcherTest.java b/tests/src/com/android/dialer/dialpad/SmartDialNameMatcherTest.java
index 492e5b4..8b7ee03 100644
--- a/tests/src/com/android/dialer/dialpad/SmartDialNameMatcherTest.java
+++ b/tests/src/com/android/dialer/dialpad/SmartDialNameMatcherTest.java
@@ -66,6 +66,20 @@
         checkMatches("William     J  Smith", "6576", false, 0, 0);
     }
 
+
+    public void testMatches_Initial() {
+        // wjs matches (W)illiam (J)ohn (S)mith
+        checkMatches("William John Smith", "957", true, 0, 1, 8, 9, 13, 14);
+        // wjsmit matches (W)illiam (J)ohn (Smit)h
+        checkMatches("William John Smith", "957648", true, 0, 1, 8, 9, 13, 17);
+        // wjohn matches (W)illiam (John) Smith
+        checkMatches("William John Smith", "95646", true, 0, 1, 8, 12);
+        // jsmi matches William (J)ohn (Smi)th
+        checkMatches("William John Smith", "5764", true, 8, 9, 13, 16);
+        // make sure multiple spaces don't mess things up
+        checkMatches("William        John   Smith", "5764", true, 15, 16, 22, 25);
+    }
+
     // TODO: Do we want to make these pass anymore?
     @Suppress
     public void testMatches_repeatedSeparators() {
@@ -102,7 +116,7 @@
     }
 
     private void checkMatches(String displayName, String query, boolean expectedMatches,
-            int expectedMatchStart, int expectedMatchEnd) {
+            int... expectedMatchPositions) {
         final SmartDialNameMatcher matcher = new SmartDialNameMatcher(query);
         final ArrayList<SmartDialMatchPosition> matchPositions =
                 new ArrayList<SmartDialMatchPosition>();
@@ -115,9 +129,14 @@
                 + "  nfkc=" + Normalizer.normalize(displayName, Normalizer.Form.NFKC)
                 + "  matches=" + matches);
         assertEquals("matches", expectedMatches, matches);
+        final int length = expectedMatchPositions.length;
+        assertEquals(length % 2, 0);
         if (matches) {
-            assertEquals("start", expectedMatchStart, matchPositions.get(0).start);
-            assertEquals("end", expectedMatchEnd, matchPositions.get(0).end);
+            for (int i = 0; i < length/2; i++) {
+                assertEquals("start", expectedMatchPositions[i * 2], matchPositions.get(i).start);
+                assertEquals("end", expectedMatchPositions[i * 2 + 1], matchPositions.get(i).end);
+            }
         }
     }
+
 }