001/** 002 * 003 * Copyright 2019 Florian Schmaus. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.jivesoftware.smack.util; 018 019public class HashCode { 020 021 private static final int MULTIPLIER_VALUE = 37; 022 023 public static class Cache { 024 private boolean calculated; 025 private int hashcode; 026 027 public int getHashCode(Calculator hashCodeCalculator) { 028 if (calculated) { 029 return hashcode; 030 } 031 032 HashCode.Builder hashCodeBuilder = new HashCode.Builder(); 033 hashCodeCalculator.calculateHash(hashCodeBuilder); 034 035 calculated = true; 036 hashcode = hashCodeBuilder.hashcode; 037 038 return hashcode; 039 } 040 041 } 042 043 @FunctionalInterface 044 public interface Calculator { 045 void calculateHash(HashCode.Builder hashCodeBuilder); 046 } 047 048 public static Builder builder() { 049 return new Builder(); 050 } 051 052 public static class Builder { 053 private int hashcode = 17; 054 055 private void applyHash() { 056 applyHash(0); 057 } 058 059 private void applyHash(int hash) { 060 hashcode = MULTIPLIER_VALUE * hashcode + hash; 061 } 062 063 public Builder append(Object object) { 064 if (object == null) { 065 applyHash(); 066 return this; 067 } 068 069 if (object.getClass().isArray()) { 070 if (object instanceof int[]) { 071 append((int[]) object); 072 } else if (object instanceof long[]) { 073 append((long[]) object); 074 } else if (object instanceof boolean[]) { 075 append((boolean[]) object); 076 } else if (object instanceof double[]) { 077 append((double[]) object); 078 } else if (object instanceof float[]) { 079 append((float[]) object); 080 } else if (object instanceof short[]) { 081 append((short[]) object); 082 } else if (object instanceof char[]) { 083 append((char[]) object); 084 } else if (object instanceof byte[]) { 085 append((byte[]) object); 086 } else { 087 append((Object[]) object); 088 } 089 } 090 applyHash(object.hashCode()); 091 return this; 092 } 093 094 public Builder append(boolean value) { 095 applyHash(value ? 0 : 1); 096 return this; 097 } 098 099 public Builder append(boolean[] array) { 100 if (array == null) { 101 applyHash(); 102 return this; 103 } 104 105 for (boolean bool : array) { 106 append(bool); 107 } 108 return this; 109 } 110 111 public Builder append(byte value) { 112 applyHash(value); 113 return this; 114 } 115 116 public Builder append(byte[] array) { 117 if (array == null) { 118 applyHash(); 119 return this; 120 } 121 122 for (byte b : array) { 123 append(b); 124 } 125 return this; 126 } 127 128 public Builder append(char value) { 129 applyHash(value); 130 return this; 131 } 132 133 public Builder append(char[] array) { 134 if (array == null) { 135 applyHash(); 136 return this; 137 } 138 139 for (char c : array) { 140 append(c); 141 } 142 return this; 143 } 144 145 public Builder append(double value) { 146 return append(Double.doubleToLongBits(value)); 147 } 148 149 public Builder append(double[] array) { 150 if (array == null) { 151 applyHash(); 152 return this; 153 } 154 155 for (double d : array) { 156 append(d); 157 } 158 return this; 159 } 160 161 public Builder append(float value) { 162 return append(Float.floatToIntBits(value)); 163 } 164 165 public Builder append(float[] array) { 166 if (array == null) { 167 applyHash(); 168 return this; 169 } 170 171 for (float f : array) { 172 append(f); 173 } 174 return this; 175 } 176 177 public Builder append(long value) { 178 applyHash((int) (value ^ (value >>> 32))); 179 return this; 180 } 181 182 public Builder append(long[] array) { 183 if (array == null) { 184 applyHash(); 185 return this; 186 } 187 188 for (long l : array) { 189 append(l); 190 } 191 return this; 192 } 193 194 public Builder append(Object[] array) { 195 if (array == null) { 196 applyHash(); 197 return this; 198 } 199 200 for (Object element : array) { 201 append(element); 202 } 203 return this; 204 } 205 206 public int build() { 207 return hashcode; 208 } 209 } 210 211}