11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Copyright 2011 Google Inc. All Rights Reserved.
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.hash;
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.nio.charset.Charset;
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * An abstract composition of multiple hash functions. {@linkplain #newHasher()} delegates to the
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@code Hasher} objects of the delegate hash functions, and in the end, they are used by
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@linkplain #makeHash(Hasher[])} that constructs the final {@code HashCode}.
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author andreou@google.com (Dimitris Andreou)
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertabstract class AbstractCompositeHashFunction extends AbstractStreamingHashFunction {
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final HashFunction[] functions;
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  AbstractCompositeHashFunction(HashFunction... functions) {
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.functions = functions;
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Constructs a {@code HashCode} from the {@code Hasher} objects of the functions. Each of them
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * has consumed the entire input and they are ready to output a {@code HashCode}. The order of
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the hashers are the same order as the functions given to the constructor.
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // this could be cleaner if it passed HashCode[], but that would create yet another array...
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /* protected */ abstract HashCode makeHash(Hasher[] hashers);
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public Hasher newHasher() {
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Hasher[] hashers = new Hasher[functions.length];
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < hashers.length; i++) {
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      hashers[i] = functions[i].newHasher();
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new Hasher() {
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Hasher putByte(byte b) {
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putByte(b);
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Hasher putBytes(byte[] bytes) {
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putBytes(bytes);
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Hasher putBytes(byte[] bytes, int off, int len) {
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putBytes(bytes, off, len);
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Hasher putShort(short s) {
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putShort(s);
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Hasher putInt(int i) {
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putInt(i);
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Hasher putLong(long l) {
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putLong(l);
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Hasher putFloat(float f) {
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putFloat(f);
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Hasher putDouble(double d) {
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putDouble(d);
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Hasher putBoolean(boolean b) {
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putBoolean(b);
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Hasher putChar(char c) {
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putChar(c);
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Hasher putString(CharSequence chars) {
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putString(chars);
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Hasher putString(CharSequence chars, Charset charset) {
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putString(chars, charset);
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public <T> Hasher putObject(T instance, Funnel<? super T> funnel) {
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (Hasher hasher : hashers) {
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hasher.putObject(instance, funnel);
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public HashCode hash() {
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return makeHash(hashers);
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final long serialVersionUID = 0L;
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
135