modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceType.java | 26 +- modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java | 74 ++++- modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java | 126 ++++++---- 3 files changed, 155 insertions(+), 71 deletions(-)
New commits: commit 8982cfc04311397df59b765c761a27725c9fb9d4 Author: Ian Springer ian.springer@redhat.com Date: Mon Nov 7 15:14:03 2011 -0500
[BZ 751421] fix so two ResourceTypes with same name (e.g. 4.x. and 5.x JBoss AS Server types) are both listed on type selection menus for Import and Create New Resource actions (https://bugzilla.redhat.com/show_bug.cgi?id=751421)
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceType.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceType.java index b44bee1..219d828 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceType.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/ResourceType.java @@ -802,10 +802,6 @@ public class ResourceType implements Serializable, Comparable<ResourceType> { this.productVersions = productVersions; }
- public int compareTo(ResourceType that) { - return this.name.compareTo(that.getName()); - } - public String getHelpText() { return helpText; } @@ -846,6 +842,24 @@ public class ResourceType implements Serializable, Comparable<ResourceType> { this.driftDefinitionTemplates = driftDefinitionTemplates; }
+ // NOTE: It's vital that compareTo() is consistent with equals(), otherwise TreeSets containing ResourceTypes, or + // TreeMaps with ResourceTypes as keys, will not work reliably. See the Javadoc for Comparable for a precise + // definition of consistent with equals(). + @Override + public int compareTo(ResourceType that) { + if (this.name == null) { + return (that.name == null) ? 0 : -1; + } + int result = (that.name == null) ? 1 : this.name.compareTo(that.name); + if (result != 0) { + return result; + } + if (this.plugin == null) { + return (that.plugin == null) ? 0 : -1; + } + return (that.plugin == null) ? 1 : this.plugin.compareTo(that.plugin); + } + @Override public boolean equals(Object obj) { if (this == obj) @@ -877,8 +891,8 @@ public class ResourceType implements Serializable, Comparable<ResourceType> {
@Override public String toString() { - return "ResourceType[id=" + this.id + ", category=" + this.category + ", name=" + this.name + ", plugin=" - + this.plugin + "]"; + return "ResourceType[id=" + this.id + ", name=" + this.name + ", plugin=" + this.plugin + ", category=" + + this.category + "]"; }
} diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java index ea0daca..e5ec18a 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/ResourceCompositeSearchView.java @@ -22,8 +22,13 @@ */ package org.rhq.enterprise.gui.coregui.client.inventory.resource;
+import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet;
import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.data.Criteria; @@ -133,18 +138,13 @@ public class ResourceCompositeSearchView extends ResourceSearchView { ResourceType parentType = parentResourceComposite.getResource().getResourceType();
// manual import type menu - // TODO: Use TreeMap instead, so the types will be sorted by name. - LinkedHashMap<String, ResourceType> importTypeValueMap = new LinkedHashMap<String, ResourceType>(); + Set<ResourceType> importableChildTypes = getImportableChildTypes(parentType); + if (!importableChildTypes.isEmpty()) { + Map<String, ResourceType> displayNames = getDisplayNames(importableChildTypes); + LinkedHashMap<String, ResourceType> importTypeValueMap = new LinkedHashMap<String, ResourceType>(displayNames);
- for (ResourceType childType : parentType.getChildResourceTypes()) { - if (childType.isSupportsManualAdd()) { - importTypeValueMap.put(childType.getName(), childType); - } - } - if (!importTypeValueMap.isEmpty()) { addTableAction(extendLocatorId("Import"), MSG.common_button_import(), null, importTypeValueMap, new AbstractTableAction(TableActionEnablement.ALWAYS) { - public void executeAction(ListGridRecord[] selection, Object actionValue) { ResourceFactoryImportWizard.showImportWizard(parentResourceComposite.getResource(), (ResourceType) actionValue); @@ -156,15 +156,11 @@ public class ResourceCompositeSearchView extends ResourceSearchView { }
// creatable child type menu - // TODO: Use TreeMap instead, so the types will be sorted by name. - LinkedHashMap<String, ResourceType> createTypeValueMap = new LinkedHashMap<String, ResourceType>(); + Set<ResourceType> creatableChildTypes = getCreatableChildTypes(parentType); + if (!creatableChildTypes.isEmpty()) { + Map<String, ResourceType> displayNames = getDisplayNames(creatableChildTypes); + LinkedHashMap<String, ResourceType> createTypeValueMap = new LinkedHashMap<String, ResourceType>(displayNames);
- for (ResourceType childType : parentType.getChildResourceTypes()) { - if (childType.isCreatable()) { - createTypeValueMap.put(childType.getName(), childType); - } - } - if (!createTypeValueMap.isEmpty()) { addTableAction(extendLocatorId("CreateChild"), MSG.common_button_create_child(), null, createTypeValueMap, new AbstractTableAction(TableActionEnablement.ALWAYS) {
@@ -179,6 +175,50 @@ public class ResourceCompositeSearchView extends ResourceSearchView { } }
+ private static Set<ResourceType> getImportableChildTypes(ResourceType type) { + Set<ResourceType> results = new TreeSet<ResourceType>(); + Set<ResourceType> childTypes = type.getChildResourceTypes(); + for (ResourceType childType : childTypes) { + if (childType.isSupportsManualAdd()) { + results.add(childType); + } + } + return results; + } + + private static Set<ResourceType> getCreatableChildTypes(ResourceType type) { + Set<ResourceType> results = new TreeSet<ResourceType>(); + Set<ResourceType> childTypes = type.getChildResourceTypes(); + for (ResourceType childType : childTypes) { + if (childType.isCreatable()) { + results.add(childType); + } + } + return results; + } + + private static Map<String, ResourceType> getDisplayNames(Set<ResourceType> types) { + Set<String> allNames = new HashSet<String>(); + Set<String> repeatedNames = new HashSet<String>(); + for (ResourceType type : types) { + String typeName = type.getName(); + if (allNames.contains(typeName)) { + repeatedNames.add(typeName); + } else { + allNames.add(typeName); + } + } + Map<String, ResourceType> results = new TreeMap<String, ResourceType>(); + for (ResourceType type : types) { + String displayName = type.getName(); + if (repeatedNames.contains(type.getName())) { + displayName += " (" + type.getPlugin() + " plugin)"; + } + results.put(displayName, type); + } + return results; + } + protected void onUninventorySuccess() { // refresh the entire gui so it encompasses any relevant tree view. Don't call this.refresh() // because CoreGUI.refresh is more comprehensive. diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java index c82d234..e7daca8 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/inventory/resource/detail/ResourceTreeView.java @@ -25,8 +25,11 @@ package org.rhq.enterprise.gui.coregui.client.inventory.resource.detail; import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.TreeMap; import java.util.TreeSet;
import com.allen_sauer.gwt.log.client.Log; @@ -497,74 +500,56 @@ public class ResourceTreeView extends LocatableVLayout { resourceContextMenu.addItem(buildMetricsMenu(resourceType, resource));
// Create Child Menu - MenuItem createChildMenu = new MenuItem(MSG.common_button_create_child()); - boolean createChildResourcesEnabled = resourcePermission.isCreateChildResources(); - if (createChildResourcesEnabled) { - Menu createChildSubMenu = new Menu(); - //sort the display items alphabetically - TreeSet<String> ordered = new TreeSet<String>(); - Map<String, ResourceType> typeMap = new HashMap<String, ResourceType>(); - for (ResourceType o : resourceType.getChildResourceTypes()) { - ordered.add(o.getName()); - typeMap.put(o.getName(), o); - } - - for (String type : ordered) { - final ResourceType childType = typeMap.get(type); - if (childType.isCreatable()) { - MenuItem createItem = new MenuItem(childType.getName()); - + Set<ResourceType> creatableChildTypes = getCreatableChildTypes(resourceType); + if (!creatableChildTypes.isEmpty()) { + MenuItem createChildMenu = new MenuItem(MSG.common_button_create_child()); + boolean hasCreateChildPermission = resourcePermission.isCreateChildResources(); + createChildMenu.setEnabled(hasCreateChildPermission); + if (hasCreateChildPermission) { + Menu createChildSubMenu = new Menu(); + Map<String, ResourceType> displayNameMap = getDisplayNames(creatableChildTypes); + Set<String> displayNames = displayNameMap.keySet(); + for (String displayName : displayNames) { + MenuItem createItem = new MenuItem(displayName); + final ResourceType childType = displayNameMap.get(displayName); createItem.addClickHandler(new ClickHandler() { - public void onClick(MenuItemClickEvent event) { ResourceFactoryCreateWizard.showCreateWizard(resource, childType); } }); - createChildSubMenu.addItem(createItem); - } + createChildMenu.setSubmenu(createChildSubMenu); } - createChildMenu.setSubmenu(createChildSubMenu); - createChildResourcesEnabled = createChildSubMenu.getItems().length > 0; + + resourceContextMenu.addItem(createChildMenu); } - createChildMenu.setEnabled(createChildResourcesEnabled); - resourceContextMenu.addItem(createChildMenu);
// Manual Import Menu - MenuItem importChildMenu = new MenuItem(MSG.common_button_import()); - boolean manualImportEnabled = resourcePermission.isCreateChildResources(); - if (manualImportEnabled) { - Menu importChildSubMenu = new Menu(); - - //sort the display items alphabetically - TreeSet<String> ordered = new TreeSet<String>(); - Map<String, ResourceType> typeMap = new HashMap<String, ResourceType>(); - for (ResourceType o : resourceType.getChildResourceTypes()) { - ordered.add(o.getName()); - typeMap.put(o.getName(), o); - } - for (String name : ordered) { - final ResourceType childType = typeMap.get(name); - if (childType.isSupportsManualAdd()) { - MenuItem importItem = new MenuItem(childType.getName()); - + Set<ResourceType> importableChildTypes = getImportableChildTypes(resourceType); + + if (!importableChildTypes.isEmpty()) { + MenuItem importChildMenu = new MenuItem(MSG.common_button_import()); + boolean hasManualImportPermission = resourcePermission.isCreateChildResources(); + importChildMenu.setEnabled(hasManualImportPermission); + if (hasManualImportPermission) { + Menu importChildSubMenu = new Menu(); + Map<String, ResourceType> displayNameMap = getDisplayNames(importableChildTypes); + Set<String> displayNames = displayNameMap.keySet(); + for (final String displayName : displayNames) { + MenuItem importItem = new MenuItem(displayName); + final ResourceType childType = displayNameMap.get(displayName); importItem.addClickHandler(new ClickHandler() { - public void onClick(MenuItemClickEvent event) { ResourceFactoryImportWizard.showImportWizard(resource, childType); } }); - importChildSubMenu.addItem(importItem); } + importChildMenu.setSubmenu(importChildSubMenu); } - - importChildMenu.setSubmenu(importChildSubMenu); - manualImportEnabled = importChildSubMenu.getItems().length > 0; + resourceContextMenu.addItem(importChildMenu); } - importChildMenu.setEnabled(manualImportEnabled); - resourceContextMenu.addItem(importChildMenu); }
private MenuItem buildMetricsMenu(final ResourceType type, final Resource resource) { @@ -938,4 +923,49 @@ public class ResourceTreeView extends LocatableVLayout { setSelectedResource(resourceId, viewPath.isRefresh()); } } + + private static Set<ResourceType> getImportableChildTypes(ResourceType type) { + Set<ResourceType> results = new TreeSet<ResourceType>(); + Set<ResourceType> childTypes = type.getChildResourceTypes(); + for (ResourceType childType : childTypes) { + if (childType.isSupportsManualAdd()) { + results.add(childType); + } + } + return results; + } + + private static Set<ResourceType> getCreatableChildTypes(ResourceType type) { + Set<ResourceType> results = new TreeSet<ResourceType>(); + Set<ResourceType> childTypes = type.getChildResourceTypes(); + for (ResourceType childType : childTypes) { + if (childType.isCreatable()) { + results.add(childType); + } + } + return results; + } + + private static Map<String, ResourceType> getDisplayNames(Set<ResourceType> types) { + Set<String> allNames = new HashSet<String>(); + Set<String> repeatedNames = new HashSet<String>(); + for (ResourceType type : types) { + String typeName = type.getName(); + if (allNames.contains(typeName)) { + repeatedNames.add(typeName); + } else { + allNames.add(typeName); + } + } + Map<String, ResourceType> results = new TreeMap<String, ResourceType>(); + for (ResourceType type : types) { + String displayName = type.getName(); + if (repeatedNames.contains(type.getName())) { + displayName += " (" + type.getPlugin() + " plugin)"; + } + results.put(displayName, type); + } + return results; + } + }