/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.depgraph.rest;
import java.net.URI;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;
import org.fudgemsg.FudgeContext;
import org.fudgemsg.FudgeMsgEnvelope;
import org.fudgemsg.MutableFudgeMsg;
import org.fudgemsg.mapping.FudgeSerializer;
import org.threeten.bp.Instant;
import org.threeten.bp.LocalDate;
import com.google.common.annotations.VisibleForTesting;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.marketdata.spec.FixedHistoricalMarketDataSpecification;
import com.opengamma.engine.marketdata.spec.LiveMarketDataSpecification;
import com.opengamma.engine.marketdata.spec.MarketData;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.engine.marketdata.spec.UserMarketDataSpecification;
import com.opengamma.engine.target.ComputationTargetReference;
import com.opengamma.engine.target.ComputationTargetRequirement;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.financial.depgraph.provider.DependencyGraphTraceProvider;
import com.opengamma.id.ExternalId;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.util.rest.AbstractDataResource;
/**
* Expose a simple dependency graph building service over the network for debugging/diagnostic purposes. This is intended to be simple to access using hand written URLs - there is not currently a
* corresponding programatic interface to the service this provides.
* <p>
* For example to find out why a graph building configuration can't satisfy a requirement, a URL such as "/value/Present Value/SECURITY/SecDb~1234" will return the failure trace (or the graph if
* successful).
*/
public final class DependencyGraphTraceProviderResource extends AbstractDataResource {
private final DependencyGraphTraceProvider _provider;
private final FudgeContext _fudgeContext;
private final DependencyGraphTraceBuilderProperties _properties;
public DependencyGraphTraceProviderResource(final DependencyGraphTraceProvider provider, final FudgeContext fudgeContext) {
_fudgeContext = fudgeContext;
_provider = provider;
_properties = new DependencyGraphTraceBuilderProperties();
}
private DependencyGraphTraceProviderResource(DependencyGraphTraceProvider provider, FudgeContext fudgeContext, DependencyGraphTraceBuilderProperties properties) {
_fudgeContext = fudgeContext;
_provider = provider;
_properties = properties;
}
@VisibleForTesting
FudgeContext getFudgeContext() {
return _fudgeContext;
}
@VisibleForTesting
DependencyGraphTraceProvider getProvider() {
return _provider;
}
@VisibleForTesting
DependencyGraphTraceBuilderProperties getProperties() {
return _properties;
}
@GET
public Response getHateaos(@Context UriInfo uriInfo) {
return hateoasResponse(uriInfo);
}
@Path("valuationTime/{valuationTime}")
public DependencyGraphTraceProviderResource setValuationTime(@PathParam("valuationTime") final String valuationTime) {
Instant parsedValuationTime = Instant.parse(valuationTime);
DependencyGraphTraceBuilderProperties properties = _properties.valuationTime(parsedValuationTime);
return new DependencyGraphTraceProviderResource(_provider, _fudgeContext, properties);
}
@Path("resolutionTime/{resolutionTime}")
public DependencyGraphTraceProviderResource setResolutionTime(@PathParam("resolutionTime") final String resolutionTime) {
VersionCorrection parsedResolutionTime = VersionCorrection.parse(resolutionTime);
DependencyGraphTraceBuilderProperties properties = _properties.resolutionTime(parsedResolutionTime);
return new DependencyGraphTraceProviderResource(_provider, _fudgeContext, properties);
}
@Path("calculationConfigurationName/{calculationConfigurationName}")
public DependencyGraphTraceProviderResource setCalculationConfigurationName(@PathParam("calculationConfigurationName") final String calculationConfigurationName) {
DependencyGraphTraceBuilderProperties properties = _properties.calculationConfigurationName(calculationConfigurationName);
return new DependencyGraphTraceProviderResource(_provider, _fudgeContext, properties);
}
@Path("defaultProperties/{defaultProperties}")
public DependencyGraphTraceProviderResource setDefaultProperties(@PathParam("defaultProperties") final String defaultProperties) {
ValueProperties valueProperties = ValueProperties.parse(defaultProperties);
DependencyGraphTraceBuilderProperties properties = _properties.defaultProperties(valueProperties);
return new DependencyGraphTraceProviderResource(_provider, _fudgeContext, properties);
}
@Path("value/{valueName}/{targetType}/{targetId}")
public DependencyGraphTraceProviderResource setValueRequirementByUniqueId(@PathParam("valueName") final String valueName, @PathParam("targetType") final String targetType,
@PathParam("targetId") final String targetId) {
UniqueId uniqueId = UniqueId.parse(targetId);
ValueRequirement valueRequirement = toValueRequirement(valueName, new ComputationTargetSpecification(ComputationTargetType.parse(targetType), uniqueId));
DependencyGraphTraceBuilderProperties properties = _properties.addRequirement(valueRequirement);
return new DependencyGraphTraceProviderResource(_provider, _fudgeContext, properties);
}
@Path("requirement/{valueName}/{targetType}/{targetId}")
public DependencyGraphTraceProviderResource setValueRequirementByExternalId(@PathParam("valueName") final String valueName, @PathParam("targetType") final String targetType,
@PathParam("targetId") final String targetId) {
ExternalId externalId = ExternalId.parse(targetId);
ValueRequirement valueRequirement = toValueRequirement(valueName, new ComputationTargetRequirement(ComputationTargetType.parse(targetType), externalId));
DependencyGraphTraceBuilderProperties properties = _properties.addRequirement(valueRequirement);
return new DependencyGraphTraceProviderResource(_provider, _fudgeContext, properties);
}
@Path("marketDataSnapshot/{snapshotId}")
public DependencyGraphTraceProviderResource setMarketDataSnapshot(@PathParam("snapshotId") final String snapshotId) {
UserMarketDataSpecification marketData = MarketData.user(UniqueId.parse(snapshotId));
DependencyGraphTraceBuilderProperties properties = _properties.addMarketData(marketData);
return new DependencyGraphTraceProviderResource(_provider, _fudgeContext, properties);
}
@Path("marketDataLiveDefault")
public DependencyGraphTraceProviderResource setMarketDataLiveDefault() {
MarketDataSpecification marketData = MarketData.live();
DependencyGraphTraceBuilderProperties properties = _properties.addMarketData(marketData);
return new DependencyGraphTraceProviderResource(_provider, _fudgeContext, properties);
}
@Path("marketDataLive/{dataSource}")
public DependencyGraphTraceProviderResource setMarketDataLive(@PathParam("dataSource") final String dataSource) {
MarketDataSpecification marketData = MarketData.live(dataSource);
DependencyGraphTraceBuilderProperties properties = _properties.addMarketData(marketData);
return new DependencyGraphTraceProviderResource(_provider, _fudgeContext, properties);
}
@Path("marketDataHistorical/{localDate}/{timeSeriesResolverKey}")
public DependencyGraphTraceProviderResource setMarketDataHistorical(@PathParam("localDate") final String localDateStr, @PathParam("timeSeriesResolverKey") final String timeSeriesResolverKey) {
LocalDate localDate = LocalDate.parse(localDateStr);
MarketDataSpecification marketData = MarketData.historical(localDate, timeSeriesResolverKey);
DependencyGraphTraceBuilderProperties properties = _properties.addMarketData(marketData);
return new DependencyGraphTraceProviderResource(_provider, _fudgeContext, properties);
}
@GET
@Path("build")
public FudgeMsgEnvelope build() {
DependencyGraphBuildTrace result = _provider.getTrace(_properties);
MutableFudgeMsg fudgeMsg = new FudgeSerializer(_fudgeContext).objectToFudgeMsg(result);
return new FudgeMsgEnvelope(fudgeMsg);
}
private ValueRequirement toValueRequirement(final String valueName, final ComputationTargetReference target) {
final String name;
final ValueProperties constraints;
final int i = valueName.indexOf('{');
if ((i > 0) && (valueName.charAt(valueName.length() - 1) == '}')) {
name = valueName.substring(0, i);
constraints = ValueProperties.parse(valueName.substring(i));
} else {
name = valueName;
constraints = ValueProperties.none();
}
return new ValueRequirement(name, target, constraints);
}
// ------------------------------------------
/**
* Builds URI for remote access to getTraceWithCalculationConfigurationName.
* @param baseUri the base uri
* @param calculationConfigurationName the calculation configuration name
* @return the URI
*/
public static URI uriCalculationConfigurationName(URI baseUri, String calculationConfigurationName) {
UriBuilder bld = UriBuilder.fromUri(baseUri).path("calculationConfigurationName/{calculationConfigurationName}");
return bld.build(calculationConfigurationName);
}
/**
* Builds URI for remote access to getTraceWithValuationTime.
* @param baseUri the base uri
* @param valuationInstant the valuation time
* @return the URI
*/
public static URI uriValuationTime(URI baseUri, Instant valuationInstant) {
String valuationInstantStr = valuationInstant.toString();
UriBuilder bld = UriBuilder.fromUri(baseUri).path("valuationTime/{valuationTime}");
return bld.build(valuationInstantStr);
}
/**
* Builds URI for remote access to getTraceWithResolutionTime.
* @param baseUri the base uri
* @param resolutionTime the resolution time
* @return the URI
*/
public static URI uriResolutionTime(URI baseUri, VersionCorrection resolutionTime) {
String resolutionTimeStr = resolutionTime.toString();
UriBuilder bld = UriBuilder.fromUri(baseUri).path("resolutionTime/{resolutionTime}");
return bld.build(resolutionTimeStr);
}
/**
* Builds URI for remote access to getTraceWithDefaultProperties.
* @param baseUri the base uri
* @param defaultProperties the default properties
* @return the URI
*/
public static URI uriDefaultProperties(URI baseUri, ValueProperties defaultProperties) {
String defaultPropertiesStr = defaultProperties.toString();
UriBuilder bld = UriBuilder.fromUri(baseUri).path("defaultProperties/{defaultProperties}");
return bld.build(defaultPropertiesStr);
}
/**
* Builds URI for remote access to getTraceWithMarketData.
* @param baseUri the base uri
* @param marketData the market data
* @return the URI
*/
public static URI uriMarketData(URI baseUri, List<MarketDataSpecification> marketData) {
for (MarketDataSpecification mdSpec : marketData) {
if (mdSpec instanceof UserMarketDataSpecification) {
String snapshotId = ((UserMarketDataSpecification) mdSpec).getUserSnapshotId().toString();
UriBuilder bld = UriBuilder.fromUri(baseUri).path("marketDataSnapshot/{snapshotId}");
baseUri = bld.build(snapshotId);
} else if (mdSpec instanceof LiveMarketDataSpecification) {
String dataSource = ((LiveMarketDataSpecification) mdSpec).getDataSource();
if (dataSource == null) {
UriBuilder bld = UriBuilder.fromUri(baseUri).path("marketDataLiveDefault");
baseUri = bld.build();
} else {
UriBuilder bld = UriBuilder.fromUri(baseUri).path("marketDataLive/{dataSource}");
baseUri = bld.build(dataSource);
}
} else if (mdSpec instanceof FixedHistoricalMarketDataSpecification) {
String snapshotDate = ((FixedHistoricalMarketDataSpecification) mdSpec).getSnapshotDate().toString();
String timeSeriesResolverKey = ((FixedHistoricalMarketDataSpecification) mdSpec).getTimeSeriesResolverKey();
UriBuilder bld = UriBuilder.fromUri(baseUri).path("marketDataHistorical/{localDate}/{timeSeriesResolverKey}");
baseUri = bld.build(snapshotDate, timeSeriesResolverKey);
}
}
return baseUri;
}
/**
* Builds URI for remote access to getTraceWithValueRequirementByUniqueId
* @param baseUri the base uri
* @param valueName the value name
* @param targetType the target type
* @param uniqueId the unique id
* @return the URI
*/
public static URI uriValueRequirementByUniqueId(URI baseUri, String valueName, String targetType, UniqueId uniqueId) {
String uniqueIdStr = uniqueId.toString();
UriBuilder bld = UriBuilder.fromUri(baseUri).path("value/{valueName}/{targetType}/{targetId}");
return bld.build(valueName, targetType, uniqueIdStr);
}
/**
* Builds URI for remote access to getTraceWithValueRequirementByExternalId
* @param baseUri the base uri
* @param valueName the value name
* @param targetType the target type
* @param externalId the external id
* @return the URI
*/
public static URI uriValueRequirementByExternalId(URI baseUri, String valueName, String targetType, ExternalId externalId) {
String externalIdStr = externalId.toString();
UriBuilder bld = UriBuilder.fromUri(baseUri).path("requirement/{valueName}/{targetType}/{targetId}");
return bld.build(valueName, targetType, externalIdStr);
}
/**
* The build call. This must be called after all of the other parameters have been added.
* @param baseUri the uri with all params added
* @return the uri complete with build call
*/
public static URI uriBuild(URI baseUri) {
UriBuilder bld = UriBuilder.fromUri(baseUri).path("build");
return bld.build();
}
}