package com.limegroup.gnutella.spam;
import java.util.Arrays;
/**
* A token holding a simple keyword
*/
public class KeywordToken extends AbstractToken {
private static final long serialVersionUID = 3257850995487748662L;
public static final int TYPE = TYPE_KEYWORD;
/**
* must be positive
*
* This is a heuristic value to prevent an token from becoming bad
* after only a small number of bad evaluations.
*/
private static final byte INITAL_GOOD = 20;
/**
* must be positive
*
* This value determines how dynamic the filter is. A low MAX value will
* allow this Token to get a bad rating after occourring only a few times in
* spam, a high value will make it very improbable that the filter will
* change its mind about a certain token without user-intervention
*/
private static final int MAX = 100;
private final byte[] _keyword;
private byte _good;
private byte _bad;
private final int _hashCode;
KeywordToken(byte[] keyword) {
// give every keyword initial credit
_good = INITAL_GOOD;
_bad = 0;
_keyword = keyword;
int h = 0;
for (int i = 0; i < _keyword.length; i++)
h = 31*h + _keyword[i];
_hashCode = h;
}
public final int hashCode() {
return _hashCode;
}
public final boolean equals(Object o) {
if (o == null)
return false;
if (! (o instanceof KeywordToken))
return false;
if (_hashCode != o.hashCode()) {
return false;
}
return Arrays.equals(_keyword, ((KeywordToken)o)._keyword);
}
/**
* implements interface <tt>Token</tt>
*/
public float getRating() {
return (float)Math.pow(1.f * _bad / (_good + _bad + 1), 2);
}
/**
* implements interface <tt>Token</tt>
*/
public void rate(int rating) {
_age = 0;
switch (rating) {
case RATING_GOOD:
_good++;
break;
case RATING_SPAM:
_bad++;
break;
case RATING_USER_MARKED_GOOD:
_bad = 0;
break;
case RATING_USER_MARKED_SPAM:
_bad = (byte) Math.min(_bad + 10, MAX);
break;
case RATING_CLEARED:
_bad = 0;
_good = INITAL_GOOD;
break;
default:
throw new IllegalArgumentException("unknown type of rating");
}
if (_good >= MAX || _bad >= MAX) {
_good = (byte) (_good * 9 / 10);
_bad = (byte) (_bad * 9 / 10);
}
}
/**
* implements interface <tt>Token</tt>
*/
public int getType() {
return TYPE;
}
/**
* overrides method from <tt>Object</tt>
*/
public String toString() {
return new String(_keyword) + " " + _good + " " + _bad;
}
}