001 /*************************************************************************************************** 002 * MODULE DESCRIPTION 003 **************************************************************************************************** 004 * 005 * NAME: SqlSearchParser.java 006 * LANGUAGE: Java2 007 * DATE: 8.4.2003 008 * AUTHOR: Miika Nurminen, Jyväskylän yliopisto 009 * 010 **************************************************************************************************** 011 * COPYRIGHT (C) KIURU -PROJECT GROUP 012 * Limited rights granted. Please refer to license 013 **************************************************************************************************** 014 * 015 **************************************************************************************************** 016 * UPDATES 017 **************************************************************************************************** 018 * 019 * 8.4.2003 Initial release 020 * 16.4.2003 Some bugs with phrase search.... /mn 021 * 022 ****************************************************************************************************/ 023 package kiurubeans; 024 025 import java.util.*; 026 import kotkabeans.Encoder; 027 028 /** 029 * Generates part of sql-query when you want to make such a query, that retrieves 030 * fields by pattern matching. This is a generalized version of 031 * kiurubeans.Tools.parseSearch method. 032 * 033 * @author Miika Nurminen 034 */ 035 public class SqlSearchParser { 036 // Attributes 037 /** Delimiters indicating OR clause*/ 038 public static final String orDelims = ",;:/"; 039 /** Delimiters indicating AND clause*/ 040 public static final String andDelims = " "; 041 /** Phrase delimiters */ 042 public static final String phraseDelims = "\"'"; 043 /** User wildcards */ 044 public static final String wildCards = "*%"; 045 046 047 /** 048 * Processes input for a single token to SQL string 049 * @param input user's input string 050 * @param fieldName SQL field to apply for search 051 */ 052 private static String format(String input,String fieldName) { 053 return " upper("+fieldName+") LIKE '" + kotkabeans.Encoder.SQLEncode(input).toUpperCase() +"' "; 054 } 055 056 /** 057 * Processes and-delimited chunk of users search string 058 * @param input user's input string 059 * @param fieldName SQL field to apply for search 060 */ 061 private static String handleAndChunk(String input,String fieldName) { 062 if (KiuruString.anyCharIndexOf(input, andDelims+wildCards+phraseDelims)==-1) { 063 return format(input+"%",fieldName); 064 } 065 input = input.replaceAll("["+Encoder.regExpEncode(wildCards)+"]", "%"); 066 PhraseStringTokenizer t = new PhraseStringTokenizer(input,andDelims,phraseDelims/*""*/); 067 StringBuffer result=new StringBuffer(20); 068 String s = null; 069 String fin = null; 070 while(t.hasMoreElements()) { 071 s = t.nextToken(); 072 if (KiuruString.anyCharIndexOf(s,phraseDelims)!=-1) { 073 fin = s.replaceAll("["+Encoder.regExpEncode(phraseDelims)+"]","");//KiuruString.stripChars(s, phraseDelims); 074 } 075 else { 076 if (s.indexOf('%')==-1) { 077 fin = "%"+s+"%"; 078 } 079 else fin = s; 080 } 081 if (result.length()>0) result.append(" AND "); 082 result.append(format(fin,fieldName)); 083 } 084 return result.toString(); 085 } 086 087 /** 088 * Generates SQL clause for searching. 089 * 090 * @param input user's input string 091 * @param fieldName SQL field to apply for search 092 * @return SQL clause for searching 093 */ 094 public static String search(String input,String fieldName) { 095 StringBuffer result = new StringBuffer(100); 096 PhraseStringTokenizer p = new PhraseStringTokenizer(input, orDelims, phraseDelims); 097 String s = null; 098 while (p.hasMoreElements()) { 099 String t = p.nextToken().trim(); // trim might be more generalized.. 100 if ( (t.length()==0) && ( (result.length()>0 || p.hasMoreElements()) )) 101 continue; 102 s=handleAndChunk(t,fieldName); 103 if ((result.length()>0) && (s.length()>0)) result.append(" OR "); 104 result.append(" ( "+s+" )"); 105 } 106 return result.toString(); 107 } 108 109 // Access methods 110 111 // Operations 112 /** Unit test. 113 * @param args command line arguments (not used). 114 */ 115 public static void main(String[] args) { 116 String[] testCases = { 117 "", 118 " ", 119 "\"agora\"", 120 "ag aud", 121 "\"ag aud\", alfa", 122 "ag aud*, '*alfa'", 123 "'*aud*' ag,Ma*,Sem" 124 }; 125 126 for (int i=0; i<testCases.length; i++) { 127 System.out.println("Test case: "+testCases[i]); 128 System.out.println(SqlSearchParser.search(testCases[i], "f")); 129 } 130 } 131 } 132 /*************************************************************************************************** 133 * COPYRIGHT (C) KIURU -PROJECT GROUP 134 * Limited rights granted. Please refer to license. 135 **************************************************************************************************/