15870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov/*
25870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Copyright (C) 2009 The Android Open Source Project
35870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov *
45870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License");
55870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * you may not use this file except in compliance with the License.
65870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * You may obtain a copy of the License at
75870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov *
85870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov *      http://www.apache.org/licenses/LICENSE-2.0
95870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov *
105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Unless required by applicable law or agreed to in writing, software
115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS,
125870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * See the License for the specific language governing permissions and
145870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * limitations under the License
155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */
165870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
175870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovpackage com.android.providers.contacts;
185870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
195870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport android.net.Uri;
205870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
215870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovimport java.util.ArrayList;
225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov/**
245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * Contacts lookup key. Used for generation and parsing of contact lookup keys as well
255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov * as doing the actual lookup.
265870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov */
275870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikovpublic class ContactLookupKey {
285870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
2992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov    public static final int LOOKUP_TYPE_SOURCE_ID = 0;
3092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov    public static final int LOOKUP_TYPE_DISPLAY_NAME = 1;
3192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov    public static final int LOOKUP_TYPE_RAW_CONTACT_ID = 2;
325d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    public static final int LOOKUP_TYPE_PROFILE = 3;
335d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro
345d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    // The Profile contact will always have a lookup key of "profile".
355d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro    public static final String PROFILE_LOOKUP_KEY = "profile";
3692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov
375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov    public static class LookupKeySegment implements Comparable<LookupKeySegment> {
385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        public int accountHashCode;
3992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov        public int lookupType;
4092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov        public String rawContactId;
415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        public String key;
425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        public long contactId;
435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        public int compareTo(LookupKeySegment another) {
455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            if (contactId > another.contactId) {
465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                return -1;
475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            }
485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            if (contactId < another.contactId) {
495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                return 1;
505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            }
515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            return 0;
525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        }
535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov    }
545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov    /**
565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov     * Returns a short hash code that functions as an additional precaution against the exceedingly
575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov     * improbable collision between sync IDs in different accounts.
585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov     */
5943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro    public static int getAccountHashCode(String accountTypeWithDataSet, String accountName) {
6043368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        if (accountTypeWithDataSet == null || accountName == null) {
615870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            return 0;
625870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        }
635870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
6443368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro        return (accountTypeWithDataSet.hashCode() ^ accountName.hashCode()) & 0xFFF;
655870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov    }
665870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
67c5fdfb79564e8b46d6aae213a312d4e1560f3a3cDave Santoro    public static void appendToLookupKey(StringBuilder lookupKey, String accountTypeWithDataSet,
6843368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro            String accountName, long rawContactId, String sourceId,
6943368a3f9e05a979e454e278d6a0e8475f08923dDave Santoro            String displayName) {
70e2a3fb8c60d68aaef5f20587e5c9cb3f6f3ffa22Megha Joshi        if (displayName == null) {
71e2a3fb8c60d68aaef5f20587e5c9cb3f6f3ffa22Megha Joshi            displayName = "";
72cf80ca3101d80a431809c3bec834bc329416ae99Dmitri Plotnikov        }
73cf80ca3101d80a431809c3bec834bc329416ae99Dmitri Plotnikov
745870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        if (lookupKey.length() != 0) {
755870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            lookupKey.append(".");
765870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        }
775870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
78c5fdfb79564e8b46d6aae213a312d4e1560f3a3cDave Santoro        lookupKey.append(getAccountHashCode(accountTypeWithDataSet, accountName));
795870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        if (sourceId == null) {
8092fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov            lookupKey.append('r').append(rawContactId).append('-').append(
8192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov                    NameNormalizer.normalize(displayName));
825870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        } else {
835870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            int pos = lookupKey.length();
845870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            lookupKey.append('i');
855870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            if (appendEscapedSourceId(lookupKey, sourceId)) {
865870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                lookupKey.setCharAt(pos, 'e');
875870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            }
885870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        }
895870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov    }
905870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
91285b771bc955305fa6d49ca23f808cecc8a13d5eDmitri Plotnikov    private static boolean appendEscapedSourceId(StringBuilder sb, String sourceId) {
925870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        boolean escaped = false;
935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        int start = 0;
945870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        while (true) {
955870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            int index = sourceId.indexOf('.', start);
965870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            if (index == -1) {
975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                sb.append(sourceId, start, sourceId.length());
985870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                break;
995870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            }
1005870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
1015870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            escaped = true;
1025870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            sb.append(sourceId, start, index);
1035870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            sb.append("..");
1045870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            start = index + 1;
1055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        }
1065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        return escaped;
1075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov    }
1085870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
1095870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov    public ArrayList<LookupKeySegment> parse(String lookupKey) {
1105870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        ArrayList<LookupKeySegment> list = new ArrayList<LookupKeySegment>();
1115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
1125d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        // If the lookup key is for the profile, just return a segment list indicating that.  The
1135d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        // caller should already be in a context in which the only contact in the database is the
1145d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        // user's profile.
1155d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        if (PROFILE_LOOKUP_KEY.equals(lookupKey)) {
1165d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro            LookupKeySegment profileSegment = new LookupKeySegment();
1175d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro            profileSegment.lookupType = LOOKUP_TYPE_PROFILE;
1185d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro            list.add(profileSegment);
1195d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro            return list;
1205d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro        }
1215d0a768b56ed4bd0dfef81b8389247ba74766659Dave Santoro
1225870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        String string = Uri.decode(lookupKey);
1235870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        int offset = 0;
1245870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        int length = string.length();
1255870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        int hashCode = 0;
12692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov        int lookupType = -1;
127e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov        boolean escaped = false;
12892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov        String rawContactId = null;
1295870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        String key;
1305870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
1315870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        while (offset < length) {
1325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            char c = 0;
1335870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
1345870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            // Parse account hash code
1355870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            hashCode = 0;
1365870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            while (offset < length) {
1375870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                c = string.charAt(offset++);
1385870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                if (c < '0' || c > '9') {
1395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                    break;
1405870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                }
1415870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                hashCode = hashCode * 10 + (c - '0');
1425870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            }
1435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
1445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            // Parse segment type
14592fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov            if (c == 'i') {
14692fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov                lookupType = LOOKUP_TYPE_SOURCE_ID;
1475870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                escaped = false;
1485870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            } else if (c == 'e') {
14992fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov                lookupType = LOOKUP_TYPE_SOURCE_ID;
1505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                escaped = true;
15192fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov            } else if (c == 'n') {
15292fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov                lookupType = LOOKUP_TYPE_DISPLAY_NAME;
15392fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov            } else if (c == 'r') {
15492fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov                lookupType = LOOKUP_TYPE_RAW_CONTACT_ID;
1555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            } else {
1565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                throw new IllegalArgumentException("Invalid lookup id: " + lookupKey);
1575870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            }
1585870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
1595870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            // Parse the source ID or normalized display name
160e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov            switch (lookupType) {
161e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                case LOOKUP_TYPE_SOURCE_ID: {
162e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    if (escaped) {
163e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        StringBuffer sb = new StringBuffer();
164e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        while (offset < length) {
165e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                            c = string.charAt(offset++);
166e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov
16751698db0c97b20e95421bc42b243e4ea315137beDmitri Plotnikov                            if (c == '.') {
168e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                if (offset == length) {
169e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                    throw new IllegalArgumentException("Invalid lookup id: " +
170e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                            lookupKey);
171e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                }
172e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                c = string.charAt(offset);
173e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov
174e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                if (c == '.') {
175e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                    sb.append('.');
176e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                    offset++;
177e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                } else {
178e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                    break;
179e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                }
180e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                            } else {
181e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                sb.append(c);
182e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                            }
183e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        }
184e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        key = sb.toString();
185e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    } else {
186e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        int start = offset;
187e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        while (offset < length) {
188e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                            c = string.charAt(offset++);
189e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                            if (c == '.') {
190e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                                break;
191e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                            }
192e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        }
1935870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                        if (offset == length) {
194e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                            key = string.substring(start);
195e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        } else {
196e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                            key = string.substring(start, offset - 1);
1975870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                        }
198e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    }
199e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    break;
200e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                }
201e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                case LOOKUP_TYPE_DISPLAY_NAME: {
202e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    int start = offset;
203e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    while (offset < length) {
204e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        c = string.charAt(offset++);
2055870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                        if (c == '.') {
2065870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                            break;
2075870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                        }
208e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    }
209e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    if (offset == length) {
210e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        key = string.substring(start);
2115870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                    } else {
212e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        key = string.substring(start, offset - 1);
2135870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                    }
214e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    break;
2155870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                }
216e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                case LOOKUP_TYPE_RAW_CONTACT_ID: {
217e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    int dash = -1;
218e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    int start = offset;
219e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    while (offset < length) {
220e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        c = string.charAt(offset);
221e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        if (c == '-' && dash == -1) {
222e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                            dash = offset;
223e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        }
224e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        offset++;
225e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        if (c == '.') {
226e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                            break;
227e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        }
22892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov                    }
229e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    if (dash != -1) {
230e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        rawContactId = string.substring(start, dash);
231e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        start = dash + 1;
2325870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                    }
233e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    if (offset == length) {
234e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        key = string.substring(start);
235e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    } else {
236e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                        key = string.substring(start, offset - 1);
237e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    }
238e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    break;
2395870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov                }
240e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                default:
241e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    // Will never happen
242e0bbba6a6026b2577e62097ea8f8f7ebe48da8f5Dmitri Plotnikov                    throw new IllegalStateException();
2435870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            }
2445870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
2455870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            LookupKeySegment segment = new LookupKeySegment();
2465870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            segment.accountHashCode = hashCode;
24792fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov            segment.lookupType = lookupType;
24892fcdfb24194e8527ef59c0af0731825ee46fa45Dmitri Plotnikov            segment.rawContactId = rawContactId;
2495870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            segment.key = key;
2505870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            segment.contactId = -1;
2515870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov            list.add(segment);
2525870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        }
2535870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov
2545870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov        return list;
2555870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov    }
2565870f2dcc2ac7715b2c078a886ee346622e7887eDmitri Plotnikov}
257