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.lang.reflect.Array;
20 import java.util.ArrayList;
21 import java.util.List;
22
23
24
25
26 public class CacheKey implements Cloneable, Serializable {
27
28 private static final long serialVersionUID = 1146682552656046210L;
29
30 public static final CacheKey NULL_CACHE_KEY = new NullCacheKey();
31
32 private static final int DEFAULT_MULTIPLYER = 37;
33 private static final int DEFAULT_HASHCODE = 17;
34
35 private int multiplier;
36 private int hashcode;
37 private long checksum;
38 private int count;
39 private List<Object> updateList;
40
41 public CacheKey() {
42 this.hashcode = DEFAULT_HASHCODE;
43 this.multiplier = DEFAULT_MULTIPLYER;
44 this.count = 0;
45 this.updateList = new ArrayList<Object>();
46 }
47
48 public CacheKey(Object[] objects) {
49 this();
50 updateAll(objects);
51 }
52
53 public int getUpdateCount() {
54 return updateList.size();
55 }
56
57 public void update(Object object) {
58 if (object != null && object.getClass().isArray()) {
59 int length = Array.getLength(object);
60 for (int i = 0; i < length; i++) {
61 Object element = Array.get(object, i);
62 doUpdate(element);
63 }
64 } else {
65 doUpdate(object);
66 }
67 }
68
69 private void doUpdate(Object object) {
70 int baseHashCode = object == null ? 1 : object.hashCode();
71
72 count++;
73 checksum += baseHashCode;
74 baseHashCode *= count;
75
76 hashcode = multiplier * hashcode + baseHashCode;
77
78 updateList.add(object);
79 }
80
81 public void updateAll(Object[] objects) {
82 for (Object o : objects) {
83 update(o);
84 }
85 }
86
87 @Override
88 public boolean equals(Object object) {
89 if (this == object) {
90 return true;
91 }
92 if (!(object instanceof CacheKey)) {
93 return false;
94 }
95
96 final CacheKey cacheKey = (CacheKey) object;
97
98 if (hashcode != cacheKey.hashcode) {
99 return false;
100 }
101 if (checksum != cacheKey.checksum) {
102 return false;
103 }
104 if (count != cacheKey.count) {
105 return false;
106 }
107
108 for (int i = 0; i < updateList.size(); i++) {
109 Object thisObject = updateList.get(i);
110 Object thatObject = cacheKey.updateList.get(i);
111 if (thisObject == null) {
112 if (thatObject != null) {
113 return false;
114 }
115 } else {
116 if (!thisObject.equals(thatObject)) {
117 return false;
118 }
119 }
120 }
121 return true;
122 }
123
124 @Override
125 public int hashCode() {
126 return hashcode;
127 }
128
129 @Override
130 public String toString() {
131 StringBuilder returnValue = new StringBuilder().append(hashcode).append(':').append(checksum);
132 for (int i = 0; i < updateList.size(); i++) {
133 returnValue.append(':').append(updateList.get(i));
134 }
135
136 return returnValue.toString();
137 }
138
139 @Override
140 public CacheKey clone() throws CloneNotSupportedException {
141 CacheKey clonedCacheKey = (CacheKey) super.clone();
142 clonedCacheKey.updateList = new ArrayList<Object>(updateList);
143 return clonedCacheKey;
144 }
145
146 }