1069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/*
2069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Copyright 2001-2004 The Apache Software Foundation.
3069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
4069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * you may not use this file except in compliance with the License.
6069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * You may obtain a copy of the License at
7069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
8069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
10069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * See the License for the specific language governing permissions and
14069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * limitations under the License.
15069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
16069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
17069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpackage org.apache.commons.codec.language;
18069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
19069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.codec.EncoderException;
20069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.codec.StringEncoder;
21069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
22069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/**
23069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Encodes a string into a double metaphone value.
24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This Implementation is based on the algorithm by <CITE>Lawrence Philips</CITE>.
25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <ul>
26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>Original Article: <a
27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * href="http://www.cuj.com/documents/s=8038/cuj0006philips/">
28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * http://www.cuj.com/documents/s=8038/cuj0006philips/</a></li>
29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <li>Original Source Code: <a href="ftp://ftp.cuj.com/pub/2000/1806/philips.zip">
30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ftp://ftp.cuj.com/pub/2000/1806/philips.zip</a></li>
31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </ul>
32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author Apache Software Foundation
34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @version $Id: DoubleMetaphone.java,v 1.24 2004/06/05 18:32:04 ggregory Exp $
35069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
36069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic class DoubleMetaphone implements StringEncoder {
37069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
38069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * "Vowels" to test for
40069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final String VOWELS = "AEIOUY";
42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Prefixes when present which are not pronounced
45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final String[] SILENT_START =
47069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    { "GN", "KN", "PN", "WR", "PS" };
48069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final String[] L_R_N_M_B_H_F_V_W_SPACE =
49069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    { "L", "R", "N", "M", "B", "H", "F", "V", "W", " " };
50069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final String[] ES_EP_EB_EL_EY_IB_IL_IN_IE_EI_ER =
51069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    { "ES", "EP", "EB", "EL", "EY", "IB", "IL", "IN", "IE", "EI", "ER" };
52069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static final String[] L_T_K_S_N_M_B_Z =
53069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    { "L", "T", "K", "S", "N", "M", "B", "Z" };
54069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
56069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Maximum length of an encoding, default is 4
57069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
58069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected int maxCodeLen = 4;
59069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
60069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Creates an instance of this DoubleMetaphone encoder
62069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public DoubleMetaphone() {
64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        super();
65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
67069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Encode a value with Double Metaphone
69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value String to encode
71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return an encoded string
72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public String doubleMetaphone(String value) {
74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return doubleMetaphone(value, false);
75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Encode a value with Double Metaphone, optionally using the alternate
79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * encoding.
80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value String to encode
82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param alternate use alternate encode
83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return an encoded string
84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public String doubleMetaphone(String value, boolean alternate) {
86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        value = cleanInput(value);
87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (value == null) {
88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return null;
89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean slavoGermanic = isSlavoGermanic(value);
92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int index = isSilentStart(value) ? 1 : 0;
93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        DoubleMetaphoneResult result = new DoubleMetaphoneResult(this.getMaxCodeLen());
95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (!result.isComplete() && index <= value.length() - 1) {
97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            switch (value.charAt(index)) {
98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'A':
99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'E':
100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'I':
101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'O':
102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'U':
103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'Y':
104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleAEIOUY(value, result, index);
105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'B':
107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('P');
108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = charAt(value, index + 1) == 'B' ? index + 2 : index + 1;
109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case '\u00C7':
111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // A C with a Cedilla
112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('S');
113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index++;
114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'C':
116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleC(value, result, index);
117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'D':
119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleD(value, result, index);
120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'F':
122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('F');
123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = charAt(value, index + 1) == 'F' ? index + 2 : index + 1;
124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'G':
126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleG(value, result, index, slavoGermanic);
127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'H':
129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleH(value, result, index);
130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'J':
132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleJ(value, result, index, slavoGermanic);
133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'K':
135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('K');
136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = charAt(value, index + 1) == 'K' ? index + 2 : index + 1;
137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'L':
139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleL(value, result, index);
140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'M':
142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('M');
143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = conditionM0(value, index) ? index + 2 : index + 1;
144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'N':
146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('N');
147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = charAt(value, index + 1) == 'N' ? index + 2 : index + 1;
148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case '\u00D1':
150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                // N with a tilde (spanish ene)
151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('N');
152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index++;
153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'P':
155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleP(value, result, index);
156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'Q':
158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('K');
159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = charAt(value, index + 1) == 'Q' ? index + 2 : index + 1;
160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'R':
162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleR(value, result, index, slavoGermanic);
163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'S':
165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleS(value, result, index, slavoGermanic);
166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'T':
168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleT(value, result, index);
169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'V':
171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('F');
172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = charAt(value, index + 1) == 'V' ? index + 2 : index + 1;
173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'W':
175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleW(value, result, index);
176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'X':
178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleX(value, result, index);
179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            case 'Z':
181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index = handleZ(value, result, index, slavoGermanic);
182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            default:
184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index++;
185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return alternate ? result.getAlternate() : result.getPrimary();
190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Encode the value using DoubleMetaphone.  It will only work if
194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * <code>obj</code> is a <code>String</code> (like <code>Metaphone</code>).
195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param obj Object to encode (should be of type String)
197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return An encoded Object (will be of type String)
198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @throws EncoderException encode parameter is not of type String
199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public Object encode(Object obj) throws EncoderException {
201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (!(obj instanceof String)) {
202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new EncoderException("DoubleMetaphone encode parameter is not of type String");
203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return doubleMetaphone((String) obj);
205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Encode the value using DoubleMetaphone.
209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value String to encode
211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return An encoded String
212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public String encode(String value) {
214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return doubleMetaphone(value);
215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Check if the Double Metaphone values of two <code>String</code> values
219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * are equal.
220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value1 The left-hand side of the encoded {@link String#equals(Object)}.
222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value2 The right-hand side of the encoded {@link String#equals(Object)}.
223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return <code>true</code> if the encoded <code>String</code>s are equal;
224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *          <code>false</code> otherwise.
225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @see #isDoubleMetaphoneEqual(String,String,boolean)
226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public boolean isDoubleMetaphoneEqual(String value1, String value2) {
228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return isDoubleMetaphoneEqual(value1, value2, false);
229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Check if the Double Metaphone values of two <code>String</code> values
233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * are equal, optionally using the alternate value.
234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value1 The left-hand side of the encoded {@link String#equals(Object)}.
236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value2 The right-hand side of the encoded {@link String#equals(Object)}.
237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param alternate use the alternate value if <code>true</code>.
238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return <code>true</code> if the encoded <code>String</code>s are equal;
239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *          <code>false</code> otherwise.
240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
241069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public boolean isDoubleMetaphoneEqual(String value1,
242069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                          String value2,
243069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                          boolean alternate) {
244069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return doubleMetaphone(value1, alternate).equals(doubleMetaphone
245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                                         (value2, alternate));
246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
248069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Returns the maxCodeLen.
250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return int
251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public int getMaxCodeLen() {
253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return this.maxCodeLen;
254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Sets the maxCodeLen.
258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param maxCodeLen The maxCodeLen to set
259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void setMaxCodeLen(int maxCodeLen) {
261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        this.maxCodeLen = maxCodeLen;
262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    //-- BEGIN HANDLERS --//
265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'A', 'E', 'I', 'O', 'U', and 'Y' cases
268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleAEIOUY(String value, DoubleMetaphoneResult result, int
270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                             index) {
271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (index == 0) {
272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('A');
273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index + 1;
275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
276069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
277069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
278069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'C' cases
279069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
280069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleC(String value,
281069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        DoubleMetaphoneResult result,
282069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        int index) {
283069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (conditionC0(value, index)) {  // very confusing, moved out
284069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('K');
285069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
286069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (index == 0 && contains(value, index, 6, "CAESAR")) {
287069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('S');
288069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
289069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index, 2, "CH")) {
290069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index = handleCH(value, result, index);
291069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index, 2, "CZ") &&
292069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                   !contains(value, index - 2, 4, "WICZ")) {
293069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- "Czerny" --//
294069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('S', 'X');
295069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
296069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index + 1, 3, "CIA")) {
297069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- "focaccia" --//
298069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('X');
299069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 3;
300069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index, 2, "CC") &&
301069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                   !(index == 1 && charAt(value, 0) == 'M')) {
302069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- double "cc" but not "McClelland" --//
303069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return handleCC(value, result, index);
304069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index, 2, "CK", "CG", "CQ")) {
305069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('K');
306069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
307069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index, 2, "CI", "CE", "CY")) {
308069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- Italian vs. English --//
309069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (contains(value, index, 3, "CIO", "CIE", "CIA")) {
310069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('S', 'X');
311069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
312069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('S');
313069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
314069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
315069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
316069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('K');
317069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (contains(value, index + 1, 2, " C", " Q", " G")) {
318069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- Mac Caffrey, Mac Gregor --//
319069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index += 3;
320069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else if (contains(value, index + 1, 1, "C", "K", "Q") &&
321069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                       !contains(value, index + 1, 2, "CE", "CI")) {
322069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index += 2;
323069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
324069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index++;
325069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
326069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
327069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
328069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
329069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
330069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
331069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
332069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'CC' cases
333069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
334069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleCC(String value,
335069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                         DoubleMetaphoneResult result,
336069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                         int index) {
337069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (contains(value, index + 2, 1, "I", "E", "H") &&
338069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            !contains(value, index + 2, 2, "HU")) {
339069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- "bellocchio" but not "bacchus" --//
340069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if ((index == 1 && charAt(value, index - 1) == 'A') ||
341069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                contains(value, index - 1, 5, "UCCEE", "UCCES")) {
342069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- "accident", "accede", "succeed" --//
343069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append("KS");
344069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
345069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- "bacci", "bertucci", other Italian --//
346069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('X');
347069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
348069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 3;
349069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {    // Pierce's rule
350069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('K');
351069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
352069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
353069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
354069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
355069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
356069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
357069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
358069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'CH' cases
359069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
360069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleCH(String value,
361069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                         DoubleMetaphoneResult result,
362069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                         int index) {
363069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (index > 0 && contains(value, index, 4, "CHAE")) {   // Michael
364069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('K', 'X');
365069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return index + 2;
366069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (conditionCH0(value, index)) {
367069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- Greek roots ("chemistry", "chorus", etc.) --//
368069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('K');
369069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return index + 2;
370069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (conditionCH1(value, index)) {
371069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- Germanic, Greek, or otherwise 'ch' for 'kh' sound --//
372069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('K');
373069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return index + 2;
374069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
375069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (index > 0) {
376069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (contains(value, 0, 2, "MC")) {
377069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append('K');
378069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                } else {
379069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append('X', 'K');
380069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
381069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
382069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('X');
383069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
384069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return index + 2;
385069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
386069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
387069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
388069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
389069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'D' cases
390069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
391069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleD(String value,
392069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        DoubleMetaphoneResult result,
393069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        int index) {
394069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (contains(value, index, 2, "DG")) {
395069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- "Edge" --//
396069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (contains(value, index + 2, 1, "I", "E", "Y")) {
397069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('J');
398069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index += 3;
399069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- "Edgar" --//
400069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
401069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append("TK");
402069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index += 2;
403069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
404069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index, 2, "DT", "DD")) {
405069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('T');
406069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
407069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
408069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('T');
409069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index++;
410069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
411069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
412069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
413069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
414069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
415069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'G' cases
416069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
417069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleG(String value,
418069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        DoubleMetaphoneResult result,
419069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        int index,
420069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        boolean slavoGermanic) {
421069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (charAt(value, index + 1) == 'H') {
422069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index = handleGH(value, result, index);
423069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (charAt(value, index + 1) == 'N') {
424069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (index == 1 && isVowel(charAt(value, 0)) && !slavoGermanic) {
425069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append("KN", "N");
426069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else if (!contains(value, index + 2, 2, "EY") &&
427069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                       charAt(value, index + 1) != 'Y' && !slavoGermanic) {
428069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append("N", "KN");
429069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
430069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append("KN");
431069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
432069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index = index + 2;
433069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index + 1, 2, "LI") && !slavoGermanic) {
434069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append("KL", "L");
435069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
436069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (index == 0 && (charAt(value, index + 1) == 'Y' || contains(value, index + 1, 2, ES_EP_EB_EL_EY_IB_IL_IN_IE_EI_ER))) {
437069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- -ges-, -gep-, -gel-, -gie- at beginning --//
438069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('K', 'J');
439069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
440069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if ((contains(value, index + 1, 2, "ER") ||
441069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    charAt(value, index + 1) == 'Y') &&
442069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                   !contains(value, 0, 6, "DANGER", "RANGER", "MANGER") &&
443069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                   !contains(value, index - 1, 1, "E", "I") &&
444069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                   !contains(value, index - 1, 3, "RGY", "OGY")) {
445069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- -ger-, -gy- --//
446069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('K', 'J');
447069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
448069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index + 1, 1, "E", "I", "Y") ||
449069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                   contains(value, index - 1, 4, "AGGI", "OGGI")) {
450069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- Italian "biaggi" --//
451069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if ((contains(value, 0 ,4, "VAN ", "VON ") || contains(value, 0, 3, "SCH")) || contains(value, index + 1, 2, "ET")) {
452069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- obvious germanic --//
453069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('K');
454069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else if (contains(value, index + 1, 4, "IER")) {
455069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('J');
456069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
457069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('J', 'K');
458069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
459069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
460069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (charAt(value, index + 1) == 'G') {
461069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
462069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('K');
463069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
464069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index++;
465069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('K');
466069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
467069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
468069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
469069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
470069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
471069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'GH' cases
472069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
473069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleGH(String value,
474069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                         DoubleMetaphoneResult result,
475069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                         int index) {
476069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (index > 0 && !isVowel(charAt(value, index - 1))) {
477069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('K');
478069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
479069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (index == 0) {
480069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (charAt(value, index + 2) == 'I') {
481069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('J');
482069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
483069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('K');
484069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
485069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
486069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if ((index > 1 && contains(value, index - 2, 1, "B", "H", "D")) ||
487069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                   (index > 2 && contains(value, index - 3, 1, "B", "H", "D")) ||
488069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                   (index > 3 && contains(value, index - 4, 1, "B", "H"))) {
489069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- Parker's rule (with some further refinements) - "hugh"
490069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
491069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
492069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (index > 2 && charAt(value, index - 1) == 'U' &&
493069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                contains(value, index - 3, 1, "C", "G", "L", "R", "T")) {
494069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- "laugh", "McLaughlin", "cough", "gough", "rough", "tough"
495069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('F');
496069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else if (index > 0 && charAt(value, index - 1) != 'I') {
497069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('K');
498069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
499069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
500069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
501069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
502069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
503069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
504069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
505069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'H' cases
506069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
507069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleH(String value,
508069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        DoubleMetaphoneResult result,
509069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        int index) {
510069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        //-- only keep if first & before vowel or between 2 vowels --//
511069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if ((index == 0 || isVowel(charAt(value, index - 1))) &&
512069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            isVowel(charAt(value, index + 1))) {
513069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('H');
514069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
515069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- also takes car of "HH" --//
516069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
517069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index++;
518069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
519069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
520069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
521069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
522069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
523069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'J' cases
524069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
525069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleJ(String value, DoubleMetaphoneResult result, int index,
526069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        boolean slavoGermanic) {
527069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (contains(value, index, 4, "JOSE") || contains(value, 0, 4, "SAN ")) {
528069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- obvious Spanish, "Jose", "San Jacinto" --//
529069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if ((index == 0 && (charAt(value, index + 4) == ' ') ||
530069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                     value.length() == 4) || contains(value, 0, 4, "SAN ")) {
531069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append('H');
532069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                } else {
533069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append('J', 'H');
534069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
535069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index++;
536069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
537069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (index == 0 && !contains(value, index, 4, "JOSE")) {
538069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append('J', 'A');
539069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                } else if (isVowel(charAt(value, index - 1)) && !slavoGermanic &&
540069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                              (charAt(value, index + 1) == 'A' || charAt(value, index + 1) == 'O')) {
541069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append('J', 'H');
542069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                } else if (index == value.length() - 1) {
543069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append('J', ' ');
544069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                } else if (!contains(value, index + 1, 1, L_T_K_S_N_M_B_Z) && !contains(value, index - 1, 1, "S", "K", "L")) {
545069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append('J');
546069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
547069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
548069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (charAt(value, index + 1) == 'J') {
549069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    index += 2;
550069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                } else {
551069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    index++;
552069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
553069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
554069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
555069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
556069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
557069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
558069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'L' cases
559069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
560069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleL(String value,
561069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        DoubleMetaphoneResult result,
562069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        int index) {
563069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        result.append('L');
564069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (charAt(value, index + 1) == 'L') {
565069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (conditionL0(value, index)) {
566069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.appendAlternate(' ');
567069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
568069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
569069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
570069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index++;
571069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
572069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
573069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
574069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
575069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
576069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'P' cases
577069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
578069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleP(String value,
579069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        DoubleMetaphoneResult result,
580069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        int index) {
581069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (charAt(value, index + 1) == 'H') {
582069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('F');
583069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
584069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
585069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('P');
586069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index = contains(value, index + 1, 1, "P", "B") ? index + 2 : index + 1;
587069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
588069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
589069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
590069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
591069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
592069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'R' cases
593069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
594069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleR(String value,
595069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        DoubleMetaphoneResult result,
596069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        int index,
597069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        boolean slavoGermanic) {
598069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (index == value.length() - 1 && !slavoGermanic &&
599069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            contains(value, index - 2, 2, "IE") &&
600069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            !contains(value, index - 4, 2, "ME", "MA")) {
601069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.appendAlternate('R');
602069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
603069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('R');
604069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
605069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return charAt(value, index + 1) == 'R' ? index + 2 : index + 1;
606069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
607069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
608069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
609069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'S' cases
610069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
611069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleS(String value,
612069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        DoubleMetaphoneResult result,
613069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        int index,
614069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        boolean slavoGermanic) {
615069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (contains(value, index - 1, 3, "ISL", "YSL")) {
616069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- special cases "island", "isle", "carlisle", "carlysle" --//
617069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index++;
618069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (index == 0 && contains(value, index, 5, "SUGAR")) {
619069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- special case "sugar-" --//
620069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('X', 'S');
621069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index++;
622069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index, 2, "SH")) {
623069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (contains(value, index + 1, 4,
624069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                         "HEIM", "HOEK", "HOLM", "HOLZ")) {
625069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- germanic --//
626069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('S');
627069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
628069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('X');
629069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
630069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
631069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index, 3, "SIO", "SIA") || contains(value, index, 4, "SIAN")) {
632069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- Italian and Armenian --//
633069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (slavoGermanic) {
634069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('S');
635069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
636069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('S', 'X');
637069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
638069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 3;
639069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if ((index == 0 && contains(value, index + 1, 1, "M", "N", "L", "W")) || contains(value, index + 1, 1, "Z")) {
640069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- german & anglicisations, e.g. "smith" match "schmidt" //
641069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            // "snider" match "schneider" --//
642069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- also, -sz- in slavic language altho in hungarian it //
643069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //   is pronounced "s" --//
644069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('S', 'X');
645069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index = contains(value, index + 1, 1, "Z") ? index + 2 : index + 1;
646069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index, 2, "SC")) {
647069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index = handleSC(value, result, index);
648069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
649069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (index == value.length() - 1 && contains(value, index - 2,
650069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                                        2, "AI", "OI")){
651069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- french e.g. "resnais", "artois" --//
652069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.appendAlternate('S');
653069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
654069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('S');
655069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
656069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index = contains(value, index + 1, 1, "S", "Z") ? index + 2 : index + 1;
657069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
658069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
659069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
660069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
661069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
662069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'SC' cases
663069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
664069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleSC(String value,
665069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                         DoubleMetaphoneResult result,
666069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                         int index) {
667069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (charAt(value, index + 2) == 'H') {
668069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- Schlesinger's rule --//
669069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (contains(value, index + 3,
670069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                         2, "OO", "ER", "EN", "UY", "ED", "EM")) {
671069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- Dutch origin, e.g. "school", "schooner" --//
672069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (contains(value, index + 3, 2, "ER", "EN")) {
673069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    //-- "schermerhorn", "schenker" --//
674069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append("X", "SK");
675069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                } else {
676069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append("SK");
677069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
678069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
679069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (index == 0 && !isVowel(charAt(value, 3)) && charAt(value, 3) != 'W') {
680069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append('X', 'S');
681069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                } else {
682069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append('X');
683069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
684069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
685069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index + 2, 1, "I", "E", "Y")) {
686069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('S');
687069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
688069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append("SK");
689069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
690069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index + 3;
691069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
692069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
693069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
694069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'T' cases
695069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
696069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleT(String value,
697069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        DoubleMetaphoneResult result,
698069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        int index) {
699069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (contains(value, index, 4, "TION")) {
700069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('X');
701069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 3;
702069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index, 3, "TIA", "TCH")) {
703069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('X');
704069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 3;
705069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, index, 2, "TH") || contains(value, index,
706069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                                               3, "TTH")) {
707069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (contains(value, index + 2, 2, "OM", "AM") ||
708069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- special case "thomas", "thames" or germanic --//
709069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                contains(value, 0, 4, "VAN ", "VON ") ||
710069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                contains(value, 0, 3, "SCH")) {
711069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('T');
712069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
713069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('0', 'T');
714069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
715069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
716069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
717069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('T');
718069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index = contains(value, index + 1, 1, "T", "D") ? index + 2 : index + 1;
719069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
720069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
721069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
722069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
723069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
724069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'W' cases
725069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
726069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleW(String value,
727069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        DoubleMetaphoneResult result,
728069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        int index) {
729069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (contains(value, index, 2, "WR")) {
730069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- can also be in middle of word --//
731069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('R');
732069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
733069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
734069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (index == 0 && (isVowel(charAt(value, index + 1)) ||
735069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                               contains(value, index, 2, "WH"))) {
736069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (isVowel(charAt(value, index + 1))) {
737069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    //-- Wasserman should match Vasserman --//
738069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append('A', 'F');
739069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                } else {
740069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    //-- need Uomo to match Womo --//
741069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result.append('A');
742069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
743069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index++;
744069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else if ((index == value.length() - 1 && isVowel(charAt(value, index - 1))) ||
745069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                       contains(value, index - 1,
746069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                5, "EWSKI", "EWSKY", "OWSKI", "OWSKY") ||
747069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                       contains(value, 0, 3, "SCH")) {
748069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- Arnow should match Arnoff --//
749069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.appendAlternate('F');
750069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index++;
751069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else if (contains(value, index, 4, "WICZ", "WITZ")) {
752069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- Polish e.g. "filipowicz" --//
753069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append("TS", "FX");
754069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index += 4;
755069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
756069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                index++;
757069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
758069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
759069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
760069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
761069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
762069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
763069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'X' cases
764069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
765069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleX(String value,
766069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        DoubleMetaphoneResult result,
767069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        int index) {
768069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (index == 0) {
769069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('S');
770069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index++;
771069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
772069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (!((index == value.length() - 1) &&
773069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                  (contains(value, index - 3, 3, "IAU", "EAU") ||
774069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                   contains(value, index - 2, 2, "AU", "OU")))) {
775069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                //-- French e.g. breaux --//
776069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append("KS");
777069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
778069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index = contains(value, index + 1, 1, "C", "X") ? index + 2 : index + 1;
779069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
780069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
781069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
782069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
783069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
784069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Handles 'Z' cases
785069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
786069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private int handleZ(String value, DoubleMetaphoneResult result, int index,
787069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        boolean slavoGermanic) {
788069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (charAt(value, index + 1) == 'H') {
789069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            //-- Chinese pinyin e.g. "zhao" or Angelina "Zhang" --//
790069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            result.append('J');
791069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index += 2;
792069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
793069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (contains(value, index + 1, 2, "ZO", "ZI", "ZA") || (slavoGermanic && (index > 0 && charAt(value, index - 1) != 'T'))) {
794069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append("S", "TS");
795069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
796069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result.append('S');
797069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
798069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            index = charAt(value, index + 1) == 'Z' ? index + 2 : index + 1;
799069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
800069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return index;
801069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
802069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
803069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    //-- BEGIN CONDITIONS --//
804069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
805069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
806069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Complex condition 0 for 'C'
807069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
808069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean conditionC0(String value, int index) {
809069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (contains(value, index, 4, "CHIA")) {
810069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return true;
811069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (index <= 1) {
812069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return false;
813069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (isVowel(charAt(value, index - 2))) {
814069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return false;
815069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (!contains(value, index - 1, 3, "ACH")) {
816069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return false;
817069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
818069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            char c = charAt(value, index + 2);
819069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return (c != 'I' && c != 'E')
820069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    || contains(value, index - 2, 6, "BACHER", "MACHER");
821069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
822069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
823069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
824069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
825069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Complex condition 0 for 'CH'
826069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
827069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean conditionCH0(String value, int index) {
828069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (index != 0) {
829069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return false;
830069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (!contains(value, index + 1, 5, "HARAC", "HARIS") &&
831069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                   !contains(value, index + 1, 3, "HOR", "HYM", "HIA", "HEM")) {
832069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return false;
833069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if (contains(value, 0, 5, "CHORE")) {
834069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return false;
835069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
836069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return true;
837069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
838069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
839069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
840069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
841069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Complex condition 1 for 'CH'
842069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
843069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean conditionCH1(String value, int index) {
844069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return ((contains(value, 0, 4, "VAN ", "VON ") || contains(value, 0,
845069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                                                   3, "SCH")) ||
846069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                contains(value, index - 2, 6, "ORCHES", "ARCHIT", "ORCHID") ||
847069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                contains(value, index + 2, 1, "T", "S") ||
848069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ((contains(value, index - 1, 1, "A", "O", "U", "E") || index == 0) &&
849069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                 (contains(value, index + 2, 1, L_R_N_M_B_H_F_V_W_SPACE) || index + 1 == value.length() - 1)));
850069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
851069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
852069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
853069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Complex condition 0 for 'L'
854069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
855069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean conditionL0(String value, int index) {
856069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (index == value.length() - 3 &&
857069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            contains(value, index - 1, 4, "ILLO", "ILLA", "ALLE")) {
858069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return true;
859069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else if ((contains(value, index - 1, 2, "AS", "OS") ||
860069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    contains(value, value.length() - 1, 1, "A", "O")) &&
861069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                   contains(value, index - 1, 4, "ALLE")) {
862069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return true;
863069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
864069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return false;
865069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
866069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
867069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
868069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
869069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Complex condition 0 for 'M'
870069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
871069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean conditionM0(String value, int index) {
872069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (charAt(value, index + 1) == 'M') {
873069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return true;
874069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
875069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return contains(value, index - 1, 3, "UMB")
876069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                && ((index + 1) == value.length() - 1 || contains(value,
877069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        index + 2, 2, "ER"));
878069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
879069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
880069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    //-- BEGIN HELPER FUNCTIONS --//
881069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
882069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
883069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Determines whether or not a value is of slavo-germanic orgin. A value is
884069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * of slavo-germanic origin if it contians any of 'W', 'K', 'CZ', or 'WITZ'.
885069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
886069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean isSlavoGermanic(String value) {
887069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return value.indexOf('W') > -1 || value.indexOf('K') > -1 ||
888069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            value.indexOf("CZ") > -1 || value.indexOf("WITZ") > -1;
889069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
890069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
891069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
892069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Determines whether or not a character is a vowel or not
893069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
894069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean isVowel(char ch) {
895069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return VOWELS.indexOf(ch) != -1;
896069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
897069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
898069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
899069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Determines whether or not the value starts with a silent letter.  It will
900069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * return <code>true</code> if the value starts with any of 'GN', 'KN',
901069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * 'PN', 'WR' or 'PS'.
902069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
903069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private boolean isSilentStart(String value) {
904069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean result = false;
905069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        for (int i = 0; i < SILENT_START.length; i++) {
906069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (value.startsWith(SILENT_START[i])) {
907069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                result = true;
908069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
909069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
910069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
911069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return result;
912069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
913069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
914069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
915069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Cleans the input
916069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
917069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private String cleanInput(String input) {
918069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (input == null) {
919069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return null;
920069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
921069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        input = input.trim();
922069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (input.length() == 0) {
923069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return null;
924069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
925069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return input.toUpperCase();
926069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
927069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
928069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
929069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Gets the character at index <code>index</code> if available, otherwise
930069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * it returns <code>Character.MIN_VALUE</code> so that there is some sort
931069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * of a default
932069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
933069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected char charAt(String value, int index) {
934069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (index < 0 || index >= value.length()) {
935069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return Character.MIN_VALUE;
936069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
937069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return value.charAt(index);
938069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
939069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
940069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
941069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Shortcut method with 1 criteria
942069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
943069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static boolean contains(String value, int start, int length,
944069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                    String criteria) {
945069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return contains(value, start, length,
946069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        new String[] { criteria });
947069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
948069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
949069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
950069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Shortcut method with 2 criteria
951069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
952069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static boolean contains(String value, int start, int length,
953069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                    String criteria1, String criteria2) {
954069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return contains(value, start, length,
955069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        new String[] { criteria1, criteria2 });
956069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
957069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
958069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
959069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Shortcut method with 3 criteria
960069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
961069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static boolean contains(String value, int start, int length,
962069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                    String criteria1, String criteria2,
963069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                    String criteria3) {
964069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return contains(value, start, length,
965069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        new String[] { criteria1, criteria2, criteria3 });
966069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
967069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
968069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
969069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Shortcut method with 4 criteria
970069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
971069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static boolean contains(String value, int start, int length,
972069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                    String criteria1, String criteria2,
973069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                    String criteria3, String criteria4) {
974069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return contains(value, start, length,
975069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        new String[] { criteria1, criteria2, criteria3,
976069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                       criteria4 });
977069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
978069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
979069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
980069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Shortcut method with 5 criteria
981069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
982069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static boolean contains(String value, int start, int length,
983069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                    String criteria1, String criteria2,
984069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                    String criteria3, String criteria4,
985069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                    String criteria5) {
986069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return contains(value, start, length,
987069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        new String[] { criteria1, criteria2, criteria3,
988069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                       criteria4, criteria5 });
989069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
990069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
991069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
992069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Shortcut method with 6 criteria
993069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
994069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static boolean contains(String value, int start, int length,
995069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                    String criteria1, String criteria2,
996069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                    String criteria3, String criteria4,
997069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                    String criteria5, String criteria6) {
998069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return contains(value, start, length,
999069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        new String[] { criteria1, criteria2, criteria3,
1000069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                       criteria4, criteria5, criteria6 });
1001069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
1002069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1003069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
1004069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Determines whether <code>value</code> contains any of the criteria
1005069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     starting
1006069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * at index <code>start</code> and matching up to length <code>length</code>
1007069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
1008069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected static boolean contains(String value, int start, int length,
1009069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                      String[] criteria) {
1010069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean result = false;
1011069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (start >= 0 && start + length <= value.length()) {
1012069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            String target = value.substring(start, start + length);
1013069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1014069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            for (int i = 0; i < criteria.length; i++) {
1015069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (target.equals(criteria[i])) {
1016069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    result = true;
1017069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    break;
1018069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
1019069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1020069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1021069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return result;
1022069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
1023069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1024069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    //-- BEGIN INNER CLASSES --//
1025069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1026069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
1027069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Inner class for storing results, since there is the optional alternate
1028069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * encoding.
1029069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
1030069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public class DoubleMetaphoneResult {
1031069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1032069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        private StringBuffer primary = new StringBuffer(getMaxCodeLen());
1033069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        private StringBuffer alternate = new StringBuffer(getMaxCodeLen());
1034069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        private int maxLength;
1035069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1036069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        public DoubleMetaphoneResult(int maxLength) {
1037069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.maxLength = maxLength;
1038069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1039069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1040069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        public void append(char value) {
1041069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            appendPrimary(value);
1042069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            appendAlternate(value);
1043069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1044069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1045069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        public void append(char primary, char alternate) {
1046069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            appendPrimary(primary);
1047069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            appendAlternate(alternate);
1048069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1049069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1050069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        public void appendPrimary(char value) {
1051069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (this.primary.length() < this.maxLength) {
1052069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                this.primary.append(value);
1053069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1054069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1055069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1056069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        public void appendAlternate(char value) {
1057069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (this.alternate.length() < this.maxLength) {
1058069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                this.alternate.append(value);
1059069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1060069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1061069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1062069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        public void append(String value) {
1063069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            appendPrimary(value);
1064069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            appendAlternate(value);
1065069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1066069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1067069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        public void append(String primary, String alternate) {
1068069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            appendPrimary(primary);
1069069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            appendAlternate(alternate);
1070069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1071069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1072069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        public void appendPrimary(String value) {
1073069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            int addChars = this.maxLength - this.primary.length();
1074069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (value.length() <= addChars) {
1075069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                this.primary.append(value);
1076069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
1077069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                this.primary.append(value.substring(0, addChars));
1078069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1079069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1080069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1081069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        public void appendAlternate(String value) {
1082069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            int addChars = this.maxLength - this.alternate.length();
1083069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (value.length() <= addChars) {
1084069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                this.alternate.append(value);
1085069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
1086069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                this.alternate.append(value.substring(0, addChars));
1087069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
1088069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1089069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1090069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        public String getPrimary() {
1091069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return this.primary.toString();
1092069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1093069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1094069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        public String getAlternate() {
1095069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return this.alternate.toString();
1096069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1097069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
1098069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        public boolean isComplete() {
1099069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return this.primary.length() >= this.maxLength &&
1100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                this.alternate.length() >= this.maxLength;
1101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
1102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
1103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project}
1104