Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Mayer2015-06-11 12:23:30 +0000
committerAxel Richard2015-09-01 07:04:21 +0000
commit26b2974f9a8f6161c9e1ec1df57a58ef48ccee32 (patch)
tree2774594cc9f2c995f91092d31fb260d2f9b63a79 /plugins
parent129a6e645bbbc85666f3799c420ce7d8cefcd30c (diff)
downloadorg.eclipse.emf.compare-26b2974f9a8f6161c9e1ec1df57a58ef48ccee32.tar.gz
org.eclipse.emf.compare-26b2974f9a8f6161c9e1ec1df57a58ef48ccee32.tar.xz
org.eclipse.emf.compare-26b2974f9a8f6161c9e1ec1df57a58ef48ccee32.zip
[469853] Unresponsive merge viewer with reference changes that yield
many insertion points MergeViewerItem.Container.hasChildren() no longer delegates to getChildren(), but uses a more efficient implementation that stops as soon as child has been found. Override hasChildren() in ResourceAttachmentChangeMergeViewerItem, because it cannot use its super implementation. Delegate to getChildren() instead, which should be okay for these kind of changes. Bug: 469853 Change-Id: I3b99832df16c2b976b4fa629414bcdc4e72c2e67 Signed-off-by: Andreas Mayer <anma-e@gmx.de> Signed-off-by: Axel Richard <axel.richard@obeo.fr>
Diffstat (limited to 'plugins')
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/MergeViewerItem.java284
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/ResourceAttachmentChangeMergeViewerItem.java20
2 files changed, 228 insertions, 76 deletions
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/MergeViewerItem.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/MergeViewerItem.java
index 964e90fb8..471c98611 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/MergeViewerItem.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/MergeViewerItem.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2015 Obeo.
+ * Copyright (c) 2012, 2015 Obeo and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -21,16 +21,20 @@ import static org.eclipse.emf.compare.utils.EMFComparePredicates.CONTAINMENT_REF
import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide;
import static org.eclipse.emf.compare.utils.EMFComparePredicates.onFeature;
+import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -38,6 +42,7 @@ import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.Conflict;
import org.eclipse.emf.compare.ConflictKind;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceKind;
@@ -54,7 +59,6 @@ import org.eclipse.emf.compare.rcp.ui.internal.util.MergeViewerUtil;
import org.eclipse.emf.compare.rcp.ui.internal.util.ResourceUIUtil;
import org.eclipse.emf.compare.rcp.ui.mergeviewer.IMergeViewer.MergeViewerSide;
import org.eclipse.emf.compare.rcp.ui.mergeviewer.item.IMergeViewerItem;
-import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.filters.IDifferenceFilter;
import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider;
import org.eclipse.emf.compare.utils.ReferenceUtil;
import org.eclipse.emf.ecore.EObject;
@@ -350,6 +354,7 @@ public class MergeViewerItem extends AdapterImpl implements IMergeViewerItem {
if (differences.isEmpty()) {
return ret;
}
+
final List<Object> sideContent = ReferenceUtil.getAsList((EObject)getSideValue(getSide()),
eStructuralFeature);
final List<Object> oppositeContent = ReferenceUtil.getAsList((EObject)getSideValue(getSide()
@@ -358,50 +363,19 @@ public class MergeViewerItem extends AdapterImpl implements IMergeViewerItem {
for (Diff diff : Lists.reverse(differences)) {
EObject value = (EObject)MergeViewerUtil.getDiffValue(diff);
Match match = getComparison().getMatch(value);
-
- // create insertion point if we are on the opposite side of the source of an ADD or on the same
- // side as the a DELETE
- DifferenceSource source = diff.getSource();
- DifferenceKind kind = diff.getKind();
- DifferenceState state = diff.getState();
- boolean b1 = source == DifferenceSource.LEFT && kind == DifferenceKind.DELETE
- && getSide() == MergeViewerSide.LEFT && DifferenceState.MERGED != state;
- boolean b2 = source == DifferenceSource.LEFT && kind == DifferenceKind.ADD
- && getSide() == MergeViewerSide.RIGHT && DifferenceState.MERGED != state;
- boolean b3 = source == DifferenceSource.RIGHT && kind == DifferenceKind.ADD
- && getSide() == MergeViewerSide.LEFT && DifferenceState.MERGED != state;
- boolean b4 = source == DifferenceSource.RIGHT && kind == DifferenceKind.DELETE
- && getSide() == MergeViewerSide.RIGHT && DifferenceState.MERGED != state;
-
- boolean b5 = (match == null || match.getLeft() == null && match.getRight() == null)
- && DifferenceState.MERGED == state;
-
- // do not duplicate insertion point for pseudo add conflict
- // so we must only create one for pseudo delete conflict
- boolean b6 = diff.getConflict() == null
- || (diff.getConflict().getKind() != ConflictKind.PSEUDO || kind == DifferenceKind.DELETE);
-
- if ((b1 || b2 || b3 || b4 || b5) && b6) {
- if (match == null && DifferenceState.MERGED == state) {
+ if (!isPseudoAddConflict(diff)
+ && (isAddOnOppositeSide(diff) || isDeleteOnSameSide(diff) || isInsertOnBothSides(diff,
+ match))) {
+ if (match == null && diff.getState() == DifferenceState.MERGED) {
EObject bestSideValue = (EObject)getBestSideValue();
match = getComparison().getMatch(bestSideValue);
match = getMatchWithNullValues(match);
}
- if (match != null) {
- EObject left = match.getLeft();
- EObject right = match.getRight();
-
- // Real add conflict (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=442898)
- if (match.getLeft() != null && match.getRight() != null) {
- if (b3) {
- continue;
- } else if (b2) {
- continue;
- }
- }
+
+ if (match != null && !isRealAddConflict(diff, match)) {
IMergeViewerItem.Container insertionPoint = new MergeViewerItem.Container(
- getComparison(), diff, left, right, match.getOrigin(), getSide(),
- getAdapterFactory());
+ getComparison(), diff, match.getLeft(), match.getRight(), match.getOrigin(),
+ getSide(), getAdapterFactory());
final int insertionIndex;
if (match.getLeft() == null && match.getRight() == null && diff.getConflict() != null
@@ -416,7 +390,7 @@ public class MergeViewerItem extends AdapterImpl implements IMergeViewerItem {
}
// offset the insertion by the number of previous insertion points in the list
- // Can not b improved by keeping the number of created insertion points because the given
+ // Cannot be improved by keeping the number of created insertion points because the given
// "values" parameter may already contains some insertion points.
int realIndex = 0;
for (int index = 0; index < insertionIndex && realIndex < ret.size(); realIndex++) {
@@ -432,6 +406,44 @@ public class MergeViewerItem extends AdapterImpl implements IMergeViewerItem {
return ret;
}
+ private boolean isAddOnOppositeSide(Diff diff) {
+ if (diff.getState() != DifferenceState.MERGED && diff.getKind() == DifferenceKind.ADD) {
+ DifferenceSource source = diff.getSource();
+ MergeViewerSide side = getSide();
+ return (source == DifferenceSource.LEFT && side == MergeViewerSide.RIGHT)
+ || (source == DifferenceSource.RIGHT && side == MergeViewerSide.LEFT);
+ }
+
+ return false;
+ }
+
+ private boolean isDeleteOnSameSide(Diff diff) {
+ if (diff.getState() != DifferenceState.MERGED && diff.getKind() == DifferenceKind.DELETE) {
+ DifferenceSource source = diff.getSource();
+ MergeViewerSide side = getSide();
+ return (source == DifferenceSource.LEFT && side == MergeViewerSide.LEFT)
+ || (source == DifferenceSource.RIGHT && side == MergeViewerSide.RIGHT);
+ }
+
+ return false;
+ }
+
+ private boolean isInsertOnBothSides(Diff diff, Match match) {
+ return diff.getState() == DifferenceState.MERGED
+ && (match == null || (match.getLeft() == null && match.getRight() == null));
+ }
+
+ private boolean isPseudoAddConflict(Diff diff) {
+ Conflict conflict = diff.getConflict();
+ return conflict != null && conflict.getKind() == ConflictKind.PSEUDO
+ && diff.getKind() == DifferenceKind.ADD;
+ }
+
+ private boolean isRealAddConflict(Diff diff, Match match) {
+ // Real add conflict (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=442898)
+ return match.getRight() != null && match.getLeft() != null && isAddOnOppositeSide(diff);
+ }
+
/**
* After merging a diff which will lead to have an insertion point on both sides, the match associated
* with this diff will be unreacheable because its left and right sides will be null. This method will
@@ -488,6 +500,46 @@ public class MergeViewerItem extends AdapterImpl implements IMergeViewerItem {
return ret;
}
+ protected boolean yieldsMergeViewerItem(Collection<?> values) {
+ Iterable<EObject> elements = filter(values, EObject.class);
+ if (fDiff != null && !Iterables.isEmpty(elements)) {
+ return true;
+ }
+
+ for (EObject element : elements) {
+ Match match = getComparison().getMatch(element);
+ if (match != null && !isMatchWithAllProxyData(match)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected boolean yieldsInsertionPoint(Iterable<Diff> diffs) {
+ return Iterables.any(diffs, new Predicate<Diff>() {
+ public boolean apply(Diff diff) {
+ if (isPseudoAddConflict(diff)) {
+ return false;
+ }
+
+ EObject value = (EObject)MergeViewerUtil.getDiffValue(diff);
+ Match match = getComparison().getMatch(value);
+ if (isAddOnOppositeSide(diff) || isDeleteOnSameSide(diff) || isInsertOnBothSides(diff, match)) {
+ if (match == null && diff.getState() == DifferenceState.MERGED) {
+ EObject bestSideValue = (EObject)getBestSideValue();
+ match = getComparison().getMatch(bestSideValue);
+ match = getMatchWithNullValues(match);
+ }
+
+ return match != null && !isRealAddConflict(diff, match);
+ }
+
+ return false;
+ }
+ });
+ }
+
/**
* Check if the given match holds a proxy on each side.
*
@@ -545,27 +597,33 @@ public class MergeViewerItem extends AdapterImpl implements IMergeViewerItem {
}
/**
- * From a list of {@link Diff}s, returns the diffs which are not filtered by a filter of the given list of
- * {@link IDifferenceFilter}.
+ * Returns a list of those of the given diffs that are displayed in a group as provided by the given group
+ * provider and satisfy the given predicate.
*
* @param unfilteredDiffs
- * the given list of unfiltered diffs.
- * @param filters
- * the given list of IDifferenceFilter.
- * @return A filtered list of diffs.
+ * the unfiltered diffs
+ * @param predicate
+ * a filter predicate; a {@code null} predicate will be satisfied by any diff
+ * @param groupProvider
+ * the active group provider
+ * @return a list of the filtered diffs
*/
- protected List<? extends Diff> filteredDiffs(List<? extends Diff> unfilteredDiffs,
- Predicate<? super EObject> predicate, IDifferenceGroupProvider group) {
- if (predicate != null) {
- List<Diff> filteredDiffs = Lists.newArrayList(unfilteredDiffs);
- for (Diff unfilteredDiff : unfilteredDiffs) {
- if (!MergeViewerUtil.isVisibleInMergeViewer(unfilteredDiff, group, predicate)) {
- filteredDiffs.remove(unfilteredDiff);
- }
- }
- return filteredDiffs;
+ protected List<? extends Diff> filteredDiffs(Iterable<? extends Diff> unfilteredDiffs,
+ Predicate<? super EObject> predicate, IDifferenceGroupProvider groupProvider) {
+ return Lists.newArrayList(filter(unfilteredDiffs, visibleInMergeViewer(predicate, groupProvider)));
+ }
+
+ protected Predicate<Diff> visibleInMergeViewer(final Predicate<? super EObject> predicate,
+ final IDifferenceGroupProvider groupProvider) {
+ if (predicate == null) {
+ return Predicates.alwaysTrue();
}
- return unfilteredDiffs;
+
+ return new Predicate<Diff>() {
+ public boolean apply(Diff diff) {
+ return MergeViewerUtil.isVisibleInMergeViewer(diff, groupProvider, predicate);
+ }
+ };
}
public static class Container extends MergeViewerItem implements IMergeViewerItem.Container {
@@ -737,10 +795,90 @@ public class MergeViewerItem extends AdapterImpl implements IMergeViewerItem {
/**
* {@inheritDoc}
*
- * @see org.eclipse.emf.compare.rcp.ui.mergeviewer.item.IMergeViewerItem.Container#hasChildren()
+ * @see org.eclipse.emf.compare.rcp.ui.mergeviewer.item.IMergeViewerItem.Container#hasChildren(IDifferenceGroupProvider,
+ * Predicate)
*/
- public boolean hasChildren(IDifferenceGroupProvider group, Predicate<? super EObject> predicate) {
- return getChildren(group, predicate).length > 0;
+ public boolean hasChildren(IDifferenceGroupProvider groupProvider,
+ Predicate<? super EObject> predicate) {
+ if (getLeft() instanceof NotLoadedFragmentMatch) {
+ NotLoadedFragmentMatch notLoadedFragmentMatch = (NotLoadedFragmentMatch)getLeft();
+ return !notLoadedFragmentMatch.getChildren().isEmpty();
+ }
+
+ Object sideValue = getSideValue(getSide());
+ EObject bestSideValue = (EObject)getBestSideValue();
+ Match match = getComparison().getMatch(bestSideValue);
+
+ Iterable<Diff> differences = match == null ? Collections.<Diff> emptyList() : ImmutableList
+ .copyOf(filter(match.getDifferences(), CONTAINMENT_REFERENCE_CHANGE));
+
+ Collection<? extends EStructuralFeature> childrenFeatures = getChildrenFeatures(bestSideValue);
+ for (EStructuralFeature eStructuralFeature : childrenFeatures) {
+ if (eStructuralFeature instanceof EReference) {
+ if (hasChildrenOfReference(groupProvider, predicate, sideValue, differences,
+ (EReference)eStructuralFeature)) {
+ return true;
+ }
+ } else if (FeatureMapUtil.isFeatureMap(eStructuralFeature)) {
+ if (hasChildrenOfFeatureMap(groupProvider, predicate, sideValue, differences,
+ eStructuralFeature)) {
+ return true;
+ }
+ }
+ }
+
+ return hasNotLoadedFragmentsItems(match);
+ }
+
+ private boolean hasChildrenOfReference(IDifferenceGroupProvider groupProvider,
+ Predicate<? super EObject> predicate, Object container, Iterable<Diff> differences,
+ EReference reference) {
+ List<Object> featureContent = ReferenceUtil.getAsList((EObject)container, reference);
+ if (yieldsMergeViewerItem(featureContent)) {
+ return true;
+ }
+
+ if (getSide() != MergeViewerSide.ANCESTOR) {
+ Iterable<Diff> differencesOnFeature = filter(differences, onFeature(reference.getName()));
+ Iterable<Diff> filteredDiffs = filter(differencesOnFeature, visibleInMergeViewer(predicate,
+ groupProvider));
+ return yieldsInsertionPoint(filteredDiffs);
+ }
+
+ return true;
+ }
+
+ private boolean hasChildrenOfFeatureMap(IDifferenceGroupProvider groupProvider,
+ Predicate<? super EObject> predicate, Object container, Iterable<Diff> differences,
+ EStructuralFeature featureMap) {
+ List<Object> mapContent = ReferenceUtil.getAsList((EObject)container, featureMap);
+ List<Object> featureContent = Lists.newArrayList();
+ Set<EStructuralFeature> derivedFeatures = Sets.newLinkedHashSet();
+ for (Object object : mapContent) {
+ if (object instanceof FeatureMap.Entry) {
+ featureContent.add(((FeatureMap.Entry)object).getValue());
+ derivedFeatures.add(((FeatureMap.Entry)object).getEStructuralFeature());
+ }
+ }
+
+ if (yieldsMergeViewerItem(featureContent)) {
+ return true;
+ }
+
+ if (getSide() != MergeViewerSide.ANCESTOR) {
+ Iterable<Diff> differencesOnFeature = filter(differences, onFeatures(derivedFeatures));
+ Iterable<Diff> filteredDiffs = filter(differencesOnFeature, visibleInMergeViewer(predicate,
+ groupProvider));
+ return yieldsInsertionPoint(filteredDiffs);
+ }
+
+ return false;
+ }
+
+ private boolean hasNotLoadedFragmentsItems(Match match) {
+ Collection<Match> childrenMatches = ResourceUIUtil.getChildrenMatchWithNotLoadedParent(
+ getComparison(), match, getSide());
+ return !childrenMatches.isEmpty();
}
@Override
@@ -752,7 +890,8 @@ public class MergeViewerItem extends AdapterImpl implements IMergeViewerItem {
/**
* {@inheritDoc}
*
- * @see org.eclipse.emf.compare.rcp.ui.mergeviewer.item.IMergeViewerItem.Container#getChildren()
+ * @see org.eclipse.emf.compare.rcp.ui.mergeviewer.item.IMergeViewerItem.Container#getChildren(IDifferenceGroupProvider,
+ * Predicate)
*/
public IMergeViewerItem[] getChildren(IDifferenceGroupProvider group,
Predicate<? super EObject> predicate) {
@@ -868,8 +1007,8 @@ public class MergeViewerItem extends AdapterImpl implements IMergeViewerItem {
List<Object> featureContent = ReferenceUtil.getAsList((EObject)container, reference);
List<IMergeViewerItem> mergeViewerItem = createMergeViewerItemFrom(featureContent);
if (getSide() != MergeViewerSide.ANCESTOR) {
- List<? extends Diff> differencesOnFeature = ImmutableList.copyOf(filter(differences,
- onFeature(reference.getName())));
+ Iterable<? extends Diff> differencesOnFeature = filter(differences, onFeature(reference
+ .getName()));
List<? extends Diff> filteredDiffs = filteredDiffs(differencesOnFeature, predicate, group);
ret.addAll(createInsertionPoints(getComparison(), reference, mergeViewerItem, filteredDiffs));
} else {
@@ -907,11 +1046,7 @@ public class MergeViewerItem extends AdapterImpl implements IMergeViewerItem {
}
List<IMergeViewerItem> mergeViewerItem = createMergeViewerItemFrom(featureContent);
if (getSide() != MergeViewerSide.ANCESTOR) {
- List<Diff> differencesOnFeature = newArrayList();
- for (EStructuralFeature derivedFeature : derivedFeatures) {
- differencesOnFeature.addAll(ImmutableList.copyOf(filter(differences,
- onFeature(derivedFeature.getName()))));
- }
+ Iterable<Diff> differencesOnFeature = filter(differences, onFeatures(derivedFeatures));
List<? extends Diff> filteredDiffs = filteredDiffs(differencesOnFeature, predicate, group);
ret.addAll(createInsertionPoints(getComparison(), featureMap, mergeViewerItem, filteredDiffs));
} else {
@@ -920,6 +1055,15 @@ public class MergeViewerItem extends AdapterImpl implements IMergeViewerItem {
return ret;
}
+ private Predicate<Diff> onFeatures(Iterable<EStructuralFeature> features) {
+ return Predicates.or(Iterables.transform(features,
+ new Function<EStructuralFeature, Predicate<? super Diff>>() {
+ public Predicate<? super Diff> apply(EStructuralFeature feature) {
+ return onFeature(feature.getName());
+ }
+ }));
+ }
+
/**
* Returns the list of children features to display within the UI.
*
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/ResourceAttachmentChangeMergeViewerItem.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/ResourceAttachmentChangeMergeViewerItem.java
index e85e0f73f..349093f29 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/ResourceAttachmentChangeMergeViewerItem.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/mergeviewer/item/impl/ResourceAttachmentChangeMergeViewerItem.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013, 2014 Obeo.
+ * Copyright (c) 2013, 2015 Obeo and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -46,8 +46,6 @@ import org.eclipse.emf.ecore.resource.Resource;
public class ResourceAttachmentChangeMergeViewerItem extends MergeViewerItem.Container {
/**
- * {@inheritDoc}
- *
* @see org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.impl.MergeViewerItem.Container#Container(Comparison
* comparison, Diff diff, Object left, Object right, Object ancestor, MergeViewerSide side,
* AdapterFactory adapterFactory)
@@ -59,8 +57,6 @@ public class ResourceAttachmentChangeMergeViewerItem extends MergeViewerItem.Con
}
/**
- * {@inheritDoc}
- *
* @see org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.impl.MergeViewerItem.Container#Container(Comparison,
* Diff, Match, MergeViewerSide, AdapterFactory)
*/
@@ -72,7 +68,19 @@ public class ResourceAttachmentChangeMergeViewerItem extends MergeViewerItem.Con
/**
* {@inheritDoc}
*
- * @see org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.impl.MergeViewerItem.Container#getChildren()
+ * @see org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.impl.MergeViewerItem.Container#hasChildren(IDifferenceGroupProvider,
+ * Predicate)
+ */
+ @Override
+ public boolean hasChildren(IDifferenceGroupProvider groupProvider, Predicate<? super EObject> predicate) {
+ return getChildren(groupProvider, predicate).length > 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.rcp.ui.internal.mergeviewer.item.impl.MergeViewerItem.Container#getChildren(IDifferenceGroupProvider,
+ * Predicate)
*/
@SuppressWarnings("unchecked")
@Override

Back to the top