1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.cache;
17
18 import java.io.Serializable;
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.StringJoiner;
22
23 import org.apache.ibatis.reflection.ArrayUtil;
24
25
26
27
28 public class CacheKey implements Cloneable, Serializable {
29
30 private static final long serialVersionUID = 1146682552656046210L;
31
32 public static final CacheKey NULL_CACHE_KEY = new CacheKey() {
33
34 @Override
35 public void update(Object object) {
36 throw new CacheException("Not allowed to update a null cache key instance.");
37 }
38
39 @Override
40 public void updateAll(Object[] objects) {
41 throw new CacheException("Not allowed to update a null cache key instance.");
42 }
43 };
44
45 private static final int DEFAULT_MULTIPLIER = 37;
46 private static final int DEFAULT_HASHCODE = 17;
47
48 private final int multiplier;
49 private int hashcode;
50 private long checksum;
51 private int count;
52
53
54 private List<Object> updateList;
55
56 public CacheKey() {
57 this.hashcode = DEFAULT_HASHCODE;
58 this.multiplier = DEFAULT_MULTIPLIER;
59 this.count = 0;
60 this.updateList = new ArrayList<>();
61 }
62
63 public CacheKey(Object[] objects) {
64 this();
65 updateAll(objects);
66 }
67
68 public int getUpdateCount() {
69 return updateList.size();
70 }
71
72 public void update(Object object) {
73 int baseHashCode = object == null ? 1 : ArrayUtil.hashCode(object);
74
75 count++;
76 checksum += baseHashCode;
77 baseHashCode *= count;
78
79 hashcode = multiplier * hashcode + baseHashCode;
80
81 updateList.add(object);
82 }
83
84 public void updateAll(Object[] objects) {
85 for (Object o : objects) {
86 update(o);
87 }
88 }
89
90 @Override
91 public boolean equals(Object object) {
92 if (this == object) {
93 return true;
94 }
95 if (!(object instanceof CacheKey)) {
96 return false;
97 }
98
99 final CacheKey cacheKey = (CacheKey) object;
100
101 if (hashcode != cacheKey.hashcode) {
102 return false;
103 }
104 if (checksum != cacheKey.checksum) {
105 return false;
106 }
107 if (count != cacheKey.count) {
108 return false;
109 }
110
111 for (int i = 0; i < updateList.size(); i++) {
112 Object thisObject = updateList.get(i);
113 Object thatObject = cacheKey.updateList.get(i);
114 if (!ArrayUtil.equals(thisObject, thatObject)) {
115 return false;
116 }
117 }
118 return true;
119 }
120
121 @Override
122 public int hashCode() {
123 return hashcode;
124 }
125
126 @Override
127 public String toString() {
128 StringJoiner returnValue = new StringJoiner(":");
129 returnValue.add(String.valueOf(hashcode));
130 returnValue.add(String.valueOf(checksum));
131 updateList.stream().map(ArrayUtil::toString).forEach(returnValue::add);
132 return returnValue.toString();
133 }
134
135 @Override
136 public CacheKey clone() throws CloneNotSupportedException {
137 CacheKey clonedCacheKey = (CacheKey) super.clone();
138 clonedCacheKey.updateList = new ArrayList<>(updateList);
139 return clonedCacheKey;
140 }
141
142 }