/*
* RHQ Management Platform
* Copyright (C) 2005-2011 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.rhq.coregui.client.admin.templates;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.types.VisibilityMode;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridField;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
import com.smartgwt.client.widgets.layout.Layout;
import com.smartgwt.client.widgets.layout.SectionStack;
import com.smartgwt.client.widgets.layout.SectionStackSection;
import com.smartgwt.client.widgets.tree.TreeGrid;
import com.smartgwt.client.widgets.tree.TreeGridField;
import com.smartgwt.client.widgets.tree.TreeNode;
import org.rhq.core.domain.resource.ResourceCategory;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.coregui.client.BookmarkableView;
import org.rhq.coregui.client.CoreGUI;
import org.rhq.coregui.client.ImageManager;
import org.rhq.coregui.client.ViewPath;
import org.rhq.coregui.client.admin.AdministrationView;
import org.rhq.coregui.client.components.TitleBar;
import org.rhq.coregui.client.components.buttons.BackButton;
import org.rhq.coregui.client.inventory.resource.type.ResourceTypeRepository;
import org.rhq.coregui.client.util.enhanced.EnhancedUtility;
import org.rhq.coregui.client.util.enhanced.EnhancedVLayout;
/**
* A tree view of all known ResourceTypes, which includes summaries of metric schedule and alert definition templates
* and allows the user to edit those templates.
*
* @author Greg Hinkle
* @author John Mazzitelli
*/
public abstract class ResourceTypeTreeView extends EnhancedVLayout implements BookmarkableView {
public static final String VIEW_PATH = AdministrationView.VIEW_ID + "/"
+ AdministrationView.SECTION_CONFIGURATION_VIEW_ID + "/";
private Layout gridCanvas;
public ResourceTypeTreeView() {
super();
setWidth100();
setHeight100();
}
abstract protected String getEditLink(String type);
abstract protected TitleBar getTitleBar();
abstract protected Collection<ListGridField> getAdditionalListGridFields(boolean isTreeGrid);
abstract protected ResourceTypeTreeNodeBuilder getNodeBuilderInstance(ListGrid platformsList,
ListGrid platformServicesList, TreeGrid serversTreeGrid);
/**
* If the subclass can support editing templates but need to utilize subcanvases to do it,
* they should override this method. This superclass implementation is a no-op.
*
* @param type the ResourceType being edited
* @param viewPath the path that is accessing the subcanvas.
*/
protected void editTemplates(ResourceType type, ViewPath viewPath) {
return; // by default, assume subclasses do not support this and simply return as a no-op
}
/**
* If the subclass can support editing templates without needing to utilize subcanvases,
* they should override this method. This superclass implementation is a no-op.
*
* @param type the ResourceType being edited
* @param event indicates the specific record in the specific list grid that contained the type being edited
*/
protected void editTemplates(ResourceType type, RecordClickEvent event) {
return; // by default, assume subclasses do not support this and simply return as a no-op
}
/**
* The default column title name for the edit column.
*
* @return title for edit column
*/
protected String getEditColumnTitle() {
return MSG.common_title_edit();
}
@Override
public void renderView(final ViewPath viewPath) {
if (viewPath.isEnd()) {
switchToCanvas(this, getGridCanvas());
} else {
final int resourceTypeId;
try {
resourceTypeId = viewPath.getCurrentAsInt();
} catch (Exception e) {
CoreGUI.getErrorHandler().handleError(MSG.widget_typeTree_badTypeId(viewPath.getCurrent().getPath()));
return;
}
ResourceTypeRepository.Cache.getInstance().getResourceTypes(resourceTypeId, getTypeMetadataTypes(),
new ResourceTypeRepository.TypeLoadedCallback() {
public void onTypesLoaded(ResourceType type) {
editTemplates(type, viewPath);
}
});
}
}
/**
* @return The Set of metadata types required by the implementing class for the selected type.
*/
protected EnumSet<ResourceTypeRepository.MetadataType> getTypeMetadataTypes() {
return EnumSet.noneOf(ResourceTypeRepository.MetadataType.class);
}
private Canvas getGridCanvas() {
if (this.gridCanvas == null) {
EnhancedVLayout layout = new EnhancedVLayout();
TitleBar titleBar = getTitleBar();
titleBar.setExtraSpace(10);
layout.addMember(titleBar);
SectionStack sectionStack = new SectionStack();
sectionStack.setVisibilityMode(VisibilityMode.MULTIPLE);
ListGrid platformsList = getCustomResourceTypeListGrid();
SectionStackSection platforms = new SectionStackSection(MSG.view_adminTemplates_platforms());
platforms.setExpanded(true);
platforms.addItem(platformsList);
ListGrid platformServicesList = getCustomResourceTypeListGrid();
SectionStackSection platformServices = new SectionStackSection(MSG.view_adminTemplates_platformServices());
platformServices.setExpanded(true);
platformServices.addItem(platformServicesList);
TreeGrid serversTreeGrid = new CustomResourceTypeTreeGrid();
SectionStackSection servers = new SectionStackSection(MSG.view_adminTemplates_servers());
servers.setExpanded(true);
servers.addItem(serversTreeGrid);
sectionStack.addSection(platforms);
sectionStack.addSection(platformServices);
sectionStack.addSection(servers);
layout.addMember(sectionStack);
this.gridCanvas = layout;
// this will asynchronously populate the grids with the appropriate data
getNodeBuilderInstance(platformsList, platformServicesList, serversTreeGrid);
}
return this.gridCanvas;
}
/**
* This will remove all members from the given parent canvas and then add
* the canvasToShow as the only member to the parent.
*
* @param parentCanvas parent to show the given canvas
* @param canvasToShow the canvas to show in the parent, if null, show the main grid canvas (not a sub-canvas)
*/
protected void switchToCanvas(Layout parentCanvas, Canvas canvasToShow) {
EnhancedUtility.destroyMembers(parentCanvas);
parentCanvas.addMember(canvasToShow);
parentCanvas.markForRedraw();
}
protected void prepareSubCanvas(Layout parentCanvas, Canvas canvasToShow, boolean showBackButton) {
EnhancedUtility.destroyMembers(parentCanvas);
if (showBackButton) {
String backLink = getEditLink(null).substring(1); // strip the #
BackButton backButton = new BackButton(MSG.view_tableSection_backButton(), backLink);
parentCanvas.addMember(backButton);
}
parentCanvas.addMember(canvasToShow);
parentCanvas.markForRedraw();
}
public CustomResourceTypeListGrid getCustomResourceTypeListGrid() {
return new CustomResourceTypeListGrid();
}
public class CustomResourceTypeListGrid extends ListGrid {
public CustomResourceTypeListGrid() {
super();
setWrapCells(true);
setFixedRecordHeights(false);
setEmptyMessage(MSG.common_msg_loading());
setSelectionType(SelectionStyle.NONE);
ArrayList<ListGridField> fields = new ArrayList<ListGridField>(7);
final ListGridField nameField = new ListGridField(ResourceTypeTreeNodeBuilder.ATTRIB_NAME,
MSG.common_title_name());
nameField.setShowValueIconOnly(false);
nameField.setCanEdit(false);
fields.add(nameField);
final ListGridField pluginField = new ListGridField(ResourceTypeTreeNodeBuilder.ATTRIB_PLUGIN,
MSG.common_title_plugin());
pluginField.setCanEdit(false);
fields.add(pluginField);
pluginField.setHidden(true);
fields.addAll(getAdditionalListGridFields(false));
ListGridField editField = new ListGridField(ResourceTypeTreeNodeBuilder.ATTRIB_EDIT, getEditColumnTitle());
editField.setType(ListGridFieldType.IMAGE);
editField.setAlign(Alignment.CENTER);
editField.setCanGroupBy(false);
editField.addRecordClickHandler(new RecordClickHandler() {
public void onRecordClick(final RecordClickEvent event) {
Record record = event.getRecord();
String editAttr = record.getAttribute(ResourceTypeTreeNodeBuilder.ATTRIB_EDIT);
if (ImageManager.getEditIcon().equals(editAttr)) {
String type = record.getAttribute(ResourceTypeTreeNodeBuilder.ATTRIB_ID);
String editLink = getEditLink(type);
if (editLink != null) {
CoreGUI.goToView(editLink);
} else {
// there is no subcanvas to go to - the subclass can do it without changing canvas
ResourceTypeRepository.Cache.getInstance().getResourceTypes(Integer.parseInt(type),
getTypeMetadataTypes(), new ResourceTypeRepository.TypeLoadedCallback() {
public void onTypesLoaded(ResourceType type) {
editTemplates(type, event);
}
});
}
}
}
});
fields.add(editField);
nameField.setWidth("*");
pluginField.setWidth("20%");
// note that the additional fields should set their own width
editField.setWidth("70");
setFields(fields.toArray(new ListGridField[fields.size()]));
}
@Override
public String getValueIcon(ListGridField field, Object value, ListGridRecord record) {
if (field.getName().equals(ResourceTypeTreeNodeBuilder.ATTRIB_NAME)) {
String categoryName = record.getAttribute(ResourceTypeTreeNodeBuilder.ATTRIB_CATEGORY);
return ImageManager.getResourceIcon(ResourceCategory.valueOf(categoryName));
} else {
return super.getValueIcon(field, value, record);
}
}
}
public class CustomResourceTypeTreeGrid extends TreeGrid {
public CustomResourceTypeTreeGrid() {
super();
setWrapCells(true);
setFixedRecordHeights(false);
setEmptyMessage(MSG.common_msg_loading());
setSelectionType(SelectionStyle.NONE);
setAnimateFolders(false);
ArrayList<ListGridField> fields = new ArrayList<ListGridField>(7);
final TreeGridField nameField = new TreeGridField(ResourceTypeTreeNodeBuilder.ATTRIB_NAME,
MSG.common_title_name());
fields.add(nameField);
final TreeGridField pluginField = new TreeGridField(ResourceTypeTreeNodeBuilder.ATTRIB_PLUGIN,
MSG.common_title_plugin());
fields.add(pluginField);
fields.addAll(getAdditionalListGridFields(true));
ListGridField editField = new TreeGridField(ResourceTypeTreeNodeBuilder.ATTRIB_EDIT, getEditColumnTitle());
editField.setType(ListGridFieldType.IMAGE);
editField.setAlign(Alignment.CENTER);
editField.addRecordClickHandler(new RecordClickHandler() {
public void onRecordClick(final RecordClickEvent event) {
Record record = event.getRecord();
String editAttr = record.getAttribute(ResourceTypeTreeNodeBuilder.ATTRIB_EDIT);
if (ImageManager.getEditIcon().equals(editAttr)) {
String type = record.getAttribute(ResourceTypeTreeNodeBuilder.ATTRIB_ID);
String editLink = getEditLink(type);
if (editLink != null) {
CoreGUI.goToView(editLink);
} else {
// there is no subcanvas to go to - the subclass can do it without changing canvas
ResourceTypeRepository.Cache.getInstance().getResourceTypes(Integer.parseInt(type),
getTypeMetadataTypes(), new ResourceTypeRepository.TypeLoadedCallback() {
public void onTypesLoaded(ResourceType type) {
editTemplates(type, event);
}
});
}
}
}
});
fields.add(editField);
nameField.setWidth("*");
pluginField.setWidth("20%");
// note that the additional fields should set their own width
editField.setWidth("70");
setFields(fields.toArray(new ListGridField[fields.size()]));
}
@Override
protected String getIcon(Record record, boolean defaultState) {
if (record instanceof TreeNode) {
if (record instanceof ResourceTypeTreeNodeBuilder.ResourceTypeTreeNode) {
String categoryName = record.getAttribute(ResourceTypeTreeNodeBuilder.ATTRIB_CATEGORY);
return ImageManager.getResourceIcon(ResourceCategory.valueOf(categoryName));
}
}
return null;
}
}
}