/* * RHQ Management Platform * Copyright (C) 2005-2013 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.storage; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.data.Criteria; import com.smartgwt.client.data.Record; import com.smartgwt.client.types.GroupStartOpen; import com.smartgwt.client.types.ImageStyle; import com.smartgwt.client.widgets.HTMLFlow; import com.smartgwt.client.widgets.Img; import com.smartgwt.client.widgets.form.fields.SpacerItem; import com.smartgwt.client.widgets.grid.CellFormatter; 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.SummaryFunction; import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.cloud.StorageNode; import org.rhq.core.domain.criteria.AlertCriteria; import org.rhq.core.domain.criteria.StorageNodeCriteria; import org.rhq.core.domain.util.PageList; import org.rhq.core.domain.util.collection.ArrayUtils; import org.rhq.coregui.client.CoreGUI; import org.rhq.coregui.client.ImageManager; import org.rhq.coregui.client.LinkManager; import org.rhq.coregui.client.alert.AlertDataSource; import org.rhq.coregui.client.alert.AlertHistoryView; import org.rhq.coregui.client.components.form.DateFilterItem; import org.rhq.coregui.client.components.table.AbstractTableAction; import org.rhq.coregui.client.components.table.RecordExtractor; import org.rhq.coregui.client.components.table.ResourceAuthorizedTableAction; import org.rhq.coregui.client.components.table.TableAction; import org.rhq.coregui.client.components.table.TableActionEnablement; import org.rhq.coregui.client.gwt.GWTServiceLookup; import org.rhq.coregui.client.inventory.resource.AncestryUtil; import org.rhq.coregui.client.util.StringUtility; import org.rhq.coregui.client.util.enhanced.EnhancedIButton.ButtonColor; import org.rhq.coregui.client.util.message.Message; /** * The view for presenting alerts on storage node resource and its children. * * @author Jirka Kremser */ public class StorageNodeAlertHistoryView extends AlertHistoryView { private final HTMLFlow header; private final int storageNodeId; private final boolean allStorageNodes; private Map<Integer, Integer> resourceIdToStorageNodeIdMap; private Map<Integer, String> storageNodeIdToAddressMap; private Date startDateAux; private Date endDateAux; private boolean initialized; public StorageNodeAlertHistoryView(String tableTitle, Map<Integer, Integer> resourceIdToStorageNodeIdMap) { this(tableTitle, ArrayUtils.unwrapArray(resourceIdToStorageNodeIdMap.keySet().toArray(new Integer[] {})), null, -1, resourceIdToStorageNodeIdMap); } public StorageNodeAlertHistoryView(String tableTitle, int[] resourceIds, HTMLFlow header, int storageNodeId) { this(tableTitle, resourceIds, header, storageNodeId, null); } public StorageNodeAlertHistoryView(String tableTitle, int[] resourceIds, HTMLFlow header, int storageNodeId, Map<Integer, Integer> resourceIdToStorageNodeIdMap) { super(tableTitle, resourceIds); this.header = header; this.storageNodeId = storageNodeId; this.allStorageNodes = storageNodeId == -1; this.resourceIdToStorageNodeIdMap = resourceIdToStorageNodeIdMap; this.initialized = false; this.storageNodeIdToAddressMap = new HashMap<Integer, String>(); } @Override public boolean isInitialized() { return super.isInitialized() && this.initialized; } @Override protected void onInit() { super.onInit(); initAddresses(); } private void initAddresses() { if (header != null && !allStorageNodes) { StorageNodeCriteria criteria = new StorageNodeCriteria(); criteria.addFilterId(storageNodeId); GWTServiceLookup.getStorageService().findStorageNodesByCriteria(criteria, new AsyncCallback<PageList<StorageNode>>() { public void onSuccess(final PageList<StorageNode> storageNodes) { if (storageNodes == null || storageNodes.isEmpty() || storageNodes.size() != 1) { Message msg = new Message(MSG.view_adminTopology_message_fetchServerFail(String .valueOf(storageNodeId)), Message.Severity.Error); CoreGUI.goToView(StorageNodeTableView.VIEW_PATH, msg); return; } final StorageNode node = storageNodes.get(0); header.setContents("<div style='text-align: center; font-weight: bold; font-size: medium;'>" + MSG.view_adminTopology_storageNodes_node() + " (" + node.getAddress() + ")</div>"); initialized = true; } public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError( MSG.view_adminTopology_message_fetchServerFail(String.valueOf(storageNodeId)) + " " + caught.getMessage(), caught); } }); } else { // fetch the addresses of all storage nodes GWTServiceLookup.getStorageService().getStorageNodes(new AsyncCallback<List<StorageNode>>() { public void onSuccess(final List<StorageNode> storageNodes) { if (storageNodes != null && !storageNodes.isEmpty()) { for (StorageNode node : storageNodes) { storageNodeIdToAddressMap.put(node.getId(), node.getAddress()); } } initialized = true; } public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError( MSG.view_adminTopology_message_fetchServerFail(String.valueOf(storageNodeId)) + " " + caught.getMessage(), caught); } }); } } @Override protected void configureTableFilters() { startDateFilter = new DateFilterItem(DateFilterItem.START_DATE_FILTER, MSG.filter_from_date()); endDateFilter = new DateFilterItem(DateFilterItem.END_DATE_FILTER, MSG.filter_to_date()); SpacerItem spacerItem = new SpacerItem(); spacerItem.setColSpan(2); if (isShowFilterForm()) { setFilterFormItems(startDateFilter, spacerItem, endDateFilter); } startDateFilter.setVisible(false); endDateFilter.setVisible(false); } @Override public AlertDataSource getDataSource() { return new AlertDataSource() { @Override public ArrayList<ListGridField> getListGridFields() { ArrayList<ListGridField> fields = super.getListGridFields(); ArrayList<ListGridField> newFields = new ArrayList<ListGridField>(fields.size()); for (ListGridField field : fields) { if ("priority".equals(field.getName()) || AncestryUtil.RESOURCE_NAME.equals(field.getName()) || AncestryUtil.RESOURCE_ANCESTRY.equals(field.getName())) { continue; } if (AlertCriteria.SORT_FIELD_CTIME.equals(field.getName())) { field.setCellFormatter(new CellFormatter() { public String format(Object o, ListGridRecord listGridRecord, int i, int i1) { if (listGridRecord.getAttribute("groupValue") != null) { return (String) o; } Integer resourceId = listGridRecord.getAttributeAsInt(AncestryUtil.RESOURCE_ID); Integer defId = listGridRecord.getAttributeAsInt("definitionId"); String url = LinkManager.getSubsystemAlertDefinitionLink(resourceId, defId); return LinkManager.getHref(url, o.toString()); } }); field.setWidth(240); } else if ("conditionValue".equals(field.getName())) { field.setWidth(140); } else if ("acknowledgingSubject".equals(field.getName())) { field.setSummaryFunction(new SummaryFunction() { public Object getSummaryValue(Record[] records, ListGridField field) { int count = 0; for (Record record : records) { if (record.getAttribute("acknowledgingSubject") != null) { count++; } } return "(" + count + " / " + records.length + ")"; } }); field.setCellFormatter(new CellFormatter() { public String format(Object o, ListGridRecord listGridRecord, int i, int i1) { if (listGridRecord.getAttribute("groupValue") != null) { return (String) o; } String ackSubject = listGridRecord.getAttribute("acknowledgingSubject"); if (ackSubject == null) { return " "; } else { Img checkedImg = new Img(ImageManager.getAlertStatusCheckedIcon(), 80, 16); checkedImg.setImageType(ImageStyle.CENTER); return checkedImg.getInnerHTML(); } } }); field.setShowGridSummary(false); field.setShowGroupSummary(true); field.setWidth(90); newFields.add(1, field); continue; } else if ("name".equals(field.getName())) { field.setCellFormatter(new CellFormatter() { public String format(Object o, ListGridRecord listGridRecord, int i, int i1) { return o.toString(); } }); field.setHidden(true); } newFields.add(field); } ListGridField descriptionField = new ListGridField("description", MSG.common_title_description()); descriptionField.setCanSortClientOnly(true); newFields.add(descriptionField); if (allStorageNodes) { // all storage nodes ListGridField storageNodeLinkField = new ListGridField("storageNodeLink", MSG.view_adminTopology_storageNodes_node()); storageNodeLinkField.setCellFormatter(new CellFormatter() { public String format(Object o, ListGridRecord listGridRecord, int i, int i1) { if (listGridRecord.getAttribute("groupValue") != null) { return (String) o; } Integer resourceId = listGridRecord.getAttributeAsInt(AncestryUtil.RESOURCE_ID); int storageNodeId = resourceIdToStorageNodeIdMap.get(resourceId); String url = LinkManager.getStorageNodeLink(storageNodeId); return LinkManager.getHref(url, storageNodeIdToAddressMap.get(storageNodeId)); } }); storageNodeLinkField.setWidth(90); newFields.add(2, storageNodeLinkField); } return newFields; } }; } @Override protected void configureListGrid(ListGrid grid) { ListGrid listGrid = super.getListGrid(); listGrid.setGroupStartOpen(GroupStartOpen.ALL); listGrid.setShowGroupSummary(true); listGrid.setShowGroupSummaryInHeader(true); listGrid.setGroupByField("name"); } @Override protected CellFormatter getDetailsLinkColumnCellFormatter() { return new CellFormatter() { public String format(Object value, ListGridRecord record, int i, int i1) { if (value == null) { return ""; } if (record.getAttribute("groupValue") != null) { return value.toString(); } String detailsUrl = getDetailUrlFromRecord(record); String formattedValue = StringUtility.escapeHtml(value.toString()); return LinkManager.getHref(detailsUrl, formattedValue); } }; } @Override public void showDetails(ListGridRecord record) { CoreGUI.goToView(getDetailUrlFromRecord(record)); } private String getDetailUrlFromRecord(ListGridRecord record) { if (record == null) { throw new IllegalArgumentException("'record' parameter is null."); } Integer recordId = getId(record); Integer resourceId = record.getAttributeAsInt(AncestryUtil.RESOURCE_ID); if (recordId != null && recordId.intValue() > 0 && resourceId != null && resourceId > 0) { return "#Resource/" + resourceId + "/Alerts/History/" + convertIDToCurrentViewPath(recordId); } else { String msg = MSG.view_tableSection_error_badId(this.getClass().toString(), (recordId == null) ? "null" : recordId.toString()); CoreGUI.getErrorHandler().handleError(msg); throw new IllegalArgumentException(msg); } } @Override protected void setupTableInteractions(final boolean hasWriteAccess) { // We override this method, because button enablement implementation from super class for "Delete All" // and "Acknowledge All" doesn't work correctly for table with using grouping. Also adding additional // button for enabling / disabling the alerts grouping. addTableAction(MSG.common_button_delete(), MSG.view_alerts_delete_confirm(), ButtonColor.RED, new ResourceAuthorizedTableAction(StorageNodeAlertHistoryView.this, TableActionEnablement.ANY, (hasWriteAccess ? null : Permission.MANAGE_ALERTS), new RecordExtractor<Integer>() { public Collection<Integer> extract(Record[] records) { List<Integer> result = new ArrayList<Integer>(records.length); for (Record record : records) { result.add(record.getAttributeAsInt("resourceId")); } return result; } }) { public void executeAction(ListGridRecord[] selection, Object actionValue) { delete(selection); } }); addTableAction(MSG.common_button_ack(), MSG.view_alerts_ack_confirm(), ButtonColor.BLUE, new ResourceAuthorizedTableAction(StorageNodeAlertHistoryView.this, TableActionEnablement.ANY, (hasWriteAccess ? null : Permission.MANAGE_ALERTS), new RecordExtractor<Integer>() { public Collection<Integer> extract(Record[] records) { List<Integer> result = new ArrayList<Integer>(records.length); for (Record record : records) { result.add(record.getAttributeAsInt("resourceId")); } return result; } }) { public void executeAction(ListGridRecord[] selection, Object actionValue) { acknowledge(selection); } }); addTableAction(MSG.common_button_delete_all(), MSG.view_alerts_delete_confirm_all(), ButtonColor.RED, new TableAction() { public boolean isEnabled(ListGridRecord[] selection) { ListGrid grid = getListGrid(); ListGridRecord[] records = (null != grid) ? grid.getRecords() : null; return (hasWriteAccess && grid != null && records != null && records.length > 0); } public void executeAction(ListGridRecord[] selection, Object actionValue) { deleteAll(); } }); addTableAction(MSG.common_button_ack_all(), MSG.view_alerts_ack_confirm_all(), new TableAction() { public boolean isEnabled(ListGridRecord[] selection) { ListGrid grid = getListGrid(); ListGridRecord[] records = (null != grid) ? grid.getRecords() : null; return (hasWriteAccess && grid != null && records != null && records.length > 0); } public void executeAction(ListGridRecord[] selection, Object actionValue) { acknowledgeAll(); } }); // alerts grouping Map<String, Object> items = new LinkedHashMap<String, Object>(2); items.put("On", true); items.put("Off", false); addTableAction(MSG.view_adminTopology_storageNodes_groupAlerts(), null, items, ButtonColor.GRAY, new AbstractTableAction(TableActionEnablement.ALWAYS) { public void executeAction(ListGridRecord[] selection, Object actionValue) { setGrouping((Boolean) actionValue); } }); } private void setGrouping(boolean grouping) { if (grouping == getListGrid().isGrouped()) { refreshTableInfo(); return; } if (grouping) { getListGrid().groupBy("name"); // save the values startDateAux = startDateFilter.getValueAsDate(); endDateAux = endDateFilter.getValueAsDate(); // clear the values startDateFilter.setValue((Date) null); endDateFilter.setValue((Date) null); startDateFilter.hide(); endDateFilter.hide(); } else { getListGrid().ungroup(); startDateFilter.setValue(startDateAux); endDateFilter.setValue(endDateAux); startDateFilter.show(); endDateFilter.show(); } // refresh the table manually, calling refresh() doesn't work here because the listgrid has set the // autoFetchData flag to true and invalidateCache() doesn't do the fetching as mentioned in the refresh() // method. final ListGrid listGrid = getListGrid(); Criteria criteria = getCurrentCriteria(); listGrid.setCriteria(criteria); listGrid.fetchData(criteria); listGrid.markForRedraw(); refreshTableInfo(); } }