package com.ibm.nmon.data.transform;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.ibm.nmon.data.DataType;
import com.ibm.nmon.data.SubDataType;
/**
* <p>
* Changes Windows Perfmon data from Bytes to KB for system, network and disk data and MB for
* memory.
* </p>
* <p>
* This class maintains state internally, so {@link #reset()} should be called after parsing a
* particular file.
* <p>
*/
public class WindowsBytesTransform implements DataTransform {
private static final Matcher VALID_TYPES = Pattern.compile(
"LogicalDisk.*|PhysicalDisk.*|Network Interface.*|Memory|System").matcher("");
// match all Bytes, but not KBytes or MBytes
private static final Matcher VALID_FIELDS = Pattern.compile("(.*?[^KM])?Bytes(.*)").matcher("");
private Map<String, Set<Integer>> changedFields = new java.util.HashMap<String, Set<Integer>>();
@Override
public DataType buildDataType(String id, String subId, String name, String... fields) {
Set<Integer> changes = new java.util.HashSet<Integer>(fields.length);
for (int i = 0; i < fields.length; i++) {
VALID_FIELDS.reset(fields[i]);
if (VALID_FIELDS.matches()) {
if ("Memory".equals(id)) {
fields[i] = VALID_FIELDS.replaceAll("$1MB$2");
}
else {
fields[i] = VALID_FIELDS.replaceAll("$1KB$2");
}
changes.add(i);
}
}
changedFields.put(name, changes);
if (subId != null) {
return new SubDataType(id, subId, name, fields);
}
else {
return new DataType(id, name, fields);
}
}
@Override
public double[] transform(DataType type, double[] data) {
Set<Integer> changes = changedFields.get(type.getName());
if (changes != null) {
for (int i = 0; i < data.length; i++) {
if (changes.contains(i)) {
if ("Memory".equals(type.getId())) {
data[i] /= 1024 * 1024;
}
else {
data[i] /= 1024;
}
}
}
}
return data;
}
@Override
public boolean isValidFor(String typeId, String subId) {
return VALID_TYPES.reset(typeId).matches();
}
public void reset() {
changedFields.clear();
}
}