/* * RHQ Management Platform * Copyright 2011, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * 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.drift; import java.util.ArrayList; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.data.Criteria; import com.smartgwt.client.data.Record; import com.smartgwt.client.data.RecordList; import com.smartgwt.client.data.ResultSet; import com.smartgwt.client.data.SortSpecifier; import com.smartgwt.client.types.SortDirection; 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 org.rhq.core.domain.common.EntityContext; import org.rhq.core.domain.drift.DriftCategory; import org.rhq.core.domain.drift.DriftDefinition; import org.rhq.coregui.client.CoreGUI; import org.rhq.coregui.client.ViewPath; import org.rhq.coregui.client.components.table.AbstractTableAction; import org.rhq.coregui.client.components.table.TableAction; import org.rhq.coregui.client.components.table.TableActionEnablement; import org.rhq.coregui.client.components.table.TableSection; import org.rhq.coregui.client.components.view.ViewName; import org.rhq.coregui.client.drift.wizard.DriftAddDefinitionWizard; import org.rhq.coregui.client.gwt.GWTServiceLookup; import org.rhq.coregui.client.util.enhanced.EnhancedIButton.ButtonColor; import org.rhq.coregui.client.util.message.Message; /** * A list view that displays a paginated table of {@link org.rhq.core.domain.drift.DriftDefinition}s. It has offers various * options on the list like filtering (maybe) and sorting, add new/delete. Double-click drills down to the carousel view for * inspecting drift for the definition. Also, allows an edit view for the def's underlying Config. This view full respects * the user's authorization, and will not allow actions on the drift defs unless the user is either the inventory * manager or has MANAGE_DRIFT permission on every resource corresponding to the drift defs being operated on. * * @author Jay Shaughnessy */ public class DriftDefinitionsView extends TableSection<DriftDefinitionDataSource> { public static final ViewName SUBSYSTEM_VIEW_ID = new ViewName("DriftDefs", MSG.common_title_definitions()); private static SortSpecifier DEFAULT_SORT_SPECIFIER = new SortSpecifier(DriftDefinitionDataSource.ATTR_NAME, SortDirection.ASCENDING); private static final Criteria INITIAL_CRITERIA = new Criteria(); public enum DetailView { Carousel, Edit, InitialSnapshot }; private EntityContext context; private boolean hasWriteAccess; private DriftDefinitionDataSource dataSource; private DetailView detailsView = DetailView.Carousel; static { DriftCategory[] categoryValues = DriftCategory.values(); String[] categoryNames = new String[categoryValues.length]; int i = 0; for (DriftCategory c : categoryValues) { categoryNames[i++] = c.name(); } // Add any INITIAL_CRITERIA here (non currently) } // for subsystem views public DriftDefinitionsView() { this(SUBSYSTEM_VIEW_ID.getTitle(), EntityContext.forSubsystemView(), false); } public DriftDefinitionsView(EntityContext entityContext) { this(SUBSYSTEM_VIEW_ID.getTitle(), entityContext, false); } public DriftDefinitionsView(String tableTitle, EntityContext entityContext) { this(tableTitle, entityContext, false); } protected DriftDefinitionsView(String tableTitle, EntityContext context, boolean hasWriteAccess) { super(tableTitle, INITIAL_CRITERIA, new SortSpecifier[] { DEFAULT_SORT_SPECIFIER }); this.context = context; this.hasWriteAccess = hasWriteAccess; setInitialCriteriaFixed(false); setDataSource(getDataSource()); } @Override public DriftDefinitionDataSource getDataSource() { if (null == this.dataSource) { this.dataSource = new DriftDefinitionDataSource(context); } return this.dataSource; } @Override protected void configureTableFilters() { // currently no table filters } @Override protected void configureTable() { ArrayList<ListGridField> dataSourceFields = getDataSource().getListGridFields(hasWriteAccess); getListGrid().setFields(dataSourceFields.toArray(new ListGridField[dataSourceFields.size()])); setupTableInteractions(hasWriteAccess); super.configureTable(); } private void setupTableInteractions(final boolean hasWriteAccess) { TableActionEnablement deleteEnablement = hasWriteAccess ? TableActionEnablement.ANY : TableActionEnablement.NEVER; TableActionEnablement detectNowEnablement = hasWriteAccess ? TableActionEnablement.SINGLE : TableActionEnablement.NEVER; addTableAction(MSG.common_button_new(), null, ButtonColor.BLUE, new TableAction() { public boolean isEnabled(ListGridRecord[] selection) { return hasWriteAccess; } public void executeAction(ListGridRecord[] selection, Object actionValue) { add(); } }); addTableAction(MSG.common_button_delete(), MSG.view_drift_confirm_deleteDefs(), ButtonColor.RED, new AbstractTableAction(deleteEnablement) { public void executeAction(ListGridRecord[] selection, Object actionValue) { delete(selection); } }); addTableAction(MSG.common_button_delete_all(), MSG.view_drift_confirm_deleteAllDefs(), ButtonColor.RED, new TableAction() { public boolean isEnabled(ListGridRecord[] selection) { ListGrid grid = getListGrid(); ResultSet resultSet = (null != grid) ? grid.getResultSet() : null; return (hasWriteAccess && grid != null && resultSet != null && !resultSet.isEmpty()); } public void executeAction(ListGridRecord[] selection, Object actionValue) { deleteAll(); } }); addTableAction(MSG.view_drift_button_detectNow(), null, ButtonColor.GRAY, new AbstractTableAction( detectNowEnablement) { @Override public boolean isEnabled(ListGridRecord[] selection) { if (selection.length == 0 || !hasWriteAccess) { return false; } return Boolean.valueOf(selection[0].getAttribute(DriftDefinitionDataSource.ATTR_IS_ENABLED)); } public void executeAction(ListGridRecord[] selection, Object actionValue) { detectDrift(selection); // will only ever be a single selection - see detectNowEnablement variable } }); } private void add() { DriftAddDefinitionWizard.showWizard(context, this); // we can refresh the table buttons immediately since the wizard is a dialog, the // user can't access enabled buttons anyway. DriftDefinitionsView.this.refreshTableInfo(); } private void delete(ListGridRecord[] records) { final String[] driftDefNames = new String[records.length]; for (int i = 0, selectionLength = records.length; i < selectionLength; i++) { ListGridRecord record = records[i]; String driftDefName = record.getAttribute(DriftDefinitionDataSource.ATTR_NAME); driftDefNames[i] = driftDefName; } deleteDriftDefinitionsByName(driftDefNames); } private void deleteAll() { final RecordList records = getListGrid().getDataAsRecordList(); final int numRecords = records.getLength(); final String[] driftDefNames = new String[numRecords]; for (int i = 0; i < numRecords; i++) { Record record = records.get(i); String driftDefName = record.getAttribute(DriftDefinitionDataSource.ATTR_NAME); driftDefNames[i] = driftDefName; } deleteDriftDefinitionsByName(driftDefNames); } private void deleteDriftDefinitionsByName(final String[] driftDefNames) { GWTServiceLookup.getDriftService().deleteDriftDefinitionsByContext(context, driftDefNames, new AsyncCallback<Integer>() { public void onSuccess(Integer resultCount) { CoreGUI.getMessageCenter().notify( new Message(MSG.view_drift_success_deleteDefs(String.valueOf(resultCount)), Message.Severity.Info)); refresh(); } public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError(MSG.view_drift_failure_deleteDefs(), caught); } }); } private void detectDrift(ListGridRecord[] records) { // we will only ever have a single record selected, hence why we can access the [0] item DriftDefinition driftDef = (DriftDefinition) records[0] .getAttributeAsObject(DriftDefinitionDataSource.ATTR_ENTITY); GWTServiceLookup.getDriftService().detectDrift(context, driftDef, new AsyncCallback<Void>() { public void onSuccess(Void result) { CoreGUI.getMessageCenter().notify( new Message(MSG.view_drift_success_detectNow(), Message.Severity.Info)); refresh(); } public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError(MSG.view_drift_failure_detectNow(), caught); } }); } @Override public void renderView(ViewPath viewPath) { // we have three detail views for drift defs, the carousel, the the config editor, and the initial snapshot. // Figure out which one we're dealing with. The default is the carousel. this.detailsView = DetailView.Carousel; if (!viewPath.isEnd() && !viewPath.isNextEnd()) { if (DetailView.Edit.name().equals(viewPath.getNext().getPath())) { this.detailsView = DetailView.Edit; } else if (DetailView.InitialSnapshot.name().equals(viewPath.getNext().getPath())) { this.detailsView = DetailView.InitialSnapshot; } } super.renderView(viewPath); } @Override public Canvas getDetailsView(Integer driftDefId) { switch (detailsView) { case Edit: return new DriftDefinitionEditView(context, driftDefId, hasWriteAccess); case InitialSnapshot: return new DriftSnapshotView(null, context.getResourceId(), driftDefId, 0, hasWriteAccess); default: return new DriftCarouselView(context, driftDefId, hasWriteAccess); } } public EntityContext getContext() { return context; } }