/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.core.link;
import java.io.Serializable;
import com.opengamma.DataNotFoundException;
import com.opengamma.core.Source;
import com.opengamma.id.VersionCorrection;
import com.opengamma.service.ServiceContext;
import com.opengamma.service.ThreadLocalServiceContext;
import com.opengamma.service.VersionCorrectionProvider;
import com.opengamma.util.ArgumentChecker;
/**
* Responsible for performing the resolve operation of a link using
* an appropriate {@link Source} instance.
*
* @param <I> the type of the identifier used by the resolver
* @param <T> the type of object provided by the resolver
* @param <S> the source used to resolve the link
*/
/* package */ abstract class SourceLinkResolver<I, T, S extends Source<?>> implements LinkResolver<I, T> , Serializable {
/**
* The specific service context to be used to look up service providers.
* May be null in which case a thread-local context will be used.
*/
private final ServiceContext _serviceContext;
/**
* Create the link resolver.
*
* @param serviceContext the context to use for service-providers, not null.
*/
/* package */ SourceLinkResolver(ServiceContext serviceContext) {
_serviceContext = ArgumentChecker.notNull(serviceContext, "serviceContext");
}
/* package */ SourceLinkResolver() {
_serviceContext = null;
}
private <R> R lookupService(Class<R> serviceClass) {
return getServiceContext().get(serviceClass);
}
@Override
public T resolve(LinkIdentifier<I, T> identifier) {
VersionCorrectionProvider vcProvider = lookupService(VersionCorrectionProvider.class);
S source = lookupService(getSourceClass());
return executeQuery(source, identifier.getType(), identifier.getIdentifier(), getVersionCorrection(vcProvider));
}
/**
* Return a service context. If one has been supplied to the class then it will
* be used, else the {@link ThreadLocalServiceContext} will be used. If no context
* can be found an exception will be thrown.
*
* @return a service context, if available
* @throws IllegalStateException if no context is available
*/
private ServiceContext getServiceContext() {
ServiceContext serviceContext = _serviceContext;
if (serviceContext == null) {
serviceContext = ThreadLocalServiceContext.getInstance();
if (serviceContext == null) {
throw new IllegalStateException("No service context found for use by the current thread");
}
}
return serviceContext;
}
//-------------------------------------------------------------------------
/**
* Get the {@link Source} class to be used to resolve the link target.
*
* @return the appropriate Source class, not null
*/
protected abstract Class<S> getSourceClass();
/**
* Get the VersionCorrection to be used during the link resolution.
* It is expected, but not required, that the supplied VersionCorrectionProvider is used.
*
* @param vcProvider the version correction provider (retrieved from the service context), not null
* @return the VersionCorrection to be used, not null
*/
protected abstract VersionCorrection getVersionCorrection(VersionCorrectionProvider vcProvider);
/**
* Execute a query against the source to retrieve the target of the link.
*
* @param source the source to retrieve the object from, not null
* @param versionCorrection the version correction to be used during the query, not null
* @return the target of the link
* @throws DataNotFoundException if the link is not resolved
*/
protected abstract T executeQuery(S source, Class<T> type, I identifier, VersionCorrection versionCorrection);
}