001    package jcolibri.test.test13.similarity;
002    
003    import java.util.ArrayList;
004    import java.util.StringTokenizer;
005    
006    import jcolibri.exception.NoApplicableSimilarityFunctionException;
007    import jcolibri.method.retrieve.NNretrieval.similarity.LocalSimilarityFunction;
008    
009    /**
010     * This function converts the text value of an attribute into several numeric
011     * values and calculates its average. Then it computes the interval difference
012     * between query and case.
013     * <p>
014     * Example:
015     * <p>
016     * <p>
017     * Query attribute: 2.0, 4.0 -> Average = 3.0
018     * <p>
019     * Case attribute: 5.0, 9.0, 4.0 -> Average = 6.0
020     * <p>
021     * If interval param is 9.0 computed similarity equals: 0.33
022     */
023    public class AverageMultipleTextValues implements LocalSimilarityFunction {
024    
025            double _interval;
026    
027            /** Creates a new instance of MaxString */
028            public AverageMultipleTextValues(double interval) {
029                    _interval = interval;
030            }
031    
032            private double extractStringAverage(String s) {
033                    ArrayList<Double> list = new ArrayList<Double>();
034                    StringTokenizer st = new StringTokenizer(s);
035                    while (st.hasMoreTokens()) {
036                            String num = st.nextToken();
037                            double dnum = 0;
038                            try {
039                                    dnum = Double.parseDouble(num);
040                            } catch (Exception e) {
041                            }
042                            if (dnum == 0) {
043                                    try {
044                                            dnum = (double) Integer.parseInt(num);
045                                    } catch (Exception e) {
046                                    }
047                            }
048                            list.add(new Double(dnum));
049                    }
050                    
051                    double total = list.size();
052                    if (total == 0)
053                            return 0;
054                    
055                    double acum = 0;
056                    for (Double Dnum : list) 
057                    {
058                            acum += Dnum.doubleValue();
059                    }
060                    return acum / total;
061            }
062    
063            public double compute(Object caseObject, Object queryObject) throws NoApplicableSimilarityFunctionException
064            {
065                    if ((caseObject == null) || (queryObject == null))
066                            return 0;
067                    if (!(caseObject instanceof java.lang.String))
068                            throw new jcolibri.exception.NoApplicableSimilarityFunctionException(this.getClass(), caseObject.getClass());
069                    if (!(queryObject instanceof java.lang.String))
070                            throw new jcolibri.exception.NoApplicableSimilarityFunctionException(this.getClass(), queryObject.getClass());
071    
072    
073                    String caseS  = (String) caseObject;
074                    String queryS = (String) queryObject;
075                    
076                    if (queryS.length() == 0)
077                            return 0;
078                    if (caseS.length() == 0)
079                            return 0;
080    
081                    double qV = extractStringAverage(queryS);
082                    double cV = extractStringAverage(caseS);
083                    return 1 - (Math.abs(qV - cV) / _interval);
084                    
085            }
086    
087            /** Applicable to String */
088            public boolean isApplicable(Object o1, Object o2)
089            {
090                    if((o1==null)&&(o2==null))
091                            return true;
092                    else if(o1==null)
093                            return o2 instanceof String;
094                    else if(o2==null)
095                            return o1 instanceof String;
096                    else
097                            return (o1 instanceof String)&&(o2 instanceof String);
098            }
099    
100    
101    }