/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.target.resolver;
import com.opengamma.core.change.ChangeManager;
import com.opengamma.core.change.PassthroughChangeManager;
import com.opengamma.engine.target.ComputationTargetTypeMap;
import com.opengamma.engine.target.logger.ResolutionLogger;
import com.opengamma.id.UniqueId;
import com.opengamma.id.UniqueIdentifiable;
import com.opengamma.id.VersionCorrection;
import com.opengamma.util.function.BinaryOperator;
/**
* {@link ObjectResolver} implementation that will use a sequence of resolvers in turn if the first fails.
*
* @param <T> the type to be resolved
*/
public class ChainedResolver<T extends UniqueIdentifiable> implements ObjectResolver<T> {
private static final class ChainedDeepResolver implements DeepResolver {
private final DeepResolver _first;
private final DeepResolver _second;
public ChainedDeepResolver(final DeepResolver first, final DeepResolver second) {
_first = first;
_second = second;
}
// DeepResolver
@Override
public UniqueIdentifiable withLogger(final UniqueIdentifiable underlying, final ResolutionLogger logger) {
UniqueIdentifiable result = _first.withLogger(underlying, logger);
if (result == null) {
result = _second.withLogger(underlying, logger);
}
return result;
}
}
private final ObjectResolver<? extends T> _first;
private final ObjectResolver<? extends T> _second;
private final DeepResolver _deep;
public ChainedResolver(final ObjectResolver<? extends T> first, final ObjectResolver<? extends T> second) {
_first = first;
_second = second;
DeepResolver firstDeep = first.deepResolver();
DeepResolver secondDeep = second.deepResolver();
if (firstDeep != null) {
if (secondDeep != null) {
_deep = new ChainedDeepResolver(firstDeep, secondDeep);
} else {
_deep = firstDeep;
}
} else {
_deep = secondDeep;
}
}
protected ObjectResolver<? extends T> getFirst() {
return _first;
}
protected ObjectResolver<? extends T> getSecond() {
return _second;
}
@Override
public T resolveObject(final UniqueId uniqueId, final VersionCorrection versionCorrection) {
T value = getFirst().resolveObject(uniqueId, versionCorrection);
if (value == null) {
value = getSecond().resolveObject(uniqueId, versionCorrection);
}
return value;
}
@Override
public ChangeManager changeManager() {
return new PassthroughChangeManager(getFirst(), getSecond());
}
@Override
public DeepResolver deepResolver() {
return _deep;
}
/**
* Utility function for creating a chain of resolvers, for example when adding them to a {@link ComputationTargetTypeMap}. The first parameter is the second resolver to use (the existing one in the
* map), the second parameter is the first resolver (the new value to the map). The returned value is the resolver chain.
*/
public static final BinaryOperator<ObjectResolver<?>> CREATE = new BinaryOperator<ObjectResolver<?>>() {
@SuppressWarnings({"rawtypes", "unchecked" })
@Override
public ObjectResolver<?> apply(final ObjectResolver<?> second, final ObjectResolver<?> first) {
return new ChainedResolver(first, second);
}
};
}