class DbPortfolioMaster extends AbstractDocumentDbMaster<PortfolioDocument> implements PortfolioMaster {

  @Override
  public PortfolioSearchResult search(final PortfolioSearchRequest request) {
    ArgumentChecker.notNull(request, "request");
    ArgumentChecker.notNull(request.getPagingRequest(), "request.pagingRequest");
    ArgumentChecker.notNull(request.getVersionCorrection(), "request.versionCorrection");
    s_logger.debug("search {}", request);

    final VersionCorrection vc = request.getVersionCorrection().withLatestFixed(now());
    final PortfolioSearchResult result = new PortfolioSearchResult(vc);

    final List<ObjectId> portfolioObjectIds = request.getPortfolioObjectIds();
    final List<ObjectId> nodeObjectIds = request.getNodeObjectIds();
    if ((portfolioObjectIds != null && portfolioObjectIds.size() == 0) ||
        (nodeObjectIds != null && nodeObjectIds.size() == 0)) {
      result.setPaging(Paging.of(request.getPagingRequest(), 0));
      return result;
    }

    final DbMapSqlParameterSource args = createParameterSource()
        .addTimestamp("version_as_of_instant", vc.getVersionAsOf())
        .addTimestamp("corrected_to_instant", vc.getCorrectedTo())
        .addValueNullIgnored("name", getDialect().sqlWildcardAdjustValue(request.getName()));
    if (request.getDepth() >= 0) {
      args.addValue("depth", request.getDepth());
    }
    if (portfolioObjectIds != null) {
      StringBuilder buf = new StringBuilder(portfolioObjectIds.size() * 10);
      for (ObjectId objectId : portfolioObjectIds) {
        checkScheme(objectId);
        buf.append(extractOid(objectId)).append(", ");
      }
      buf.setLength(buf.length() - 2);
      args.addValue("sql_search_portfolio_ids", buf.toString());
    }
    if (nodeObjectIds != null) {
      StringBuilder buf = new StringBuilder(nodeObjectIds.size() * 10);
      for (ObjectId objectId : nodeObjectIds) {
        checkScheme(objectId);
        buf.append(extractOid(objectId)).append(", ");
      }
      buf.setLength(buf.length() - 2);
      args.addValue("sql_search_node_ids", buf.toString());
    }
    args.addValue("visibility", request.getVisibility().getVisibilityLevel());
    args.addValue("sort_order", ORDER_BY_MAP.get(request.getSortOrder()));
    args.addValue("paging_offset", request.getPagingRequest().getFirstItem());
    args.addValue("paging_fetch", request.getPagingRequest().getPagingSize());

    if (request.isIncludePositions()) {
      String[] sql = {getElSqlBundle().getSql("Search", args), getElSqlBundle().getSql("SearchCount", args) };
      doSearch(request.getPagingRequest(), sql, args, new PortfolioDocumentExtractor(true, true), result);
    } else {
      String[] sql = {getElSqlBundle().getSql("SearchNoPositions", args), getElSqlBundle().getSql("SearchCount", args) };
      doSearch(request.getPagingRequest(), sql, args, new PortfolioDocumentExtractor(false, true), result);
    }
    return result;
  }

  public  DbPortfolioMaster(final DbConnector dbConnector);

}