/*
* 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.inventory.groups.detail;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.List;
import com.google.gwt.core.client.GWT;
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.widgets.layout.VLayout;
import org.rhq.core.domain.common.EntityContext;
import org.rhq.core.domain.measurement.MeasurementDefinition;
import org.rhq.core.domain.measurement.composite.MeasurementDataNumericHighLowComposite;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.resource.group.GroupCategory;
import org.rhq.core.domain.resource.group.ResourceGroup;
import org.rhq.core.domain.resource.group.composite.ResourceGroupAvailability;
import org.rhq.coregui.client.CoreGUI;
import org.rhq.coregui.client.gwt.GWTServiceLookup;
import org.rhq.coregui.client.inventory.AutoRefresh;
import org.rhq.coregui.client.inventory.common.AbstractD3GraphListView;
import org.rhq.coregui.client.inventory.common.detail.AbstractTwoLevelTabSetView;
import org.rhq.coregui.client.inventory.common.graph.CustomDateRangeState;
import org.rhq.coregui.client.inventory.common.graph.MetricGraphData;
import org.rhq.coregui.client.inventory.common.graph.graphtype.AvailabilityOverUnderGraphType;
import org.rhq.coregui.client.inventory.common.graph.graphtype.StackedBarMetricGraphImpl;
import org.rhq.coregui.client.inventory.resource.detail.monitoring.MetricD3Graph;
import org.rhq.coregui.client.inventory.resource.detail.monitoring.avail.AvailabilityD3GraphView;
import org.rhq.coregui.client.inventory.resource.type.ResourceTypeRepository;
import org.rhq.coregui.client.util.Log;
import org.rhq.coregui.client.util.async.CountDownLatch;
/**
* Build the Group version of the View that shows the individual graph views.
* @author Mike Thompson
*/
public final class D3GroupGraphListView extends AbstractD3GraphListView implements AutoRefresh, AbstractTwoLevelTabSetView.ViewRenderedListener {
private final ResourceGroup resourceGroup;
private VLayout graphsVLayout;
private int selectedMeasurementDefinitionId;
public D3GroupGraphListView(ResourceGroup resourceGroup, boolean showAvailability) {
super();
this.resourceGroup = resourceGroup;
this.showAvailabilityGraph = showAvailability;
setOverflow(Overflow.HIDDEN);
}
public D3GroupGraphListView(ResourceGroup resourceGroup, int measurementDefinitionId, boolean showAvailability) {
super();
this.resourceGroup = resourceGroup;
this.selectedMeasurementDefinitionId = measurementDefinitionId;
this.showAvailabilityGraph = showAvailability;
setOverflow(Overflow.HIDDEN);
}
@Override
protected void onDraw() {
super.onDraw();
destroyMembers();
addMember(buttonBarDateTimeRangeEditor);
if (showAvailabilityGraph) {
availabilityGraph = AvailabilityD3GraphView.create(
new AvailabilityOverUnderGraphType(resourceGroup.getId()));
addMember(availabilityGraph);
}
graphsVLayout = new VLayout();
graphsVLayout.setOverflow(Overflow.AUTO);
graphsVLayout.setWidth100();
graphsVLayout.setHeight100();
buildGraphs();
addMember(graphsVLayout);
}
public void refreshData() {
this.onDraw();
}
/**
* Build whatever graph metrics (MeasurementDefinitions) are defined for the resource.
*/
private void buildGraphs() {
queryAvailability(EntityContext.forGroup(resourceGroup), CustomDateRangeState.getInstance().getStartTime(),
CustomDateRangeState.getInstance().getEndTime(), null);
final ArrayList<MeasurementDefinition> measurementDefinitions = new ArrayList<MeasurementDefinition>();
if (resourceGroup.getGroupCategory() == GroupCategory.COMPATIBLE) {
// Load the fully fetched ResourceType.
ResourceType groupType = resourceGroup.getResourceType();
ResourceTypeRepository.Cache.getInstance().getResourceTypes(
groupType.getId(),
EnumSet.of(ResourceTypeRepository.MetadataType.measurements),
new ResourceTypeRepository.TypeLoadedCallback() {
public void onTypesLoaded(ResourceType type) {
resourceGroup.setResourceType(type);
}
});
for (MeasurementDefinition def : resourceGroup.getResourceType().getMetricDefinitions()) {
if (selectedMeasurementDefinitionId == def.getId()){
measurementDefinitions.add(def);
}
}
Collections.sort(measurementDefinitions, new Comparator<MeasurementDefinition>() {
public int compare(MeasurementDefinition o1, MeasurementDefinition o2) {
return new Integer(o1.getDisplayOrder()).compareTo(o2.getDisplayOrder());
}
});
int[] measDefIdArray = new int[measurementDefinitions.size()];
for (int i = 0; i < measDefIdArray.length; i++) {
measDefIdArray[i] = measurementDefinitions.get(i).getId();
}
GWTServiceLookup.getMeasurementDataService().findDataForCompatibleGroup(resourceGroup.getId(), measDefIdArray,
CustomDateRangeState.getInstance().getStartTime(), CustomDateRangeState.getInstance().getEndTime(), 60,
new AsyncCallback<List<List<MeasurementDataNumericHighLowComposite>>>() {
@Override
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_graphs_loadFailed(), caught);
loadingLabel.setContents(MSG.view_resource_monitor_graphs_loadFailed());
}
@Override
public void onSuccess(List<List<MeasurementDataNumericHighLowComposite>> result) {
if (result.isEmpty()) {
loadingLabel.setContents(MSG.view_resource_monitor_graphs_noneAvailable());
} else {
loadingLabel.hide();
int i = 0;
for (List<MeasurementDataNumericHighLowComposite> data : result) {
buildIndividualGraph(measurementDefinitions.get(i++), data);
}
// There is a weird timing case when availabilityGraph can be null
if (availabilityGraph != null) {
availabilityGraph.setGroupAvailabilityList(groupAvailabilityList);
new Timer() {
@Override
public void run() {
availabilityGraph.drawJsniChart();
buttonBarDateTimeRangeEditor.updateTimeRangeToNow();
}
}.schedule(150);
}
}
}
});
}
}
protected void queryAvailability(final EntityContext groupContext, Long startTime, Long endTime,
final CountDownLatch countDownLatch) {
final long timerStart = System.currentTimeMillis();
// now return the availability
GWTServiceLookup.getAvailabilityService().getAvailabilitiesForResourceGroup(groupContext.getGroupId(),
startTime, endTime, new AsyncCallback<List<ResourceGroupAvailability>>() {
@Override
public void onFailure(Throwable caught) {
CoreGUI.getErrorHandler().handleError(MSG.view_resource_monitor_availability_loadFailed(), caught);
if (countDownLatch != null) {
countDownLatch.countDown();
}
}
@Override
public void onSuccess(List<ResourceGroupAvailability> groupAvailList) {
Log.debug("\nSuccessfully queried group availability in: "
+ (System.currentTimeMillis() - timerStart) + " ms.");
groupAvailabilityList = groupAvailList;
if (countDownLatch != null) {
countDownLatch.countDown();
}
}
});
}
@Override
public void onViewRendered() {
refreshData();
}
private void buildIndividualGraph(MeasurementDefinition measurementDefinition,
List<MeasurementDataNumericHighLowComposite> data) {
Log.debug("D3GroupGraphListView.MD: "+measurementDefinition);
MetricGraphData metricGraphData = MetricGraphData.createForResourceGroup(resourceGroup.getId(),
resourceGroup.getName(), measurementDefinition, data);
StackedBarMetricGraphImpl graph = GWT.create(StackedBarMetricGraphImpl.class);
graph.setMetricGraphData(metricGraphData);
graph.setGraphListView(this);
MetricD3Graph graphView = new MetricD3Graph<D3GroupGraphListView>(graph, this);
graphView.setWidth("95%");
graphView.setHeight(MULTI_CHART_HEIGHT);
graphsVLayout.addMember(graphView);
}
}