class DbRequest {

    public Result execRequest(final RequestParserMultiple requestParser, List<OntologyModel> ontologies)
        throws MetaDataExecutionException,
        InvalidParseOperationException, BadRequestException,
        VitamDBException {
        final RequestMultiple request = requestParser.getRequest();
        final RequestToAbstract requestToMongodb = RequestToMongodb.getRequestToMongoDb(requestParser);
        final int maxQuery = request.getNbQueries();
        boolean checkConsistency = false;
        Result<MetadataDocument<?>> roots;

        MetadataCollections metadataCollections;
        if (requestParser.model() == FILTERARGS.UNITS) {
            roots = checkUnitStartupRoots(requestParser);
            metadataCollections = MetadataCollections.UNIT;
        } else {
            metadataCollections = MetadataCollections.OBJECTGROUP;
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug(String.format("OBJECTGROUPS DbRequest: %s", requestParser.toString()));
            }
            roots = checkObjectGroupStartupRoots(requestParser);
        }

        DynamicParserTokens parserTokens =
            new DynamicParserTokens(metadataCollections.getVitamDescriptionResolver(), ontologies);

        Result<MetadataDocument<?>> result = roots;
        int rank = 0;
        // if roots is empty, check if first query gives a non empty roots (empty query allowed for insert)
        if (result.getCurrentIds().isEmpty() && maxQuery > 0) {
            final Result<MetadataDocument<?>> newResult =
                executeQuery(requestParser, requestToMongodb, rank, result, parserTokens);

            if (newResult != null && !newResult.getCurrentIds().isEmpty() && !newResult.isError()) {
                result = newResult;
                checkConsistency = true;
            } else {
                LOGGER.debug(
                    NO_RESULT_AT_RANK + rank + FROM + requestParser + WHERE_PREVIOUS_IS + result);
                // XXX TODO P1 should be adapted to have a correct error feedback
                result = new ResultError(requestParser.model())
                    .addError(newResult != null ? newResult.getCurrentIds().toString() : NO_RESULT_TRUE)
                    .addError(NO_RESULT_AT_RANK2 + rank).addError(FROM2 + requestParser)
                    .addError(WHERE_PREVIOUS_RESULT_WAS + result).setTotal(newResult != null ? newResult.total : 0);
                return result;
            }
            LOGGER.debug("Query: {}\n\tResult: {}", requestParser, result);
            rank++;
        }
        // Stops if no result (empty)
        for (; !result.getCurrentIds().isEmpty() && rank < maxQuery; rank++) {
            final Result<MetadataDocument<?>> newResult =
                executeQuery(requestParser, requestToMongodb, rank, result, parserTokens);
            if (newResult == null) {
                LOGGER.debug(
                    NO_RESULT_AT_RANK + rank + FROM + requestParser + WHERE_PREVIOUS_IS + result);
                // XXX TODO P1 should be adapted to have a correct error feedback
                result = new ResultError(result.type)
                    .addError(result.getCurrentIds().toString())
                    .addError(NO_RESULT_AT_RANK2 + rank).addError(FROM2 + requestParser)
                    .addError(WHERE_PREVIOUS_RESULT_WAS + result);
                return result;
            }
            if (!newResult.getCurrentIds().isEmpty() && !newResult.isError()) {
                result = newResult;
            } else {
                LOGGER.debug(
                    NO_RESULT_AT_RANK + rank + FROM + requestParser + WHERE_PREVIOUS_IS + result);
                // XXX TODO P1 should be adapted to have a correct error feedback
                result = new ResultError(newResult.type)
                    .addError(newResult != null ? newResult.getCurrentIds().toString() : NO_RESULT_TRUE)
                    .addError(NO_RESULT_AT_RANK2 + rank).addError(FROM2 + requestParser)
                    .addError(WHERE_PREVIOUS_RESULT_WAS + result);
                return result;
            }
            LOGGER.debug("Query: {}\n\tResult: {}", requestParser, result);
        }
        // others do not allow empty result
        if (result.getCurrentIds().isEmpty()) {
            LOGGER.debug(NO_RESULT_AT_RANK + rank + FROM + requestParser + WHERE_PREVIOUS_IS + result);
            // XXX TODO P1 should be adapted to have a correct error feedback
            result = new ResultError(result.type)
                .addError(result != null ? result.getCurrentIds().toString() : NO_RESULT_TRUE)
                .addError(NO_RESULT_AT_RANK2 + rank).addError(FROM2 + requestParser)
                .addError(WHERE_PREVIOUS_RESULT_WAS + result);
            return result;
        }
        if (request instanceof DeleteMultiQuery) {
            final Result<MetadataDocument<?>> newResult =
                lastDeleteFilterProjection((DeleteToMongodb) requestToMongodb, result);
            if (newResult != null) {
                result = newResult;
            }
        } else {
            // Select part
            // get facets
            // get result
            final Result<MetadataDocument<?>> newResult =
                lastSelectFilterProjection((SelectToMongodb) requestToMongodb, result, checkConsistency);

            if (newResult != null) {
                result = newResult;
            }
        }
        LOGGER.debug("Results: {}", result);
        return result;
    }

    @VisibleForTesting  DbRequest(MongoDbMetadataRepository<Unit> mongoDbUnitRepository,
        MongoDbMetadataRepository<ObjectGroup> mongoDbObjectGroupRepository,
        FieldHistoryManager fieldHistoryManager);
    public  DbRequest();

}