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; } }