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 metaphone value. 24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Initial Java implementation by <CITE>William B. Brogden. December, 1997</CITE>. 26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Permission given by <CITE>wbrogden</CITE> for code to be used anywhere. 27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </p> 28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <CITE>Hanging on the Metaphone</CITE> by <CITE>Lawrence Philips</CITE> in <CITE>Computer Language of Dec. 1990, p 30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 39.</CITE> 31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </p> 32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author Apache Software Foundation 34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @version $Id: Metaphone.java,v 1.20 2004/06/05 18:32:04 ggregory Exp $ 35d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath * 36d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath * @deprecated Please use {@link java.net.URL#openConnection} instead. 37d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath * Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a> 38d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath * for further details. 39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 40d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath@Deprecated 41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic class Metaphone implements StringEncoder { 42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Five values in the English language 45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private String vowels = "AEIOU" ; 47069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 48069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 49069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Variable used in Metaphone algorithm 50069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 51069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private String frontv = "EIY" ; 52069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 53069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 54069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Variable used in Metaphone algorithm 55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 56069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private String varson = "CSPTG" ; 57069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 58069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 59069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The max code length for metaphone is 4 60069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private int maxCodeLen = 4 ; 62069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Creates an instance of the Metaphone encoder 65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Metaphone() { 67069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project super(); 68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Find the metaphone value of a String. This is similar to the 72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * soundex algorithm, but better at finding similar sounding words. 73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * All input is converted to upper case. 74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Limitations: Input format is expected to be a single ASCII word 75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * with only characters in the A - Z range, no punctuation or numbers. 76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param txt String to find the metaphone code for 78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return A metaphone code corresponding to the String supplied 79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public String metaphone(String txt) { 81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project boolean hard = false ; 82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if ((txt == null) || (txt.length() == 0)) { 83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return "" ; 84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // single character is itself 86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (txt.length() == 1) { 87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return txt.toUpperCase() ; 88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project char[] inwd = txt.toUpperCase().toCharArray() ; 91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project StringBuffer local = new StringBuffer(40); // manipulate 93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project StringBuffer code = new StringBuffer(10) ; // output 94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // handle initial 2 characters exceptions 95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project switch(inwd[0]) { 96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'K' : 97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'G' : 98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'P' : /* looking for KN, etc*/ 99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (inwd[1] == 'N') { 100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project local.append(inwd, 1, inwd.length - 1); 101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project local.append(inwd); 103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'A': /* looking for AE */ 106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (inwd[1] == 'E') { 107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project local.append(inwd, 1, inwd.length - 1); 108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project local.append(inwd); 110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'W' : /* looking for WR or WH */ 113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (inwd[1] == 'R') { // WR -> R 114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project local.append(inwd, 1, inwd.length - 1); 115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; 116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (inwd[1] == 'H') { 118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project local.append(inwd, 1, inwd.length - 1); 119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project local.setCharAt(0, 'W'); // WH -> W 120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project local.append(inwd); 122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'X' : /* initial X becomes S */ 125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project inwd[0] = 'S'; 126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project local.append(inwd); 127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; 128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project default : 129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project local.append(inwd); 130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } // now local has working string with initials fixed 131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project int wdsz = local.length(); 133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project int n = 0 ; 134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project while ((code.length() < this.getMaxCodeLen()) && 136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (n < wdsz) ) { // max code size of 4 works well 137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project char symb = local.charAt(n) ; 138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // remove duplicate letters except C 139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if ((symb != 'C') && (isPreviousChar( local, n, symb )) ) { 140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project n++ ; 141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { // not dup 142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project switch(symb) { 143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'A' : case 'E' : case 'I' : case 'O' : case 'U' : 144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (n == 0) { 145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append(symb); 146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; // only use vowel if leading char 148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'B' : 149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if ( isPreviousChar(local, n, 'M') && 150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project isLastChar(wdsz, n) ) { // B is silent if word ends in MB 151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append(symb); 154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'C' : // lots of C special cases 156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /* discard if SCI, SCE or SCY */ 157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if ( isPreviousChar(local, n, 'S') && 158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project !isLastChar(wdsz, n) && 159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (this.frontv.indexOf(local.charAt(n + 1)) >= 0) ) { 160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (regionMatch(local, n, "CIA")) { // "CIA" -> X 163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('X'); 164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (!isLastChar(wdsz, n) && 167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (this.frontv.indexOf(local.charAt(n + 1)) >= 0)) { 168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('S'); 169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; // CI,CE,CY -> S 170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isPreviousChar(local, n, 'S') && 172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project isNextChar(local, n, 'H') ) { // SCH->sk 173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('K') ; 174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; 175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isNextChar(local, n, 'H')) { // detect CH 177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if ((n == 0) && 178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (wdsz >= 3) && 179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project isVowel(local,2) ) { // CH consonant -> K consonant 180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('K'); 181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('X'); // CHvowel -> X 183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('K'); 186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; 188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'D' : 189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (!isLastChar(wdsz, n + 1) && 190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project isNextChar(local, n, 'G') && 191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (this.frontv.indexOf(local.charAt(n + 2)) >= 0)) { // DGE DGI DGY -> J 192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('J'); n += 2 ; 193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('T'); 195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; 197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'G' : // GH silent at end or before consonant 198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isLastChar(wdsz, n + 1) && 199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project isNextChar(local, n, 'H')) { 200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (!isLastChar(wdsz, n + 1) && 203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project isNextChar(local,n,'H') && 204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project !isVowel(local,n+2)) { 205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if ((n > 0) && 208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ( regionMatch(local, n, "GN") || 209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project regionMatch(local, n, "GNED") ) ) { 210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; // silent G 211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isPreviousChar(local, n, 'G')) { 213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project hard = true ; 214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project hard = false ; 216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (!isLastChar(wdsz, n) && 218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (this.frontv.indexOf(local.charAt(n + 1)) >= 0) && 219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (!hard)) { 220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('J'); 221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('K'); 223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; 225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'H': 226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isLastChar(wdsz, n)) { 227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; // terminal H 228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if ((n > 0) && 230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (this.varson.indexOf(local.charAt(n - 1)) >= 0)) { 231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isVowel(local,n+1)) { 234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('H'); // Hvowel 235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'F': 238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'J' : 239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'L' : 240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'M': 241069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'N' : 242069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'R' : 243069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append(symb); 244069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'K' : 246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (n > 0) { // not initial 247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (!isPreviousChar(local, n, 'C')) { 248069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append(symb); 249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append(symb); // initial K 252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; 254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'P' : 255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (isNextChar(local,n,'H')) { 256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // PH -> F 257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('F'); 258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append(symb); 260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; 262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'Q' : 263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('K'); 264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'S' : 266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (regionMatch(local,n,"SH") || 267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project regionMatch(local,n,"SIO") || 268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project regionMatch(local,n,"SIA")) { 269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('X'); 270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('S'); 272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'T' : 275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (regionMatch(local,n,"TIA") || 276069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project regionMatch(local,n,"TIO")) { 277069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('X'); 278069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 279069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 280069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (regionMatch(local,n,"TCH")) { 281069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Silent if in "TCH" 282069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break; 283069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 284069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // substitute numeral 0 for TH (resembles theta after all) 285069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (regionMatch(local,n,"TH")) { 286069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('0'); 287069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } else { 288069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('T'); 289069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 290069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; 291069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'V' : 292069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('F'); break ; 293069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'W' : case 'Y' : // silent if not followed by vowel 294069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (!isLastChar(wdsz,n) && 295069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project isVowel(local,n+1)) { 296069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append(symb); 297069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 298069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; 299069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'X' : 300069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('K'); code.append('S'); 301069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project break ; 302069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project case 'Z' : 303069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.append('S'); break ; 304069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } // end switch 305069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project n++ ; 306069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } // end else from symb != 'C' 307069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (code.length() > this.getMaxCodeLen()) { 308069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project code.setLength(this.getMaxCodeLen()); 309069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 310069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 311069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return code.toString(); 312069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 313069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 314069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private boolean isVowel(StringBuffer string, int index) { 315069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return (this.vowels.indexOf(string.charAt(index)) >= 0); 316069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 317069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 318069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private boolean isPreviousChar(StringBuffer string, int index, char c) { 319069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project boolean matches = false; 320069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if( index > 0 && 321069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project index < string.length() ) { 322069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project matches = string.charAt(index - 1) == c; 323069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 324069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return matches; 325069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 326069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 327069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private boolean isNextChar(StringBuffer string, int index, char c) { 328069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project boolean matches = false; 329069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if( index >= 0 && 330069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project index < string.length() - 1 ) { 331069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project matches = string.charAt(index + 1) == c; 332069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 333069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return matches; 334069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 335069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 336069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private boolean regionMatch(StringBuffer string, int index, String test) { 337069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project boolean matches = false; 338069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if( index >= 0 && 339069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (index + test.length() - 1) < string.length() ) { 340069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project String substring = string.substring( index, index + test.length()); 341069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project matches = substring.equals( test ); 342069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 343069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return matches; 344069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 345069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 346069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private boolean isLastChar(int wdsz, int n) { 347069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return n + 1 == wdsz; 348069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 349069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 350069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 351069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 352069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Encodes an Object using the metaphone algorithm. This method 353069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * is provided in order to satisfy the requirements of the 354069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Encoder interface, and will throw an EncoderException if the 355069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * supplied object is not of type java.lang.String. 356069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 357069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param pObject Object to encode 358069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return An object (or type java.lang.String) containing the 359069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * metaphone code which corresponds to the String supplied. 360069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @throws EncoderException if the parameter supplied is not 361069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * of type java.lang.String 362069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 363069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object encode(Object pObject) throws EncoderException { 364069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (!(pObject instanceof java.lang.String)) { 365069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new EncoderException("Parameter supplied to Metaphone encode is not of type java.lang.String"); 366069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 367069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return metaphone((String) pObject); 368069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 369069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 370069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 371069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Encodes a String using the Metaphone algorithm. 372069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 373069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param pString String object to encode 374069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return The metaphone code corresponding to the String supplied 375069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 376069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public String encode(String pString) { 377069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return metaphone(pString); 378069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 379069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 380069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 381069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Tests is the metaphones of two strings are identical. 382069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 383069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param str1 First of two strings to compare 384069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param str2 Second of two strings to compare 385069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return true if the metaphones of these strings are identical, 386069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * false otherwise. 387069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 388069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public boolean isMetaphoneEqual(String str1, String str2) { 389069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return metaphone(str1).equals(metaphone(str2)); 390069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 391069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 392069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 393069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Returns the maxCodeLen. 394069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @return int 395069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 396069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public int getMaxCodeLen() { return this.maxCodeLen; } 397069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 398069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 399069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Sets the maxCodeLen. 400069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @param maxCodeLen The maxCodeLen to set 401069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 402069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public void setMaxCodeLen(int maxCodeLen) { this.maxCodeLen = maxCodeLen; } 403069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 404069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project} 405