/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.depgraph;
import java.util.Collection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.opengamma.engine.function.ParameterizedFunction;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.util.tuple.Triple;
/* package */final class ExistingResolutionsStep extends FunctionApplicationStep implements ResolvedValueCallback {
private static final Logger s_logger = LoggerFactory.getLogger(ExistingResolutionsStep.class);
private ResolutionPump _pump;
/**
* Creates a new instance.
* <p>
* The {@code resolvedOutput} parameter must be normalized.
*
* @param task the resolve task this step is part of, not null
* @param base the superclass data, not null
* @param resolved the resolved function information, not null
* @param resolvedOutput the provisional resolved value specification, not null
*/
public ExistingResolutionsStep(final ResolveTask task, final FunctionIterationStep.IterationBaseStep base,
final Triple<ParameterizedFunction, ValueSpecification, Collection<ValueSpecification>> resolved, final ValueSpecification resolvedOutput) {
super(task, base, resolved, resolvedOutput);
}
@Override
public void failed(final GraphBuildingContext context, final ValueRequirement value, final ResolutionFailure failure) {
s_logger.debug("Failed to resolve {} from {}", value, this);
// Don't store the failures from trying the existing ones; they might be for different value requirements that we've just piggy-backed onto
// All existing resolutions have been completed, so now try the actual application
setRunnableTaskState(new FunctionApplicationStep(getTask(), getIterationBase(), getResolved(), getResolvedOutput()), context);
}
@Override
public void resolved(final GraphBuildingContext context, final ValueRequirement valueRequirement, final ResolvedValue value, final ResolutionPump pump) {
s_logger.debug("Resolved {} from {}", value, this);
if (pump != null) {
synchronized (this) {
_pump = pump;
}
if (!pushResult(context, value, false)) {
synchronized (this) {
assert _pump == pump;
_pump = null;
}
context.pump(pump);
}
} else {
// We don't have a state to pump as this is the producer's last result, but this isn't the last we'll do
synchronized (this) {
_pump = ResolutionPump.Dummy.INSTANCE;
}
if (!pushResult(context, value, false)) {
context.failed(this, valueRequirement, null);
}
}
}
@Override
public void recursionDetected() {
// No-op
}
@Override
protected void pump(final GraphBuildingContext context) {
final ResolutionPump pump;
synchronized (this) {
pump = _pump;
_pump = null;
}
if (pump == null) {
// Rogue pump -- see PumpingState.finished for an explanation
return;
}
if (pump != ResolutionPump.Dummy.INSTANCE) {
s_logger.debug("Pumping underlying delegate");
context.pump(pump);
} else {
// All existing resolutions have been completed, so now try the actual application
setRunnableTaskState(new FunctionApplicationStep(getTask(), getIterationBase(), getResolved(), getResolvedOutput()), context);
}
}
@Override
protected void discard(final GraphBuildingContext context) {
final ResolutionPump pump;
synchronized (this) {
pump = _pump;
_pump = null;
}
if (pump != null) {
context.close(pump);
}
}
@Override
public String toString() {
return "EXISTING_RESOLUTIONS" + getObjectId();
}
}