View Javadoc
1   /*
2    * Copyright 2004-2025 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.ibatis.sqlmap.engine.cache;
17  
18  import java.io.Serializable;
19  import java.util.ArrayList;
20  import java.util.List;
21  import java.util.Objects;
22  
23  /**
24   * Hash value generator for cache keys.
25   */
26  public class CacheKey implements Cloneable, Serializable {
27  
28    private static final long serialVersionUID = 1L;
29  
30    /** The Constant DEFAULT_MULTIPLYER. */
31    private static final int DEFAULT_MULTIPLYER = 37;
32  
33    /** The Constant DEFAULT_HASHCODE. */
34    private static final int DEFAULT_HASHCODE = 17;
35  
36    /** The multiplier. */
37    private int multiplier;
38  
39    /** The hashcode. */
40    private int hashcode;
41  
42    /** The checksum. */
43    private long checksum;
44  
45    /** The count. */
46    private int count;
47  
48    /** The param list. */
49    private List paramList = new ArrayList<>();
50  
51    /**
52     * Default constructor.
53     */
54    public CacheKey() {
55      hashcode = DEFAULT_HASHCODE;
56      multiplier = DEFAULT_MULTIPLYER;
57      count = 0;
58    }
59  
60    /**
61     * Constructor that supplies an initial hashcode.
62     *
63     * @param initialNonZeroOddNumber
64     *          - the hashcode to use
65     */
66    public CacheKey(int initialNonZeroOddNumber) {
67      hashcode = initialNonZeroOddNumber;
68      multiplier = DEFAULT_MULTIPLYER;
69      count = 0;
70    }
71  
72    /**
73     * Costructor that supplies an initial hashcode and multiplier.
74     *
75     * @param initialNonZeroOddNumber
76     *          - the hashcode to use
77     * @param multiplierNonZeroOddNumber
78     *          - the multiplier to use
79     */
80    public CacheKey(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber) {
81      hashcode = initialNonZeroOddNumber;
82      multiplier = multiplierNonZeroOddNumber;
83      count = 0;
84    }
85  
86    /**
87     * Updates this object with new information based on an int value.
88     *
89     * @param x
90     *          - the int value
91     *
92     * @return the cache key
93     */
94    public CacheKey update(int x) {
95      update(Integer.valueOf(x));
96      return this;
97    }
98  
99    /**
100    * Updates this object with new information based on an object.
101    *
102    * @param object
103    *          - the object
104    *
105    * @return the cachekey
106    */
107   public CacheKey update(Object object) {
108     int baseHashCode = object.hashCode();
109 
110     count++;
111     checksum += baseHashCode;
112     baseHashCode *= count;
113 
114     hashcode = multiplier * hashcode + baseHashCode;
115 
116     paramList.add(object);
117 
118     return this;
119   }
120 
121   @Override
122   public boolean equals(Object object) {
123     if (this == object) {
124       return true;
125     }
126     if (!(object instanceof CacheKey)) {
127       return false;
128     }
129 
130     final CacheKey cacheKey = (CacheKey) object;
131 
132     if (hashcode != cacheKey.hashcode || checksum != cacheKey.checksum || count != cacheKey.count) {
133       return false;
134     }
135 
136     for (int i = 0; i < paramList.size(); i++) {
137       Object thisParam = paramList.get(i);
138       Object thatParam = cacheKey.paramList.get(i);
139       if (!Objects.equals(thisParam, thatParam)) {
140         return false;
141       }
142     }
143 
144     return true;
145   }
146 
147   @Override
148   public int hashCode() {
149     return hashcode;
150   }
151 
152   @Override
153   public String toString() {
154     StringBuilder returnValue = new StringBuilder().append(hashcode).append('|').append(checksum);
155     for (Object element : paramList) {
156       returnValue.append('|').append(element);
157     }
158 
159     return returnValue.toString();
160   }
161 
162   @Override
163   public CacheKey clone() throws CloneNotSupportedException {
164     CacheKey clonedCacheKey = (CacheKey) super.clone();
165     clonedCacheKey.paramList = new ArrayList<>(paramList);
166     return clonedCacheKey;
167   }
168 
169 }