1// Copyright 2011 Google Inc. All Rights Reserved.
2
3package com.google.common.hash;
4
5import java.nio.charset.Charset;
6
7/**
8 * An abstract composition of multiple hash functions. {@linkplain #newHasher()} delegates to the
9 * {@code Hasher} objects of the delegate hash functions, and in the end, they are used by
10 * {@linkplain #makeHash(Hasher[])} that constructs the final {@code HashCode}.
11 *
12 * @author andreou@google.com (Dimitris Andreou)
13 */
14abstract class AbstractCompositeHashFunction extends AbstractStreamingHashFunction {
15  final HashFunction[] functions;
16
17  AbstractCompositeHashFunction(HashFunction... functions) {
18    this.functions = functions;
19  }
20
21  /**
22   * Constructs a {@code HashCode} from the {@code Hasher} objects of the functions. Each of them
23   * has consumed the entire input and they are ready to output a {@code HashCode}. The order of
24   * the hashers are the same order as the functions given to the constructor.
25   */
26  // this could be cleaner if it passed HashCode[], but that would create yet another array...
27  /* protected */ abstract HashCode makeHash(Hasher[] hashers);
28
29  @Override
30  public Hasher newHasher() {
31    final Hasher[] hashers = new Hasher[functions.length];
32    for (int i = 0; i < hashers.length; i++) {
33      hashers[i] = functions[i].newHasher();
34    }
35    return new Hasher() {
36      @Override public Hasher putByte(byte b) {
37        for (Hasher hasher : hashers) {
38          hasher.putByte(b);
39        }
40        return this;
41      }
42
43      @Override public Hasher putBytes(byte[] bytes) {
44        for (Hasher hasher : hashers) {
45          hasher.putBytes(bytes);
46        }
47        return this;
48      }
49
50      @Override public Hasher putBytes(byte[] bytes, int off, int len) {
51        for (Hasher hasher : hashers) {
52          hasher.putBytes(bytes, off, len);
53        }
54        return this;
55      }
56
57      @Override public Hasher putShort(short s) {
58        for (Hasher hasher : hashers) {
59          hasher.putShort(s);
60        }
61        return this;
62      }
63
64      @Override public Hasher putInt(int i) {
65        for (Hasher hasher : hashers) {
66          hasher.putInt(i);
67        }
68        return this;
69      }
70
71      @Override public Hasher putLong(long l) {
72        for (Hasher hasher : hashers) {
73          hasher.putLong(l);
74        }
75        return this;
76      }
77
78      @Override public Hasher putFloat(float f) {
79        for (Hasher hasher : hashers) {
80          hasher.putFloat(f);
81        }
82        return this;
83      }
84
85      @Override public Hasher putDouble(double d) {
86        for (Hasher hasher : hashers) {
87          hasher.putDouble(d);
88        }
89        return this;
90      }
91
92      @Override public Hasher putBoolean(boolean b) {
93        for (Hasher hasher : hashers) {
94          hasher.putBoolean(b);
95        }
96        return this;
97      }
98
99      @Override public Hasher putChar(char c) {
100        for (Hasher hasher : hashers) {
101          hasher.putChar(c);
102        }
103        return this;
104      }
105
106      @Override public Hasher putString(CharSequence chars) {
107        for (Hasher hasher : hashers) {
108          hasher.putString(chars);
109        }
110        return this;
111      }
112
113      @Override public Hasher putString(CharSequence chars, Charset charset) {
114        for (Hasher hasher : hashers) {
115          hasher.putString(chars, charset);
116        }
117        return this;
118      }
119
120      @Override public <T> Hasher putObject(T instance, Funnel<? super T> funnel) {
121        for (Hasher hasher : hashers) {
122          hasher.putObject(instance, funnel);
123        }
124        return this;
125      }
126
127      @Override public HashCode hash() {
128        return makeHash(hashers);
129      }
130    };
131  }
132
133  private static final long serialVersionUID = 0L;
134}
135