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 66f7d00d617e8bea7c15583fae4efd5e7a202f7b..40887f011aac6bd3652f4995ff28ff86398c183a 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 @@ -2,7 +2,7 @@ CompositionUtils.java 34c0a191bd0fb4176c94b4d61abb5c88a679d5e8 GREEN ConstraintsUtils.java 0f8be020f2ca4bb08931c32452163c04a28e30ce GREEN EMFResourceUtils.java 979d0e1f4f66a2b3e715d2da0ebef6493f547fd7 GREEN EcoreSerializerBase.java 0a0c2969d793d2e68094c55c8f7b0a662ef6e5d5 GREEN -EcoreUtils.java 91087233c50130c4abde858d892c6a1e7991e1bf GREEN +EcoreUtils.java 3a41fa0ff5a0ea30a132eeac11cb04edb40ba4fa 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 91087233c50130c4abde858d892c6a1e7991e1bf..3a41fa0ff5a0ea30a132eeac11cb04edb40ba4fa 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 @@ -17,6 +17,7 @@ package org.fortiss.tooling.kernel.utils; import static java.util.stream.Collectors.toList; import static org.eclipse.emf.common.notify.Notification.EVENT_TYPE_COUNT; +import static org.eclipse.emf.common.util.ECollections.unmodifiableEList; 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; @@ -29,6 +30,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -36,7 +38,6 @@ import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.impl.NotificationImpl; import org.eclipse.emf.common.util.AbstractEList; import org.eclipse.emf.common.util.BasicEList; -import org.eclipse.emf.common.util.ECollections; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.ecore.EClass; @@ -108,27 +109,41 @@ public class EcoreUtils { /** * From a given {@link EList} with objects of type <code>S</code>, create another unmodifiable - * {@link EList} with objects of type <code>T</code>. The resulting {@link EList} is - * unmodifiable thereby it represents only a view over the source list. + * {@link EList} whose elements satisfy the given predicate. * - * @param target - * a class representing type <code>T</code>. + * @param pred + * {@link Predicate} to test each element of the given list against. * @param srcList - * an EList with objects of type <code>S</code>. + * an EList with objects to tested. * @return an unmodifiable EList of objects of type T. */ - @SuppressWarnings("unchecked") - public static <T> EList<T> pickInstanceOf(Class<T> target, List<?> srcList) { + public static <S> EList<?> pickInstanceOf(Predicate<S> pred, List<S> srcList) { if(srcList == null) { return null; } - EList<T> result = new BasicEList<T>(); - for(Object sourceElement : srcList) { - if(target.isAssignableFrom(sourceElement.getClass())) { - result.add((T)sourceElement); + EList<S> result = new BasicEList<>(); + for(S sourceElement : srcList) { + if(pred.test(sourceElement)) { + result.add(sourceElement); } } - return ECollections.unmodifiableEList(result); + return unmodifiableEList(result); + } + + /** + * From a given {@link EList} with objects of type <code>S</code>, create another unmodifiable + * {@link EList} with objects of type <code>T</code> if assignable. + * + * @param target + * a class representing type <code>T</code>. + * @param srcList + * an EList with objects to tested. + * @return an unmodifiable EList of objects of type T. + */ + @SuppressWarnings("unchecked") + public static <S, T> EList<T> pickInstanceOf(Class<T> target, List<S> srcList) { + Predicate<S> isAssignable = element -> target.isAssignableFrom(element.getClass()); + return (EList<T>)pickInstanceOf(isAssignable, srcList); } /** @@ -140,27 +155,16 @@ public class EcoreUtils { * * @param targetClasses * a collection of classes representing types of elements to be picked. - * @param sourceList + * @param srcList * an EList with objects of type <code>S</code>. * @return an unmodifiable EList of objects of type <code>S</code> containing only the * targetClasses instances. */ - public static <S> EList<S> pickInstanceOf(Collection<Class<?>> targetClasses, - List<S> sourceList) { - if(sourceList == null) { - return null; - } - EList<S> result = new BasicEList<S>(); - for(S sourceElement : sourceList) { - Class<?> sourceClass = sourceElement.getClass(); - for(Class<?> targetClass : targetClasses) { - if(targetClass.isAssignableFrom(sourceClass)) { - result.add(sourceElement); - break; - } - } - } - return ECollections.unmodifiableEList(result); + @SuppressWarnings("unchecked") + public static <S> EList<S> pickInstanceOf(Collection<Class<?>> targetClasses, List<S> srcList) { + Predicate<S> isAssignableFromAny = element -> targetClasses.stream() + .anyMatch(t -> t.isAssignableFrom(element.getClass())); + return (EList<S>)pickInstanceOf(isAssignableFromAny, srcList); } /** @@ -171,23 +175,38 @@ public class EcoreUtils { * * @param targetClass * a class representing types of elements to be picked. - * @param sourceList + * @param srcList * an {@link EList} with objects of type <code>S</code>. * @return an unmodifiable {@link EList} of objects of type <code>S</code> containing only the * <code>targetClass</code> instances */ - public static <S> EList<S> filterOutInstanceOf(Class<?> targetClass, List<S> sourceList) { + @SuppressWarnings("unchecked") + public static <S> EList<S> filterOutInstanceOf(Class<?> targetClass, List<S> srcList) { + Predicate<S> isNotAssignable = element -> !targetClass.isAssignableFrom(element.getClass()); + return (EList<S>)pickInstanceOf(isNotAssignable, srcList); + } + + /** + * From a given {@link EList} with source objects of type <code>S</code> pick the first object + * which satisfies the given {@link Predicate}. + * + * @param pred + * {@link Predicate} to test elements of the given list against. + * @param sourceList + * an {@link EList} with objects of type <code>S</code>. + * @return an object of type <code>T</code> or <code>null</code> if none exists. + */ + @SuppressWarnings("unchecked") + public static <S, T extends S> T pickFirstInstanceOf(Predicate<S> pred, List<S> sourceList) { if(sourceList == null) { return null; } - EList<S> result = new BasicEList<S>(); for(S sourceElement : sourceList) { - Class<?> sourceClass = sourceElement.getClass(); - if(!targetClass.isAssignableFrom(sourceClass)) { - result.add(sourceElement); + if(pred.test(sourceElement)) { + return (T)sourceElement; } } - return ECollections.unmodifiableEList(result); + return null; } /** @@ -200,37 +219,29 @@ public class EcoreUtils { * an {@link EList} with objects of type <code>S</code>. * @return an object of type <code>T</code> or <code>null</code> if none exists. */ - @SuppressWarnings("unchecked") public static <S, T extends S> T pickFirstInstanceOf(Class<T> targetClass, List<S> sourceList) { - if(sourceList == null) { - return null; - } - for(S sourceElement : sourceList) { - if(targetClass.isAssignableFrom(sourceElement.getClass())) { - return (T)sourceElement; - } - } - return null; + Predicate<S> isAssignable = element -> targetClass.isAssignableFrom(element.getClass()); + return pickFirstInstanceOf(isAssignable, sourceList); } /** - * For a given {@link EObject} recursively returns all its children that have a - * certain type. + * For a given {@link EObject} recursively returns all its children that satisfy the given + * {@link Predicate}. * * @param parent * the parent {@link EObject}. - * @param type - * the type. + * @param pred + * {@link Predicate} to be satisfied by the children. * @return a list of children. */ @SuppressWarnings("unchecked") - public static <S> EList<S> getChildrenWithType(EObject parent, Class<S> type) { + public static <S> EList<S> getChildrenWith(EObject parent, Predicate<EObject> pred) { EList<S> children = new BasicEList<S>(); - TreeIterator<EObject> content = EcoreUtil.getAllContents(parent, true); + TreeIterator<EObject> content = getAllContents(parent, true); while(content.hasNext()) { EObject child = content.next(); - if(type.isAssignableFrom(child.getClass())) { + if(pred.test(child)) { children.add((S)child); } } @@ -238,49 +249,81 @@ public class EcoreUtils { } /** - * For a given {@link EObject}, recursively returns the first child that has a certain type. - * Using this method is more efficient than returning the first element of the result of + * For a given {@link EObject} recursively returns all its children that have the given type. + * + * @param parent + * the parent {@link EObject}. + * @param type + * the type. + * @return a list of children. + */ + public static <S> EList<S> getChildrenWithType(EObject parent, Class<S> type) { + Predicate<EObject> isAssignable = element -> type.isAssignableFrom(element.getClass()); + return getChildrenWith(parent, isAssignable); + } + + /** + * For a given {@link EObject}, recursively returns the first child that satisfies the given + * {@link Predicate}. + * This method is more efficient than returning the first element of the result of * {@link #getChildrenWithType(EObject, Class)}. * * @param parent * the parent {@link EObject} - * @param type - * the type + * @param pred + * {@link Predicate} to be satisfied by child elements. * * @return the first child of the given type. */ @SuppressWarnings("unchecked") - public static <S> S getFirstChildWithType(EObject parent, Class<S> type) { + public static <S> S getFirstChildWith(EObject parent, Predicate<EObject> pred) { TreeIterator<EObject> content = EcoreUtil.getAllContents(parent, true); while(content.hasNext()) { EObject child = content.next(); - if(type.isAssignableFrom(child.getClass())) { + if(pred.test(child)) { return (S)child; } } return null; } + /** + * For a given {@link EObject}, recursively returns the first child that has a certain type. + * Using this method is more efficient than returning the first element of the result of + * {@link #getChildrenWithType(EObject, Class)}. + * + * @param parent + * the parent {@link EObject} + * @param type + * the type + * + * @return the first child of the given type. + */ + public static <S> S getFirstChildWithType(EObject parent, Class<S> type) { + Predicate<EObject> isAssignable = element -> type.isAssignableFrom(element.getClass()); + return getFirstChildWith(parent, isAssignable); + } + /** * Returns a list of all parent {@link EObject}s that have the type <code>type</code>. If none * are found, an empty list is returned. * - * @param startElement + * @param child * The {@link EObject} from which the "upwards" search shall begin. - * @param type - * The class type which is used to filter the search. + * @param pred + * {@link Predicate} to be satisfied by parent elements. * @return List of parent {@link EObject}s of type <code>type</code>. */ @SuppressWarnings("unchecked") - public static <T extends EObject> EList<T> getParentsWithType(EObject startElement, - Class<T> type) { + public static <T extends EObject> EList<T> getParentsWith(EObject child, + Predicate<EObject> pred) { EList<T> parentElements = new BasicEList<T>(); - EObject currentParent = startElement.eContainer(); + EObject currentParent = child.eContainer(); while(currentParent != null) { - if(type.isAssignableFrom(currentParent.getClass())) { + if(pred.test(currentParent)) { parentElements.add((T)currentParent); } currentParent = currentParent.eContainer(); @@ -289,21 +332,35 @@ public class EcoreUtils { } /** - * Returns the first parent {@link EObject} that has the type <code>T</code>. If none are - * found, null is returned. + * Returns a list of all parent {@link EObject}s that have the type <code>type</code>. If none + * are found, an empty list is returned. * - * @param startElement + * @param child * The {@link EObject} from which the "upwards" search shall begin. * @param type - * The class type to find the first parent with. + * The class type which is used to filter the search. + * @return List of parent {@link EObject}s of type <code>type</code>. + */ + public static <T extends EObject> EList<T> getParentsWithType(EObject child, Class<T> type) { + Predicate<EObject> isAssignable = element -> type.isAssignableFrom(element.getClass()); + return getParentsWith(child, isAssignable); + } + + /** + * Returns the first parent {@link EObject} that satisfies the given {@link Predicate}. If none + * are found, null is returned. + * + * @param child + * The {@link EObject} from which the "upwards" search shall begin. + * @param pred + * {@link Predicate} to be satisfied by parent elements. * @return List of parent {EObject} of type <code>T</code>. */ @SuppressWarnings("unchecked") - public static <T extends EObject> T getFirstParentWithType(EObject startElement, - Class<T> type) { - EObject currentParent = startElement.eContainer(); + public static <T extends EObject> T getFirstParentWith(EObject child, Predicate<EObject> pred) { + EObject currentParent = child.eContainer(); while(currentParent != null) { - if(type.isAssignableFrom(currentParent.getClass())) { + if(pred.test(currentParent)) { return (T)currentParent; } currentParent = currentParent.eContainer(); @@ -311,6 +368,21 @@ public class EcoreUtils { return null; } + /** + * Returns the first parent {@link EObject} that has the type <code>T</code>. If none are + * found, null is returned. + * + * @param child + * The {@link EObject} from which the "upwards" search shall begin. + * @param type + * Type of the parent that is searched. + * @return List of parent {EObject} of type <code>T</code>. + */ + public static <T extends EObject> T getFirstParentWithType(EObject child, Class<T> type) { + Predicate<EObject> isAssignable = element -> type.isAssignableFrom(element.getClass()); + return getFirstParentWith(child, isAssignable); + } + /** * Returns true if <code>candidateAncestor</code> is an ancestor of <code>startElement</code>. *