001/*
002 * Copyright (c) 2015-2020, Oracle and/or its affiliates. All rights reserved.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.tribuo.hash;
018
019import com.oracle.labs.mlrg.olcut.config.Config;
020import com.oracle.labs.mlrg.olcut.provenance.ConfiguredObjectProvenance;
021import com.oracle.labs.mlrg.olcut.provenance.Provenance;
022import com.oracle.labs.mlrg.olcut.provenance.primitives.StringProvenance;
023
024import java.io.IOException;
025import java.io.ObjectInputStream;
026import java.util.Collections;
027import java.util.Map;
028
029/**
030 * Hashes names using String.hashCode().
031 */
032public final class HashCodeHasher extends Hasher {
033    private static final long serialVersionUID = 2L;
034
035    @Config(mandatory = true,description="Salt used in the hash.")
036    private transient String salt = null;
037
038    private static final HashCodeHasherProvenance provenance = new HashCodeHasherProvenance();
039
040    /**
041     * for olcut.
042     */
043    private HashCodeHasher() { }
044
045    public HashCodeHasher(String salt) {
046        this.salt = salt;
047    }
048
049    @Override
050    public String hash(String name) {
051        if (salt == null) {
052            throw new IllegalStateException("Salt not set");
053        }
054        String salted = salt + name;
055        return ""+salted.hashCode();
056    }
057
058    @Override
059    public void setSalt(String salt) {
060        if (Hasher.validateSalt(salt)) {
061            this.salt = salt;
062        } else {
063            throw new IllegalArgumentException("Salt: '" + salt + ", does not meet the requirements for a salt.");
064        }
065    }
066
067    @Override
068    public ConfiguredObjectProvenance getProvenance() {
069        return provenance;
070    }
071
072    @Override
073    public String toString() {
074        return "HashCodeHasher()";
075    }
076
077    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
078        in.defaultReadObject();
079        salt = null;
080    }
081
082    /**
083     * Provenance for the {@link HashCodeHasher}.
084     */
085    public final static class HashCodeHasherProvenance implements ConfiguredObjectProvenance {
086        private static final long serialVersionUID = 1L;
087
088        HashCodeHasherProvenance() {}
089
090        public HashCodeHasherProvenance(Map<String, Provenance> map) { }
091
092        @Override
093        public Map<String, Provenance> getConfiguredParameters() {
094            return Collections.singletonMap("salt",new StringProvenance("salt",""));
095        }
096
097        @Override
098        public String getClassName() {
099            return HashCodeHasher.class.getName();
100        }
101
102        @Override
103        public String toString() {
104            return generateString("Hasher");
105        }
106
107        @Override
108        public int hashCode() {
109            return 31;
110        }
111
112        @Override
113        public boolean equals(Object other) {
114            return other instanceof HashCodeHasher;
115        }
116    }
117}