[/code][code="java"]
Dashbord中的Generic Sample Rule用的是[b]FieldToValueRule.class[/b][FTVR],该类有几个很重要的方法,getExtractedKeys、calculateKpi,我们先来看getExtractedKeys方法
protected Object[] getExtractedKeys(RuleNode ruleNode, RuleDimension ruleDimension) {
// Find the name of the value field
Object valueField = ruleDimension.getInputParameter(INPUT_PARAM_KEY_VALUE_FIELD);
if (valueField == null) {
log.error("getExtractedKeys: no " + INPUT_PARAM_KEY_VALUE_FIELD +
" is defined for " + ruleNode.getID());
return new Object[]{};
}
if (!(valueField instanceof String)) {
log.error("getExtractedKeys: " + INPUT_PARAM_KEY_VALUE_FIELD +
" for " + ruleNode.getID() + " is not defined as a String.");
return new Object[]{};
}
log.debug("getExtractedKeys: input param " + INPUT_PARAM_KEY_VALUE_FIELD +
"[" + valueField + "]");
// Extract this field
String valueFieldStr = (String) valueField;
return new String[]{valueFieldStr};
}
由代码我们可以得知,改方法是从Kpi的页面输入参数 Field Name中提取值,并通过包装成String[]返回,该方法返回的数组一般只有一个元素,即我们需要从sample获得的值key,如Object[]={dValue}
显然得到了keys过后,我们就需要到sample中取得对应的values,如何得到values呢?
在的父类LeafRule的方法extractSample中
protected ExtractedSample extractSample(RuleNode node, RuleDimension kpi, SampleWrapper rawSample)
{
Object[] extractedKeys = getExtractedKeys(node, kpi);
Object[] sampleData = new Object[extractedKeys.length];
for (int i = 0; i < extractedKeys.length; ++i) {
Object key = extractedKeys[i];
sampleData[i] = rawSample.getValue(key);
}
long timeStampValue = getTimeStamp(node, kpi, rawSample);
return new ExtractedSample(sampleData, timeStampValue);
}
我们可以看到,这里调用了getExtractedKeys,并利用getExtractedKeys返回的keys,从sample中获得真正的values,最后把values赋给ExtractedSample对象。所以,ExtractedSample对象就保存了某个sample中我们感兴趣的value(一般情况下只有一个value)。
value有了,我们是不是就可以进行计算了呢? 显然不是的,因为在kpi的selector进行过滤的时候,可能存在几个满足过滤条件的sample,所以我们这里也应该有多个ExtractedSample才对。原来在LeafRule中还有一个processSamples方法
该方法太长了,就不贴了。在改方法中有一段
ExtractedSampleContainer extractedSamples = new ExtractedSampleContainer();
while (iterator.hasNext()) {
SampleWrapper rawSample = iterator.next();
ExtractedSample sample = extractSample(node, kpi, rawSample);
if ((sample.getTimeStamp() != 0L) && (access.getDataEndTime() / sample.getTimeStamp() > 900L)) {
log.error(MessageRepository.getMessage("120729"));
}
extractedSamples.add(sample);
}
这段代码中的iterator就是所有同时满足过滤条件的sample。所以BAC会先遍历这个iterator,对里面的每个sample都建立一个ExtractedSample ,并保存到ExtractedSampleContainer 中,备用 :lol:
最后,ExtractedSampleContainer 被当做参数传递给FTVR的calculateKpi方法。
protected void calculateKpi(RuleTrinityModelAccess access, RuleNode node,
RuleDimension kpi, ExtractedSampleContainer sampleContainer) {
// current kpi's objective
RuleObjective curObjective = getDashboardObjective(kpi);
if (sampleContainer == null || sampleContainer.size() == 0) {
log.debug("EMPTY samples container");
return;
}
/* the last sample */
ExtractedSample sample = sampleContainer.get(0);
/* the sample's value */
double value = 0;
Object fieldValue = sample.getValue(iKEY_VALUE_FIELD);
if (!(fieldValue instanceof Number)) {
Object fieldName = kpi
.getInputParameter(INPUT_PARAM_KEY_VALUE_FIELD);
log.error("FieldToValueRule: value for sample field[" + fieldName
+ "]" + " is not a Number. Aborting");
return;
}
if (fieldValue == null) {
Object fieldName = kpi
.getInputParameter(INPUT_PARAM_KEY_VALUE_FIELD);
log.error("FieldToValueRule: value for sample field[" + fieldName
+ "] null." + " - sets value to null");
} else {
value = ((Number) fieldValue).doubleValue();
}
log.debug("calculateKpi: sets value to " + value);
setResultData(access, node, kpi, curObjective,
DashboardRulesConstants.RESULT_VALUE, new Double(value));
}
在该方法中先取得ExtractedSampleContainer中的第一个ExtractedSample,然后从ExtractedSample中取得第一个value,该value也就是我们在前面所保存的value。
然后判断value是否为数字,如果不是数字那么就丢弃,所以在界面上就会看见“暂缺”。若果是数字,那么就展示出来。
可能分析得不是很精确,不过大体的原理就是这样的了。