1 /** 2 * Copyright 2005 Steve Molloy 3 * 4 * This file is part of OV4J. 5 * 6 * OV4J is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 8 * 9 * OV4J is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License along with OV4J; if not, write to the Free Software 13 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 14 * 15 */ 16 package org.ov4j.comp; 17 18 import java.util.logging.Level; 19 import java.util.logging.Logger; 20 21 /** 22 * This class is used to compare 2 strings as character sequences. 23 * 24 * @author smolloy 25 */ 26 public class StringComparisonResult extends ComparisonResult<String> { 27 /** 28 * Logger for this class 29 */ 30 private static final Logger logger = Logger.getLogger(StringComparisonResult.class.getName()); 31 32 /** How close the 2 strings are to each other. */ 33 private double similitude; 34 35 /** 36 * @see org.ov4j.comp.ComparisonResult#compute() 37 */ 38 @Override 39 public void compute() { 40 if (StringComparisonResult.logger.isLoggable(Level.FINER)) { 41 StringComparisonResult.logger.entering("StringComparisonResult", "compute()", "start"); 42 } 43 44 computeSimilitude(); 45 if (getOriginal() != null && getChanged() != null) { 46 if (getChanged().length() > 0) { 47 setPrecision(Math.min(1.0, Math.max(0.0, similitude / getChanged().length()))); 48 } else { 49 setPrecision(1.0); 50 } 51 if (getOriginal().length() > 0) { 52 setRecall(Math.min(1.0, Math.max(0.0, similitude / getOriginal().length()))); 53 } else { 54 setRecall(1.0); 55 } 56 } else if (getOriginal() != null) { 57 setPrecision(1.0); 58 setRecall(0.0); 59 } else if (getChanged() != null) { 60 setPrecision(0.0); 61 setRecall(1.0); 62 } else { 63 setPrecision(1.0); 64 setRecall(1.0); 65 } 66 67 if (StringComparisonResult.logger.isLoggable(Level.FINER)) { 68 StringComparisonResult.logger.exiting("StringComparisonResult", "compute()", "end"); 69 } 70 } 71 72 /** 73 * Compute the similitude. 74 */ 75 public void computeSimilitude() { 76 if (StringComparisonResult.logger.isLoggable(Level.FINER)) { 77 StringComparisonResult.logger.entering("StringComparisonResult", "computeSimilitude()", "start"); 78 } 79 80 if (getOriginal() != null && getChanged() != null) { 81 final char[] oChars = getOriginal().toCharArray(); 82 final char[] cChars = getChanged().toCharArray(); 83 double dist = 0; 84 int i = 0, j = 0; 85 while (i < oChars.length && j < cChars.length) { 86 if (oChars[i] == cChars[j]) { 87 i++; 88 j++; 89 } else { 90 int oIdx = getOriginal().indexOf(cChars[j], i); 91 int cIdx = getChanged().indexOf(oChars[i], j); 92 if (oIdx < 0) { 93 oIdx = Integer.MAX_VALUE; 94 } 95 if (cIdx < 0) { 96 cIdx = Integer.MAX_VALUE; 97 } 98 if (oIdx == cIdx) { 99 final NumericComparisonResult<Integer> numRes = new NumericComparisonResult<Integer>(); 100 numRes.setOriginal(Integer.valueOf(oChars[i])); 101 numRes.setChanged(Integer.valueOf(cChars[j])); 102 numRes.compute(); 103 dist += 1.0 - numRes.getPrecision(); 104 i++; 105 j++; 106 } else if (oIdx < cIdx) { 107 dist++; 108 i++; 109 } else { 110 dist++; 111 j++; 112 } 113 } 114 } 115 dist += oChars.length - i; 116 dist += cChars.length - j; 117 similitude = Math.abs(Math.max((double) oChars.length, (double) cChars.length) - dist); 118 } else if (getOriginal() != null || getChanged() != null) { 119 similitude = 0.0; 120 } else { 121 similitude = 1.0; 122 } 123 124 if (StringComparisonResult.logger.isLoggable(Level.FINER)) { 125 StringComparisonResult.logger.exiting("StringComparisonResult", "computeSimilitude()", "end"); 126 } 127 } 128 129 /** 130 * @see org.ov4j.comp.ComparisonResult#fastCompute() 131 */ 132 @Override 133 public void fastCompute() { 134 if (StringComparisonResult.logger.isLoggable(Level.FINER)) { 135 StringComparisonResult.logger.entering("StringComparisonResult", "fastCompute()", "start"); 136 } 137 138 if (getOriginal() != null && getChanged() != null && getOriginal().equals(getChanged())) { 139 setPrecision(1.0); 140 } 141 142 if (StringComparisonResult.logger.isLoggable(Level.FINER)) { 143 StringComparisonResult.logger.exiting("StringComparisonResult", "fastCompute()", "end"); 144 } 145 } 146 147 /** 148 * @return Returns the similitude. 149 */ 150 public double getSimilitude() { 151 return similitude; 152 } 153 154 /** 155 * @param similitude 156 * The similitude to set. 157 */ 158 public void setSimilitude(final double similitude) { 159 this.similitude = similitude; 160 } 161 }