class DbRequest {

    public UpdatedDocument execRuleRequest(final String documentId, final RuleActions ruleActions,
        Map<String, DurationData> bindRuleToDuration, OntologyValidator ontologyValidator, UnitValidator unitValidator,
        List<OntologyModel> ontologyModels)
        throws InvalidParseOperationException, MetaDataExecutionException, InvalidCreateOperationException,
        MetaDataNotFoundException, MetadataValidationException {

        final Integer tenantId = ParameterHelper.getTenantParameter();

        int tries = 0;

        while (tries < 3) {
            MetadataCollections metadataCollections = MetadataCollections.UNIT;

            MongoCollection<MetadataDocument<?>> collection = metadataCollections.getCollection();
            MetadataDocument<?> document = collection.find(and(
                eq(MetadataDocument.ID, documentId),
                eq(MetadataDocument.TENANT_ID, VitamThreadUtils.getVitamSession().getTenantId())
            )).first();
            if (document == null) {
                throw new MetaDataNotFoundException("Document not found by id " + documentId);
            }

            final JsonNode jsonDocument = JsonHandler.toJsonNode(document);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("DEBUG update {} to update to {}", jsonDocument,
                    JsonHandler.prettyPrint(ruleActions));
            }
            DynamicParserTokens parserTokens =
                new DynamicParserTokens(metadataCollections.getVitamDescriptionResolver(), ontologyModels);
            final MongoDbInMemory mongoInMemory = new MongoDbInMemory(jsonDocument,
                parserTokens);

            // Add operationId to #operations
            UpdateMultiQuery updateQuery = new UpdateMultiQuery();
            updateQuery
                .addActions(push(VitamFieldsHelper.operations(), VitamThreadUtils.getVitamSession().getRequestId()));

            final RequestParserMultiple updateRequest = new UpdateParserMultiple(new MongoDbVarNameAdapter());
            updateRequest.parse(updateQuery.getFinalUpdateById());
            mongoInMemory.getUpdateJson(updateRequest);

            // Update rules
            final ObjectNode updatedJsonDocument =
                (ObjectNode) mongoInMemory.getUpdateJsonForRule(ruleActions, bindRuleToDuration);

            fieldHistoryManager.trigger(jsonDocument, updatedJsonDocument);

            Integer documentVersion = document.getVersion();
            int newDocumentVersion = documentVersion + 1;
            Integer atomicVersion = document.getAtomicVersion();
            int newAtomicVersion = atomicVersion == null ? newDocumentVersion : atomicVersion + 1;

            updatedJsonDocument.put(VitamDocument.VERSION, newDocumentVersion);
            updatedJsonDocument.put(MetadataDocument.ATOMIC_VERSION, newAtomicVersion);

            Unit updatedDocument = new Unit(updatedJsonDocument);

            // Ontology checks & format transformation
            final ObjectNode transformedUpdatedDocument
                = ontologyValidator.verifyAndReplaceFields(updatedJsonDocument);

            // Unit validation
            unitValidator.validateUnit(transformedUpdatedDocument);

            // Make Update
            final Bson condition;
            if (atomicVersion == null) {
                condition = and(
                    eq(MetadataDocument.ID, documentId),
                    eq(MetadataDocument.TENANT_ID, VitamThreadUtils.getVitamSession().getTenantId()),
                    exists(MetadataDocument.ATOMIC_VERSION, false));
            } else {
                condition = and(
                    eq(MetadataDocument.ID, documentId),
                    eq(MetadataDocument.TENANT_ID, VitamThreadUtils.getVitamSession().getTenantId()),
                    eq(MetadataDocument.ATOMIC_VERSION, atomicVersion));
            }

            LOGGER.debug("DEBUG update {}", transformedUpdatedDocument);
            UpdateResult result = collection.replaceOne(condition, updatedDocument);
            if (result.getModifiedCount() == 1) {
                indexFieldsUpdated(updatedDocument, tenantId);
                return new UpdatedDocument(documentId, jsonDocument, JsonHandler.toJsonNode(updatedDocument));
            }
            tries++;
        }

        throw new MetaDataExecutionException("Can not modify document " + documentId);
    }

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

}