1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-24 08:44:01 +02:00

Bug 239050

Makes getAncestorOfType() return the closest ancestor in terms of
depth.  Also adds a new method, getAllAncestorsOfType(), which returns all
the ancestors of the specified type in an array.
This commit is contained in:
Marc Khouzam 2008-07-16 19:08:05 +00:00
parent 0006e4ba15
commit 963ba7e067

View file

@ -11,8 +11,12 @@
*******************************************************************************/
package org.eclipse.dd.dsf.datamodel;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
@ -26,10 +30,15 @@ public class DMContexts {
* Convenience constant.
*/
public static final IDMContext[] EMPTY_CONTEXTS_ARRAY = new IDMContext[0];
/**
* Finds a data model context of given type among ancestors of the
* specified context.
* specified context. The returned ancestor is the one closest to the
* specified context, in terms of depth.
*
* Note that for efficiency, this method does not re-use getAllAncestorsOfType()
* to avoid the unnecessary creation of an array.
*
* @param ctx DMC to search.
* @param ancestorType Class type of the desired DMC ancestor.
* @return Returns the ancestor if found, null otherwise.
@ -39,22 +48,65 @@ public class DMContexts {
public static <V extends IDMContext> V getAncestorOfType(IDMContext ctx, Class<V> ancestorType) {
if(ctx == null)
return null;
// Check the first context here for efficiency
if (ancestorType.isAssignableFrom(ctx.getClass())) {
return (V)ctx;
}
for (IDMContext parent : ctx.getParents()) {
if (ancestorType.isAssignableFrom(parent.getClass())) {
return (V)parent;
}
}
// Use a LinkedHashSet to avoid duplicates and preserver insertion-order
Set<IDMContext> nodes = new LinkedHashSet<IDMContext>();
nodes.addAll(Arrays.asList(ctx.getParents()));
while (nodes.isEmpty() == false) {
Set<IDMContext> parents = nodes;
nodes = new LinkedHashSet<IDMContext>();
for (IDMContext parent : parents) {
if (ancestorType.isAssignableFrom(parent.getClass())) {
return (V)parent;
}
for (IDMContext parent : ctx.getParents()) {
V ancestor = getAncestorOfType(parent, ancestorType);
if (ancestor != null) return ancestor;
nodes.addAll(Arrays.asList(parent.getParents()));
}
}
return null;
}
/**
* Finds all data model contexts of given type among ancestors of the
* specified context. Ancestors are returned in order of closest to farthest,
* in terms of depth.
* @param ctx DMC to search.
* @param ancestorType Class type of the desired DMC ancestor.
* @return Returns all ancestors found, null if none.
*/
@ThreadSafe
@SuppressWarnings("unchecked")
public static <V extends IDMContext> V[] getAllAncestorsOfType(IDMContext ctx, Class<V> ancestorType) {
if(ctx == null)
return null;
// Use a LinkedHashSet to avoid duplicates and preserver insertion-order
Set<V> requestedAncestors = new LinkedHashSet<V>();
Set<IDMContext> nodes = new LinkedHashSet<IDMContext>();
nodes.add(ctx);
while (nodes.isEmpty() == false) {
Set<IDMContext> parents = nodes;
nodes = new LinkedHashSet<IDMContext>();
for (IDMContext parent : parents) {
if (ancestorType.isAssignableFrom(parent.getClass())) {
requestedAncestors.add((V)parent);
}
nodes.addAll(Arrays.asList(parent.getParents()));
}
}
if (requestedAncestors.isEmpty()) return null;
else {
V[] v = (V[])Array.newInstance(ancestorType, 0);
return requestedAncestors.toArray(v);
}
}
/**
* Checks all ancestors for a given context to see if the given