Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import org.eclipse.equinox.internal.p2.ui.model.*;
import org.eclipse.equinox.internal.p2.ui.query.IUViewQueryContext;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.operations.InstallOperation;
Expand Down Expand Up @@ -87,4 +88,57 @@ public void testInstallDrilldown() {
assertEquals("1.1", 1, children.length);
}

/**
* Test that when grouping by category is disabled (flat view),
* items that are members of categories are still visible.
* This tests the fix for issue #990.
*/
public void testFlatViewShowsCategoryMembers() {
// Create a repository with:
// - A category that contains a non-group IU
// - A group IU (should always be visible)
HashMap<String, String> categoryProperties = new HashMap<>();
categoryProperties.put("org.eclipse.equinox.p2.type.category", "true");
HashMap<String, String> groupProperties = new HashMap<>();
groupProperties.put("org.eclipse.equinox.p2.type.group", "true");

IInstallableUnit nonGroupIU = createIU("NonGroupIU", Version.create("1.0.0"), NO_REQUIRES, NO_PROPERTIES, true);
IInstallableUnit groupIU = createIU("GroupIU", Version.create("1.0.0"), NO_REQUIRES, groupProperties, true);
IInstallableUnit category = createIU("TestCategory", Version.create("1.0.0"),
createRequiredCapabilities(IInstallableUnit.NAMESPACE_IU_ID, "NonGroupIU"), categoryProperties, true);

IMetadataRepository repo = createTestMetdataRepository(new IInstallableUnit[] { category, nonGroupIU, groupIU });

// Create a MetadataRepositories element with FLAT view context
IUViewQueryContext context = new IUViewQueryContext(IUViewQueryContext.AVAILABLE_VIEW_FLAT);
MetadataRepositories repoElement = new MetadataRepositories(context, ui, null);
repoElement.setQueryable(repo);

MetadataRepositoryElement element = new MetadataRepositoryElement(repoElement, repo.getLocation(), true);
Object[] children = element.getChildren(element);

// In flat view, we should see both the group IU and the non-group IU (because it's in a category)
// We should NOT see the category itself
boolean foundGroupIU = false;
boolean foundNonGroupIU = false;
boolean foundCategory = false;

for (Object child : children) {
if (child instanceof AvailableIUElement) {
IInstallableUnit iu = ((AvailableIUElement) child).getIU();
if (iu.getId().equals("GroupIU")) {
foundGroupIU = true;
} else if (iu.getId().equals("NonGroupIU")) {
foundNonGroupIU = true;
}
} else if (child instanceof CategoryElement) {
foundCategory = true;
}
}

assertTrue("2.1 - Group IU should be visible in flat view", foundGroupIU);
assertTrue("2.2 - Non-group category member should be visible in flat view", foundNonGroupIU);
assertFalse("2.3 - Category should not be visible in flat view", foundCategory);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,53 @@ private IQuery<IInstallableUnit> createEnvironmentFilterQuery(IUViewQueryContext
return QueryUtil.createCompoundQuery(query, filterQuery, true);
}

/**
* Creates a query that matches IUs that are either groups or members of any category.
* This is used when showing a flat view to include both installable features (groups)
* and items that are part of categories.
*
* Note: This method creates a compound query from individual category member queries.
* While this could impact performance with a large number of categories, it follows
* the established pattern in this class and ensures consistency with category view behavior.
*
* @param queryable the queryable to search for categories
* @param topLevelQuery the base query for visible IUs (typically groups, with environment filter already applied)
* @param context the view query context
* @param targetProfile the target profile for environment filtering
* @return a compound query matching groups or category members
*/
private IQuery<IInstallableUnit> createGroupsOrCategoryMembersQuery(IQueryable<IInstallableUnit> queryable, IQuery<IInstallableUnit> topLevelQuery, IUViewQueryContext context, IProfile targetProfile) {
// First, get all categories
IQuery<IInstallableUnit> categoryQuery = QueryUtil.createIUCategoryQuery();
categoryQuery = createEnvironmentFilterQuery(context, targetProfile, categoryQuery);
IQueryResult<IInstallableUnit> categories = queryable.query(categoryQuery, null);

// If there are no categories, just return the top level query
if (categories.isEmpty()) {
return topLevelQuery;
}

// Collect queries for all category members
List<IQuery<IInstallableUnit>> memberQueries = new ArrayList<>();
for (IInstallableUnit category : categories) {
IQuery<IInstallableUnit> memberQuery = QueryUtil.createIUCategoryMemberQuery(category);
// Apply environment filter to category members as well
memberQuery = createEnvironmentFilterQuery(context, targetProfile, memberQuery);
memberQueries.add(memberQuery);
}

// If there are no valid category member queries, return just the top level query
if (memberQueries.isEmpty()) {
return topLevelQuery;
}

// Combine all member queries with OR to get union of all category members
IQuery<IInstallableUnit> allCategoryMembersQuery = QueryUtil.createCompoundQuery(memberQueries, false);

// Finally, combine groups OR category members
return QueryUtil.createCompoundQuery(topLevelQuery, allCategoryMembersQuery, false);
}

public ElementQueryDescriptor getQueryDescriptor(final QueriedElement element) {
// Initialize queryable, queryContext, and queryType from the element.
// In some cases we override this.
Expand Down Expand Up @@ -128,6 +175,11 @@ public ElementQueryDescriptor getQueryDescriptor(final QueriedElement element) {
// Showing child IU's of a group of repositories, or of a single repository
if (element instanceof MetadataRepositories || element instanceof MetadataRepositoryElement) {
if (context.getViewType() == IUViewQueryContext.AVAILABLE_VIEW_FLAT || !context.getUseCategories()) {
// When not grouping by categories, show both groups and items that are members of any category
// The cast is safe because in the AVAILABLE_IUS case, queryable is always an IQueryable<IInstallableUnit>
@SuppressWarnings("unchecked")
IQueryable<IInstallableUnit> iuQueryable = (IQueryable<IInstallableUnit>) queryable;
topLevelQuery = createGroupsOrCategoryMembersQuery(iuQueryable, topLevelQuery, context, targetProfile);
AvailableIUWrapper wrapper = new AvailableIUWrapper(queryable, element, false, context.getShowAvailableChildren());
if (showLatest) {
topLevelQuery = QueryUtil.createLatestQuery(topLevelQuery);
Expand Down
Loading