From 20fa99617d54cb5e959b39ac5c72827dfeb330d4 Mon Sep 17 00:00:00 2001
From: Simon Barner <barner@fortiss.org>
Date: Fri, 19 Feb 2021 13:07:01 +0100
Subject: [PATCH] Add getChildrenWithType(EObject, Class<T>,
 Collection<Class<?extends T>)

* For the given EObject, this specialization returns the most nested
  ancestors of given type that does not have any ancestors of any
  of the provided admissible specializations.

Issue-Ref: 4104
Issue-Url: https://git.fortiss.org/af3/af3/-/issues/4104

Signed-off-by: Simon Barner <barner@fortiss.org>
---
 .../org/fortiss/tooling/kernel/utils/.ratings |  2 +-
 .../tooling/kernel/utils/EcoreUtils.java      | 21 +++++++++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/.ratings b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/.ratings
index 8d0eaa94b..6b4f47f2c 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/.ratings
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/.ratings
@@ -1,7 +1,7 @@
 CompositionUtils.java 34c0a191bd0fb4176c94b4d61abb5c88a679d5e8 GREEN
 EMFResourceUtils.java 68e6712a52349548bf85346900b17aa65b5f0ea9 GREEN
 EcoreSerializerBase.java 0a0c2969d793d2e68094c55c8f7b0a662ef6e5d5 GREEN
-EcoreUtils.java 18416b5c214410a02eb35596fd807a1cc27d6b35 GREEN
+EcoreUtils.java c38ac59cd7abad71a03d8666bf0943b40b90e58d YELLOW
 ExtensionPointUtils.java 7ce63242b49eb9a7cd4eaadd223f5ebce1dfd75b GREEN
 HierarchicalNameComparator.java 6face1b673126701a0721af48ead2f9766c17d46 GREEN
 IdentifierUtils.java fff43dc4e84cdd89c3ece4f5d9d89aec4b0749c2 GREEN
diff --git a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/EcoreUtils.java b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/EcoreUtils.java
index 18416b5c2..c38ac59cd 100644
--- a/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/EcoreUtils.java
+++ b/org.fortiss.tooling.kernel/src/org/fortiss/tooling/kernel/utils/EcoreUtils.java
@@ -22,6 +22,8 @@ import static org.eclipse.emf.ecore.util.EcoreUtil.getAllContents;
 import static org.eclipse.emf.ecore.util.EcoreUtil.getRootContainer;
 import static org.eclipse.emf.ecore.util.EcoreUtil.replace;
 import static org.eclipse.emf.ecore.util.EcoreUtil.UsageCrossReferencer.find;
+import static org.fortiss.tooling.common.util.LambdaUtils.asStream;
+import static org.fortiss.tooling.common.util.LambdaUtils.isAssignableFromAny;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -268,6 +270,25 @@ public class EcoreUtils {
 		return getChildrenWith(parent, isAssignable);
 	}
 
+	/**
+	 * For the given {@code element}, return the most nested ancestors of type {@code clazz} that
+	 * does not have any ancestors of any of the {@code admissibleSpecializations}.
+	 */
+	@SuppressWarnings({"rawtypes", "unchecked"})
+	public static <T extends EObject> Collection<T> getChildrenWithType(EObject element,
+			Class<T> clazz, Collection<Class<? extends T>> admissibleSpecializations) {
+
+		Predicate<? super EObject> hasApplicableChildren =
+				modelElement -> asStream(modelElement.eAllContents())
+						.anyMatch(c -> isAssignableFromAny((Collection)admissibleSpecializations,
+								c.getClass()));
+
+		Stream<T> executionUnits = asStream(element.eAllContents()).filter(clazz::isInstance)
+				.filter(hasApplicableChildren.negate()).map(clazz::cast);
+
+		return executionUnits.collect(toList());
+	}
+
 	/**
 	 * For a given {@link EObject}, recursively returns the first child that satisfies the given
 	 * {@link Predicate}.
-- 
GitLab