package com.ibm.nmon.data;
import java.util.TreeMap;
import java.util.Set;
import com.ibm.nmon.interval.Interval;
/**
* <p>
* A container for all the data in a single parsed file.
* </p>
*
* <p>
* A data set will define a set of DataTypes and span some number of time intervals. For each
* interval, there will a single DataRecord. Each record will contain at least one DataType with an
* associated array of values.
* </p>
*
* Conceptually, the structure is as follows:
*
* <pre>
* DataSet
* time 1
* DataRecord
* DataType a
* value 1
* value 2
* ...
* value n
* DataType b
* value 1
* value 2
* ...
* value n
* ...
* DataType x
* time 2
* DataRecord
* DataType a
* value 1
* value 2
* ...
* value n
* DataType b
* value 1
* value 2
* ...
* value n
* ...
* DataType x
* ...
* time n
* </pre>
*/
public abstract class DataSet implements Comparable<DataSet> {
private final TreeMap<String, DataType> dataTypes = new TreeMap<String, DataType>();
// associate data with each timestamp
private final TreeMap<Long, DataRecord> data = new TreeMap<Long, DataRecord>();
public abstract String getHostname();
public abstract void setHostname(String hostname);
public abstract String getSourceFile();
public final void addType(DataType type) {
if (type != null) {
if (dataTypes.containsKey(type.getId())) {
throw new IllegalArgumentException("cannot redefine DataType " + type.getId()
+ " within the same data set");
}
else {
dataTypes.put(type.getId(), type);
}
}
}
// callers are responsible fore removing the type with any associated DataRecords
final void removeType(DataType type) {
if (type != null) {
dataTypes.remove(type.getId());
}
}
public final boolean containsType(String typeId) {
return dataTypes.containsKey(typeId);
}
public final DataType getType(String typeId) {
return dataTypes.get(typeId);
}
/**
* @return all the DataTypes defined in this data set
*/
public final Iterable<DataType> getTypes() {
return java.util.Collections.unmodifiableCollection(dataTypes.values());
}
public final int getTypeCount() {
return dataTypes.size();
}
public final void addRecord(DataRecord record) {
if (record != null) {
data.put(record.getTime(), record);
}
}
/**
* @return the number of DataRecords in this data set.
*/
public final int getRecordCount() {
return data.size();
}
public final int getRecordCount(Interval interval) {
if (Interval.DEFAULT.equals(interval)) {
return data.size();
}
else {
return data.subMap(interval.getStart(), true, interval.getEnd(), true).size();
}
}
public final DataRecord getRecord(long time) {
return data.get(time);
}
/**
* @return all the DataRecords in this data set, sorted by time, earliest first.
*/
public final Iterable<DataRecord> getRecords() {
return java.util.Collections.unmodifiableCollection(data.values());
}
public final Iterable<DataRecord> getRecords(Interval interval) {
if (Interval.DEFAULT.equals(interval)) {
return java.util.Collections.unmodifiableCollection(data.values());
}
else {
return java.util.Collections.unmodifiableCollection(data.subMap(interval.getStart(), true,
interval.getEnd(), true).values());
}
}
/**
* @return all the timestamps recorded by this data set.
*/
public final Set<Long> getTimes() {
return java.util.Collections.unmodifiableSet(data.keySet());
}
public final long getStartTime() {
return data.firstKey();
}
public final long getEndTime() {
return data.size() == 0 ? Long.MIN_VALUE : data.lastKey();
}
public final void adjustTimes(long adjustmentMillis) {
if (adjustmentMillis == 0) {
return;
}
// recreate the data using the new times
TreeMap<Long, DataRecord> newData = new TreeMap<Long, DataRecord>();
for (long time : data.keySet()) {
DataRecord record = data.get(time);
record.adjustTime(adjustmentMillis);
newData.put(time + adjustmentMillis, record);
}
// data is final, so recopy it back
data.clear();
data.putAll(newData);
}
@Override
public final String toString() {
return getHostname();
}
@Override
public final int hashCode() {
return (getHostname() + '|' + getStartTime() + '|' + getEndTime()).hashCode();
}
@Override
public final boolean equals(Object obj) {
if (obj == this) {
return true;
}
else if (obj instanceof DataSet) {
DataSet data = (DataSet) obj;
return this.getHostname().equals(data.getHostname()) && (this.getStartTime() == data.getStartTime())
&& (this.getEndTime() == data.getEndTime());
}
else {
return false;
}
}
@Override
public final int compareTo(DataSet f) {
int compare = this.getHostname().compareTo(f.getHostname());
if (compare == 0) {
if (this.data.isEmpty() && this.data.isEmpty()) {
return 0;
}
else if (this.getStartTime() == f.getStartTime()) {
if (this.getEndTime() == f.getEndTime()) {
return 0;
}
else {
return this.getEndTime() > f.getEndTime() ? 1 : -1;
}
}
else {
return this.getStartTime() > f.getStartTime() ? 1 : -1;
}
}
else {
return compare;
}
}
}