/*
|
* CDDL HEADER START
|
*
|
* The contents of this file are subject to the terms of the
|
* Common Development and Distribution License, Version 1.0 only
|
* (the "License"). You may not use this file except in compliance
|
* with the License.
|
*
|
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
|
* or http://forgerock.org/license/CDDLv1.0.html.
|
* See the License for the specific language governing permissions
|
* and limitations under the License.
|
*
|
* When distributing Covered Code, include this CDDL HEADER in each
|
* file and include the License file at legal-notices/CDDLv1_0.txt.
|
* If applicable, add the following below this CDDL HEADER, with the
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
* information:
|
* Portions Copyright [yyyy] [name of copyright owner]
|
*
|
* CDDL HEADER END
|
*
|
*
|
* Copyright 2009-2010 Sun Microsystems, Inc.
|
*/
|
package org.opends.guitools.controlpanel.datamodel;
|
|
import static org.opends.messages.AdminToolMessages.*;
|
|
import java.util.ArrayList;
|
import java.util.Collection;
|
import java.util.Comparator;
|
import java.util.HashSet;
|
import java.util.LinkedHashSet;
|
import java.util.Set;
|
import java.util.TreeSet;
|
|
import org.opends.guitools.controlpanel.util.Utilities;
|
import org.opends.messages.Message;
|
|
/**
|
* The abstract table model used to display all the network groups.
|
* @param <T> the type of the objects passed externally to the table model.
|
* @param <P> the type of the objects used internally by the table model.
|
*/
|
public abstract class MonitoringTableModel<T, P> extends SortableTableModel
|
implements Comparator<P>
|
{
|
private static final long serialVersionUID = -3974562860632179025L;
|
private Set<P> data = new HashSet<P>();
|
private ArrayList<String[]> dataArray = new ArrayList<String[]>();
|
private ArrayList<P> dataSourceArray = new ArrayList<P>();
|
private boolean showAverages;
|
private long runningTime;
|
|
private String[] columnNames = {};
|
private Message NO_VALUE_SET = INFO_CTRL_PANEL_NO_MONITORING_VALUE.get();
|
private Message NOT_IMPLEMENTED = INFO_CTRL_PANEL_NOT_IMPLEMENTED.get();
|
|
|
/**
|
* The attributes to be displayed.
|
*/
|
private LinkedHashSet<MonitoringAttributes> attributes =
|
new LinkedHashSet<MonitoringAttributes>();
|
/**
|
* The sort column of the table.
|
*/
|
private int sortColumn = 0;
|
/**
|
* Whether the sorting is ascending or descending.
|
*/
|
private boolean sortAscending = true;
|
|
/**
|
* Indicates whether a total row must be added or not. The default behavior
|
* is to add it.
|
* @return <CODE>true</CODE> if a total row must be added and
|
* <CODE>false</CODE> otherwise.
|
*/
|
protected boolean addTotalRow()
|
{
|
return true;
|
}
|
|
/**
|
* Sets the data for this table model.
|
* @param newData the data for this table model.
|
* @param runningTime the running time of the server in miliseconds.
|
*/
|
public void setData(Set<T> newData, long runningTime)
|
{
|
this.runningTime = runningTime;
|
Set<P> newInternalData = convertToInternalData(newData);
|
|
// When we show the averages, the data displayed changes (even if the
|
// monitoring data has not).
|
if (!newInternalData.equals(data) || showAverages)
|
{
|
data.clear();
|
data.addAll(newInternalData);
|
updateDataArray();
|
fireTableDataChanged();
|
}
|
}
|
|
/**
|
* Updates the table model contents and sorts its contents depending on the
|
* sort options set by the user.
|
*/
|
public void forceResort()
|
{
|
updateDataArray();
|
fireTableDataChanged();
|
}
|
|
/**
|
* Updates the table model contents, sorts its contents depending on the
|
* sort options set by the user and updates the column structure.
|
*/
|
public void forceDataStructureChange()
|
{
|
updateDataArray();
|
fireTableStructureChanged();
|
fireTableDataChanged();
|
}
|
|
/**
|
* {@inheritDoc}
|
*/
|
public int getColumnCount()
|
{
|
return columnNames.length;
|
}
|
|
/**
|
* {@inheritDoc}
|
*/
|
public int getRowCount()
|
{
|
return dataArray.size();
|
}
|
|
/**
|
* {@inheritDoc}
|
*/
|
public Object getValueAt(int row, int col)
|
{
|
return dataArray.get(row)[col];
|
}
|
|
/**
|
* {@inheritDoc}
|
*/
|
public String getColumnName(int col) {
|
return columnNames[col];
|
}
|
|
/**
|
* Returns whether the sort is ascending or descending.
|
* @return <CODE>true</CODE> if the sort is ascending and <CODE>false</CODE>
|
* otherwise.
|
*/
|
public boolean isSortAscending()
|
{
|
return sortAscending;
|
}
|
|
/**
|
* Sets whether to sort ascending of descending.
|
* @param sortAscending whether to sort ascending or descending.
|
*/
|
public void setSortAscending(boolean sortAscending)
|
{
|
this.sortAscending = sortAscending;
|
}
|
|
/**
|
* Returns the column index used to sort.
|
* @return the column index used to sort.
|
*/
|
public int getSortColumn()
|
{
|
return sortColumn;
|
}
|
|
/**
|
* Sets the column index used to sort.
|
* @param sortColumn column index used to sort..
|
*/
|
public void setSortColumn(int sortColumn)
|
{
|
this.sortColumn = sortColumn;
|
}
|
|
/**
|
* Returns the attributes displayed by this table model.
|
* @return the attributes displayed by this table model.
|
*/
|
public Collection<MonitoringAttributes> getAttributes()
|
{
|
return attributes;
|
}
|
|
/**
|
* Returns the header to be used for the name of the object.
|
* @return the header to be used for the name of the object.
|
*/
|
protected abstract Message getNameHeader();
|
|
/**
|
* Sets the operations displayed by this table model.
|
* @param attributes the attributes displayed by this table model.
|
* @param showAverages whether the averages (when makes sense) should be
|
* displayed or not.
|
*/
|
public void setAttributes(LinkedHashSet<MonitoringAttributes> attributes,
|
boolean showAverages)
|
{
|
this.showAverages = showAverages;
|
this.attributes.clear();
|
this.attributes.addAll(attributes);
|
int columnCount = attributes.size() + 1;
|
if (showAverages)
|
{
|
for (MonitoringAttributes attr : attributes)
|
{
|
if (attr.canHaveAverage())
|
{
|
columnCount ++;
|
}
|
}
|
}
|
columnNames = new String[columnCount];
|
columnNames[0] = getHeader(getNameHeader());
|
int i = 1;
|
for (MonitoringAttributes attribute : attributes)
|
{
|
columnNames[i] = getHeader(attribute.getMessage(), 15);
|
if (showAverages && attribute.canHaveAverage())
|
{
|
i++;
|
columnNames[i] = getAverageHeader(attribute);
|
}
|
i++;
|
}
|
}
|
|
/**
|
* Updates the array data. This includes resorting it.
|
*/
|
private void updateDataArray()
|
{
|
TreeSet<P> sortedSet = new TreeSet<P>(this);
|
sortedSet.addAll(data);
|
dataArray.clear();
|
dataSourceArray.clear();
|
for (P ach : sortedSet)
|
{
|
String[] s = getLine(ach);
|
dataArray.add(s);
|
dataSourceArray.add(ach);
|
}
|
|
// Add the total: always at the end
|
if (addTotalRow())
|
{
|
String[] line = new String[columnNames.length];
|
line[0] = "<html><b>"+INFO_CTRL_PANEL_TOTAL_LABEL.get().toString()+
|
"</b>";
|
for (int i=1; i<line.length; i++)
|
{
|
boolean valueSet = false;
|
boolean notImplemented = false;
|
long totalValue = 0;
|
for (int j=0; j<dataArray.size(); j++)
|
{
|
String[] l = dataArray.get(j);
|
String value = l[i];
|
try
|
{
|
long v = Long.parseLong(value);
|
totalValue += v;
|
valueSet = true;
|
}
|
catch (Throwable t)
|
{
|
notImplemented = NOT_IMPLEMENTED.toString().equals(value);
|
}
|
}
|
if (notImplemented)
|
{
|
line[i] = NOT_IMPLEMENTED.toString();
|
}
|
else if (valueSet)
|
{
|
line[i] = String.valueOf(totalValue);
|
}
|
else
|
{
|
line[i] = NO_VALUE_SET.toString();
|
}
|
}
|
dataArray.add(line);
|
}
|
}
|
|
/**
|
* {@inheritDoc}
|
*/
|
protected String[] getColumnNames()
|
{
|
return columnNames;
|
}
|
|
/**
|
* Converts the provided data into internal data to be used by the table
|
* model.
|
* @param o the set of objects to convert.
|
* @return the set of objects to be used by the table model.
|
*/
|
protected abstract Set<P> convertToInternalData(Set<T> o);
|
|
/**
|
* Returns the label to be used for the provided internal object.
|
* @param o the internal object.
|
* @return the label to be used for the provided internal object.
|
*/
|
protected abstract String getName(P o);
|
|
/**
|
* Returns the monitoring entry associated with the provided object.
|
* @param o the internal object.
|
* @return the monitoring entry associated with the provided object. Returns
|
* <CODE>null</CODE> if there is no monitoring entry associated.
|
*/
|
protected abstract CustomSearchResult getMonitoringEntry(P o);
|
|
private String[] getLine(P o)
|
{
|
String[] line = new String[columnNames.length];
|
line[0] = getName(o);
|
int i = 1;
|
CustomSearchResult monitoringEntry = getMonitoringEntry(o);
|
for (MonitoringAttributes attribute : attributes)
|
{
|
line[i] = Utilities.getMonitoringValue(
|
attribute, monitoringEntry);
|
if (showAverages && attribute.canHaveAverage())
|
{
|
i++;
|
try
|
{
|
if (runningTime > 0)
|
{
|
long v = Long.parseLong(line[i - 1]);
|
long average = (1000 * v) / runningTime;
|
String s = String.valueOf(average);
|
int index = s.indexOf(".");
|
// Show a maximum of two decimals.
|
if ((index != -1) && ((index + 3) < s.length()))
|
{
|
s = s.substring(0, index + 3);
|
}
|
line[i] = s;
|
}
|
else
|
{
|
line[i] = NO_VALUE_SET.toString();
|
}
|
}
|
catch (Throwable t)
|
{
|
line[i] = NO_VALUE_SET.toString();
|
}
|
}
|
i++;
|
}
|
return line;
|
}
|
|
/**
|
* Returns the String to be used as header on the table to display the average
|
* for a given monitoring attribute.
|
* @param attr the monitoring attribute.
|
* @return the String to be used as header on the table to display the average
|
* for a given monitoring attribute.
|
*/
|
private String getAverageHeader(MonitoringAttributes attr)
|
{
|
return getHeader(INFO_CTRL_PANEL_AVERAGE_HEADER.get(
|
attr.getMessage().toString()), 15);
|
}
|
|
/**
|
* Returns the first value for a given attribute in the provided entry.
|
* @param sr the entry.
|
* @param attrName the attribute name.
|
* @return the first value for a given attribute in the provided entry.
|
*/
|
protected Object getFirstMonitoringValue(CustomSearchResult sr,
|
String attrName)
|
{
|
return Utilities.getFirstMonitoringValue(sr, attrName);
|
}
|
|
/**
|
* Returns a list of integer with all the values of two monitoring entries
|
* compared.
|
* @param monitor1 the first monitoring entry.
|
* @param monitor2 the second monitoring entry.
|
* @return a list of integer with all the values of two monitoring entries
|
* compared.
|
*/
|
protected ArrayList<Integer> getMonitoringPossibleResults(
|
CustomSearchResult monitor1, CustomSearchResult monitor2)
|
{
|
ArrayList<Integer> possibleResults = new ArrayList<Integer>();
|
for (MonitoringAttributes operation : getAttributes())
|
{
|
int possibleResult;
|
if (monitor1 == null)
|
{
|
if (monitor2 == null)
|
{
|
possibleResult = 0;
|
}
|
else
|
{
|
possibleResult = -1;
|
}
|
}
|
else if (monitor2 == null)
|
{
|
possibleResult = 1;
|
}
|
else
|
{
|
Object v1 = null;
|
Object v2 = null;
|
|
for (String attrName : monitor1.getAttributeNames())
|
{
|
if (operation.getAttributeName().equalsIgnoreCase(attrName))
|
{
|
v1 = getFirstMonitoringValue(monitor1, attrName);
|
break;
|
}
|
}
|
for (String attrName : monitor2.getAttributeNames())
|
{
|
if (operation.getAttributeName().equalsIgnoreCase(attrName))
|
{
|
v2 = getFirstMonitoringValue(monitor2, attrName);
|
break;
|
}
|
}
|
|
if (v1 == null)
|
{
|
if (v2 == null)
|
{
|
possibleResult = 0;
|
}
|
else
|
{
|
possibleResult = -1;
|
}
|
}
|
else if (v2 == null)
|
{
|
possibleResult = 1;
|
}
|
else
|
{
|
if (v1 instanceof Number)
|
{
|
if (v2 instanceof Number)
|
{
|
if ((v1 instanceof Double) || (v2 instanceof Double))
|
{
|
double n1 = ((Number)v1).doubleValue();
|
double n2 = ((Number)v2).doubleValue();
|
if (n1 > n2)
|
{
|
possibleResult = 1;
|
}
|
else if (n1 < n2)
|
{
|
possibleResult = -1;
|
}
|
else
|
{
|
possibleResult = 0;
|
}
|
}
|
else
|
{
|
long n1 = ((Number)v1).longValue();
|
long n2 = ((Number)v2).longValue();
|
if (n1 > n2)
|
{
|
possibleResult = 1;
|
}
|
else if (n1 < n2)
|
{
|
possibleResult = -1;
|
}
|
else
|
{
|
possibleResult = 0;
|
}
|
}
|
}
|
else
|
{
|
possibleResult = 1;
|
}
|
}
|
else if (v2 instanceof Number)
|
{
|
possibleResult = -1;
|
}
|
else
|
{
|
possibleResult = v1.toString().compareTo(v2.toString());
|
}
|
}
|
}
|
possibleResults.add(possibleResult);
|
}
|
return possibleResults;
|
}
|
}
|