001 package jcolibri.method.retrieve.NNretrieval.similarity.local; 002 003 import java.io.BufferedReader; 004 import java.io.InputStream; 005 import java.io.InputStreamReader; 006 import java.util.ArrayList; 007 import java.util.StringTokenizer; 008 009 import org.apache.commons.logging.LogFactory; 010 011 import jcolibri.method.retrieve.NNretrieval.similarity.LocalSimilarityFunction; 012 013 /** 014 * Similarity function that uses a table to obtain the similarity between two values. 015 * Allowed values are Strings or Enums. The table is read from a text file with the following format: 016 * <ul> 017 * <li>1st line: coma separated n categories 018 * <li>following n lines: n double values separated by comma. 019 * </ul> 020 */ 021 public class Table implements LocalSimilarityFunction 022 { 023 024 double matrix[][] = null; 025 026 ArrayList<String> categories = new ArrayList<String>(); 027 028 public Table(String filename) 029 { 030 try 031 { 032 InputStream is = jcolibri.util.FileIO.openFile(filename); 033 BufferedReader br = null; 034 br = new BufferedReader(new InputStreamReader(is)); 035 if (br == null) 036 { 037 org.apache.commons.logging.LogFactory.getLog(this.getClass()).error("Cannot find file: " + filename); 038 return; 039 } 040 String line = br.readLine(); 041 StringTokenizer st = new StringTokenizer(line, ","); 042 while (st.hasMoreTokens()) 043 categories.add(st.nextToken()); 044 int size = categories.size(); 045 046 matrix = new double[size][size]; 047 048 int i = 0; 049 while ((line = br.readLine()) != null) 050 { 051 st = new StringTokenizer(line, ","); 052 int j = 0; 053 while (st.hasMoreTokens()) 054 matrix[i][j++] = Double.parseDouble(st.nextToken()); 055 i++; 056 } 057 058 } catch (Exception e) 059 { 060 org.apache.commons.logging.LogFactory.getLog(this.getClass()).error(e); 061 062 } 063 } 064 065 /** 066 * Applies the similarity function. 067 * 068 * @param caseObject is a String or Enum 069 * @param queryObject is a String or Enum 070 * @return result of apply the similarity function. 071 */ 072 public double compute(Object caseObject, Object queryObject) throws jcolibri.exception.NoApplicableSimilarityFunctionException 073 { 074 if ((caseObject == null) || (queryObject == null)) 075 return 0; 076 if (! ((caseObject instanceof java.lang.String)||(caseObject instanceof Enum))) 077 throw new jcolibri.exception.NoApplicableSimilarityFunctionException(this.getClass(), caseObject.getClass()); 078 if (! ((queryObject instanceof java.lang.String)||(queryObject instanceof Enum))) 079 throw new jcolibri.exception.NoApplicableSimilarityFunctionException(this.getClass(), queryObject.getClass()); 080 081 String caseS; 082 String queryS; 083 if(caseObject instanceof String) 084 { 085 caseS = (String) caseObject; 086 queryS = (String) queryObject; 087 }else 088 { 089 caseS = ((Enum)caseObject).toString(); 090 queryS = ((Enum)queryObject).toString(); 091 } 092 if (matrix == null) 093 { 094 LogFactory.getLog(this.getClass()).error("Similarity table empty"); 095 return 0; 096 } 097 098 int pos1 = categories.indexOf(caseS); 099 if (pos1 == -1) 100 { 101 LogFactory.getLog(this.getClass()).error(caseS + " not found in table"); 102 return 0; 103 } 104 int pos2 = categories.indexOf(queryS); 105 if (pos2 == -1) 106 { 107 LogFactory.getLog(this.getClass()).error(queryS + " not found in table"); 108 return 0; 109 } 110 return matrix[pos1][pos2]; 111 112 } 113 114 /** Applicable to String or Enum */ 115 public boolean isApplicable(Object o1, Object o2) 116 { 117 if((o1==null)&&(o2==null)) 118 return true; 119 else if(o1==null) 120 return (o2 instanceof String)||(o2 instanceof Enum); 121 else if(o2==null) 122 return (o1 instanceof String)||(o1 instanceof Enum); 123 else 124 return ((o1 instanceof String)&&(o2 instanceof String)) || 125 ((o1 instanceof Enum)&&(o2 instanceof Enum)); 126 } 127 }