/* * 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, version 2, as * published by the Free Software Foundation, and/or the GNU Lesser * General Public License, version 2.1, also as published by the Free * Software Foundation. * * 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 and the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU General Public License * and the GNU Lesser 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.bundle.create; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.types.Alignment; import com.smartgwt.client.types.TitleOrientation; import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.form.DynamicForm; import com.smartgwt.client.widgets.form.fields.HeaderItem; import com.smartgwt.client.widgets.form.fields.RadioGroupItem; import com.smartgwt.client.widgets.form.fields.events.ChangedEvent; import com.smartgwt.client.widgets.form.fields.events.ChangedHandler; import com.smartgwt.client.widgets.grid.ListGridRecord; import org.rhq.core.domain.bundle.BundleGroup; import org.rhq.core.domain.bundle.BundleVersion; import org.rhq.core.domain.bundle.composite.BundleGroupAssignmentComposite; import org.rhq.coregui.client.CoreGUI; import org.rhq.coregui.client.bundle.group.BundleGroupSelector; import org.rhq.coregui.client.bundle.group.BundleGroupsDataSource; import org.rhq.coregui.client.components.wizard.AbstractWizardStep; import org.rhq.coregui.client.gwt.GWTServiceLookup; import org.rhq.coregui.client.util.FormUtility; import org.rhq.coregui.client.util.enhanced.EnhancedVLayout; import org.rhq.coregui.client.util.message.Message; /** * @author Jay Shaughnessy */ public class BundleGroupsStep extends AbstractWizardStep { // BZ 1252142: We don't want the usual 30s timeout for GWT service calls when creating the initial bundle // version. We can't advance the wizard until the bundle version creation is complete and for large // distribution files it can take some time to move the uploaded [tmp] file from disk into the DB. So, use // a liberal timeout here... private static final int BUNDLE_CREATE_INITIAL_VERSION_TIMEOUT = 10 * 60 * 1000; private enum ProcessingStatus { IDLE, TOKEN }; private EnhancedVLayout canvas; private DynamicForm radioForm; private AbstractBundleCreateWizard wizard = null; private boolean isInitialVersion; private BundleGroupSelector selector; private ProcessingStatus currentProcess = ProcessingStatus.IDLE; public BundleGroupsStep(AbstractBundleCreateWizard wizard) { this.wizard = wizard; } public Canvas getCanvas() { canvas = new EnhancedVLayout(); canvas.setWidth100(); // go get the assignable/assigned bundle groups for this new bundle version, initial or not this.isInitialVersion = this.wizard.getBundleVersion() == null || this.wizard.getBundleVersion().getVersionOrder() == 0; if (isInitialVersion) { prepareInitialVersionCanvas(canvas); } else { prepareNonInitialVersionCanvas(canvas); } return canvas; } private void prepareInitialVersionCanvas(final EnhancedVLayout canvas) { BundleGroupAssignmentComposite composite = wizard.getBundleGroupAssignmentComposite(); final Map<BundleGroup, Boolean> map = composite.getBundleGroupMap(); if (composite.isCanBeUnassigned()) { radioForm = new DynamicForm(); radioForm.setNumCols(1); radioForm.setColWidths(350); final RadioGroupItem radioGroupItem = new RadioGroupItem("RadioOptions"); radioGroupItem.setTitleOrientation(TitleOrientation.TOP); radioGroupItem.setTitle(MSG.view_bundle_createWizard_groupsStep_radioTitle()); radioGroupItem.setRequired(true); radioGroupItem.setAlign(Alignment.LEFT); LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>(); valueMap.put("unassigned", MSG.view_bundle_createWizard_groupsStep_leaveUnassigned()); valueMap.put("assign", MSG.view_bundle_createWizard_groupsStep_assign()); radioGroupItem.setValueMap(valueMap); radioGroupItem.setValue(map.isEmpty() ? "unassigned" : "assign"); radioGroupItem.addChangedHandler(new ChangedHandler() { public void onChanged(ChangedEvent event) { if (map.isEmpty()) { radioGroupItem.setValue("unassigned"); } else { selector.setDisabled("unassigned".equals(event.getValue())); } canvas.markForRedraw(); } }); FormUtility.addContextualHelp(radioGroupItem, MSG.view_bundle_createWizard_groupsStep_help()); radioForm.setItems(radioGroupItem); canvas.addMember(radioForm); selector = getSelector(map, false); selector.setDisabled(map.isEmpty()); canvas.addMember(selector); } else if (!map.isEmpty()) { DynamicForm form = new DynamicForm(); form.setWidth100(); HeaderItem selectorTitleItem = new HeaderItem(); selectorTitleItem.setWidth(375); selectorTitleItem.setValue(MSG.view_bundle_createWizard_groupsStep_assign()); FormUtility.addContextualHelp(selectorTitleItem, MSG.view_bundle_createWizard_groupsStep_help()); form.setItems(selectorTitleItem); canvas.addMember(form); selector = getSelector(map, false); canvas.addMember(selector); } else { // can't call wizard show message, the canvas is not yet created, so make the canvas the message DynamicForm form = new DynamicForm(); form.setWidth100(); HeaderItem errorHeaderItem = new HeaderItem(); errorHeaderItem.setAttribute("wrap", true); // forum tip, only way I could get the text to wrap errorHeaderItem.setWidth(650); errorHeaderItem.setValue(MSG.view_bundle_createWizard_groupsStep_noAssignable()); FormUtility.addContextualHelp(errorHeaderItem, MSG.view_bundle_createWizard_groupsStep_help()); form.setItems(errorHeaderItem); canvas.addMember(form); CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_groupsStep_noAssignable()); } } private void prepareNonInitialVersionCanvas(EnhancedVLayout canvas) { BundleGroupAssignmentComposite composite = wizard.getBundleGroupAssignmentComposite(); final Map<BundleGroup, Boolean> map = composite.getBundleGroupMap(); selector = getSelector(map, true); if (!selector.hasInitialSelection()) { selector.destroy(); DynamicForm form = new DynamicForm(); form.setWidth100(); HeaderItem unassignedHeaderItem = new HeaderItem(); unassignedHeaderItem.setAttribute("wrap", true); // forum tip, only way I could get the text to wrap unassignedHeaderItem.setWidth(650); unassignedHeaderItem.setValue(MSG.view_bundle_createWizard_groupsStep_unassigned()); FormUtility.addContextualHelp(unassignedHeaderItem, MSG.view_bundle_createWizard_groupsStep_help()); form.setItems(unassignedHeaderItem); canvas.addMember(form); } else { DynamicForm form = new DynamicForm(); form.setWidth100(); HeaderItem selectorTitleItem = new HeaderItem(); selectorTitleItem.setWidth(650); selectorTitleItem.setValue(MSG.view_bundle_createWizard_groupsStep_assigned()); FormUtility.addContextualHelp(selectorTitleItem, MSG.view_bundle_createWizard_groupsStep_help()); form.setItems(selectorTitleItem); canvas.addMember(form); canvas.addMember(selector); } } private BundleGroupSelector getSelector(final Map<BundleGroup, Boolean> map, boolean readOnly) { BundleGroupSelector result; if (map.isEmpty()) { result = new BundleGroupSelector(readOnly); } else { Set<BundleGroup> bundleGroups = map.keySet(); Integer[] idsFilter = new Integer[bundleGroups.size()]; int i = 0; for (BundleGroup bundleGroup : bundleGroups) { idsFilter[i++] = bundleGroup.getId(); } List<ListGridRecord> initiallyAssigned = new ArrayList<ListGridRecord>(bundleGroups.size()); BundleGroupsDataSource ds = new BundleGroupsDataSource(); for (BundleGroup bundleGroup : bundleGroups) { if (map.get(bundleGroup) == Boolean.TRUE) { initiallyAssigned.add(ds.copyValues(bundleGroup)); } } result = new BundleGroupSelector(idsFilter, initiallyAssigned.toArray(new ListGridRecord[initiallyAssigned .size()]), readOnly); } return result; } public Set<BundleGroup> getSelectedBundleGroups() { return selector.getSelectedItems(); } public boolean nextPage() { wizard.getView().hideMessage(); if (isInitialVersion) { if (selector.isDisabled()) { // if the user chooses to leave unassigned and the bundle version has already been created, we're done if (null != wizard.getBundleVersion()) { return true; } } else { // make sure at least one group is selected if the selector is active if (selector.getSelectedItems().isEmpty()) { wizard.getView().showMessage(MSG.view_bundle_createWizard_groupsStep_noneAssigned()); return false; } } } if (null == wizard.getBundleVersion()) { if (null != wizard.getCreateInitialBundleVersionRecipe()) { processRecipe(); } else if (null != wizard.getCreateInitialBundleVersionToken()) { processToken(); } else { Exception e = new IllegalStateException( "Unexpected error: can't create initial version, no recipe or token"); wizard.getView().showMessage(e.getMessage()); CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), e); wizard.setBundleVersion(null); wizard.setCreateInitialBundleVersionRecipe(""); } } else { processAssignment(); } return false; } private int[] getInitialBundleIds() { if (selector.isDisabled()) { return null; } Set<BundleGroup> bundleGroups = selector.getSelectedItems(); wizard.setInitialBundleGroups(bundleGroups); int[] result = new int[bundleGroups.size()]; int i = 0; for (BundleGroup bundleGroup : bundleGroups) { result[i++] = bundleGroup.getId(); } return result; } private void processRecipe() { GWTServiceLookup.getBundleService(BUNDLE_CREATE_INITIAL_VERSION_TIMEOUT).createInitialBundleVersionViaRecipe( getInitialBundleIds(), this.wizard.getCreateInitialBundleVersionRecipe(), new AsyncCallback<BundleVersion>() { @Override public void onSuccess(BundleVersion result) { CoreGUI.getMessageCenter().notify( new Message( MSG.view_bundle_createWizard_createSuccessful(result.getName(), result.getVersion()), Message.Severity.Info)); wizard.setBundleVersion(result); wizard.getView().incrementStep(); // go to the next step } @Override public void onFailure(Throwable caught) { wizard.getView().showMessage(caught.getMessage()); CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), caught); wizard.setBundleVersion(null); wizard.setCreateInitialBundleVersionRecipe(""); } }); } private void processToken() { if (this.currentProcess == ProcessingStatus.TOKEN) { wizard.getView().showMessage(MSG.view_bundle_createWizard_assigningBundleGroupInProgress()); return; } this.currentProcess = ProcessingStatus.TOKEN; GWTServiceLookup.getBundleService(BUNDLE_CREATE_INITIAL_VERSION_TIMEOUT).createInitialBundleVersionViaToken( getInitialBundleIds(), this.wizard.getCreateInitialBundleVersionToken(), new AsyncCallback<BundleVersion>() { @Override public void onSuccess(BundleVersion result) { CoreGUI.getMessageCenter().notify( new Message( MSG.view_bundle_createWizard_createSuccessful(result.getName(), result.getVersion()), Message.Severity.Info)); wizard.setBundleVersion(result); wizard.getView().incrementStep(); // go to the next step currentProcess = ProcessingStatus.IDLE; } @Override public void onFailure(Throwable caught) { wizard.getView().showMessage(caught.getMessage()); CoreGUI.getErrorHandler().handleError(MSG.view_bundle_createWizard_createFailure(), caught); wizard.setBundleVersion(null); wizard.setCreateInitialBundleVersionToken(null); currentProcess = ProcessingStatus.IDLE; } }); } private void processAssignment() { GWTServiceLookup.getBundleService().assignBundlesToBundleGroups(getInitialBundleIds(), new int[] { wizard.getBundleVersion().getBundle().getId() }, new AsyncCallback<Void>() { @Override public void onSuccess(Void result) { CoreGUI.getMessageCenter().notify( new Message(MSG.view_bundle_createWizard_groupsStep_successAssign(wizard.getBundleVersion() .getBundle().getName(), wizard.getBundleVersion().getName()), Message.Severity.Info)); wizard.getView().incrementStep(); // go to the next step } @Override public void onFailure(Throwable caught) { String msg = MSG.view_bundle_createWizard_groupsStep_failedAssign(wizard.getBundleVersion().getBundle() .getName(), wizard.getBundleVersion().getName()); wizard.getView().showMessage(msg); CoreGUI.getErrorHandler().handleError(msg, caught); } }); } @Override public boolean previousPage() { wizard.getView().hideMessage(); return true; } public String getName() { return MSG.common_title_bundleGroups(); } }