1 package cz.cuni.amis.pogamut.multi.communication.worldview.property;
2
3 import cz.cuni.amis.pogamut.base.communication.worldview.object.WorldObjectId;
4 import cz.cuni.amis.pogamut.multi.agent.ITeamId;
5 import cz.cuni.amis.pogamut.multi.communication.translator.event.ISharedPropertyUpdateResult;
6 import cz.cuni.amis.pogamut.multi.communication.translator.event.ISharedPropertyUpdatedEvent;
7 import cz.cuni.amis.pogamut.multi.communication.translator.event.ISharedPropertyUpdateResult.Result;
8 import cz.cuni.amis.pogamut.multi.communication.worldview.object.ISharedProperty;
9 import cz.cuni.amis.utils.HashCode;
10 import cz.cuni.amis.utils.NullCheck;
11 import cz.cuni.amis.utils.SafeEquals;
12 import cz.cuni.amis.utils.exception.PogamutException;
13
14
15
16
17
18
19
20
21
22
23 public abstract class AbstractSharedProperty<TYPE> implements ISharedProperty<TYPE> {
24
25 protected PropertyId propertyId = null;
26 protected boolean dirty = false;
27 protected Class<?> compositeClass = null;
28 protected TYPE value;
29 private int hashCode;
30
31 @Override
32 public boolean nullOverrides()
33 {
34 return false;
35 }
36
37
38
39
40
41 protected abstract TYPE cloneValue();
42
43 public AbstractSharedProperty(WorldObjectId objId, String identifier, TYPE value, Class<?> compositeClass)
44 {
45 this.propertyId = PropertyId.get(objId, identifier);
46 this.compositeClass = compositeClass;
47 this.value = value;
48 HashCode hc = new HashCode();
49 hc.add(propertyId);
50 this.hashCode = hc.getHash();
51 }
52
53
54
55
56
57
58 public AbstractSharedProperty(AbstractSharedProperty source)
59 {
60 this.hashCode = source.hashCode;
61 this.propertyId = source.propertyId;
62 this.dirty = source.dirty;
63 this.compositeClass = source.compositeClass;
64 this.value = (TYPE) source.cloneValue();
65 }
66
67
68
69
70
71
72
73 public AbstractSharedProperty( WorldObjectId objectId, String identifier, Class compositeClass)
74 {
75 this(objectId, identifier, (TYPE)null, compositeClass);
76 }
77
78 @Override
79 public int hashCode() {
80 return hashCode;
81 }
82
83 @Override
84 public boolean equals(Object another) {
85 if (another == null) return false;
86 if (!(another instanceof ISharedProperty)) { return false; }
87 ISharedProperty other = (ISharedProperty)another;
88 if (!getPropertyValueClass().isAssignableFrom(other.getPropertyValueClass())) return false;
89 return ((this.isDirty() == other.isDirty()) && (SafeEquals.equals(this.getValue(), other.getValue()))) && this.getPropertyId().equals(other.getPropertyId());
90 }
91
92 @Override
93 public abstract ISharedProperty<TYPE> clone();
94
95 @Override
96 public TYPE getValue() {
97 return value;
98 }
99
100 @Override
101 public void setValue(TYPE value) {
102 this.value = value;
103 }
104
105 @Override
106 public Class getCompositeClass()
107 {
108 return compositeClass;
109 }
110
111 @Override
112 public boolean isDirty()
113 {
114 return dirty;
115 }
116
117 public void setDirty(boolean value)
118 {
119 this.dirty = value;
120 }
121
122 @Override
123 public WorldObjectId getObjectId()
124 {
125 return this.propertyId.getWorldObjectId();
126 }
127
128 @Override
129 public PropertyId getPropertyId()
130 {
131 return this.propertyId;
132 }
133
134 @Override
135 public ISharedPropertyUpdatedEvent createUpdateEvent(long time, ITeamId teamId)
136 {
137 return new GenericPropertyUpdate(this, time, teamId);
138 }
139
140 public static class GenericPropertyUpdate implements ISharedPropertyUpdatedEvent
141 {
142
143 private ISharedProperty data;
144 private long time;
145 private ITeamId teamId;
146
147 public GenericPropertyUpdate(ISharedProperty data, long time, ITeamId teamId)
148 {
149 this.data = data;
150 NullCheck.check(this.data, "data");
151 this.time = time;
152 this.teamId = teamId;
153 }
154
155 @Override
156 public long getSimTime() {
157 return time;
158 }
159
160 @Override
161 public WorldObjectId getObjectId() {
162 return data.getObjectId();
163 }
164
165 @Override
166 public PropertyId getPropertyId() {
167 return data.getPropertyId();
168 }
169
170 @Override
171 public ITeamId getTeamId() {
172 return this.teamId;
173 }
174
175 @Override
176 public ISharedPropertyUpdateResult update(ISharedProperty property) {
177 if ( property == null )
178 {
179
180 data = data.clone();
181 return new ISharedPropertyUpdateResult.SharedPropertyUpdateResult(Result.CREATED, data);
182 }
183
184 if (!data.getPropertyValueClass().isAssignableFrom(property.getPropertyValueClass())) {
185
186 throw new PogamutException("Unexpected object type provided for update, expected value class " + data.getPropertyValueClass() + " got data with value class " + property.getPropertyValueClass(), this);
187 }
188
189 ISharedProperty original = property;
190 boolean updated = false;
191 if ( !SafeEquals.equals(original.getValue(), data.getValue()) )
192 {
193 if ( property.nullOverrides() )
194 {
195 updated = true;
196 original.setValue(data.getValue());
197 }
198 else if ( data.getValue() != null )
199 {
200 updated = true;
201 original.setValue(data.getValue());
202 }
203 }
204 this.data = original;
205
206 if (updated)
207 {
208 return new ISharedPropertyUpdateResult.SharedPropertyUpdateResult(Result.UPDATED, original);
209 }
210 return new ISharedPropertyUpdateResult.SharedPropertyUpdateResult(Result.SAME, original);
211
212
213 }
214 }
215
216 }