Skip to content

Commit e0d6122

Browse files
committed
CachedModel: use unmodifiable wrapper on Type.all (fixes #189)
1 parent 654eca1 commit e0d6122

File tree

2 files changed

+60
-7
lines changed
  • plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/models
  • tests/org.eclipse.epsilon.eol.engine.test.unit/src/org/eclipse/epsilon/eol/models

2 files changed

+60
-7
lines changed

plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/models/CachedModel.java

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,23 @@
1010
******************************************************************************/
1111
package org.eclipse.epsilon.eol.models;
1212

13-
import java.util.*;
13+
import java.util.ArrayList;
14+
import java.util.Collection;
15+
import java.util.Collections;
16+
import java.util.Deque;
17+
import java.util.List;
18+
import java.util.Map;
19+
import java.util.NavigableSet;
20+
import java.util.Set;
21+
import java.util.SortedSet;
22+
1423
import org.eclipse.epsilon.common.concurrent.ConcurrencyUtils;
1524
import org.eclipse.epsilon.common.util.Multimap;
1625
import org.eclipse.epsilon.common.util.StringProperties;
1726
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
18-
import org.eclipse.epsilon.eol.exceptions.models.*;
27+
import org.eclipse.epsilon.eol.exceptions.models.EolModelElementTypeNotFoundException;
28+
import org.eclipse.epsilon.eol.exceptions.models.EolModelLoadingException;
29+
import org.eclipse.epsilon.eol.exceptions.models.EolNotInstantiableModelElementTypeException;
1930

2031
/**
2132
* A model that performs memoization of allContents, getAllOfType
@@ -155,7 +166,22 @@ protected Collection<ModelElementType> wrap(Collection<ModelElementType> content
155166
}
156167
return result;
157168
}
158-
169+
170+
@SuppressWarnings({ "unchecked", "rawtypes" })
171+
protected <T> Collection<T> wrapUnmodifiable(Collection<T> original) {
172+
if (original instanceof List) {
173+
return Collections.unmodifiableList((List) original);
174+
} else if (original instanceof NavigableSet) {
175+
return Collections.unmodifiableNavigableSet((NavigableSet) original);
176+
} else if (original instanceof SortedSet) {
177+
return Collections.unmodifiableSortedSet((SortedSet) original);
178+
} else if (original instanceof Set) {
179+
return Collections.unmodifiableSet((Set) original);
180+
} else {
181+
return Collections.unmodifiableCollection(original);
182+
}
183+
}
184+
159185
protected void addToCache(String type, ModelElementType instance) throws EolModelElementTypeNotFoundException {
160186
assert cachingEnabled;
161187

@@ -214,11 +240,11 @@ public Collection<ModelElementType> allContents() {
214240
if (allContentsCache == null) {
215241
allContentsCache = wrap(allContentsFromModel());
216242
if (allContentsCache == null) {
217-
return wrap(new ArrayList<>(0));
243+
return wrapUnmodifiable(wrap(new ArrayList<>(0)));
218244
}
219245
}
220246
}
221-
return allContentsCache;
247+
return wrapUnmodifiable(allContentsCache);
222248
}
223249
else return wrap(allContentsFromModel());
224250
}
@@ -262,7 +288,7 @@ else if (values == null) {
262288
);
263289
}
264290

265-
return values;
291+
return wrapUnmodifiable(values);
266292
}
267293

268294
@Override

tests/org.eclipse.epsilon.eol.engine.test.unit/src/org/eclipse/epsilon/eol/models/CachedModelTests.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,20 @@
99
******************************************************************************/
1010
package org.eclipse.epsilon.eol.models;
1111

12-
import static org.junit.Assert.assertTrue;
1312
import static org.junit.Assert.assertFalse;
13+
import static org.junit.Assert.assertThrows;
14+
import static org.junit.Assert.assertTrue;
1415
import static org.mockito.Mockito.never;
1516
import static org.mockito.Mockito.spy;
1617
import static org.mockito.Mockito.times;
1718
import static org.mockito.Mockito.verify;
1819
import static org.mockito.Mockito.when;
20+
1921
import java.util.ArrayList;
2022
import java.util.Arrays;
2123
import java.util.Collection;
2224
import java.util.Collections;
25+
2326
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
2427
import org.eclipse.epsilon.eol.exceptions.models.EolEnumerationValueNotFoundException;
2528
import org.eclipse.epsilon.eol.exceptions.models.EolModelElementTypeNotFoundException;
@@ -58,6 +61,14 @@ public void shouldNotComputeAllContentsOnSecondCall() throws Exception {
5861

5962
verify(model, times(1)).allContentsFromModel();
6063
}
64+
65+
@SuppressWarnings("resource")
66+
@Test
67+
public void shouldNotAllowChanges() throws Exception {
68+
final SimpleCachedModel model = new SimpleCachedModel();
69+
assertThrows(UnsupportedOperationException.class,
70+
() -> model.allContents().add("x"));
71+
}
6172
}
6273

6374
public static class AllOfTypeCachingTests {
@@ -113,6 +124,14 @@ public void shouldNotComputeAllOfTypeIfTypeIsEquivalentToACachedType() throws Ex
113124

114125
verify(model, never()).getAllOfTypeFromModel("org.example.Widget");
115126
}
127+
128+
@SuppressWarnings("resource")
129+
@Test
130+
public void shouldNotAllowChanges() throws Exception {
131+
final SimpleCachedModel model = new SimpleCachedModel();
132+
assertThrows(UnsupportedOperationException.class,
133+
() -> model.getAllOfType("Widget").add("x"));
134+
}
116135
}
117136

118137
public static class AllOfKindCachingTests {
@@ -168,6 +187,14 @@ public void shouldNotComputeAllOfKindIfKindIsEquivalentToACachedKind() throws Ex
168187

169188
verify(model, never()).getAllOfKindFromModel("org.example.Widget");
170189
}
190+
191+
@SuppressWarnings("resource")
192+
@Test
193+
public void shouldNotAllowChanges() throws Exception {
194+
final SimpleCachedModel model = new SimpleCachedModel();
195+
assertThrows(UnsupportedOperationException.class,
196+
() -> model.getAllOfKind("Widget").add("x"));
197+
}
171198
}
172199

173200
// TODO create / delete before caching has occured

0 commit comments

Comments
 (0)