1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.core.api.mo;
17
18 import org.apache.commons.lang.builder.EqualsBuilder;
19 import org.apache.commons.lang.builder.HashCodeBuilder;
20 import org.apache.commons.lang.builder.ToStringBuilder;
21 import org.kuali.rice.core.api.CoreConstants;
22 import org.kuali.rice.core.api.util.collect.CollectionUtils;
23
24 import javax.xml.bind.Unmarshaller;
25 import javax.xml.bind.annotation.XmlTransient;
26 import java.io.IOException;
27 import java.io.ObjectInputStream;
28 import java.io.ObjectOutputStream;
29 import java.lang.reflect.Field;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 @XmlTransient
46 public abstract class AbstractDataTransferObject implements ModelObjectComplete {
47
48 private transient volatile Integer _hashCode;
49 private transient volatile String _toString;
50
51 protected AbstractDataTransferObject() {
52 super();
53 }
54
55 @Override
56 public int hashCode() {
57
58
59 Integer h = _hashCode;
60 if (h == null) {
61 synchronized (this) {
62 h = _hashCode;
63 if (h == null) {
64 _hashCode = h = Integer.valueOf(HashCodeBuilder.reflectionHashCode(this, Constants.HASH_CODE_EQUALS_EXCLUDE));
65 }
66 }
67 }
68
69 return h.intValue();
70 }
71
72 @Override
73 public boolean equals(Object obj) {
74 return EqualsBuilder.reflectionEquals(obj, this, Constants.HASH_CODE_EQUALS_EXCLUDE);
75 }
76
77 @Override
78 public String toString() {
79
80
81 String t = _toString;
82 if (t == null) {
83 synchronized (this) {
84 t = _toString;
85 if (t == null) {
86 _toString = t = ToStringBuilder.reflectionToString(this);
87 }
88 }
89 }
90
91 return t;
92 }
93
94 @SuppressWarnings("unused")
95 protected void beforeUnmarshal(Unmarshaller u, Object parent) throws Exception {
96 }
97
98 @SuppressWarnings("unused")
99 protected void afterUnmarshal(Unmarshaller u, Object parent) throws Exception {
100 CollectionUtils.makeUnmodifiableAndNullSafe(this);
101 }
102
103 private transient Object serializationMutex = new Object();
104
105 private void writeObject(ObjectOutputStream out) throws IOException {
106 synchronized (serializationMutex) {
107 clearFutureElements();
108 out.defaultWriteObject();
109 }
110 }
111
112 private void readObject(ObjectInputStream ois) throws IOException,
113 ClassNotFoundException {
114 ois.defaultReadObject();
115 serializationMutex = new Object();
116 }
117
118
119
120
121
122 private void clearFutureElements() {
123 try {
124 Field futureElementsField = getClass().getDeclaredField(CoreConstants.CommonElements.FUTURE_ELEMENTS);
125 boolean originalAccessible = futureElementsField.isAccessible();
126 futureElementsField.setAccessible(true);
127 try {
128 futureElementsField.set(this, null);
129 } finally {
130 futureElementsField.setAccessible(originalAccessible);
131 }
132 } catch (NoSuchFieldException e) {
133
134 } catch (IllegalAccessException e) {
135
136 }
137 }
138
139
140
141
142
143 protected static class Constants {
144 final static String[] HASH_CODE_EQUALS_EXCLUDE = { CoreConstants.CommonElements.FUTURE_ELEMENTS, "_hashCode", "_toString" };
145 }
146 }