/*
* RHQ Management Platform
* Copyright (C) 2005-2010 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.inventory.common.detail.operation.history;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.FormErrorOrientation;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.HTMLPane;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.CloseClickEvent;
import com.smartgwt.client.widgets.events.CloseClickHandler;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.StaticTextItem;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.operation.OperationDefinition;
import org.rhq.core.domain.operation.OperationHistory;
import org.rhq.core.domain.operation.OperationRequestStatus;
import org.rhq.coregui.client.BookmarkableView;
import org.rhq.coregui.client.ImageManager;
import org.rhq.coregui.client.ViewPath;
import org.rhq.coregui.client.components.configuration.ConfigurationEditor;
import org.rhq.coregui.client.components.table.TimestampCellFormatter;
import org.rhq.coregui.client.util.enhanced.EnhancedVLayout;
import org.rhq.coregui.client.util.enhanced.EnhancedVStack;
/**
* @author Greg Hinkle
*/
public abstract class AbstractOperationHistoryDetailsView<T extends OperationHistory> extends EnhancedVStack implements
BookmarkableView {
private T operationHistory;
private DynamicForm form;
public AbstractOperationHistoryDetailsView() {
super();
setWidth100();
setHeight100();
setOverflow(Overflow.AUTO);
setLayoutMargin(0);
setMembersMargin(16);
}
@Override
protected void onDraw() {
super.onDraw();
destroyMembers();
if (this.operationHistory != null) {
displayDetails(this.operationHistory);
}
}
/**
* This method should be called by {@link #lookupDetails(int)} upon successful lookup of an operation history.
*
* @param operationHistory the operation history to be displayed
*/
protected void displayDetails(final T operationHistory) {
for (Canvas child : getMembers()) {
removeChild(child);
}
this.operationHistory = operationHistory;
// History Basic Details
form = new DynamicForm();
form.setWidth100();
form.setWrapItemTitles(false);
List<FormItem> items = createFields(operationHistory);
form.setFields(items.toArray(new FormItem[items.size()]));
addMember(form);
// Parameters (if applicable)
if (operationHistory.getParameters() != null) {
EnhancedVLayout parametersSection = new EnhancedVLayout();
Label title = new Label("<h4>" + MSG.view_operationHistoryDetails_parameters() + "</h4>");
title.setHeight(27);
parametersSection.addMember(title);
OperationDefinition operationDefinition = operationHistory.getOperationDefinition();
ConfigurationDefinition parametersConfigurationDefinition = operationDefinition
.getParametersConfigurationDefinition();
if (parametersConfigurationDefinition != null
&& !parametersConfigurationDefinition.getPropertyDefinitions().isEmpty()) {
ConfigurationEditor editor = new ConfigurationEditor(parametersConfigurationDefinition,
operationHistory.getParameters());
editor.setReadOnly(true);
parametersSection.addMember(editor);
} else {
Label noParametersLabel = new Label("This operation does not take any parameters.");
noParametersLabel.setHeight(17);
parametersSection.addMember(noParametersLabel);
}
addMember(parametersSection);
}
// Results (if applicable)
Canvas resultsSection = buildResultsSection(operationHistory);
if (resultsSection != null) {
addMember(resultsSection);
}
}
protected List<FormItem> createFields(final T operationHistory) {
List<FormItem> items = new ArrayList<FormItem>();
OperationRequestStatus status = operationHistory.getStatus();
StaticTextItem idItem = new StaticTextItem(AbstractOperationHistoryDataSource.Field.ID, "Execution ID");
idItem.setValue(operationHistory.getId());
items.add(idItem);
StaticTextItem operationItem = new StaticTextItem(AbstractOperationHistoryDataSource.Field.OPERATION_NAME,
MSG.view_operationHistoryDetails_operation());
OperationDefinition operationDefinition = operationHistory.getOperationDefinition();
operationItem.setValue(operationDefinition.getDisplayName());
items.add(operationItem);
StaticTextItem submittedItem = new StaticTextItem(AbstractOperationHistoryDataSource.Field.STARTED_TIME,
MSG.view_operationHistoryDetails_dateSubmitted());
if (operationHistory.getStartedTime() == 0) {
// must have executed serially, halt-on-error was true and a previous resource op failed, thus this never even got submitted to the agent for invocation
submittedItem.setValue(MSG.common_val_never());
} else {
submittedItem.setValue(TimestampCellFormatter.format(operationHistory.getStartedTime()));
}
items.add(submittedItem);
StaticTextItem completedItem = new StaticTextItem("completed", MSG.view_operationHistoryDetails_dateCompleted());
if (status == OperationRequestStatus.INPROGRESS) {
completedItem.setValue(MSG.common_val_na());
} else if (status == OperationRequestStatus.CANCELED) {
completedItem.setValue(MSG.common_val_never());
} else {
completedItem.setValue(TimestampCellFormatter.format(new Date(operationHistory.getStartedTime()
+ operationHistory.getDuration())));
}
items.add(completedItem);
StaticTextItem requesterItem = new StaticTextItem(AbstractOperationHistoryDataSource.Field.SUBJECT,
MSG.view_operationHistoryDetails_requestor());
requesterItem.setEscapeHTML(true);
requesterItem.setValue(operationHistory.getSubjectName());
items.add(requesterItem);
StaticTextItem statusItem = new StaticTextItem(AbstractOperationHistoryDataSource.Field.STATUS,
MSG.view_operationHistoryDetails_status());
String icon = ImageManager.getFullImagePath(ImageManager.getOperationResultsIcon(status));
statusItem.setValue("<img src='" + icon + "'/>");
items.add(statusItem);
switch (status) {
case SUCCESS:
statusItem.setTooltip(MSG.common_status_success());
break;
case CANCELED:
case FAILURE:
if (status == OperationRequestStatus.CANCELED) {
statusItem.setTooltip(MSG.common_status_canceled());
} else {
statusItem.setTooltip(MSG.common_status_failed());
}
StaticTextItem errorLinkItem = new StaticTextItem("errorLink");
errorLinkItem.setTextAlign(Alignment.LEFT);
errorLinkItem.setAlign(Alignment.LEFT);
errorLinkItem.setVAlign(VerticalAlignment.BOTTOM);
errorLinkItem.setErrorOrientation(FormErrorOrientation.LEFT);
errorLinkItem.setTitle(MSG.common_severity_error());
errorLinkItem.setValue("<span style=\"text-decoration:underline;\">"
+ getShortErrorMessage(operationHistory) + "<span>");
errorLinkItem.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
final Window winModal = new Window();
winModal.setTitle(MSG.common_title_details());
winModal.setOverflow(Overflow.VISIBLE);
winModal.setShowMinimizeButton(false);
winModal.setShowMaximizeButton(true);
winModal.setIsModal(true);
winModal.setShowModalMask(true);
winModal.setAutoSize(true);
winModal.setAutoCenter(true);
winModal.setShowResizer(true);
winModal.setCanDragResize(true);
winModal.centerInPage();
winModal.addCloseClickHandler(new CloseClickHandler() {
@Override
public void onCloseClick(CloseClickEvent event) {
winModal.markForDestroy();
}
});
HTMLPane htmlPane = new HTMLPane();
htmlPane.setMargin(10);
htmlPane.setDefaultWidth(500);
htmlPane.setDefaultHeight(400);
String errorMsg = operationHistory.getErrorMessage();
if (errorMsg == null) {
errorMsg = MSG.common_status_failed();
}
htmlPane.setContents("<pre>" + errorMsg + "</pre>");
winModal.addItem(htmlPane);
winModal.show();
}
});
items.add(errorLinkItem);
break;
case INPROGRESS:
statusItem.setTooltip(MSG.common_status_inprogress());
break;
}
/*
Operation: View Process List
Date Submitted: 3/11/10, 12:24:02 PM, EST
Date Completed: 3/11/10, 12:24:03 PM, EST
Requester: rhqadmin
Status: Failure
Error Message: __Exception: Cannot connect...__
*/
return items;
}
protected abstract Canvas buildResultsSection(T operationHistory);
protected abstract void lookupDetails(int historyId);
protected T getOperationHistory() {
return this.operationHistory;
}
@Override
public void renderView(ViewPath viewPath) {
int historyId = viewPath.getCurrentAsInt();
lookupDetails(historyId);
}
private static String getShortErrorMessage(OperationHistory operationHistory) {
String errMsg = operationHistory.getErrorMessage();
if (errMsg == null) {
errMsg = MSG.common_status_failed();
} else if (errMsg.length() > 80) {
errMsg = errMsg.substring(0, 80) + "...";
}
return errMsg;
}
}