/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
/**
* <p>This package contains push notifications (no longer used).</p>
* <em>THIS IS OUT OF DATE. SEE {@link com.opengamma.web.analytics.rest}</em>
* <p>This package provides push notifications when changes occur to resources requested through the REST interface.
* This includes analytics data, entities and queries for entities.</p>
*
* <h1>Establishing a Connection</h1>
* <p>Before a client can receive notifications of updates it must establish a connection and be assigned a
* client ID. A connection corresponds to a single view, e.g. a single browser tab. A user can have multiple
* connections active at the same time. A connection is set up with a request to the handshake URL:</p>
* <pre>
* /handshake</pre>
* <p>The response contains JSON with the client ID, e.g.</p>
* <pre>
* {"clientId": "1234"}</pre>
*
* <h1>Subscribing to Notifications of Updates</h1>
* <p>There is no way to explicitly subscribe to notifications. If a client ID is included in a request
* for a REST resource a subscription will be created. e.g.</p>
* <pre>
* /jax/portfolios/DbPrt~234</pre>
* <p>will return the portfolio details and</p>
* <pre>
* /jax/portfolios/DbPrt~234?clientId=1234</pre>
* <p>will return the portfolio details and set up a subscription. The client with ID {@code 1234} will
* receive a notification if the portfolio is updated.</p>
* <p>There are three different types of object that can produce updates:</p>
*
* <h2>Entities</h2>
* <p>If a client requests an entity (for example a portfolio as shown above) it will receive a notification
* if the entity is updated. To enable this the REST method that returns the entity must have a parameter annotated
* with {@link com.opengamma.web.analytics.rest.Subscribe}. The annotation must be on a string parameter that can be parsed by
* {@link com.opengamma.id.UniqueId#parse(String)} and the parameter must also have a {@link javax.ws.rs.PathParam} annotation. See
* {@link com.opengamma.web.portfolio.WebPortfoliosResource#findPortfolio(String)} for an example.</p>
*
* <h2>Queries</h2>
* <p>If a client performs a query to search for multiple entities it will receive a notification if something
* is updated that <em>might</em> change the result of the query. For example if a client searches for positions:</p>
* <pre>
* /jax/positions?minquantity=5&maxquantity=10&identifier=</pre>
* <p>an update would be sent if <em>any</em> position were updated, not only those with a size in the range 5-10.
* This is a very conservative approach which will often lead to a client re-running a query and receiving the same
* results. A complete solution to this problem would be much more complex and this behaviour is not a problem if the
* queries are cheap.</p>
* <p>To enable subscriptions for queries the REST method must be annotated with {@link com.opengamma.web.analytics.rest.SubscribeMaster} and
* the type(s) of master specified as annotation parameters. See
* {@link com.opengamma.web.portfolio.WebPortfoliosResource#getJSON(Integer, Integer, Integer, String, String, java.util.List, java.util.List, Boolean)}
* for an example.</p>
*
* <h2>Querying Available View Definitions, Market Data Snapshots and Aggregators</h2>
* <p>The view definitions, market data snapshots and aggregators available in the system can be queried as follows:</p>
* <pre>
* /jax/viewdefinitions</pre>
* <p>returns</p>
* <pre>
* [{id: viewDefId1, name: viewDefName1}, {id: viewDefId2, name: viewDefName2}, ...]
* </pre>
* <p>and</p>
* <pre>
* /jax/marketdatasnapshots</pre>
* <p>returns</p>
* <pre>
* [{basisViewName: basisViewName1, snapshots: [{id: snapshot1Id, name: snapshot1Name}, {id: snapshot2Id, name: snapshot2Name}, ...]},
* {basisViewName: basisViewName2, snapshots: [{id: snapshot3Id, name: snapshot3Name}, {id: snapshot4Id, name: snapshot4Name}, ...]}, ...]
* </pre>
* <p>and</p>
* <pre>
* /jax/aggregators</pre>
* <p>returns</p>
* <pre>
* [aggregatorName1, aggregatorName2, ...]
* </pre>
*
** <h2>Views</h2>
* <p>Before a client can receive data for a view it must create a viewport. This is done by making a {@code POST}
* request to:</p>
* <pre>
* /jax/viewports?clientId=...</pre>
* <p>The response will contain JSON with the URL for the newly-created viewport, e.g.</p>
* <pre>
* {"viewportUrl": "/jax/viewports/567"}</pre>
*
* <p>The request must contain JSON which defines the viewport:</p>
* <pre>
* {"viewDefinitionName": ...
* "marketDataType": ...
* "marketDataProvider": ...
* "snapshotId": ...
* "aggregatorName": ...
* "portfolioViewport":
* {"rowIds": [rowId1, rowId2, ...],
* "lastTimestamps": [timestamp1, timestamp2, ...],
* "dependencyGraphCells": [[row, col], [row, col], ...]
* "fullConversionModeCells": [[row, col], [row, col], ...]},
* "primitiveViewport":
* {"rowIds": [rowId1, rowId2, ...],
* "lastTimestamps": [timestamp1, timestamp2, ...],
* "dependencyGraphCells": [[row, col], [row, col], ...],
* "fullConversionModeCells": [[row, col], [row, col], ...]}</pre>
* <ul>
* <li>{@code viewDefinitionName}: name of the view definition (see below)</li>
* <li>{@code marketDataType}: {@code "live"} or {@code "snapshot"}</li>
* <li>{@code marketDataProvider}: name of the market data provider. Only relevant for live data. Omit or {@code "Automatic"} for default provider</li>
* <li>{@code snapshotId}: ID of the market data snapshot (see below). Required if using a market data snapshot. <em>TODO No testing has
* been done using snapshots yet, only live data</em></li>
* <li>{@code portfolioViewport / primitiveViewport}: viewport definition for the separate grids showing portfolio
* and primitive data</li>
* <li>{@code rowIds}: The zero-based row indices whose data should be included in the results.</li>
* <li>{@code lastTimestamps}: The timestamp of the last update the client received for each row. Each item
* in {@code lastTimestamps} refers to the row at the same index in {@code rowIds}. Therefore {@code rowIds} and
* {@code lastTimestamps} must be the same length. If no previous result has been received for the row then
* null should be sent.</li>
* <li>{@code dependencyGraphCells}: array of two-element arrays with the row and column numbers of cells whose
* dependency graph should be included in the results.</li>
* <li>{@code fullConversionModeCells}: array of two-elements arrays with the row and column numbers of cells
* whose full data should be sent to the client. This is for cells that contain multi-valued data (e.g.
* yield curves) where the user can open a pop-up to view the full data.</li>
* </ul>
*
* <h1>Receiving Notifications of Updates</h1>
* <p>A client receives updates by making a request to the update URL for its client ID.</p>
* <pre>
* /updates/{clientId}</pre>
* <p>This request blocks until one of the following:</p>
*
* <h2>The request times out.</h2>
* <p>In this case the response body will be empty.</p>
*
* <h2>An item for which the client has a subscription is updated.</h2>
* <p>The response contains JSON with the REST URLs of any updated items, e.g.</p>
* <pre>
* {"updates": ["/jax/portfolios", "/jax/positions/DbPos~2345"]}</pre>
* <p>Notifications for a client are queued if the client doesn't have a connection open to the update URL when
* the notification arrives. When the client re-establishes the connection the notifications will be delivered
* immediately.</p>
*
* <h2>Notifications Generated by Entities and Queries</h2>
* <p>The URL used to make the original REST request is published when an entity or query changes (see example
* above).</p>
*
* <h2>Notifications Generated by Viewports</h2>
* <p>Viewports generate notifications when the grid structure changes and when the data changes. The URLs are:</p>
* <pre>
* /jax/viewports/{viewportId}/grid
* /jax/viewports/{viewportId}/data</pre>
* <p>The format of the JSON returned from these URLs is unchanged from the Cometd implementation. <em>TODO is
* that documented anywhere?</em></p>
*
* <h1>Cancelling Subscriptions</h1>
* <p>There is no way to unsubscribe for notifications for a particular URL. When any notification is published
* for a URL all subscriptions for that URL are cancelled. When and if the client makes another request to that
* URL a new subscription will be set up.</p>
* <p><em>Is it feasible to not have an unsubscribe mechanism? A long running
* client could create a lot of subscriptions that wouldn't be cleared unless the underlying object were updated.
* Subscriptions are fairly lightweight so this might not be a massive problem.</em></p>
*
* <h1>TODO</h1>
* <p>The following still needs to be done:</p>
* <ul>
* <li>Creating a viewport without a client ID is supported at the moment but there is no mechanism to
* clean up views created in this way. So they are a massive resource leak. An explicit closing mechanism
* and a timeout mechanism are required.</li>
* <li>There is no validation that a client ID belongs to the user who is requesting it. This should work once
* we have user logins.</li>
* <li>There is no way to close a client connection apart from waiting for it to time out. There is support
* in the back end but no RESTful interface.</li>
* <li>Query subscriptions are created when the user just visits the query page, e.g. /jax/portfolios. This
* probably isn't what we want, a subscription should probably be created if there are some query params
* specifying what to search for. it might even be necessary to allow the relevant query params to be
* specified in the annotation</li>
* <li>Should subscriptions be created from the POST methods that create entities? A new filter would be needed
* that looked at the redirecting response to find the URL of the new entity.</li>
* </ul>
*/
package com.opengamma.web.analytics.push;