package com.bfs;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.BitSet;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A implementation of HashType that is used within the implemented
* BloomFilter.
*/
public class MD5Hash implements HashType {
public static final String MD5 = "MD5";
static final Logger LOGGER = Logger.getLogger(MD5Hash.class.getSimpleName());
@Override
public int[] hash(int numberofHashes, int maxValue, byte[] str) {
MessageDigest hash;
if(numberofHashes <= 0){
throw new IllegalArgumentException("number of hashes should be greater than 0.");
}
if(maxValue <= 0){
throw new IllegalArgumentException("maxValue should be greater than 0.");
}
if(null == str){
throw new IllegalArgumentException("byte to hash should not be null.");
}
try {
hash = MessageDigest.getInstance(MD5);
} catch (NoSuchAlgorithmException e) {
LOGGER.log(Level.SEVERE, "Can not compute hash :" + e);
throw new RuntimeException(e);
}
int[] indicies = new int[numberofHashes];
int calHashes = 0;
byte[] bytes = new byte[0];
while (calHashes < numberofHashes) {
hash.update(bytes);
bytes = hash.digest(str);
BitSet hashed = BitSet.valueOf(bytes);
int hashBits = bytes.length * 8;
int filterSize = 32 - Integer.numberOfLeadingZeros(maxValue);
for (int split = 0; split < (hashBits / filterSize)
&& calHashes < numberofHashes; split++) {
int start = split * filterSize;
int end = (split + 1) * filterSize;
BitSet hashSlice = hashed.get(start, end);
long[] longHash = hashSlice.toLongArray();
int intHash = longHash.length > 0 ? (int) longHash[0] : 0;
if (intHash < maxValue) {
indicies[calHashes] = intHash;
calHashes++;
}
}
}
return indicies;
}
}