@Override
 public void clientDisconnected() {
   AnalyticsViewClientConnection connection = _viewConnections.remove(_viewId);
   if (connection != null) {
     s_logger.debug("Client disconnected, closing view with ID {}", _viewId);
     connection.close();
   }
 }
 /**
  * Returns a view client given its view ID.
  *
  * @param viewId ID of the view
  * @return the view client.
  * @throws DataNotFoundException If there's no view with the specified ID
  */
 public ViewClient getViewCient(String viewId) {
   AnalyticsViewClientConnection connection = _viewConnections.get(viewId);
   if (connection == null) {
     s_logger.debug("Received request for unknown view ID {}", viewId);
     throw new DataNotFoundException("No view found with ID " + viewId);
   }
   return connection.getViewClient();
 }
 /**
  * Deletes a view.
  *
  * @param viewId ID of the view
  * @throws DataNotFoundException If there's no view with the specified ID
  */
 public void deleteView(String viewId) {
   AnalyticsViewClientConnection connection = _viewConnections.remove(viewId);
   if (connection == null) {
     s_logger.debug("Received request to delete unknown view ID {}", viewId);
     throw new DataNotFoundException("No view found with ID " + viewId);
   }
   s_logger.debug("Closing view with ID {}", viewId);
   connection.close();
 }
 /**
  * Creates a new view.
  *
  * @param request Details of the view
  * @param clientId ID of the client connection
  * @param user User requesting the view
  * @param clientConnection Connection that will be notified of changes to the view
  * @param viewId ID of the view, must be unique
  * @param viewCallbackId ID that's passed to the listener when the view's portfolio grid structure
  *     changes
  * @param portfolioGridId ID that's passed to the listener when the view's portfolio grid
  *     structure changes
  * @param primitivesGridId ID that's passed to the listener when the view's primitives grid
  *     structure changes
  * @param errorId
  */
 public void createView(
     ViewRequest request,
     String clientId,
     UserPrincipal user,
     ClientConnection clientConnection,
     String viewId,
     Object viewCallbackId,
     String portfolioGridId,
     String primitivesGridId,
     String errorId) {
   if (_viewConnections.containsKey(viewId)) {
     throw new IllegalArgumentException("View ID " + viewId + " is already in use");
   }
   AggregatedViewDefinition aggregatedViewDef =
       new AggregatedViewDefinition(_aggregatedViewDefManager, request);
   ViewDefinition viewDef =
       (ViewDefinition) _configSource.get(aggregatedViewDef.getUniqueId()).getValue();
   VersionCorrection versionCorrection = request.getPortfolioVersionCorrection();
   // this can be null for a primitives-only view
   UniqueId portfolioId = viewDef.getPortfolioId();
   Supplier<Portfolio> portfolioSupplier;
   ObjectId portfolioObjectId;
   if (portfolioId != null) {
     portfolioObjectId = portfolioId.getObjectId();
   } else {
     portfolioObjectId = null;
   }
   portfolioSupplier =
       new PortfolioSupplier(
           portfolioObjectId,
           versionCorrection,
           _positionSource,
           _securitySource,
           _portfolioResolutionExecutor);
   // TODO something a bit more sophisticated with the executor
   ViewClient viewClient = _viewProcessor.createViewClient(user);
   s_logger.debug("Client ID {} creating new view with ID {}", clientId, viewId);
   ViewportListener viewportListener = new LoggingViewportListener(viewClient);
   PortfolioEntityExtractor entityExtractor =
       new PortfolioEntityExtractor(versionCorrection, _securityMaster);
   // TODO add filtering change listener to portfolio master which calls portfolioChanged() on the
   // outer view
   boolean primitivesOnly = portfolioId == null;
   ErrorManager errorManager = new ErrorManager(errorId);
   AnalyticsView view =
       new SimpleAnalyticsView(
           aggregatedViewDef.getUniqueId(),
           primitivesOnly,
           versionCorrection,
           viewId,
           portfolioGridId,
           primitivesGridId,
           _targetResolver,
           viewportListener,
           _blotterColumnMapper,
           portfolioSupplier,
           entityExtractor,
           request.showBlotterColumns(),
           errorManager);
   AnalyticsView lockingView = new LockingAnalyticsView(view);
   AnalyticsView notifyingView = new NotifyingAnalyticsView(lockingView, clientConnection);
   AnalyticsView timingView = new TimingAnalyticsView(notifyingView);
   AnalyticsView catchingView =
       new CatchingAnalyticsView(timingView, errorManager, clientConnection);
   AutoCloseable securityListener =
       new MasterNotificationListener<>(_securityMaster, catchingView);
   AutoCloseable positionListener =
       new MasterNotificationListener<>(_positionMaster, catchingView);
   AutoCloseable portfolioListener =
       new PortfolioListener(portfolioObjectId, catchingView, _positionSource);
   List<AutoCloseable> listeners =
       Lists.newArrayList(securityListener, positionListener, portfolioListener);
   AnalyticsViewClientConnection connection =
       new AnalyticsViewClientConnection(
           request,
           aggregatedViewDef,
           viewClient,
           catchingView,
           listeners,
           _parallelViewRecompilation,
           _marketDataSpecificationRepository,
           _portfolioResolutionExecutor,
           _securitySource);
   _viewConnections.put(viewId, connection);
   // need to notify the listener that the view has been created
   // TODO would it be neater to leave this to the constructor of NotifyingAnalyticsView
   clientConnection.itemUpdated(viewCallbackId);
   connection.start();
   clientConnection.addDisconnectionListener(new DisconnectionListener(viewId));
 }