001/* 002 * ============================================================================ 003 * Copyright © 2002-2023 by Thomas Thrien. 004 * All Rights Reserved. 005 * ============================================================================ 006 * Licensed to the public under the agreements of the GNU Lesser General Public 007 * License, version 3.0 (the "License"). You may obtain a copy of the License at 008 * 009 * http://www.gnu.org/licenses/lgpl.html 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, WITHOUT 013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 014 * License for the specific language governing permissions and limitations 015 * under the License. 016 */ 017 018package org.tquadrat.foundation.util; 019 020import static java.util.Locale.ROOT; 021import static org.apiguardian.api.API.Status.STABLE; 022import static org.tquadrat.foundation.lang.CommonConstants.UTF8; 023import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument; 024 025import java.io.File; 026import java.io.IOException; 027import java.io.Serializable; 028import java.math.BigInteger; 029import java.nio.charset.Charset; 030import java.nio.file.Path; 031import java.security.MessageDigest; 032import java.util.Arrays; 033import java.util.zip.Checksum; 034 035import org.apiguardian.api.API; 036import org.tquadrat.foundation.annotation.ClassVersion; 037import org.tquadrat.foundation.util.internal.HashImpl; 038 039/** 040 * <p>{@summary The definition for a wrapper around hash values of any kind.} 041 * These hashes are often used as checksums to validate the integrity of files 042 * or messages.</p> 043 * 044 * @version $Id: Hash.java 1052 2023-03-06 06:30:36Z tquadrat $ 045 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 046 * @UMLGraph.link 047 * @since 0.1.1 048 */ 049@SuppressWarnings( "NewClassNamingConvention" ) 050@ClassVersion( sourceVersion = "$Id: Hash.java 1052 2023-03-06 06:30:36Z tquadrat $" ) 051@API( status = STABLE, since = "0.1.1" ) 052public sealed interface Hash extends Cloneable, Serializable 053 permits HashImpl 054{ 055 /*---------*\ 056 ====** Methods **========================================================== 057 \*---------*/ 058 /** 059 * Returns the hash as an array of bytes. 060 * 061 * @return The hash value. 062 */ 063 public byte [] bytes(); 064 065 /** 066 * Creates and returns a copy of this object. 067 * 068 * @return The copy of this instance. 069 */ 070 public Hash clone(); 071 072 /** 073 * Creates the hash for the given byte array, using the given algorithm. 074 * 075 * @param data The input data. 076 * @param algorithm The algorithm 077 * @return A new instance of {@code Hash}. 078 */ 079 public static Hash create( final byte [] data, final Checksum algorithm ) 080 { 081 return HashImpl.create( data, algorithm ); 082 } // create() 083 084 /** 085 * Creates the hash for the given String, using the given algorithm. 086 * 087 * @param data The input data. 088 * @param algorithm The algorithm 089 * @return A new instance of {@code Hash}. 090 */ 091 public static Hash create( final CharSequence data, final Checksum algorithm ) 092 { 093 return create( data, UTF8, algorithm ); 094 } // create() 095 096 /** 097 * Creates the hash for the given String, using the given algorithm. 098 * 099 * @param data The input data. 100 * @param encoding The encoding for the String. 101 * @param algorithm The algorithm 102 * @return A new instance of {@code Hash}. 103 */ 104 public static Hash create( final CharSequence data, final Charset encoding, final Checksum algorithm ) 105 { 106 return HashImpl.create( requireNonNullArgument( data, "data" ).toString().getBytes( requireNonNullArgument( encoding, "encoding" ) ), algorithm ); 107 } // create() 108 109 /** 110 * Creates the hash for the given file, using the given algorithm. 111 * 112 * @param data The input data. 113 * @param algorithm The algorithm 114 * @return A new instance of {@code Hash}. 115 * @throws IOException Problems to process the file. 116 */ 117 public static Hash create( final File data, final Checksum algorithm ) throws IOException 118 { 119 return create( requireNonNullArgument( data, "data" ).toPath(), algorithm ); 120 } // create() 121 122 /** 123 * Creates the hash for the given file, using the given algorithm. 124 * 125 * @param data The input data. 126 * @param algorithm The algorithm 127 * @return A new instance of {@code Hash}. 128 * @throws IOException Problems to process the file. 129 */ 130 public static Hash create( final Path data, final Checksum algorithm ) throws IOException 131 { 132 return HashImpl.create( data, algorithm ); 133 } // create() 134 135 /** 136 * Creates the hash for the given byte array, using the given algorithm. 137 * 138 * @param data The input data. 139 * @param algorithm The algorithm 140 * @return A new instance of {@code Hash}. 141 */ 142 public static Hash create( final byte [] data, final MessageDigest algorithm ) 143 { 144 return HashImpl.create( data, algorithm ); 145 } // create() 146 147 /** 148 * Creates the hash for the given String, using the given algorithm. 149 * 150 * @param data The input data. 151 * @param algorithm The algorithm 152 * @return A new instance of {@code Hash}. 153 */ 154 public static Hash create( final CharSequence data, final MessageDigest algorithm ) 155 { 156 return create( data, UTF8, algorithm ); 157 } // create() 158 159 /** 160 * Creates the hash for the given String, using the given algorithm. 161 * 162 * @param data The input data. 163 * @param encoding The encoding for the String. 164 * @param algorithm The algorithm 165 * @return A new instance of {@code Hash}. 166 */ 167 public static Hash create( final CharSequence data, final Charset encoding, final MessageDigest algorithm ) 168 { 169 return HashImpl.create( requireNonNullArgument( data, "data" ).toString().getBytes( requireNonNullArgument( encoding, "encoding" ) ), algorithm ); 170 } // create() 171 172 /** 173 * Creates the hash for the given file, using the given algorithm. 174 * 175 * @param data The input data. 176 * @param algorithm The algorithm 177 * @throws IOException Problems to process the file. 178 * @return A new instance of {@code Hash}. 179 */ 180 public static Hash create( final File data, final MessageDigest algorithm ) throws IOException 181 { 182 return create( requireNonNullArgument( data, "data" ).toPath(), algorithm ); 183 } // create() 184 185 /** 186 * Creates the hash for the given file, using the given algorithm. 187 * 188 * @param data The input data. 189 * @param algorithm The algorithm 190 * @return A new instance of {@code Hash}. 191 * @throws IOException Problems to process the file. 192 */ 193 public static Hash create( final Path data, final MessageDigest algorithm ) throws IOException 194 { 195 return HashImpl.create( data, algorithm ); 196 } // create() 197 198 /** 199 * Creates an instance of {@code Hash} from the given byte array. 200 * 201 * @param hashValue The hash value. 202 * @return A new instance of {@code Hash}. 203 */ 204 public static Hash from( final byte [] hashValue ) { return new HashImpl( hashValue ); } 205 206 /** 207 * Creates an instance of {@code Hash} from the given String. 208 * 209 * @param hashValue The hash value. 210 * @return A new instance of {@code Hash}. 211 */ 212 public static Hash from( final CharSequence hashValue ) { return HashImpl.from( hashValue ); } 213 214 /** 215 * Returns this hash as a number. 216 * 217 * @return The number. 218 */ 219 public default BigInteger number() { return new BigInteger( bytes() ); } 220 221 /** 222 * Validates whether the given hash value matches with this hash instance. 223 * 224 * @param hashValue The hash value to test. 225 * @return {@code true} if the hash value matches with this hash instance, 226 * {@code false} otherwise. 227 */ 228 public default boolean validate( final byte [] hashValue ) { return Arrays.equals( bytes(), hashValue ); } 229 230 /** 231 * Validates whether the given hash value matches with this hash instance. 232 * 233 * @param hashValue The hash value to test. 234 * @return {@code true} if the hash value matches with this hash instance, 235 * {@code false} otherwise. 236 */ 237 public default boolean validate( final long hashValue ) { return number().longValue() == hashValue; } 238 239 /** 240 * Validates whether the given hash value matches with this hash instance. 241 * 242 * @param hashValue The hash value to test. 243 * @return {@code true} if the hash value matches with this hash instance, 244 * {@code false} otherwise. 245 */ 246 public default boolean validate( final CharSequence hashValue ) 247 { 248 return toString().toLowerCase( ROOT ) 249 .equals( requireNonNullArgument( hashValue, "hashValue" ).toString().toLowerCase( ROOT ) ); 250 } // validate() 251} 252// interface Hash 253 254/* 255 * End of File 256 */