package org.rhq.coregui.client.resource; /* * 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. */ import java.util.HashSet; import java.util.List; import java.util.Map; import com.google.gwt.user.client.rpc.AsyncCallback; import com.smartgwt.client.data.DSRequest; import com.smartgwt.client.data.DSResponse; import com.smartgwt.client.data.DataSourceField; import com.smartgwt.client.data.Record; import com.smartgwt.client.data.fields.DataSourceImageField; import com.smartgwt.client.data.fields.DataSourceTextField; import com.smartgwt.client.rpc.RPCResponse; import com.smartgwt.client.widgets.grid.ListGridField; import com.smartgwt.client.widgets.grid.ListGridRecord; import org.rhq.core.domain.criteria.Criteria; import org.rhq.core.domain.resource.ResourceType; import org.rhq.core.domain.resource.composite.ProblemResourceComposite; import org.rhq.core.domain.util.PageList; import org.rhq.coregui.client.CoreGUI; import org.rhq.coregui.client.ImageManager; import org.rhq.coregui.client.dashboard.Portlet; import org.rhq.coregui.client.dashboard.portlets.recent.problems.ProblemResourcesPortlet; import org.rhq.coregui.client.gwt.GWTServiceLookup; import org.rhq.coregui.client.inventory.resource.AncestryUtil; import org.rhq.coregui.client.inventory.resource.type.ResourceTypeRepository; import org.rhq.coregui.client.inventory.resource.type.ResourceTypeRepository.TypesLoadedCallback; import org.rhq.coregui.client.util.RPCDataSource; /** * Responsible for defining and populating the Smart GWT datasource details and * translating the deserialized content into specific record entries for display * * @author Simeon Pinder * @author Jay Shaughnessy */ public class ProblemResourcesDataSource extends RPCDataSource<ProblemResourceComposite, Criteria> { public enum Field { ALERTS("numAlerts", MSG.common_title_alerts()), AVAILABILITY("availabilityType", MSG.common_title_availability()), RESOURCE("resource", MSG.common_title_resource()); /** * Corresponds to a property name of Resource (e.g. resourceType.name). */ private String propertyName; /** * The table header for the field or property (e.g. Type). */ private String title; private Field(String propertyName, String title) { this.propertyName = propertyName; this.title = title; } public String propertyName() { return propertyName; } public String title() { return title; } public ListGridField getListGridField() { return new ListGridField(propertyName, title); } public ListGridField getListGridField(int width) { return new ListGridField(propertyName, title, width); } } private Portlet portlet = null; private long oldestDate = -1; //configure elements private int maximumProblemResourcesToDisplay = -1; private int maximumProblemResourcesWithinHours = -1; /** * Build list of fields for the datasource and then adds them to it. * @param problemResourcesPortlet */ public ProblemResourcesDataSource(Portlet problemResourcesPortlet) { this.portlet = problemResourcesPortlet; List<DataSourceField> fields = addDataSourceFields(); addFields(fields); } @Override protected List<DataSourceField> addDataSourceFields() { List<DataSourceField> fields = super.addDataSourceFields(); DataSourceTextField alertsField = new DataSourceTextField(Field.ALERTS.propertyName, Field.ALERTS.title()); fields.add(alertsField); DataSourceImageField availabilityField = new DataSourceImageField(Field.AVAILABILITY.propertyName, Field.AVAILABILITY.title(), 20); availabilityField.setCanEdit(false); fields.add(availabilityField); return fields; } @Override protected Criteria getFetchCriteria(DSRequest request) { // we don't use criteria fetch for this datasource, just return null return null; } /** Fetch the ProblemResource data, and populate the response object appropriately. * * @param request incoming request * @param response outgoing response */ public void executeFetch(final DSRequest request, final DSResponse response, final Criteria unused) { long ctime = -1; int maxItems = -1; //retrieve current portlet display settings if ((this.portlet != null) && (this.portlet instanceof ProblemResourcesPortlet)) { ProblemResourcesPortlet problemPortlet = (ProblemResourcesPortlet) this.portlet; //populate criteria with portlet preferences defined. if (problemPortlet != null) { if (getMaximumProblemResourcesToDisplay() > 0) { maxItems = getMaximumProblemResourcesToDisplay(); } //define the time window if (getMaximumProblemResourcesWithinHours() > 0) { ctime = System.currentTimeMillis() - (getMaximumProblemResourcesWithinHours() * 60 * 60 * 1000); setOldestDate(ctime); } } } GWTServiceLookup.getResourceService().findProblemResources(ctime, maxItems, new AsyncCallback<PageList<ProblemResourceComposite>>() { public void onFailure(Throwable throwable) { CoreGUI.getErrorHandler().handleError(MSG.dataSource_problemResources_error_fetchFailure(), throwable); response.setStatus(RPCResponse.STATUS_FAILURE); processResponse(request.getRequestId(), response); } public void onSuccess(PageList<ProblemResourceComposite> result) { dataRetrieved(result, response, request); } }); } protected void dataRetrieved(final PageList<ProblemResourceComposite> result, final DSResponse response, final DSRequest request) { HashSet<Integer> typesSet = new HashSet<Integer>(); HashSet<String> ancestries = new HashSet<String>(); for (ProblemResourceComposite resourceComposite : result) { typesSet.add(resourceComposite.getResourceTypeId()); ancestries.add(resourceComposite.getAncestry()); } // In addition to the types of the result resources, get the types of their ancestry // NOTE: this may be too labor intensive in general, but since this datasource is a singleton I couldn't // make it easily optional. typesSet.addAll(AncestryUtil.getAncestryTypeIds(ancestries)); ResourceTypeRepository typeRepo = ResourceTypeRepository.Cache.getInstance(); typeRepo.getResourceTypes(typesSet.toArray(new Integer[typesSet.size()]), new TypesLoadedCallback() { @Override public void onTypesLoaded(Map<Integer, ResourceType> types) { // Smartgwt has issues storing a Map as a ListGridRecord attribute. Wrap it in a pojo. AncestryUtil.MapWrapper typesWrapper = new AncestryUtil.MapWrapper(types); Record[] records = buildRecords(result); for (Record record : records) { // To avoid a lot of unnecessary String construction, be lazy about building ancestry hover text. // Store the types map off the records so we can build a detailed hover string as needed. record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY_TYPES, typesWrapper); // Build the decoded ancestry Strings now for display record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY_VALUE, AncestryUtil.getAncestryValue(record)); } response.setData(records); // for paging to work we have to specify size of full result set, but if a limit has been set, // respect the limit int resultSize = result.getTotalSize(); if (maximumProblemResourcesToDisplay > 0 && maximumProblemResourcesToDisplay < resultSize) { resultSize = maximumProblemResourcesToDisplay; } response.setTotalRows(resultSize); processResponse(request.getRequestId(), response); } }); } @Override public ListGridRecord copyValues(ProblemResourceComposite from) { ListGridRecord record = new ListGridRecord(); record.setAttribute("id", from.getResourceId()); record.setAttribute(Field.ALERTS.propertyName, from.getNumAlerts()); record.setAttribute(Field.AVAILABILITY.propertyName, ImageManager.getAvailabilityIconFromAvailType(from .getAvailabilityType())); record.setAttribute(Field.RESOURCE.propertyName, from.getResourceName()); // for ancestry handling record.setAttribute(AncestryUtil.RESOURCE_NAME, from.getResourceName()); record.setAttribute(AncestryUtil.RESOURCE_ANCESTRY, from.getAncestry()); record.setAttribute(AncestryUtil.RESOURCE_TYPE_ID, from.getResourceTypeId()); record.setAttribute("entity", from); return record; } @Override public ProblemResourceComposite copyValues(Record from) { throw new UnsupportedOperationException("ProblemResource data is read only"); } public long getOldestDate() { return oldestDate; } public void setOldestDate(long oldestDate) { this.oldestDate = oldestDate; } public int getMaximumProblemResourcesToDisplay() { return maximumProblemResourcesToDisplay; } public void setMaximumProblemResourcesToDisplay(int maxPerRow) { this.maximumProblemResourcesToDisplay = maxPerRow; } public void setMaximumProblemResourcesWithinHours(int maximumProblemResourcesWithinHours) { this.maximumProblemResourcesWithinHours = maximumProblemResourcesWithinHours; } public int getMaximumProblemResourcesWithinHours() { return maximumProblemResourcesWithinHours; } }