com.opengamma.web.analytics.rest.WebUiResource.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.web.analytics.rest.WebUiResource.java

Source

/**
 * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.web.analytics.rest;

import java.net.URI;
import java.security.Principal;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threeten.bp.Instant;
import org.threeten.bp.LocalDateTime;
import org.threeten.bp.format.DateTimeFormatter;

import com.google.common.collect.ImmutableMap;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.view.client.ViewClient;
import com.opengamma.engine.view.client.ViewClientState;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.livedata.UserPrincipal;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.OpenGammaClock;
import com.opengamma.util.rest.RestUtils;
import com.opengamma.web.analytics.AnalyticsView;
import com.opengamma.web.analytics.AnalyticsViewManager;
import com.opengamma.web.analytics.ErrorInfo;
import com.opengamma.web.analytics.GridCell;
import com.opengamma.web.analytics.GridStructure;
import com.opengamma.web.analytics.MarketDataSpecificationJsonReader;
import com.opengamma.web.analytics.ViewRequest;
import com.opengamma.web.analytics.ViewportDefinition;
import com.opengamma.web.analytics.ViewportResults;
import com.opengamma.web.analytics.formatting.TypeFormatter;
import com.opengamma.web.analytics.json.ValueRequirementFormParam;
import com.opengamma.web.analytics.push.ClientConnection;
import com.opengamma.web.analytics.push.ConnectionManager;

/**
 * REST resource for the analytics grid. This resource class specifies the endpoints of every object in the
 * hierarchy of grids, dependency graphs and viewports in the analytics viewer.
 */
@Path("views")
public class WebUiResource {

    private static final Logger s_logger = LoggerFactory.getLogger(WebUiResource.class);
    private static final DateTimeFormatter CSV_TIME_FORMAT = DateTimeFormatter.ofPattern("yyyy_MM_dd_HH_mm_ss");

    /** For generating IDs for the views. */
    private static final AtomicLong s_nextViewId = new AtomicLong(0);
    /** For generating IDs for the viewports and dependency graphs. */
    private static final AtomicInteger s_nextId = new AtomicInteger(0);

    /** For creating and retrieving views. */
    private final AnalyticsViewManager _viewManager;
    /** For looking up a client's connection. */
    private final ConnectionManager _connectionManager;

    public WebUiResource(AnalyticsViewManager viewManager, ConnectionManager connectionManager) {
        ArgumentChecker.notNull(viewManager, "viewManager");
        ArgumentChecker.notNull(connectionManager, "connectionManager");
        _viewManager = viewManager;
        _connectionManager = connectionManager;
    }

    @POST
    public Response createView(@Context SecurityContext securityContext, @Context UriInfo uriInfo,
            @FormParam("requestId") String requestId, @FormParam("viewDefinitionId") String viewDefinitionId,
            @FormParam("aggregators") List<String> aggregators,
            @FormParam("marketDataProviders") String marketDataProviders,
            @FormParam("valuationTime") String valuationTime,
            @FormParam("portfolioVersionTime") String portfolioVersionTime,
            @FormParam("portfolioCorrectionTime") String portfolioCorrectionTime,
            @FormParam("clientId") String clientId, @FormParam("blotter") Boolean blotter) {
        ArgumentChecker.notEmpty(requestId, "requestId");
        ArgumentChecker.notEmpty(viewDefinitionId, "viewDefinitionId");
        ArgumentChecker.notNull(aggregators, "aggregators");
        ArgumentChecker.notEmpty(marketDataProviders, "marketDataProviders");
        ArgumentChecker.notEmpty(clientId, "clientId");
        boolean blotterColumns = blotter == null ? false : blotter;
        List<MarketDataSpecification> marketDataSpecs = MarketDataSpecificationJsonReader
                .buildSpecifications(marketDataProviders);
        VersionCorrection versionCorrection = VersionCorrection.of(parseInstant(portfolioVersionTime),
                parseInstant(portfolioCorrectionTime));
        ViewRequest viewRequest = new ViewRequest(UniqueId.parse(viewDefinitionId), aggregators, marketDataSpecs,
                parseInstant(valuationTime), versionCorrection, blotterColumns);
        String viewId = Long.toString(s_nextViewId.getAndIncrement());
        URI portfolioGridUri = uriInfo.getAbsolutePathBuilder().path(viewId).path("portfolio").build();
        URI primitivesGridUri = uriInfo.getAbsolutePathBuilder().path(viewId).path("primitives").build();
        Principal userPrincipal = securityContext.getUserPrincipal();
        String userName = userPrincipal != null ? userPrincipal.getName() : null;
        ClientConnection connection = _connectionManager.getConnectionByClientId(userName, clientId);
        URI uri = uriInfo.getAbsolutePathBuilder().path(viewId).build();
        ImmutableMap<String, Object> callbackMap = ImmutableMap.<String, Object>of("id", requestId, "message",
                uri.getPath());
        URI errorUri = uriInfo.getAbsolutePathBuilder().path(viewId).path("errors").build();
        UserPrincipal ogUserPrincipal = userName != null ? UserPrincipal.getLocalUser(userName)
                : UserPrincipal.getTestUser();
        _viewManager.createView(viewRequest, clientId, ogUserPrincipal, connection, viewId, callbackMap,
                portfolioGridUri.getPath(), primitivesGridUri.getPath(), errorUri.getPath());
        return Response.status(Response.Status.CREATED).build();
    }

    @Path("{viewId}")
    @DELETE
    public void deleteView(@PathParam("viewId") String viewId) {
        _viewManager.deleteView(viewId);
    }

    @Path("{viewId}/pauseOrResume")
    @PUT
    public Response pauseOrResumeView(@PathParam("viewId") String viewId, @FormParam("state") String state) {
        ViewClient viewClient = _viewManager.getViewCient(viewId);
        state = StringUtils.stripToNull(state);
        Response response = Response.status(Response.Status.BAD_REQUEST).build();
        if (state != null) {
            ViewClientState currentState = viewClient.getState();
            state = state.toUpperCase();
            switch (state) {
            case "PAUSE":
            case "P":
                if (currentState != ViewClientState.TERMINATED) {
                    viewClient.pause();
                    response = Response.ok().build();
                }
                break;
            case "RESUME":
            case "R":
                if (currentState != ViewClientState.TERMINATED) {
                    viewClient.resume();
                    response = Response.ok().build();
                }
                break;
            default:
                s_logger.warn("client {} requesting for invalid view client state change to {}", viewId, state);
                response = Response.status(Response.Status.BAD_REQUEST).build();
                break;
            }
        }
        return response;
    }

    @Path("{viewId}/{gridType}")
    @GET
    public GridStructure getGridStructure(@PathParam("viewId") String viewId,
            @PathParam("gridType") String gridType) {
        return _viewManager.getView(viewId).getInitialGridStructure(gridType(gridType));
    }

    @Path("{viewId}/{gridType}/viewports")
    @POST
    public Response createViewport(@Context UriInfo uriInfo, @PathParam("viewId") String viewId,
            @PathParam("gridType") String gridType, @FormParam("requestId") int requestId,
            @FormParam("version") int version, @FormParam("rows") List<Integer> rows,
            @FormParam("columns") List<Integer> columns, @FormParam("cells") List<GridCell> cells,
            @FormParam("format") TypeFormatter.Format format, @FormParam("enableLogging") Boolean enableLogging) {
        ViewportDefinition viewportDefinition = ViewportDefinition.create(version, rows, columns, cells, format,
                enableLogging);
        int viewportId = s_nextId.getAndIncrement();
        String viewportIdStr = Integer.toString(viewportId);
        UriBuilder viewportUriBuilder = uriInfo.getAbsolutePathBuilder().path(viewportIdStr);
        String callbackId = viewportUriBuilder.build().getPath();
        String structureCallbackId = viewportUriBuilder.path("structure").build().getPath();
        _viewManager.getView(viewId).createViewport(requestId, gridType(gridType), viewportId, callbackId,
                structureCallbackId, viewportDefinition);
        return Response.status(Response.Status.CREATED).build();
    }

    @Path("{viewId}/{gridType}/viewports/{viewportId}")
    @PUT
    public void updateViewport(@PathParam("viewId") String viewId, @PathParam("gridType") String gridType,
            @PathParam("viewportId") int viewportId, @FormParam("version") int version,
            @FormParam("rows") List<Integer> rows, @FormParam("columns") List<Integer> columns,
            @FormParam("cells") List<GridCell> cells, @FormParam("format") TypeFormatter.Format format,
            @FormParam("enableLogging") Boolean enableLogging) {
        ViewportDefinition viewportDef = ViewportDefinition.create(version, rows, columns, cells, format,
                enableLogging);
        _viewManager.getView(viewId).updateViewport(gridType(gridType), viewportId, viewportDef);
    }

    @Path("{viewId}/{gridType}/viewports/{viewportId}/structure")
    @GET
    public GridStructure getViewportGridStructure(@PathParam("viewId") String viewId,
            @PathParam("gridType") String gridType, @PathParam("viewportId") int viewportId) {
        return _viewManager.getView(viewId).getGridStructure(gridType(gridType), viewportId);
    }

    @Path("{viewId}/{gridType}/viewports/{viewportId}")
    @GET
    public ViewportResults getViewportData(@PathParam("viewId") String viewId,
            @PathParam("gridType") String gridType, @PathParam("viewportId") int viewportId) {
        return _viewManager.getView(viewId).getData(gridType(gridType), viewportId);
    }

    @Path("{viewId}/{gridType}/viewports/{viewportId}")
    @DELETE
    public void deleteViewport(@PathParam("viewId") String viewId, @PathParam("gridType") String gridType,
            @PathParam("viewportId") int viewportId) {
        _viewManager.getView(viewId).deleteViewport(gridType(gridType), viewportId);
    }

    @Path("{viewId}/{gridType}/depgraphs")
    @POST
    public Response openDependencyGraph(@Context UriInfo uriInfo, @PathParam("viewId") String viewId,
            @PathParam("gridType") String gridType, @FormParam("requestId") int requestId,
            @FormParam("row") Integer row, @FormParam("col") Integer col,
            @FormParam("calcConfigName") String calcConfigName,
            @FormParam("valueRequirement") ValueRequirementFormParam valueRequirementParam) {
        int graphId = s_nextId.getAndIncrement();
        String graphIdStr = Integer.toString(graphId);
        URI graphUri = uriInfo.getAbsolutePathBuilder().path(graphIdStr).build();
        String callbackId = graphUri.getPath();
        if (row != null && col != null) {
            _viewManager.getView(viewId).openDependencyGraph(requestId, gridType(gridType), graphId, callbackId,
                    row, col);
        } else if (calcConfigName != null && valueRequirementParam != null) {
            ValueRequirement req = valueRequirementParam.getValueRequirement();
            _viewManager.getView(viewId).openDependencyGraph(requestId, gridType(gridType), graphId, callbackId,
                    calcConfigName, req);
        }
        return Response.status(Response.Status.CREATED).build();
    }

    @Path("{viewId}/{gridType}/depgraphs/{depgraphId}")
    @GET
    public GridStructure getDependencyGraphGridStructure(@PathParam("viewId") String viewId,
            @PathParam("gridType") String gridType, @PathParam("depgraphId") int depgraphId) {
        return _viewManager.getView(viewId).getInitialGridStructure(gridType(gridType), depgraphId);
    }

    @Path("{viewId}/{gridType}/depgraphs/{depgraphId}")
    @DELETE
    public void deleteDependencyGraph(@PathParam("viewId") String viewId, @PathParam("gridType") String gridType,
            @PathParam("depgraphId") int depgraphId) {
        _viewManager.getView(viewId).closeDependencyGraph(gridType(gridType), depgraphId);
    }

    @Path("{viewId}/{gridType}/depgraphs/{depgraphId}/viewports")
    @POST
    public Response createDependencyGraphViewport(@Context UriInfo uriInfo, @PathParam("viewId") String viewId,
            @PathParam("gridType") String gridType, @PathParam("depgraphId") int depgraphId,
            @FormParam("requestId") int requestId, @FormParam("version") int version,
            @FormParam("rows") List<Integer> rows, @FormParam("columns") List<Integer> columns,
            @FormParam("cells") List<GridCell> cells, @FormParam("format") TypeFormatter.Format format,
            @FormParam("enableLogging") Boolean enableLogging) {
        ViewportDefinition viewportDefinition = ViewportDefinition.create(version, rows, columns, cells, format,
                enableLogging);
        int viewportId = s_nextId.getAndIncrement();
        String viewportIdStr = Integer.toString(viewportId);
        UriBuilder viewportUriBuilder = uriInfo.getAbsolutePathBuilder().path(viewportIdStr);
        String callbackId = viewportUriBuilder.build().getPath();
        String structureCallbackId = viewportUriBuilder.path("structure").build().getPath();
        _viewManager.getView(viewId).createViewport(requestId, gridType(gridType), depgraphId, viewportId,
                callbackId, structureCallbackId, viewportDefinition);
        return Response.status(Response.Status.CREATED).build();
    }

    @Path("{viewId}/{gridType}/depgraphs/{depgraphId}/viewports/{viewportId}")
    @PUT
    public void updateDependencyGraphViewport(@PathParam("viewId") String viewId,
            @PathParam("gridType") String gridType, @PathParam("depgraphId") int depgraphId,
            @PathParam("viewportId") int viewportId, @FormParam("version") int version,
            @FormParam("rows") List<Integer> rows, @FormParam("columns") List<Integer> columns,
            @FormParam("cells") List<GridCell> cells, @FormParam("format") TypeFormatter.Format format,
            @FormParam("enableLogging") Boolean enableLogging) {
        ViewportDefinition viewportDef = ViewportDefinition.create(version, rows, columns, cells, format,
                enableLogging);
        _viewManager.getView(viewId).updateViewport(gridType(gridType), depgraphId, viewportId, viewportDef);
    }

    @Path("{viewId}/{gridType}/depgraphs/{depgraphId}/viewports/{viewportId}/structure")
    @GET
    public GridStructure getDependencyGraphViewportGridStructure(@PathParam("viewId") String viewId,
            @PathParam("gridType") String gridType, @PathParam("depgraphId") int depgraphId,
            @PathParam("viewportId") int viewportId) {
        return _viewManager.getView(viewId).getGridStructure(gridType(gridType), depgraphId, viewportId);
    }

    @Path("{viewId}/{gridType}/depgraphs/{depgraphId}/viewports/{viewportId}")
    @GET
    public ViewportResults getDependencyGraphViewportData(@PathParam("viewId") String viewId,
            @PathParam("gridType") String gridType, @PathParam("depgraphId") int depgraphId,
            @PathParam("viewportId") int viewportId) {
        return _viewManager.getView(viewId).getData(gridType(gridType), depgraphId, viewportId);
    }

    @Path("{viewId}/{gridType}/depgraphs/{depgraphId}/viewports/{viewportId}")
    @DELETE
    public void deleteDependencyGraphViewport(@PathParam("viewId") String viewId,
            @PathParam("gridType") String gridType, @PathParam("depgraphId") int depgraphId,
            @PathParam("viewportId") int viewportId) {
        _viewManager.getView(viewId).deleteViewport(gridType(gridType), depgraphId, viewportId);
    }

    @Path("{viewId}/errors")
    @GET
    public List<ErrorInfo> getErrors(@PathParam("viewId") String viewId) {
        return _viewManager.getView(viewId).getErrors();
    }

    @Path("{viewId}/errors/{errorId}")
    @DELETE
    public void deleteError(@PathParam("viewId") String viewId, @PathParam("errorId") long errorId) {
        _viewManager.getView(viewId).deleteError(errorId);
    }

    /**
     * Produces view port results as CSV
     *
     * @param response the injected servlet response, not null.
     * @param viewId ID of the view
     * @param gridTypeStr the grid type, 'portfolio' or 'primitives'
     * @return The view port result as csv
     */
    @GET
    @Path("{viewId}/{gridType}/data")
    @Produces(RestUtils.TEXT_CSV)
    public ViewportResults getViewportResultAsCsv(@PathParam("viewId") String viewId,
            @PathParam("gridType") String gridTypeStr, @Context HttpServletResponse response) {
        AnalyticsView view = _viewManager.getView(viewId);
        AnalyticsView.GridType gridType = gridType(gridTypeStr);
        ViewportResults result = view.getAllGridData(gridType, TypeFormatter.Format.CELL);
        Instant valuationTime;
        if (result.getValuationTime() != null) {
            valuationTime = result.getValuationTime();
        } else {
            valuationTime = OpenGammaClock.getInstance().instant();
        }
        LocalDateTime time = LocalDateTime.ofInstant(valuationTime, OpenGammaClock.getZone());

        String filename = String.format("%s-%s-%s.csv", view.getViewDefinitionId(), gridType.name().toLowerCase(),
                time.toString(CSV_TIME_FORMAT));
        response.addHeader("content-disposition", "attachment; filename=\"" + filename + "\"");
        return view.getAllGridData(gridType, TypeFormatter.Format.CELL);
    }

    /**
     * @param instantString An ISO-8601 string representing an instant or null
     * @return The parsed string or null if the input is null
     */
    private static Instant parseInstant(String instantString) {
        if (instantString == null) {
            return null;
        } else {
            return Instant.parse(instantString);
        }
    }

    private static AnalyticsView.GridType gridType(String gridType) {
        return AnalyticsView.GridType.valueOf(gridType.toUpperCase());
    }
}