[373968] Fix CCE if flattening a heterogeneous Collection
diff --git a/plugins/org.eclipse.ocl/src/org/eclipse/ocl/util/CollectionUtil.java b/plugins/org.eclipse.ocl/src/org/eclipse/ocl/util/CollectionUtil.java
index 24374b8..c38fee0 100644
--- a/plugins/org.eclipse.ocl/src/org/eclipse/ocl/util/CollectionUtil.java
+++ b/plugins/org.eclipse.ocl/src/org/eclipse/ocl/util/CollectionUtil.java
@@ -468,45 +468,29 @@
// Note: As OCL 2.3 (OMG 10-11-42) section A.2.5.8 fails to specify how to
// flatten an OrderedSet, we choose to flatten it into an OrderedSet
// represented by a LinkedHashSet.
- Collection<?> result = self;
-
- for (;;) {
- if (result.isEmpty()) {
+ Collection<Object> result = null;
+ for (Object object : self) {
+ if (object instanceof Collection<?>) {
+ result = createNewCollectionOfSameKind(self);
break;
- }
-
- Iterator<?> it = result.iterator();
- Object object = it.next();
-
- // if the element type is not a collection type, the result is the
- // current collection.
- if (!(object instanceof Collection<?>)) {
- break;
- }
-
- Collection<Object> newResult = null;
- if (result instanceof Bag<?>) {
- newResult = createNewBag();
- } else if (result instanceof Set<?>) {
- newResult = createNewSet();
- } else {
- // Sequence
- newResult = createNewSequence();
- }
-
- // the element type is a collection type -- flatten one level
- newResult.addAll((Collection<?>) object);
- while (it.hasNext()) {
- newResult.addAll((Collection<?>) it.next());
- }
-
- result = newResult;
- // loop until the result is empty or the first element is not a
- // collection
+ }
}
-
+ if (result == null) { // Already flat
+ return self;
+ }
+ flattenRecursion(result, self);
return result;
}
+ private static void flattenRecursion(Collection<Object> result, Collection<?> children) {
+ for (Object object : children) {
+ if (object instanceof Collection<?>) {
+ flattenRecursion(result, (Collection<?>) object);
+ }
+ else {
+ result.add(object);
+ }
+ }
+ }
/**
* Obtains the type of the flattened form of the specified collection type.
diff --git a/tests/org.eclipse.ocl.ecore.tests/src/org/eclipse/ocl/ecore/tests/CollectionsTest.java b/tests/org.eclipse.ocl.ecore.tests/src/org/eclipse/ocl/ecore/tests/CollectionsTest.java
index 02fd7c5..96fa628 100644
--- a/tests/org.eclipse.ocl.ecore.tests/src/org/eclipse/ocl/ecore/tests/CollectionsTest.java
+++ b/tests/org.eclipse.ocl.ecore.tests/src/org/eclipse/ocl/ecore/tests/CollectionsTest.java
@@ -403,7 +403,7 @@
assertTrue(check(helper,
"",
"OrderedSet{Sequence{'a', 'b'}, Sequence{'b', 'c', 'd'}}->flatten()" +
- " = Set{'b', 'c', 'a', 'd'}"));
+ " = OrderedSet{'a', 'b', 'c', 'd'}"));
assertTrue(check(helper,
"",
@@ -500,7 +500,7 @@
assertTrue(check(helper, "",
"OrderedSet{OrderedSet{}, OrderedSet{}}->flatten()" +
- " = Set{}"));
+ " = OrderedSet{}"));
assertTrue(check(helper, "",
"Sequence{Sequence{}, Sequence{}}->flatten()" +
@@ -529,7 +529,7 @@
assertTrue(check(helper,
"",
"OrderedSet{Sequence{Set{'a'}, Set{'b'}}, Sequence{Set{'b', 'c'}, Set{'d'}}}->flatten()" +
- " = Set{'b', 'c', 'a', 'd'}"));
+ " = OrderedSet{'a', 'b', 'c', 'd'}"));
assertTrue(check(helper,
"",
@@ -560,7 +560,7 @@
assertTrue(check(helper,
"",
"OrderedSet{OrderedSet{Sequence{}, Sequence{}}, OrderedSet{Sequence{}, Sequence{}}}->flatten()" +
- " = Set{}"));
+ " = OrderedSet{}"));
assertTrue(check(helper,
"",
diff --git a/tests/org.eclipse.ocl.uml.tests/src/org/eclipse/ocl/uml/tests/CollectionsTest.java b/tests/org.eclipse.ocl.uml.tests/src/org/eclipse/ocl/uml/tests/CollectionsTest.java
index 13c088f..ea0e574 100644
--- a/tests/org.eclipse.ocl.uml.tests/src/org/eclipse/ocl/uml/tests/CollectionsTest.java
+++ b/tests/org.eclipse.ocl.uml.tests/src/org/eclipse/ocl/uml/tests/CollectionsTest.java
@@ -394,7 +394,7 @@
assertTrue(check(helper,
"",
"OrderedSet{Sequence{'a', 'b'}, Sequence{'b', 'c', 'd'}}->flatten()" +
- " = Set{'b', 'c', 'a', 'd'}"));
+ " = OrderedSet{'a', 'b', 'c', 'd'}"));
assertTrue(check(helper,
"",