/* * 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., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package org.rhq.coregui.client.inventory.groups.detail.inventory; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Map; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.types.Overflow; import com.smartgwt.client.widgets.IButton; import com.smartgwt.client.widgets.events.ClickEvent; import com.smartgwt.client.widgets.events.ClickHandler; import com.smartgwt.client.widgets.toolbar.ToolStrip; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.composite.ResourceConfigurationComposite; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; import org.rhq.core.domain.resource.ResourceAncestryFormat; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.composite.ResourcePermission; import org.rhq.core.domain.resource.group.ResourceGroup; import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite; import org.rhq.core.domain.util.ResourceTypeUtility; import org.rhq.coregui.client.CoreGUI; import org.rhq.coregui.client.RefreshableView; import org.rhq.coregui.client.components.configuration.ConfigurationEditor; import org.rhq.coregui.client.components.configuration.GroupConfigurationEditor; import org.rhq.coregui.client.components.configuration.GroupMemberConfiguration; import org.rhq.coregui.client.components.configuration.PropertyValueChangeEvent; import org.rhq.coregui.client.components.configuration.PropertyValueChangeListener; import org.rhq.coregui.client.gwt.ConfigurationGWTServiceAsync; import org.rhq.coregui.client.gwt.GWTServiceLookup; import org.rhq.coregui.client.gwt.ResourceGWTServiceAsync; import org.rhq.coregui.client.inventory.resource.type.ResourceTypeRepository; import org.rhq.coregui.client.util.enhanced.EnhancedIButton; import org.rhq.coregui.client.util.enhanced.EnhancedIButton.ButtonColor; import org.rhq.coregui.client.util.enhanced.EnhancedVLayout; import org.rhq.coregui.client.util.message.Message; import org.rhq.coregui.client.util.message.Message.Severity; import org.rhq.coregui.client.util.message.MessageCenter; /** * A view for editing a group's current plugin configuration. * * @author Ian Springer * @author John Mazzitelli */ public class GroupPluginConfigurationEditView extends EnhancedVLayout implements PropertyValueChangeListener, RefreshableView { private final ConfigurationGWTServiceAsync configurationService = GWTServiceLookup.getConfigurationService(); private final ResourceGWTServiceAsync resourceService = GWTServiceLookup.getResourceService(); private ResourceGroup group; private ResourcePermission resourcePermission; private ConfigurationDefinition configurationDefinition; private List<GroupMemberConfiguration> memberConfigurations; private ConfigurationEditor editor; private IButton saveButton; private boolean refreshing = false; public GroupPluginConfigurationEditView(ResourceGroupComposite groupComposite) { super(); this.group = groupComposite.getResourceGroup(); this.resourcePermission = groupComposite.getResourcePermission(); } @Override protected void onDraw() { super.onDraw(); ToolStrip toolStrip = new ToolStrip(); toolStrip.setWidth100(); toolStrip.setExtraSpace(10); toolStrip.setMembersMargin(5); toolStrip.setLayoutMargin(5); this.saveButton = new EnhancedIButton(MSG.common_button_save(), ButtonColor.BLUE); this.saveButton.setTooltip(MSG.view_group_pluginConfig_edit_saveTooltip()); this.saveButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent clickEvent) { save(); } }); toolStrip.addMember(saveButton); addMember(toolStrip); refresh(); if (!this.resourcePermission.isInventory()) { Message message = new Message(MSG.view_group_pluginConfig_edit_noperm(), Message.Severity.Info, EnumSet.of( Message.Option.Transient, Message.Option.Sticky)); CoreGUI.getMessageCenter().notify(message); } } @Override public void refresh() { if (this.refreshing) { return; // we are already in the process of refreshing, don't do it again } this.refreshing = true; this.saveButton.disable(); if (editor != null) { editor.destroy(); removeMember(editor); } // TODO (ips): If editor != null, use editor.reload() instead. loadConfigurationDefinition(); loadConfigurations(); } private void initEditor() { if (this.configurationDefinition != null && this.memberConfigurations != null) { this.editor = new GroupConfigurationEditor(this.configurationDefinition, this.memberConfigurations); this.editor.setEditorTitle(MSG.view_group_pluginConfig_edit_currentGroupProperties()); this.editor.setOverflow(Overflow.AUTO); this.editor.addPropertyValueChangeListener(this); this.editor.setReadOnly(!this.resourcePermission.isConfigureWrite()); addMember(editor, 0); this.refreshing = false; } } private void loadConfigurationDefinition() { if (this.configurationDefinition == null) { final ResourceType type = this.group.getResourceType(); ResourceTypeRepository.Cache.getInstance().getResourceTypes(new Integer[] { type.getId() }, EnumSet.of(ResourceTypeRepository.MetadataType.pluginConfigurationDefinition), new ResourceTypeRepository.TypesLoadedCallback() { public void onTypesLoaded(Map<Integer, ResourceType> types) { configurationDefinition = types.get(type.getId()).getPluginConfigurationDefinition(); if (configurationDefinition == null) { throw new IllegalStateException("Connection settings are not supported by this group."); } initEditor(); } }); } } private void loadConfigurations() { this.memberConfigurations = null; this.configurationService.findPluginConfigurationsForGroup(group.getId(), new AsyncCallback<Map<Integer, Configuration>>() { public void onFailure(Throwable caught) { handleLoadFailure(caught); } public void onSuccess(final Map<Integer, Configuration> configMap) { final Integer[] resourceIds = configMap.keySet().toArray(new Integer[configMap.size()]); resourceService.getResourcesAncestry(resourceIds, ResourceAncestryFormat.EXTENDED, new AsyncCallback<Map<Integer, String>>() { public void onFailure(Throwable caught) { handleLoadFailure(caught); } public void onSuccess(Map<Integer, String> labelMap) { memberConfigurations = new ArrayList<GroupMemberConfiguration>(configMap.size()); for (Integer resourceId : resourceIds) { String label = labelMap.get(resourceId); Configuration configuration = configMap.get(resourceId); GroupMemberConfiguration memberConfiguration = new GroupMemberConfiguration( resourceId, label, configuration); if (configuration == null || configuration.getProperties().isEmpty()) { throw new RuntimeException( "The server did not return the connection settings for one or more member resources."); } memberConfigurations.add(memberConfiguration); } initEditor(); } }); } }); } private void handleLoadFailure(Throwable caught) { refreshing = false; if (caught.getMessage().contains("ConfigurationUpdateStillInProgressException")) { CoreGUI.getMessageCenter().notify( new Message(MSG.view_group_pluginConfig_members_fetchFailureConnInProgress(), caught, Severity.Info)); } else { CoreGUI.getErrorHandler().handleError( MSG.view_group_pluginConfig_members_fetchFailureConn(group.toString()), caught); } } private void save() { List<ResourceConfigurationComposite> resourceConfigurations = convertToCompositeList(); GWTServiceLookup.getConfigurationService().updatePluginConfigurationsForGroup(this.group.getId(), resourceConfigurations, new AsyncCallback<Void>() { public void onFailure(Throwable caught) { String typeName = ResourceTypeUtility.displayName(group.getResourceType()); CoreGUI.getErrorHandler().handleError( MSG.view_group_pluginConfig_edit_saveFailure(typeName, group.getName()), caught); } public void onSuccess(Void result) { CoreGUI.getMessageCenter().notify( new Message(MSG.view_group_pluginConfig_edit_saveInitiated_concise(), MSG .view_group_pluginConfig_edit_saveInitiated_full( ResourceTypeUtility.displayName(group.getResourceType()), group.getName()), Message.Severity.Info)); refresh(); } }); } private List<ResourceConfigurationComposite> convertToCompositeList() { List<ResourceConfigurationComposite> resourceConfigurations = new ArrayList<ResourceConfigurationComposite>( this.memberConfigurations.size()); for (GroupMemberConfiguration memberConfiguration : this.memberConfigurations) { resourceConfigurations.add(new ResourceConfigurationComposite(memberConfiguration.getId(), memberConfiguration.getConfiguration())); } return resourceConfigurations; } @Override public void propertyValueChanged(PropertyValueChangeEvent event) { MessageCenter messageCenter = CoreGUI.getMessageCenter(); Message message; if (event.isInvalidPropertySetChanged()) { Map<String, String> invalidPropertyNames = event.getInvalidPropertyNames(); if (invalidPropertyNames.isEmpty()) { this.saveButton.enable(); message = new Message(MSG.view_group_pluginConfig_edit_valid(), Message.Severity.Info, EnumSet.of( Message.Option.Transient, Message.Option.Sticky)); } else { this.saveButton.disable(); message = new Message( MSG.view_group_pluginConfig_edit_invalid(invalidPropertyNames.values().toString()), Message.Severity.Error, EnumSet.of(Message.Option.Transient, Message.Option.Sticky)); } messageCenter.notify(message); } else if (event.getInvalidPropertyNames().isEmpty()) { this.saveButton.enable(); } else { this.saveButton.disable(); } } }