/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.view.client;
import java.util.Map;
import org.apache.commons.lang.ObjectUtils;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.value.ComputedValueResult;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.view.DeltaDefinition;
import com.opengamma.engine.view.ViewCalculationResultModel;
import com.opengamma.engine.view.ViewComputationResultModel;
import com.opengamma.engine.view.ViewDefinition;
import com.opengamma.engine.view.ViewDeltaResultModel;
import com.opengamma.engine.view.ViewResultModel;
import com.opengamma.engine.view.impl.InMemoryViewDeltaResultModel;
import com.opengamma.util.tuple.Pair;
/**
* Produces {@link ViewDeltaResultModel} instances by comparing two {@link ViewComputationResultModel}.
*/
public class ViewDeltaResultCalculator {
/**
* Computes the delta between and old and new results.
*
* @param viewDefinition the view definition to which the results apply
* @param previousResult the previous result
* @param result the new result
* @return the delta between the two results, not null
*/
public static ViewDeltaResultModel computeDeltaModel(ViewDefinition viewDefinition, ViewResultModel previousResult, ViewResultModel result) {
InMemoryViewDeltaResultModel deltaModel = new InMemoryViewDeltaResultModel();
deltaModel.setViewCycleExecutionOptions(result.getViewCycleExecutionOptions());
deltaModel.setCalculationTime(result.getCalculationTime());
deltaModel.setCalculationDuration(result.getCalculationDuration());
deltaModel.setVersionCorrection(result.getVersionCorrection());
deltaModel.setViewCycleId(result.getViewCycleId());
deltaModel.setViewProcessId(result.getViewProcessId());
if (previousResult != null) {
deltaModel.setPreviousCalculationTime(previousResult.getCalculationTime());
}
for (String calcConfigName : result.getCalculationConfigurationNames()) {
final DeltaDefinition deltaDefinition = viewDefinition.getCalculationConfiguration(calcConfigName).getDeltaDefinition();
final ViewCalculationResultModel resultCalcModel = result.getCalculationResult(calcConfigName);
final ViewCalculationResultModel previousCalcModel = previousResult != null ? previousResult.getCalculationResult(calcConfigName) : null;
for (ComputationTargetSpecification targetSpec : resultCalcModel.getAllTargets()) {
computeDeltaModel(deltaDefinition, deltaModel, targetSpec, calcConfigName, previousCalcModel, resultCalcModel);
}
}
return deltaModel;
}
private static void computeDeltaModel(DeltaDefinition deltaDefinition, InMemoryViewDeltaResultModel deltaModel, ComputationTargetSpecification targetSpec,
String calcConfigName, ViewCalculationResultModel previousCalcModel, ViewCalculationResultModel resultCalcModel) {
final Map<Pair<String, ValueProperties>, ComputedValueResult> resultValues = resultCalcModel.getValues(targetSpec);
if (resultValues != null) {
if (previousCalcModel == null) {
// Everything is new/delta because this is a new calculation context.
for (Map.Entry<Pair<String, ValueProperties>, ComputedValueResult> resultEntry : resultValues.entrySet()) {
deltaModel.addValue(calcConfigName, resultEntry.getValue());
}
} else {
final Map<Pair<String, ValueProperties>, ComputedValueResult> previousValues = previousCalcModel.getValues(targetSpec);
if (previousValues == null) {
// Everything is new/delta because this is a new target.
for (ComputedValueResult result : resultValues.values()) {
deltaModel.addValue(calcConfigName, result);
}
} else {
// Have to individual delta.
for (Map.Entry<Pair<String, ValueProperties>, ComputedValueResult> resultEntry : resultValues.entrySet()) {
ComputedValueResult resultValue = resultEntry.getValue();
ComputedValueResult previousValue = previousValues.get(resultEntry.getKey());
// REVIEW jonathan 2010-05-07 -- The previous value that we're comparing with is the value from the last
// computation cycle, not the value that we last emitted as a delta. It is therefore important that the
// DeltaComparers take this into account in their implementation of isDelta. E.g. they should compare the
// values after truncation to the required decimal place, rather than testing whether the difference of the
// full values is greater than some threshold; this way, there will always be a point beyond which a change
// is detected, even in the event of gradual creep.
if (deltaDefinition.isDelta(previousValue, resultValue) || !ObjectUtils.equals(previousValue.getAggregatedExecutionLog(), resultValue.getAggregatedExecutionLog())) {
deltaModel.addValue(calcConfigName, resultEntry.getValue());
}
}
}
}
}
}
}