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 }