/*
* RHQ Management Platform
* Copyright (C) 2005-2012 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.topology;
import static org.rhq.coregui.client.admin.topology.AgentDatasourceField.FIELD_AFFINITY_GROUP;
import static org.rhq.coregui.client.admin.topology.ServerDatasourceField.FIELD_ADDRESS;
import static org.rhq.coregui.client.admin.topology.ServerDatasourceField.FIELD_CTIME;
import static org.rhq.coregui.client.admin.topology.ServerDatasourceField.FIELD_MTIME;
import static org.rhq.coregui.client.admin.topology.ServerDatasourceField.FIELD_NAME;
import static org.rhq.coregui.client.admin.topology.ServerDatasourceField.FIELD_OPERATION_MODE;
import static org.rhq.coregui.client.admin.topology.ServerDatasourceField.FIELD_PORT;
import static org.rhq.coregui.client.admin.topology.ServerDatasourceField.FIELD_SECURE_PORT;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.types.VisibilityMode;
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.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.StaticTextItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.validator.IntegerRangeValidator;
import com.smartgwt.client.widgets.layout.SectionStack;
import com.smartgwt.client.widgets.layout.SectionStackSection;
import org.rhq.core.domain.cloud.AffinityGroup;
import org.rhq.core.domain.cloud.Server;
import org.rhq.core.domain.cloud.Server.OperationMode;
import org.rhq.core.domain.criteria.ServerCriteria;
import org.rhq.core.domain.util.PageList;
import org.rhq.coregui.client.BookmarkableView;
import org.rhq.coregui.client.CoreGUI;
import org.rhq.coregui.client.LinkManager;
import org.rhq.coregui.client.ViewPath;
import org.rhq.coregui.client.components.table.TimestampCellFormatter;
import org.rhq.coregui.client.gwt.GWTServiceLookup;
import org.rhq.coregui.client.util.Log;
import org.rhq.coregui.client.util.StringUtility;
import org.rhq.coregui.client.util.enhanced.EnhancedIButton;
import org.rhq.coregui.client.util.enhanced.EnhancedToolStrip;
import org.rhq.coregui.client.util.enhanced.EnhancedVLayout;
import org.rhq.coregui.client.util.enhanced.EnhancedIButton.ButtonColor;
import org.rhq.coregui.client.util.message.Message;
/**
* Shows details of a server.
*
* @author Jirka Kremser
*/
public class ServerDetailView extends EnhancedVLayout implements BookmarkableView {
private final int serverId;
private static final int SECTION_COUNT = 2;
private final SectionStack sectionStack;
private SectionStackSection detailsSection = null;
private SectionStackSection agentSection = null;
private volatile int initSectionCount = 0;
public ServerDetailView(int serverId) {
super();
this.serverId = serverId;
setHeight100();
setWidth100();
setOverflow(Overflow.AUTO);
sectionStack = new SectionStack();
sectionStack.setVisibilityMode(VisibilityMode.MULTIPLE);
sectionStack.setWidth100();
sectionStack.setHeight100();
sectionStack.setMargin(5);
sectionStack.setOverflow(Overflow.VISIBLE);
}
@Override
protected void onInit() {
super.onInit();
ServerCriteria criteria = new ServerCriteria();
criteria.addFilterId(serverId);
GWTServiceLookup.getTopologyService().findServersByCriteria(criteria, new AsyncCallback<PageList<Server>>() {
public void onSuccess(final PageList<Server> servers) {
if (servers == null || servers.isEmpty() || servers.size() != 1) {
CoreGUI.getErrorHandler().handleError(
MSG.view_adminTopology_message_fetchServerFail(String.valueOf(serverId)));
initSectionCount = SECTION_COUNT;
return;
}
prepareDetailsSection(sectionStack, servers.get(0));
prepareAgentSection(sectionStack, servers.get(0));
}
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(
MSG.view_adminTopology_message_fetchServerFail(String.valueOf(serverId)) + " "
+ caught.getMessage(), caught);
initSectionCount = SECTION_COUNT;
}
});
}
public boolean isInitialized() {
return initSectionCount >= SECTION_COUNT;
}
@Override
protected void onDraw() {
super.onDraw();
// wait until we have all of the sections before we show them. We don't use InitializableView because,
// it seems they are not supported (in the applicable renderView()) at this level.
new Timer() {
final long startTime = System.currentTimeMillis();
public void run() {
if (isInitialized()) {
if (null != detailsSection) {
sectionStack.addSection(detailsSection);
}
if (null != agentSection) {
sectionStack.addSection(agentSection);
}
addMember(sectionStack);
markForRedraw();
} else {
// don't wait forever, give up after 20s and show what we have
long elapsedMillis = System.currentTimeMillis() - startTime;
if (elapsedMillis > 20000) {
initSectionCount = SECTION_COUNT;
}
schedule(100); // Reschedule the timer.
}
}
}.run(); // fire the timer immediately
}
private void prepareAgentSection(SectionStack stack, Server server) {
SectionStackSection section = new SectionStackSection(MSG.view_adminTopology_serverDetail_connectedAgents());
section.setExpanded(true);
AgentTableView agentsTable = new AgentTableView(serverId, false);
section.setItems(agentsTable);
agentSection = section;
initSectionCount++;
return;
}
private void prepareDetailsSection(SectionStack stack, final Server server) {
final DynamicForm form = new DynamicForm();
form.setMargin(10);
form.setWidth100();
form.setWrapItemTitles(false);
form.setNumCols(2);
StaticTextItem nameItem = new StaticTextItem(FIELD_NAME.propertyName(), FIELD_NAME.title());
nameItem.setValue("<b>" + server.getName() + "</b>");
final TextItem addressItem = new TextItem(FIELD_ADDRESS.propertyName(), FIELD_ADDRESS.title());
addressItem.setRequired(true);
addressItem.setValue(server.getAddress());
IntegerRangeValidator portValidator = new IntegerRangeValidator();
portValidator.setMin(0);
portValidator.setMax(65535);
final TextItem portItem = new TextItem(FIELD_PORT.propertyName(), FIELD_PORT.title());
portItem.setRequired(true);
portItem.setValidators(portValidator);
portItem.setValue(server.getPort());
final TextItem securePortItem = new TextItem(FIELD_SECURE_PORT.propertyName(), FIELD_SECURE_PORT.title());
securePortItem.setRequired(true);
securePortItem.setValidators(portValidator);
securePortItem.setValue(server.getSecurePort());
final SelectItem operationModeItem = new SelectItem(FIELD_OPERATION_MODE.propertyName(),
MSG.view_adminTopology_serverDetail_operationMode());
operationModeItem.setValueMap("NORMAL", "MAINTENANCE");
operationModeItem.setValue(server.getOperationMode());
// make clickable link for affinity group
StaticTextItem affinityGroupItem = new StaticTextItem(FIELD_AFFINITY_GROUP.propertyName(),
FIELD_AFFINITY_GROUP.title());
String affinityGroupItemText = "";
AffinityGroup ag = server.getAffinityGroup();
if (ag != null && ag.getName() != null && !ag.getName().isEmpty()) {
String detailsUrl = "#" + AffinityGroupTableView.VIEW_PATH + "/" + ag.getId();
String formattedValue = StringUtility.escapeHtml(ag.getName());
affinityGroupItemText = LinkManager.getHref(detailsUrl, formattedValue);
}
affinityGroupItem.setValue(affinityGroupItemText);
StaticTextItem installationDateItem = new StaticTextItem(FIELD_CTIME.propertyName(), FIELD_CTIME.title());
installationDateItem.setValue(TimestampCellFormatter.format(Long.valueOf(server.getCtime()),
TimestampCellFormatter.DATE_TIME_FORMAT_LONG));
StaticTextItem lastUpdateItem = new StaticTextItem(FIELD_MTIME.propertyName(), FIELD_MTIME.title());
lastUpdateItem.setValue(TimestampCellFormatter.format(Long.valueOf(server.getMtime()),
TimestampCellFormatter.DATE_TIME_FORMAT_LONG));
IButton saveButton = new EnhancedIButton(MSG.common_button_save(), ButtonColor.BLUE);
saveButton.setOverflow(Overflow.VISIBLE);
saveButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
if (form.validate()) {
server.setAddress(addressItem.getValueAsString());
server.setPort(Integer.parseInt(portItem.getValueAsString()));
server.setSecurePort(Integer.parseInt(securePortItem.getValueAsString()));
server.setOperationMode(OperationMode.valueOf(operationModeItem.getValueAsString()));
GWTServiceLookup.getTopologyService().updateServer(server, new AsyncCallback<Void>() {
public void onSuccess(Void result) {
Message msg = new Message(MSG.view_adminTopology_message_serverUpdated(server.getName()),
Message.Severity.Info);
CoreGUI.getMessageCenter().notify(msg);
}
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(
MSG.view_adminTopology_message_serverUpdateFail(server.getName()) + " "
+ caught.getMessage(), caught);
}
});
}
}
});
form.setItems(nameItem, addressItem, portItem, securePortItem, operationModeItem, affinityGroupItem,
installationDateItem, lastUpdateItem);
EnhancedToolStrip footer = new EnhancedToolStrip();
footer.setPadding(5);
footer.setWidth100();
footer.setMembersMargin(15);
footer.addMember(saveButton);
SectionStackSection section = new SectionStackSection(MSG.common_title_details());
section.setExpanded(true);
section.setItems(form, footer);
detailsSection = section;
initSectionCount++;
}
@Override
public void renderView(ViewPath viewPath) {
Log.debug("ServerDetailView: " + viewPath);
}
}