/*
* RHQ Management Platform
* Copyright (C) 2005-2014 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package org.rhq.coregui.client.inventory.resource.type;
import static java.lang.Boolean.FALSE;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Set;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.fields.DataSourceTextField;
import com.smartgwt.client.types.DSDataFormat;
import com.smartgwt.client.types.DSProtocol;
import com.smartgwt.client.widgets.tree.TreeNode;
import org.rhq.core.domain.criteria.ResourceTypeCriteria;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.ResourceTypeUtility;
import org.rhq.coregui.client.CoreGUI;
import org.rhq.coregui.client.IconEnum;
import org.rhq.coregui.client.ImageManager;
import org.rhq.coregui.client.Messages;
import org.rhq.coregui.client.gwt.GWTServiceLookup;
import org.rhq.coregui.client.gwt.ResourceTypeGWTServiceAsync;
/**
* @author Greg Hinkle
*/
public class ResourceTypePluginTreeDataSource extends DataSource {
private static final String ID = "id";
private static final String PARENT_ID = "parentId";
private static final String ITEM_ID = "itemId";
private static final String NAME = "name";
private static final String PLUGIN = "plugin";
private static final String CATEGORY = "category";
private final Messages MSG = CoreGUI.getMessages();
private final ResourceTypeGWTServiceAsync resourceTypeService = GWTServiceLookup.getResourceTypeGWTService();
private final boolean showIgnoredResourceTypes;
public ResourceTypePluginTreeDataSource(boolean showIgnoredResourceTypes) {
this.showIgnoredResourceTypes = showIgnoredResourceTypes;
setClientOnly(false);
setDataProtocol(DSProtocol.CLIENTCUSTOM);
setDataFormat(DSDataFormat.CUSTOM);
DataSourceTextField idField = new DataSourceTextField(ID, MSG.common_title_id());
idField.setPrimaryKey(true);
DataSourceTextField parentIdField = new DataSourceTextField(PARENT_ID, MSG.view_type_parentId());
parentIdField.setForeignKey(ID);
DataSourceTextField itemIdField = new DataSourceTextField(ITEM_ID);
DataSourceTextField resourceNameField = new DataSourceTextField(NAME, MSG.common_title_name());
DataSourceTextField resourceKeyField = new DataSourceTextField(PLUGIN, MSG.common_title_plugin());
DataSourceTextField resourceTypeField = new DataSourceTextField(CATEGORY, MSG.common_title_category());
setFields(idField, parentIdField, itemIdField, resourceNameField, resourceKeyField, resourceTypeField);
}
@Override
protected Object transformRequest(DSRequest request) {
DSResponse response = new DSResponse();
response.setAttribute("clientContext", request.getAttributeAsObject("clientContext"));
// Asume success
response.setStatus(0);
switch (request.getOperationType()) {
case FETCH:
executeFetch(request, response);
break;
default:
break;
}
return request.getData();
}
private void executeFetch(final DSRequest request, final DSResponse response) {
String parentIdString = request.getCriteria().getAttributeAsString(PARENT_ID);
if (parentIdString != null) {
processResponse(request.getRequestId(), response);
} else {
ResourceTypeCriteria criteria = new ResourceTypeCriteria();
criteria.addFilterIgnored((showIgnoredResourceTypes ? null : FALSE));
criteria.fetchParentResourceTypes(true);
PageControl pc = PageControl.getUnlimitedInstance();
pc.addDefaultOrderingField("name");
criteria.setPageControl(pc);
resourceTypeService.findResourceTypesByCriteria(criteria, new AsyncCallback<PageList<ResourceType>>() {
@Override
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(MSG.view_type_typeTreeLoadFailure(), caught);
}
@Override
public void onSuccess(PageList<ResourceType> result) {
TreeNodesBuilder treeNodesBuilder = new TreeNodesBuilder(result);
response.setData(treeNodesBuilder.buildNodes());
processResponse(request.getRequestId(), response);
}
});
}
}
private static class TreeNodesBuilder {
private final PageList<ResourceType> resourceTypes;
HashMap<String, ArrayList<ResourceType>> rootTypes;
HashMap<ResourceType, ArrayList<ResourceType>> typeChildren;
int id;
ArrayList<TreeNode> nodes;
private TreeNodesBuilder(PageList<ResourceType> resourceTypes) {
this.resourceTypes = resourceTypes;
}
TreeNode[] buildNodes() {
rootTypes = new LinkedHashMap<String, ArrayList<ResourceType>>();
typeChildren = new LinkedHashMap<ResourceType, ArrayList<ResourceType>>();
id = 0;
nodes = new ArrayList<TreeNode>(resourceTypes.size() + 1 /* at least this size*/);
// Add a dummy node so that if the user selects a plugin or resource type, he has
// the ability to undo the selection. This data source is used with a IPickTreeItem
// and that widget does not allow you to select the initial value once the user
// selects a value. See https://bugzilla.redhat.com/show_bug.cgi?id=749801.
nodes.add(new TreeNode(""));
for (ResourceType type : resourceTypes) {
String plugin = type.getPlugin();
Set<ResourceType> parentTypes = type.getParentResourceTypes();
if (parentTypes == null || parentTypes.isEmpty() || parentTypes.size() > 1) {
ArrayList<ResourceType> pluginRoots = rootTypes.get(plugin);
if (pluginRoots == null) {
pluginRoots = new ArrayList<ResourceType>();
rootTypes.put(plugin, pluginRoots);
}
pluginRoots.add(type);
} else {
ResourceType parentType = parentTypes.iterator().next();
ArrayList<ResourceType> siblingTypes = typeChildren.get(parentType);
if (siblingTypes == null) {
siblingTypes = new ArrayList<ResourceType>();
typeChildren.put(parentType, siblingTypes);
}
siblingTypes.add(type);
}
}
for (String pluginName : rootTypes.keySet()) {
PluginTreeNode pluginNode = new PluginTreeNode(null, String.valueOf(id++), pluginName);
nodes.add(pluginNode);
for (ResourceType rootType : rootTypes.get(pluginName)) {
ResourceTypeTreeNode typeNode = new ResourceTypeTreeNode(pluginNode.id, String.valueOf(id++),
rootType);
nodes.add(typeNode);
addChildrenRecursively(typeNode);
}
}
return nodes.toArray(new TreeNode[nodes.size()]);
}
void addChildrenRecursively(ResourceTypeTreeNode parentNode) {
ResourceType parentType = parentNode.resourceType;
ArrayList<ResourceType> siblings = typeChildren.get(parentType);
if (siblings == null) {
return;
}
for (ResourceType type : siblings) {
ResourceTypeTreeNode typeNode = new ResourceTypeTreeNode(parentNode.id, String.valueOf(id++), type);
nodes.add(typeNode);
addChildrenRecursively(typeNode);
}
}
}
private static class PluginTreeNode extends TreeNode {
static String pluginStr = CoreGUI.getMessages().common_title_plugin();
final String parentId;
final String id;
PluginTreeNode(String parentId, String id, String pluginName) {
this.parentId = parentId;
this.id = id;
setID(id);
setParentID(parentId);
setAttribute(ID, id);
setAttribute(PARENT_ID, parentId);
setAttribute(ITEM_ID, pluginName);
setAttribute(NAME, pluginName + " " + pluginStr);
setIcon(IconEnum.PLUGIN.getIcon16x16Path());
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ResourceTypeTreeNode that = (ResourceTypeTreeNode) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
}
private static class ResourceTypeTreeNode extends TreeNode {
final String parentId;
final String id;
final ResourceType resourceType;
private ResourceTypeTreeNode(String parentId, String id, ResourceType resourceType) {
this.parentId = parentId;
this.id = id;
this.resourceType = resourceType;
setID(id);
setParentID(parentId);
setAttribute(ID, id);
setAttribute(PARENT_ID, parentId);
setAttribute(ITEM_ID, resourceType.getId());
setAttribute(NAME, ResourceTypeUtility.displayName(resourceType));
setAttribute(PLUGIN, resourceType.getPlugin());
setIcon(ImageManager.getResourceIcon(resourceType.getCategory()));
}
public ResourceType getResourceType() {
return resourceType;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ResourceTypeTreeNode that = (ResourceTypeTreeNode) o;
return id.equals(that.id);
}
@Override
public int hashCode() {
return id.hashCode();
}
}
}